From 22e1bb3fcc3b3db1c0f5c2e6a4aecaf408c307a5 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Sun, 04 Jan 2026 18:29:46 +0000
Subject: [PATCH] Merge branch 'main' of https://github.com/jakevdwerf/jvb

---
 assets/js/min/handleSelection.min.js |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/assets/js/min/handleSelection.min.js b/assets/js/min/handleSelection.min.js
index f57924b..26a0fa2 100644
--- a/assets/js/min/handleSelection.min.js
+++ b/assets/js/min/handleSelection.min.js
@@ -1 +1 @@
-window.jvbHandleSelection=class{constructor(e){this.container=e.container,this.ui=e.ui||{},this.itemSelector=e.itemSelector||".item",this.checkboxSelector=e.checkboxSelector||'[name*="select-item"]',this.selectedItems=new Set,this.lastSelected=null,this.subscribers=new Set,this.init()}init(){this.clickHandler=this.handleClick.bind(this),this.changeHandler=this.handleChange.bind(this),this.keyHandler=this.handleKeys.bind(this),this.container.addEventListener("click",this.clickHandler),this.container.addEventListener("change",this.changeHandler),this.container.addEventListener("keydown",this.keyHandler)}handleKeys(e){(e.ctrlKey||e.metaKey)&&"a"===e.key&&(e.preventDefault(),this.ui.selectAll&&(this.ui.selectAll.checked=!0,this.selectAll(!0),window.jvbA11y&&window.jvbA11y.announce("All items selected"))),"Escape"===e.key&&this.selectedItems.size>0&&(this.selectAll(!1),window.jvbA11y&&window.jvbA11y.announce("Selection cleared")),("Delete"===e.key||"Backspace"===e.key)&&!e.target.matches("input, textarea")&&this.selectedItems>0&&(e.preventDefault(),confirm(`Remove ${this.selectedItems.size} selected item${1!==this.selectedItems.size?"s":""}?`)&&this.deselect(this.selectedItems))}handleClick(e){const t=e.target.closest(`${this.checkboxSelector}, label[for]`);if(!t)return;const s="LABEL"===t.tagName?document.getElementById(t.getAttribute("for")):t;if(s)if(e.shiftKey&&this.lastSelected)e.preventDefault(),this.handleRangeSelection(s);else{const e=s.closest(this.itemSelector);e&&(this.lastSelected=e)}}handleChange(e){if(this.ui.selectAll&&e.target===this.ui.selectAll)this.selectAll(e.target.checked);else{const t=e.target.closest(this.checkboxSelector);if(!t)return;this.toggleSelection(this.getItemId(t))}}toggleSelection(e){if(!e)return;let t=!0;this.selectedItems.has(e)?(t=!1,this.selectedItems.delete(e)):this.selectedItems.add(e),t?this.notify("item-selected",{selectedItem:e,selectedItems:this.selectedItems,container:this.container}):this.notify("item-deselected",{selectedItem:e,selectedItems:this.selectedItems,container:this.container}),this.updateSelectionUI()}selectAll(e){const t=this.container.querySelectorAll(this.itemSelector);e||(this.selectedItems.clear(),this.ui.selectAll&&(this.ui.selectAll.checked=!1)),t.forEach((t=>{const s=this.getItemId(t),i=t.querySelector(this.checkboxSelector);i&&(i.checked=e),e&&s&&this.selectedItems.add(s)})),this.notify("select-all",{container:this.container,selected:e,items:t}),this.updateSelectionUI()}clearSelection(){this.selectAll(!1)}handleRangeSelection(e){if(!this.lastSelected)return void(this.lastSelected=e.closest(this.itemSelector));const t=e.closest(this.itemSelector);if(!t)return;const s=Array.from(this.container.querySelectorAll(this.itemSelector)),i=s.indexOf(this.lastSelected),c=s.indexOf(t);if(-1===i||-1===c)return;const l=Math.min(i,c),n=Math.max(i,c);let h=!e.checked;for(let e=l;e<=n;e++){const t=s[e],i=t.querySelector(this.checkboxSelector),c=this.getItemId(t);i&&c&&(i.checked=h,this.selectedItems.add(c))}this.lastSelected=t,this.updateSelectionUI(),this.notify("range-selected",{selectedItems:this.selectedItems,container:this.container});const r=n-l+1;window.jvbA11y&&window.jvbA11y.announce(`Selected ${r} items in range`)}updateSelectionUI(){const e=this.selectedItems.size,t=this.container.querySelectorAll(this.itemSelector).length;if(this.ui.bulkControls&&(this.ui.bulkControls.hidden=0===e),this.ui.count){const t=1===e?"item":"items";this.ui.count.textContent=0===e?"":`{ ${e} ${t} selected }`,this.ui.count.hidden=0===e}if(this.ui.selectAll){this.ui.selectAll.checked=t>0&&e===t,this.ui.selectAll.indeterminate=e>0&&e<t;const s=this.ui.selectAll.nextElementSibling||this.ui.selectAll.previousElementSibling;s&&"LABEL"===s.tagName&&(s.textContent=t>0&&e===t?"Clear Selection":"Select All")}}getItemId(e){const t=e.closest(this.itemSelector);return t?t.dataset.id||t.dataset.itemId||t.dataset.uploadId||t.id:null}getSelected(){return Array.from(this.selectedItems)}isSelected(e){return this.selectedItems.has(e)}select(e){(Array.isArray(e)?e:[e]).forEach((e=>{this.selectedItems.add(e);const t=this.container.querySelector(`${this.itemSelector}[data-id="${e}"]`);if(t){const e=t.querySelector(this.checkboxSelector);e&&(e.checked=!0)}})),this.updateSelectionUI(),this.notify("item-selected",{selectedItem:id,selectedItems:this.selectedItems,container:this.container})}deselect(e){(Array.isArray(e)?e:[e]).forEach((e=>{this.selectedItems.delete(e);const t=this.container.querySelector(`${this.itemSelector}[data-id="${e}"]`);if(t){const e=t.querySelector(this.checkboxSelector);e&&(e.checked=!1)}})),this.updateSelectionUI(),this.notify("item-deselected",{selectedItem:id,selectedItems:this.selectedItems,container:this.container})}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}notify(e,t){this.subscribers.forEach((s=>s(e,t)))}destroy(){this.container&&(this.container.removeEventListener("click",this.clickHandler),this.container.removeEventListener("change",this.changeHandler),this.container.removeEventListener("keydown",this.keyHandler)),this.clearSelection(),this.subscribers.clear(),this.container=null,this.ui=null,this.lastSelected=null}};
\ No newline at end of file
+window.jvbHandleSelection=class{constructor(e){this.container=e.container,this.selectors={item:e.item||".item",count:e.count||".selection-count",bulkControls:e.bulkControls||".selection-actions",checkbox:e.checkbox||'[name*="select-item"]',selectAll:e.selectAll||"[data-select-all]",wrapper:e.wrapper||":has(.item-grid)"},this.ui=window.uiFromSelectors(this.selectors,this.container),this.selectedItems=new Set,this.lastSelected=null,this.lastSelectedWrapper=null,this.lastClicked=null,this.subscribers=new Set,this.initListeners()}initListeners(){this.clickHandler=this.handleClick.bind(this),this.changeHandler=this.handleChange.bind(this),this.keyHandler=this.handleKeys.bind(this),this.container.addEventListener("change",this.changeHandler),this.container.addEventListener("click",this.clickHandler),this.container.addEventListener("keydown",this.keyHandler)}handleChange(e){if(e.target.matches(this.selectors.selectAll))this.handleSelectAll(e.target);else if(e.target.matches(this.selectors.checkbox)){const t=e.target.closest(this.selectors.item);if(!t)return;const s=this.getItemWrapper(t),i=this.getItemId(t);this.lastSelectedWrapper&&s&&s!==this.lastSelectedWrapper&&!e.shiftKey&&this.clearSelection(),e.target.checked?this.select(i,!1):this.deselect(i,!1),this.lastSelected=i,this.lastSelectedWrapper=s}}handleClick(e){const t=e.target.closest(this.selectors.item),s=t?this.getItemWrapper(t):null;if(s&&(this.lastClicked=s),t&&!e.target.matches(this.selectors.checkbox)&&this.lastSelectedWrapper&&s&&s!==this.lastSelectedWrapper&&!e.shiftKey&&(this.clearSelection(),this.lastSelectedWrapper=s),!e.shiftKey)return;if(!e.target.closest(this.selectors.checkbox)||!this.lastSelected||!this.lastSelectedWrapper)return;if(!t||!s)return;if(s!==this.lastSelectedWrapper)return;const i=Array.from(s.querySelectorAll(this.selectors.item)),l=this.getItemId(t),c=i.findIndex((e=>this.getItemId(e)===this.lastSelected)),r=i.findIndex((e=>this.getItemId(e)===l));if(-1===c||-1===r)return;const[n,h]=[Math.min(c,r),Math.max(c,r)];i.slice(n,h+1).forEach((e=>{this.select(this.getItemId(e))})),this.notify("range-selected",{selectedItems:new Set(this.selectedItems),wrapper:s})}getItemWrapper(e){if(!e)return null;const t=this.selectors.wrapper.split(",").map((e=>e.trim()));for(const s of t){const t=e.closest(s);if(t)return t}return null}handleKeys(e){if((e.ctrlKey||e.metaKey)&&"a"===e.key){if(e.preventDefault(),!this.lastClicked)return this.clearSelection(),void(window.jvbA11y&&window.jvbA11y.announce("Selection cleared"));const t=this.lastClicked.querySelectorAll(this.selectors.item),s=Array.from(t).map((e=>this.getItemId(e)));s.some((e=>this.selectedItems.has(e)))?(s.forEach((e=>this.deselect(e))),this.selectedItems.size>0?window.jvbA11y&&window.jvbA11y.announce("Selection cleared in current group"):window.jvbA11y&&window.jvbA11y.announce("Selection cleared")):(this.clearSelection(),window.jvbA11y&&window.jvbA11y.announce("All selections cleared"))}"Escape"===e.key&&this.selectedItems.size>0&&(this.clearSelection(),window.jvbA11y&&window.jvbA11y.announce("Selection cleared"))}handleSelectAll(e){const t=this.getItemWrapper(e)||e.closest(this.selectors.wrapper);if(!t)return;this.lastSelectedWrapper&&t!==this.lastSelectedWrapper&&this.clearSelection();const s=t.querySelectorAll(this.selectors.item),i=Array.from(s).map((e=>this.getItemId(e)));e.checked?(i.forEach((e=>this.select(e,!0,!1))),this.lastSelectedWrapper=t):(i.forEach((e=>this.deselect(e,!0,!1))),0===this.selectedItems.size&&(this.lastSelectedWrapper=null));let l=e.nextElementSibling||e.previousElementSibling;l&&"LABEL"===l.tagName&&(l.textContent=e.checked&&s.length>0?"Clear Selection":"Select All"),this.updateSelectionUI(),this.notify("select-all",{wrapper:t,checked:e.checked,ids:i,selectedItems:new Set(this.selectedItems)})}getItemId(e){return e.dataset.uploadId}select(e,t=!0,s=!0){this.selectedItems.has(e)||(this.selectedItems.add(e),t&&this.setCheckboxState(e,!0),s&&this.updateSelectionUI(),this.notify("item-selected",{id:e,selectedItems:new Set(this.selectedItems)}))}deselect(e,t=!0,s=!0){this.selectedItems.has(e)&&(this.selectedItems.delete(e),t&&this.setCheckboxState(e,!1),s&&this.updateSelectionUI(),this.notify("item-deselected",{id:e,selectedItems:new Set(this.selectedItems)}))}toggle(e){this.selectedItems.has(e)?this.deselect(e):this.select(e),this.updateSelectionUI()}clearSelection(){this.selectedItems.forEach((e=>this.setCheckboxState(e,!1))),this.selectedItems.clear(),this.lastSelected=null,this.lastSelectedWrapper=null,this.container.querySelectorAll(this.selectors.selectAll).forEach((e=>{e.checked=!1;const t=e.nextElementSibling||e.previousElementSibling;"LABEL"===t?.tagName&&(t.textContent="Select All")})),this.updateSelectionUI(),this.notify("selection-cleared",{selectedItems:new Set})}isSelected(e){return this.selectedItems.has(e)}getSelection(){return new Set(this.selectedItems)}setCheckboxState(e,t){const s=this.container.querySelector(`[data-upload-id="${e}"]`),i=s?.querySelector(this.selectors.checkbox);i&&i.checked!==t&&(i.checked=t)}updateSelectionUI(){if(!this.lastClicked||!this.ui.count)return;const e=this.selectedItems.size;let t=this.lastClicked.querySelector(this.selectors.bulkControls);t&&(t.hidden=0===e);let s=this.lastClicked.querySelector(this.selectors.count);if(s){const t=1===e?"item":"items";s.textContent=0===e?"":`{ ${e} ${t} selected }`,s.hidden=0===e}}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}notify(e,t){this.subscribers.forEach((s=>{try{s(e,t)}catch(e){console.error("HandleSelection subscriber error:",e)}}))}destroy(){this.container.removeEventListener("change",this.changeHandler),this.container.removeEventListener("click",this.clickHandler),this.container.removeEventListener("keydown",this.keyHandler),this.subscribers.clear(),this.selectedItems.clear()}};
\ No newline at end of file

--
Gitblit v1.10.0