diff --git a/public/dist/main.js b/public/dist/main.js index 841cb328..8e06b6d6 100644 --- a/public/dist/main.js +++ b/public/dist/main.js @@ -12,7 +12,7 @@ ${n?`Expression: "`+n+`" const isActive = $store.bulkSelection.isActiveEditor($el.nextElementSibling); $el.dataset.active = isActive; $el.setAttribute("aria-expanded", isActive); - }`),t.setAttribute(`x-show`,`$store.bulkSelection.isActiveEditor($el)`),t.setAttribute(`x-collapse`,``),t.setAttribute(`:class`,`$store.bulkSelection.isActiveEditor($el) && 'active'`),t.insertAdjacentElement(`beforebegin`,n),this.editors.push(t),!t.classList.contains(`no-ajax`)&&t.addEventListener(`submit`,async n=>{n.preventDefault();try{t.parentElement.classList.add(`pointer-events-none`);let n=await fetch(t.action,{method:`POST`,body:new FormData(t)});if(!n.ok)throw Error(`Server error: ${n.status}`);let r=new URL(window.location);r.pathname+=`.body`;let i=await fetch(r.toString()).then(e=>e.text());t.reset(),this.deselectAll(),e.morph(document.querySelector(`.list-container, .items-container`),i),this.announce(`Bulk operation completed successfully`)}catch(e){this.announce(`Bulk operation failed: ${e.message}`),alert(`Bulk operation failed: ${e.message}`)}finally{t.parentElement.classList.remove(`pointer-events-none`)}})}})}function os(){return{init(){this.$root.querySelectorAll(`form`).forEach(e=>this.$store.bulkSelection.registerForm(e))}}}function ss({itemNo:e,itemId:t}={}){return{init(){let n=this.$root.querySelector(`input[type='checkbox']`);this.$store.bulkSelection.registerOption({itemNo:e,itemId:t,el:n})},selected(){return this.$store.bulkSelection.isSelected(t)},events:{"@click"(e){if(e.shiftKey){this.$store.bulkSelection.selectUntil(t);return}this.$store.bulkSelection.toggle(t)},"@contextmenu"(e){e.preventDefault(),this.$store.bulkSelection.selectUntil(t)},"@keydown.space.prevent"(){this.$store.bulkSelection.toggle(t)},"@keydown.enter.prevent"(){this.$store.bulkSelection.toggle(t)}}}}function cs(){document.addEventListener(`keypress`,function(e){if(e.key!==` `)return;let t=new Set,n=window.getSelection(),r=n.rangeCount;if(n.type===`Range`){e.preventDefault();for(let e=0;e{e.addEventListener(`click`,async function(t){if(!t.target.classList.contains(`edit-in-list`))return;t.preventDefault();let n=t.target.dataset.entityType,r=t.target.closest(`[x-data]`),i=[];if(r&&window.Alpine){let e=window.Alpine.$data(r);e?.entity?.Tags&&(i=e.entity.Tags)}let a=await(async function(){let e=new URL(`${window.location.origin}/partials/autocompleter`);return e.searchParams.append(`selectedItems`,JSON.stringify(i)),e.searchParams.append(`title`,`Edit tags`),e.searchParams.append(`sortBy`,`most_used_${n}`),e.searchParams.append(`id`,`tagEditor_${Math.random()}`),e.searchParams.append(`elName`,`editedId`),e.searchParams.append(`url`,`/v1/tags`),e.searchParams.append(`addUrl`,`/v1/tag`),fetch(e.toString()).then(e=>e.text())})(),o=document.createElement(`form`);o.dataset.inlineEditor=`true`,o.addEventListener(`submit`,e=>{e.preventDefault()}),o.addEventListener(`multiple-input`,e=>{fetch(`/v1/`+n+`s/replaceTags`,{method:`POST`,body:new FormData(o)})}),o.className=`mb-6 p-4 active`;let s=document.createElement(`input`);s.setAttribute(`:value`,`entity.ID`),s.name=`ID`,s.type=`hidden`;let c=new DOMParser().parseFromString(a,`text/html`);o.replaceChildren(...c.body.childNodes),o.appendChild(s),e.innerHTML=``,e.appendChild(o),window.Alpine.initTree(o),setTimeout(()=>o.querySelector(`[x-ref='autocompleter']`)?.focus(),10)})})}function ls(e){try{return JSON.parse(e||`{}`)}catch{return{}}}function us(e){e.store(`savedSetting`,{sessionSettings:ls(sessionStorage.getItem(`settings`)),localSettings:ls(localStorage.getItem(`settings`)),registerEl(e,t=!0,n=!0){let r=t?this.localSettings:this.sessionSettings,i=t?localStorage:sessionStorage;e.checked===void 0?e.value=r[e.name]??n:So(e,(r[e.name]??n)?.toString()===`true`),e.addEventListener(`change`,()=>{let t=e.checked??e.value;r[e.name]=t,i.setItem(`settings`,JSON.stringify(r))})}})}var N=new Map,ds=3e4,fs=50;function ps(e){let t=e.toLowerCase(),n=N.get(t);return n&&Date.now()-n.timestamp=fs){let e=N.keys().next().value;N.delete(e)}N.set(n,{results:t,timestamp:Date.now()})}function hs(){return{isOpen:!1,query:``,results:[],selectedIndex:0,loading:!1,requestAborter:null,debounceTimer:null,_liveRegion:null,typeIcons:{resource:`๐Ÿ“„`,note:`๐Ÿ“`,group:`๐Ÿ‘ฅ`,tag:`๐Ÿท`,category:`๐Ÿ“`,resourceCategory:`๐Ÿ“‚`,query:`๐Ÿ”`,relationType:`๐Ÿ”—`,noteType:`๐Ÿ“‹`},typeLabels:{resource:`Resource`,note:`Note`,group:`Group`,tag:`Tag`,category:`Category`,resourceCategory:`Resource Category`,query:`Query`,relationType:`Relation Type`,noteType:`Note Type`},init(){this._liveRegion=Go(),this._keydownHandler=e=>{(e.metaKey||e.ctrlKey)&&e.key===`k`&&(e.preventDefault(),this.toggle())},document.addEventListener(`keydown`,this._keydownHandler),this.$watch(`isOpen`,e=>{e&&(this.$nextTick(()=>{this.$refs.searchInput?.focus()}),this.announce(`Search dialog opened. Type to search resources, notes, groups, and tags.`))})},announce(e){this._liveRegion?.announce(e)},destroy(){this._liveRegion?.destroy(),this._keydownHandler&&document.removeEventListener(`keydown`,this._keydownHandler),this.debounceTimer&&clearTimeout(this.debounceTimer),this.requestAborter&&=(this.requestAborter(),null)},toggle(){this.isOpen=!this.isOpen,this.isOpen&&(this.query=``,this.results=[],this.selectedIndex=0)},close(){this.isOpen=!1,this.query=``,this.results=[]},search(){this.debounceTimer&&clearTimeout(this.debounceTimer),this.requestAborter&&=(this.requestAborter(),null);let e=this.query.trim();if(e.length<2){this.results=[];return}let t=ps(e);if(t){this.results=t,this.selectedIndex=0,this.results.length>0?this.announce(`${this.results.length} result${this.results.length===1?``:`s`} found. Use arrow keys to navigate.`):this.announce(`No results found.`);return}let n=e.length<3?300:150;this.debounceTimer=setTimeout(()=>{this.loading=!0;let{abort:t,ready:n}=M(`/v1/search?q=${encodeURIComponent(e)}&limit=15`);this.requestAborter=t,n.then(e=>e.json()).then(t=>{this.query.trim()===e&&(this.results=t.results||[],this.selectedIndex=0,ms(e,this.results),this.results.length>0?this.announce(`${this.results.length} result${this.results.length===1?``:`s`} found. Use arrow keys to navigate.`):this.announce(`No results found.`))}).catch(e=>{e.name!==`AbortError`&&console.error(`Search error:`,e)}).finally(()=>{this.loading=!1})},n)},navigateUp(){this.results.length!==0&&(this.selectedIndex=this.selectedIndex===0?this.results.length-1:this.selectedIndex-1,this.scrollToSelected(),this.announceSelectedResult())},navigateDown(){this.results.length!==0&&(this.selectedIndex=(this.selectedIndex+1)%this.results.length,this.scrollToSelected(),this.announceSelectedResult())},announceSelectedResult(){let e=this.results[this.selectedIndex];if(e){let t=this.getLabel(e.type);this.announce(`${e.name}, ${t}, ${this.selectedIndex+1} of ${this.results.length}`)}},scrollToSelected(){this.$nextTick(()=>{let e=this.$refs.resultsList?.querySelector(`[data-selected="true"]`);e&&e.scrollIntoView({block:`nearest`})})},selectResult(){let e=this.results[this.selectedIndex];e&&this.navigateTo(e.url)},navigateTo(e){if(e&&(e.startsWith(`/`)||e.startsWith(`?`)||e.startsWith(`#`)))this.close(),window.location.href=e;else try{new URL(e,window.location.origin).origin===window.location.origin&&(this.close(),window.location.href=e)}catch{}},getIcon(e){return this.typeIcons[e]||`๐Ÿ“Œ`},getLabel(e){return this.typeLabels[e]||e},highlightMatch(e,t){if(!e||!t)return e;let n=this.escapeHTML(e),r=this.escapeHTML(t),i=RegExp(`(${this.escapeRegex(r)})`,`gi`);return n.replace(i,`$1`)},escapeHTML(e){let t=document.createElement(`div`);return t.textContent=e,t.innerHTML},escapeRegex(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}}}var gs={isOpen:!1,currentIndex:0,items:[],loading:!1,pageLoading:!1,currentPage:1,hasNextPage:!1,hasPrevPage:!1,baseUrl:``,pageSize:50,loadedPages:new Set,requestAborter:null,triggerElement:null},_s={_extractItemsFromLinks(e){return Array.from(e).map(e=>{let t=e.dataset.resourceHash||``,n=t?`&v=${t}`:``;return{id:parseInt(e.dataset.resourceId,10),viewUrl:`/v1/resource/view?id=${e.dataset.resourceId}${n}`,contentType:e.dataset.contentType||``,name:e.dataset.resourceName||e.querySelector(`img`)?.alt||``,hash:t,width:parseInt(e.dataset.resourceWidth,10)||0,height:parseInt(e.dataset.resourceHeight,10)||0,ownerName:e.dataset.ownerName||``,ownerId:parseInt(e.dataset.ownerId,10)||0}}).filter(e=>e.contentType?.startsWith(`image/`)||e.contentType?.startsWith(`video/`))},initFromDOM(){let e=document.querySelectorAll(`.list-container, .gallery, .dashboard-grid`);if(e.length===0)return;let t=[];e.forEach(e=>{let n=e.querySelectorAll(`[data-lightbox-item]`);t.push(...this._extractItemsFromLinks(n))}),this.items=t;let n=new URLSearchParams(window.location.search);this.currentPage=parseInt(n.get(`page`),10)||1,this.baseUrl=window.location.pathname+window.location.search;let r=document.querySelector(`nav[aria-label="Pagination"]`);r?(this.hasNextPage=r.dataset.hasNext===`true`,this.hasPrevPage=r.dataset.hasPrev===`true`):(this.hasPrevPage=this.currentPage>1,this.hasNextPage=!1),this.loadedPages.add(this.currentPage);let i=e[0].dataset.pageSize;i?this.pageSize=parseInt(i,10)||50:window.location.pathname.includes(`/simple`)&&(this.pageSize=200)},openFromClick(e,t,n){if(!n?.startsWith(`image/`)&&!n?.startsWith(`video/`)){window.location.href=e.currentTarget.href;return}e.preventDefault(),this.triggerElement=e.currentTarget;let r=e.currentTarget.closest(`[data-lightbox-source]`);if(r){this._openFromSourceContainer(r,t);return}let i=this.items.findIndex(e=>e.id===t);i!==-1&&this.open(i)},_openFromSourceContainer(e,t){let n=e.querySelectorAll(`[data-lightbox-item]`),r=this._extractItemsFromLinks(n);if(r.length===0)return;let i=e.dataset.lightboxSource,a=e.dataset.lightboxParamName,o=e.dataset.lightboxParamValue,s=new URL(i,window.location.origin);s.searchParams.set(a,o),this.items=r,this.baseUrl=s.pathname+s.search,this.currentPage=1,this.loadedPages=new Set([1]),this.pageSize=50,this.hasNextPage=r.length>=5,this.hasPrevPage=!1;let c=r.findIndex(e=>e.id===t);c!==-1&&this.open(c)},open(e){this._savedScrollY=window.scrollY,document.body.style.position=`fixed`,document.body.style.top=`-${this._savedScrollY}px`,document.body.style.left=`0`,document.body.style.right=`0`,document.body.style.overflow=`hidden`,this.currentIndex=e,this.isOpen=!0,this.loading=!0,document.activeElement&&document.activeElement!==document.body&&document.activeElement.blur();let t=this.getCurrentItem(),n=this.isVideo(t?.contentType)?`video`:this.isSvg(t?.contentType)?`SVG`:`image`;this.announce(`Opened ${n}: ${t?.name||`media`}. ${this.currentIndex+1} of ${this.items.length}`),this.scheduleMediaCheck(),this.quickTagPanelOpen&&this.fetchResourceDetails()},close(){this.pauseCurrentVideo(),this.isFullscreen&&=(document.exitFullscreen?document.exitFullscreen().catch(()=>{}):document.webkitExitFullscreen&&document.webkitExitFullscreen(),!1),this.editPanelOpen&&this.closeEditPanel(),this.quickTagPanelOpen&&this.closeQuickTagPanel(),this.isOpen=!1,this.loading=!1,this.resetZoom();let e=this._savedScrollY;document.body.style.position=``,document.body.style.top=``,document.body.style.left=``,document.body.style.right=``,document.body.style.overflow=``,window.scrollTo(0,e),this.requestAborter&&=(this.requestAborter(),null),this.triggerElement&&=(this.triggerElement.focus({preventScroll:!0}),null),this.announce(`Media viewer closed`),requestAnimationFrame(()=>{window.scrollTo(0,e)})},async next(){this.pageLoading||(this.pauseCurrentVideo(),this.resetZoom(),this.currentIndex0)this.currentIndex--,this.loading=!0,this.announcePosition(),this.scheduleMediaCheck(),this.onResourceChange();else if(this.hasPrevPage){let e=await this.loadPrevPage();e>0&&(this.currentIndex=e-1,this.loading=!0,this.announcePosition(),this.scheduleMediaCheck(),this.onResourceChange())}}},announcePosition(){let e=this.getCurrentItem();this.announce(`${e?.name||`Media`}, ${this.currentIndex+1} of ${this.items.length}`)},async loadNextPage(){let e=this.currentPage+1;if(this.loadedPages.has(e)){this.currentPage=e;return}this.pageLoading=!0,this.announce(`Loading more items...`);try{let{items:t,hasNextPage:n}=await this.fetchPage(e);if(t.length===0){this.hasNextPage=!1,this.announce(`No more items`);return}this.items=[...this.items,...t],this.loadedPages.add(e),this.currentPage=e,this.hasNextPage=n,this.announce(`Loaded ${t.length} more items`)}catch(e){e.name!==`AbortError`&&(console.error(`Failed to load next page:`,e),this.announce(`Failed to load more items`))}finally{this.pageLoading=!1}},async loadPrevPage(){if(this.currentPage<=1)return 0;let e=this.currentPage-1;if(this.loadedPages.has(e))return this.currentPage=e,this.hasPrevPage=e>1,0;this.pageLoading=!0,this.announce(`Loading previous items...`);try{let{items:t}=await this.fetchPage(e),n=t.length;return this.items=[...t,...this.items],this.currentIndex+=n,this.loadedPages.add(e),this.hasPrevPage=e>1,this.announce(`Loaded ${n} previous items`),n}catch(e){return e.name!==`AbortError`&&(console.error(`Failed to load previous page:`,e),this.announce(`Failed to load previous items`)),0}finally{this.pageLoading=!1}},async fetchPage(e){this.requestAborter&&this.requestAborter();let t=new URL(this.baseUrl,window.location.origin);t.searchParams.set(`page`,e);let{abort:n,ready:r}=M(t.pathname+`.json`+t.search);this.requestAborter=n;let i=await r;if(!i.ok)throw Error(`Failed to fetch page: ${i.status}`);let a=await i.json();this.requestAborter=null;let o=a.resources||[],s=(a.pagination||{}).NextLink?.Selected===!0;return{items:o.filter(e=>e.ContentType?.startsWith(`image/`)||e.ContentType?.startsWith(`video/`)).map(e=>{let t=e.Hash?`&v=${e.Hash}`:``;return{id:e.ID,viewUrl:`/v1/resource/view?id=${e.ID}${t}`,contentType:e.ContentType,name:e.Name||``,hash:e.Hash||``,width:e.Width||0,height:e.Height||0,ownerName:e.Owner?.Name||``,ownerId:e.Owner?.ID||0}}),hasNextPage:s}},isImage(e){return e?.startsWith(`image/`)&&!this.isSvg(e)},isSvg(e){return e===`image/svg+xml`},isVideo(e){return e?.startsWith(`video/`)},getCurrentItem(){return this.items[this.currentIndex]},onMediaLoaded(){this.loading=!1},checkIfMediaLoaded(e){if(e){if(e.tagName===`IMG`&&e.complete&&(this.isSvg(this.getCurrentItem()?.contentType)||e.naturalWidth>0)){this.loading=!1;return}if(e.tagName===`OBJECT`&&e.contentDocument){this.loading=!1;return}e.tagName===`VIDEO`&&e.readyState>=3&&(this.loading=!1)}},scheduleMediaCheck(){requestAnimationFrame(()=>{requestAnimationFrame(()=>{let e=document.querySelector(`[role="dialog"] img, [role="dialog"] video, [role="dialog"] object`);e&&this.checkIfMediaLoaded(e)})})},restartVideo(){let e=document.querySelector(`[role="dialog"] video`);e&&(e.currentTime=0,e.play())},pauseCurrentVideo(){let e=document.querySelector(`[x-show="$store.lightbox.isOpen"] video`);e&&!e.paused&&e.pause()}},vs={isFullscreen:!1,zoomLevel:1,minZoom:1,maxZoom:5,panX:0,panY:0,imageRect:null,containerRect:null,animationsDisabled:!1,animationTimeout:null},ys={fullscreenSupported(){return!!(document.fullscreenEnabled||document.webkitFullscreenEnabled)},async toggleFullscreen(){if(!this.fullscreenSupported())return;let e=document.querySelector(`[role="dialog"][aria-modal="true"]`);if(e)try{this.isFullscreen?document.exitFullscreen?await document.exitFullscreen():document.webkitExitFullscreen&&await document.webkitExitFullscreen():e.requestFullscreen?await e.requestFullscreen():e.webkitRequestFullscreen&&await e.webkitRequestFullscreen()}catch(e){console.error(`Fullscreen toggle failed:`,e)}},isZoomed(){return this.zoomLevel>1},setZoomLevel(e){let t=this.zoomLevel;this.zoomLevel=Math.max(this.minZoom,Math.min(this.maxZoom,e)),this.zoomLevel!==t&&this.zoomLevel===1&&(this.panX=0,this.panY=0)},resetZoom(){this.zoomLevel=1,this.panX=0,this.panY=0,this.hideZoomPresets()},hideZoomPresets(){let e=document.getElementById(`zoom-preset-popover`);e?.matches(`:popover-open`)&&e.hidePopover()},showZoomPresets(e){let t=document.getElementById(`zoom-preset-popover`);if(!t)return;if(t.matches(`:popover-open`)){t.hidePopover();return}let n=this.zoomPresets();if(!n.length)return;let r=this;t.innerHTML=``,Object.assign(t.style,{background:`rgba(0,0,0,0.8)`,backdropFilter:`blur(8px)`,border:`1px solid rgba(255,255,255,0.1)`,borderRadius:`0.375rem`,padding:`0.25rem 0`,margin:`0`,minWidth:`7rem`,textAlign:`center`,color:`white`,fontSize:`0.875rem`});for(let e of n){let n=document.createElement(`button`);n.textContent=e.label,n.style.cssText=`display:block;width:100%;padding:0.375rem 0.75rem;transition:background 150ms;font-variant-numeric:tabular-nums;background:none;border:none;color:inherit;cursor:pointer;font-size:inherit;`,n.addEventListener(`mouseenter`,()=>n.style.background=`rgba(255,255,255,0.2)`),n.addEventListener(`mouseleave`,()=>n.style.background=`none`),n.addEventListener(`click`,t=>{t.stopPropagation(),r.setNativeZoom(e.nativePct)}),t.appendChild(n)}let i=e.getBoundingClientRect();t.showPopover();let a=t.getBoundingClientRect();t.style.position=`fixed`,t.style.left=i.left+i.width/2-a.width/2+`px`,t.style.top=i.top-a.height-4+`px`,t.style.bottom=`auto`,t.style.right=`auto`},announceZoom(){this.zoomLevel===1?this.announce(`Zoom reset to 100%`):this.announce(`Zoomed to ${Math.round(this.zoomLevel*100)}%`)},nativeZoomPercent(){let e=this.loading,t=this.zoomLevel,n=this.getCurrentItem();if(!n||this.isVideo(n.contentType)||e)return null;let r=this.getMediaElement();if(!r)return null;let i=r.element,a=i.naturalWidth,o=i.clientWidth;if(!a||!o)return null;let s=t*o/a*100;return Math.round(s)+`%`},zoomPresets(){let e=this.getMediaElement();if(!e)return[];let t=e.element,n=t.naturalWidth,r=t.clientWidth,i=t.clientHeight;if(!n||!r)return[];let a=Math.round(r/n*100),o=[25,50,100,200,300,500],s=[{label:`Fit (`+a+`%)`,nativePct:null}],c=window.innerWidth*.9,l=window.innerHeight*.9;if(r&&i){let e=Math.min(c/r,l/i);if(e>1.01&&e<=this.maxZoom){let t=Math.round(e*r/n*100);s.push({label:`Stretch (`+t+`%)`,nativePct:`stretch`})}}for(let e of o){let t=e/100*(n/r);t>=this.minZoom&&t<=this.maxZoom&&e!==a&&s.push({label:e+`%`,nativePct:e})}return s},setNativeZoom(e){if(this.hideZoomPresets(),e===null){this.setZoomLevel(1),this.announceZoom();return}let t=this.getMediaElement();if(!t)return;let n=t.element,r=n.clientWidth,i=n.clientHeight;if(!r||!i)return;let a;if(e===`stretch`){let e=window.innerWidth*.9,t=window.innerHeight*.9;a=Math.min(e/r,t/i)}else{let t=n.naturalWidth;if(!t)return;a=e/100*(t/r)}this.panX=0,this.panY=0,this.setZoomLevel(a),this.constrainPan(),this.announceZoom()},getMediaElement(){let e=document.querySelector(`[role="dialog"] img, [role="dialog"] object`);return e?{element:e,rect:e.getBoundingClientRect()}:null},getContainerRect(){return document.querySelector(`[role="dialog"] .relative.max-h-\\[90vh\\]`)?.getBoundingClientRect()||null},constrainPan(){if(this.zoomLevel<=1){this.panX=0,this.panY=0;return}let e=this.getMediaElement(),t=this.getContainerRect();if(!e||!t)return;let n=e.element,r=n.clientWidth,i=n.clientHeight,a=r*this.zoomLevel,o=i*this.zoomLevel,s=Math.max(0,(a-t.width)/2/this.zoomLevel),c=Math.max(0,(o-t.height)/2/this.zoomLevel);this.panX=Math.max(-s,Math.min(s,this.panX)),this.panY=Math.max(-c,Math.min(c,this.panY))},disableAnimations(){this.animationsDisabled=!0,this.animationTimeout&&clearTimeout(this.animationTimeout),this.animationTimeout=setTimeout(()=>{this.animationsDisabled=!1,this.animationTimeout=null},100)}},bs={touchStartX:null,touchStartY:null,pinchStartDistance:null,pinchStartZoom:null,pinchStartCenterX:null,pinchStartCenterY:null,pinchCenterX:null,pinchCenterY:null,pinchOriginX:null,pinchOriginY:null,pinchImageX:null,pinchImageY:null,isDragging:!1,dragStartX:null,dragStartY:null,dragStartPanX:null,dragStartPanY:null,dragVelocityX:0,dragVelocityY:0,lastDragTime:null,lastDragX:null,lastDragY:null,_navDebounce:!1,_wheelDebounceTimer:null,_wheelNavDirection:0,_wheelNavTime:0,_prevWheelAbsDelta:0,_wheelIncreaseCount:0},xs={getPinchDistance(e){let t=e[0].clientX-e[1].clientX,n=e[0].clientY-e[1].clientY;return Math.sqrt(t*t+n*n)},getPinchCenter(e){return{x:(e[0].clientX+e[1].clientX)/2,y:(e[0].clientY+e[1].clientY)/2}},handleTouchStart(e){if(e.target.closest(`[data-edit-panel]`)){this.touchStartX=null;return}if(e.touches.length===2){e.preventDefault(),this.pinchStartDistance=this.getPinchDistance(e.touches),this.pinchStartZoom=this.zoomLevel;let t=this.getPinchCenter(e.touches);this.pinchStartCenterX=t.x,this.pinchStartCenterY=t.y,this.pinchCenterX=t.x,this.pinchCenterY=t.y;let n=this.getMediaElement();if(n){let e=n.rect,r=e.left+e.width/2,i=e.top+e.height/2;this.pinchOriginX=r-this.zoomLevel*this.panX,this.pinchOriginY=i-this.zoomLevel*this.panY,this.pinchImageX=(t.x-this.pinchOriginX)/this.zoomLevel-this.panX,this.pinchImageY=(t.y-this.pinchOriginY)/this.zoomLevel-this.panY}else this.pinchOriginX=null,this.pinchOriginY=null,this.pinchImageX=null,this.pinchImageY=null}else e.touches.length===1&&(this.touchStartX=e.touches[0].clientX,this.touchStartY=e.touches[0].clientY,this.isZoomed()&&(this.dragStartPanX=this.panX,this.dragStartPanY=this.panY))},handleTouchMove(e){if(!this.isVideo(this.getCurrentItem()?.contentType)){if(e.touches.length===2){e.preventDefault();let t=this.getPinchCenter(e.touches);if(this.pinchStartDistance!==null){this.disableAnimations();let n=this.getPinchDistance(e.touches)/this.pinchStartDistance;this.setZoomLevel(this.pinchStartZoom*n),this.pinchOriginX!==null&&(this.panX=(t.x-this.pinchOriginX)/this.zoomLevel-this.pinchImageX,this.panY=(t.y-this.pinchOriginY)/this.zoomLevel-this.pinchImageY,this.constrainPan()),this.pinchCenterX=t.x,this.pinchCenterY=t.y}}else if(e.touches.length===1&&this.isZoomed()&&this.touchStartX!==null){e.preventDefault(),this.disableAnimations();let t=e.touches[0].clientX-this.touchStartX,n=e.touches[0].clientY-this.touchStartY;this.panX=(this.dragStartPanX||0)+t/this.zoomLevel,this.panY=(this.dragStartPanY||0)+n/this.zoomLevel,this.constrainPan()}}},handleTouchEnd(e){if(this.pinchStartDistance!==null){if(this.zoomLevel50&&!this._navDebounce&&(this._navDebounce=!0,setTimeout(()=>{this._navDebounce=!1},300),e>0?this.next():this.prev())}this.pinchStartDistance=null,this.pinchStartZoom=null,this.pinchStartCenterX=null,this.pinchStartCenterY=null,this.pinchCenterX=null,this.pinchCenterY=null,this.pinchOriginX=null,this.pinchOriginY=null,this.pinchImageX=null,this.pinchImageY=null,this.announceZoom();return}if(this.touchStartX===null)return;let t=e.changedTouches[0].clientX,n=e.changedTouches[0].clientY,r=this.touchStartX-t,i=this.touchStartY-n;if(Math.abs(r)>Math.abs(i)&&Math.abs(r)>50&&!this.isZoomed()){if(this._navDebounce)return;this._navDebounce=!0,setTimeout(()=>{this._navDebounce=!1},300),r>0?this.next():this.prev()}this.touchStartX=null,this.touchStartY=null},handleWheel(e){if(!this.isVideo(this.getCurrentItem()?.contentType)){if(e.ctrlKey){e.preventDefault(),this.disableAnimations();let t=this.getMediaElement(),n=this.zoomLevel,r=this.panX,i=this.panY,a=1.002**-e.deltaY;this.setZoomLevel(this.zoomLevel*a);let o=this.zoomLevel;if(o!==n&&t){let a=t.rect,s=a.left+a.width/2,c=a.top+a.height/2,l=s-n*r,u=c-n*i,d=e.clientX-l,f=e.clientY-u;this.panX=r+d*(1/o-1/n),this.panY=i+f*(1/o-1/n),this.constrainPan()}this._zoomAnnounceDebounce||(this._zoomAnnounceDebounce=!0,setTimeout(()=>{this.announceZoom(),this._zoomAnnounceDebounce=!1},500));return}if(this.isZoomed())e.preventDefault(),this.disableAnimations(),this.panX-=e.deltaX/this.zoomLevel,this.panY-=e.deltaY/this.zoomLevel,this.constrainPan();else{let t=Math.abs(e.deltaX),n=Math.abs(e.deltaY)>t?e.deltaY:e.deltaX,r=Math.abs(n);if(r>10){if(e.preventDefault(),this._wheelDebounce){let e=Math.sign(n)!==this._wheelNavDirection,t=performance.now()-this._wheelNavTime;if(r>this._prevWheelAbsDelta?this._wheelIncreaseCount++:this._wheelIncreaseCount=0,this._prevWheelAbsDelta=r,e||t>150&&this._wheelIncreaseCount>=3)clearTimeout(this._wheelDebounceTimer),this._wheelDebounce=!1,this._navDebounce=!1;else{clearTimeout(this._wheelDebounceTimer),this._wheelDebounceTimer=setTimeout(()=>{this._wheelDebounce=!1,this._navDebounce=!1,this._wheelIncreaseCount=0,this._prevWheelAbsDelta=0},300);return}}if(this._navDebounce)return;this._wheelDebounce=!0,this._navDebounce=!0,this._wheelNavDirection=Math.sign(n),this._wheelNavTime=performance.now(),this._prevWheelAbsDelta=r,this._wheelIncreaseCount=0,this._wheelDebounceTimer=setTimeout(()=>{this._wheelDebounce=!1,this._navDebounce=!1,this._wheelIncreaseCount=0,this._prevWheelAbsDelta=0},300),n>0?this.next():this.prev()}}}},handleDoubleClick(e){if(!this.isVideo(this.getCurrentItem()?.contentType))if(e.preventDefault(),this.zoomLevel===1){let t=this.getMediaElement();if(!t)return;let n=t.element,r=n.clientWidth,i=n.clientHeight,a=n.naturalWidth||r,o=n.naturalHeight||i,s=Math.max(a/r,o/i),c=Math.max(this.minZoom+.01,Math.min(this.maxZoom,s)),l=t.rect,u=e.clientX-(l.left+l.width/2),d=e.clientY-(l.top+l.height/2);this.panX=-u,this.panY=-d,this.setZoomLevel(c),this.constrainPan(),this.announceZoom()}else this.setZoomLevel(1),this.announceZoom()},handleMouseDown(e){this.isVideo(this.getCurrentItem()?.contentType)||e.target.closest(`button`)||e.target.closest(`[data-edit-panel]`)||(e.preventDefault(),this.isDragging=!0,this.dragStartX=e.clientX,this.dragStartY=e.clientY,this.dragStartPanX=this.panX,this.dragStartPanY=this.panY,this.lastDragX=e.clientX,this.lastDragY=e.clientY,this.lastDragTime=performance.now(),this.dragVelocityX=0,this.dragVelocityY=0)},handleMouseMove(e){if(!this.isDragging)return;let t=performance.now(),n=t-this.lastDragTime;if(n>0&&(this.dragVelocityX=(e.clientX-this.lastDragX)/n,this.dragVelocityY=(e.clientY-this.lastDragY)/n),this.lastDragX=e.clientX,this.lastDragY=e.clientY,this.lastDragTime=t,this.isZoomed()){this.disableAnimations();let t=e.clientX-this.dragStartX,n=e.clientY-this.dragStartY;this.panX=this.dragStartPanX+t/this.zoomLevel,this.panY=this.dragStartPanY+n/this.zoomLevel,this.constrainPan()}},handleMouseUp(e){if(!this.isDragging)return;let t=e.clientX-this.dragStartX,n=e.clientY-this.dragStartY,r=Math.sqrt(t*t+n*n),i=Math.sqrt(this.dragVelocityX**2+this.dragVelocityY**2);this.isDragging=!1,!this.isZoomed()&&Math.abs(this.dragVelocityX)>Math.abs(this.dragVelocityY)&&(i>.3||r>30)&&!this._navDebounce&&(this._navDebounce=!0,setTimeout(()=>{this._navDebounce=!1},300),t<0?this.next():t>0&&this.prev()),this.dragStartX=null,this.dragStartY=null;let a=document.querySelector(`[role="dialog"][aria-modal="true"]`);a&&a.focus()}},Ss={editPanelOpen:!1,resourceDetails:null,detailsLoading:!1,detailsCache:new Map,detailsAborter:null,_savingTagIds:new Set,needsRefreshOnClose:!1},Cs={handleEscape(){return this.close(),!0},async openEditPanel(){window.innerWidth<1024&&this.quickTagPanelOpen&&this.closeQuickTagPanel(),this.editPanelOpen=!0,this.announce(`Info panel opened`),await this.fetchResourceDetails(),requestAnimationFrame(()=>{let e=document.querySelector(`[data-edit-panel]`);if(e){let t=e.querySelector(`input, textarea`);t&&t.focus()}})},closeEditPanel(){this.editPanelOpen=!1,this.quickTagPanelOpen||(this.detailsAborter&&=(this.detailsAborter(),null),this.resourceDetails=null),!this.quickTagPanelOpen&&this.needsRefreshOnClose&&(this.needsRefreshOnClose=!1,this.refreshPageContent()),this.announce(`Info panel closed`)},formatBytes(e){let t=Number(e);if(!Number.isFinite(t)||t<=0)return``;let n=1024,r=[`B`,`KB`,`MB`,`GB`,`TB`],i=Math.min(r.length-1,Math.floor(Math.log(t)/Math.log(n)));return parseFloat((t/n**+i).toFixed(1))+` `+r[i]},formatDateTime(e){if(!e)return``;let t=e instanceof Date?e:new Date(e);if(Number.isNaN(t.getTime()))return``;try{return t.toLocaleString(void 0,{dateStyle:`medium`,timeStyle:`short`})}catch{return t.toLocaleString()}},async refreshPageContent(){let e=document.querySelector(`.list-container, .items-container`);if(e)try{let t=new URL(window.location);t.pathname+=`.body`;let n=await fetch(t.toString());if(!n.ok)return;let r=await n.text(),i=new DOMParser().parseFromString(r,`text/html`).querySelector(`.list-container, .items-container`);if(i&&window.Alpine){let t=window.scrollX,n=window.scrollY;window.Alpine.morph(e,i,{updating(e,t,n,r){e._x_dataStack&&(t._x_dataStack=e._x_dataStack)}}),window.scrollTo(t,n),this.updateItemsFromDOM()}}catch(e){console.error(`Failed to refresh page content:`,e)}},updateItemsFromDOM(){let e=document.querySelector(`.list-container, .gallery`);if(!e)return;let t=e.querySelectorAll(`[data-lightbox-item]`),n=new Map;t.forEach(e=>{let t=parseInt(e.dataset.resourceId,10),r=e.dataset.contentType||``;if(r.startsWith(`image/`)||r.startsWith(`video/`)){let i=e.dataset.resourceHash||``,a=i?`&v=${i}`:``;n.set(t,{id:t,viewUrl:`/v1/resource/view?id=${t}${a}`,contentType:r,name:e.dataset.resourceName||e.querySelector(`img`)?.alt||``,hash:i})}});for(let e=0;e100&&this.detailsCache.delete(this.detailsCache.keys().next().value),this.detailsLoading=!0,this.detailsAborter&&this.detailsAborter();try{let{abort:e,ready:n}=M(`/resource.json?id=${t}`);this.detailsAborter=e;let r=await n;if(!r.ok)throw Error(`Failed to fetch resource: ${r.status}`);let i=await r.json(),a=i.resource||i;this.getCurrentItem()?.id===t&&(this.resourceDetails=a,this.detailsCache.set(t,a)),this.detailsAborter=null}catch(e){e.name!==`AbortError`&&(console.error(`Failed to fetch resource details:`,e),this.announce(`Failed to load resource details`))}finally{this.detailsLoading=!1}},async onResourceChange(){if(!this.editPanelOpen&&!this.quickTagPanelOpen)return;let e=document.activeElement,t=document.querySelector(`[data-edit-panel]`),n=null;e&&t?.contains(e)&&(e.id?n=`#${e.id}`:e.matches(`input[placeholder]`)&&(n=`input[placeholder="${e.getAttribute(`placeholder`)}"]`)),this.resourceDetails=null;let r=this.getCurrentItem()?.id;r&&this.detailsCache.delete(r),await this.fetchResourceDetails(),n&&requestAnimationFrame(()=>{let e=document.querySelector(`[data-edit-panel] ${n}`);e&&e.focus()}),this.onQuickTagResourceChange()},async updateName(e){let t=this.getCurrentItem()?.id;if(!t||!this.resourceDetails)return;let n=this.resourceDetails.Name;if(e===n)return;this.resourceDetails.Name=e;let r=this.items[this.currentIndex];r&&(r.name=e);try{let n=new FormData;n.append(`Name`,e);let r=await fetch(`/v1/resource/editName?id=${t}`,{method:`POST`,body:n,headers:{Accept:`application/json`}});if(!r.ok)throw Error(`Failed to update name: ${r.status}`);this.detailsCache.set(t,{...this.resourceDetails}),this.needsRefreshOnClose=!0,this.announce(`Name updated`)}catch(e){console.error(`Failed to update name:`,e),this.resourceDetails.Name=n,r&&(r.name=n),this.announce(`Failed to update name`)}},async updateDescription(e){let t=this.getCurrentItem()?.id;if(!t||!this.resourceDetails)return;let n=this.resourceDetails.Description;if(e!==n){this.resourceDetails.Description=e;try{let n=new FormData;n.append(`Description`,e);let r=await fetch(`/v1/resource/editDescription?id=${t}`,{method:`POST`,body:n,headers:{Accept:`application/json`}});if(!r.ok)throw Error(`Failed to update description: ${r.status}`);this.detailsCache.set(t,{...this.resourceDetails}),this.needsRefreshOnClose=!0,this.announce(`Description updated`)}catch(e){console.error(`Failed to update description:`,e),this.resourceDetails.Description=n,this.announce(`Failed to update description`)}}},async saveTagAddition(e){let t=this.getCurrentItem()?.id;if(!(!t||this._savingTagIds.has(e.ID))){this._savingTagIds.add(e.ID),this.resourceDetails&&(this.resourceDetails.Tags||(this.resourceDetails.Tags=[]),this.resourceDetails.Tags.some(t=>t.ID===e.ID)||this.resourceDetails.Tags.push(e));try{let n=new FormData;n.append(`ID`,t),n.append(`EditedId`,e.ID);let r=await fetch(`/v1/resources/addTags`,{method:`POST`,body:n,headers:{Accept:`application/json`}});if(!r.ok)throw Error(`Failed to add tag: ${r.status}`);this.resourceDetails&&this.detailsCache.set(t,{...this.resourceDetails}),this.needsRefreshOnClose=!0,this.announce(`Added tag: ${e.Name}`),this.recordRecentTag(e)}catch(t){if(console.error(`Failed to add tag:`,t),this.resourceDetails?.Tags){let t=this.resourceDetails.Tags.findIndex(t=>t.ID===e.ID);t!==-1&&this.resourceDetails.Tags.splice(t,1)}throw this.announce(`Failed to add tag`),t}finally{this._savingTagIds.delete(e.ID)}}},async saveTagRemoval(e){let t=this.getCurrentItem()?.id;if(t){if(this.resourceDetails?.Tags){let t=this.resourceDetails.Tags.findIndex(t=>t.ID===e.ID);t!==-1&&this.resourceDetails.Tags.splice(t,1)}try{let n=new FormData;n.append(`ID`,t),n.append(`EditedId`,e.ID);let r=await fetch(`/v1/resources/removeTags`,{method:`POST`,body:n,headers:{Accept:`application/json`}});if(!r.ok)throw Error(`Failed to remove tag: ${r.status}`);this.resourceDetails&&this.detailsCache.set(t,{...this.resourceDetails}),this.needsRefreshOnClose=!0,this.announce(`Removed tag: ${e.Name}`)}catch(t){throw console.error(`Failed to remove tag:`,t),this.resourceDetails?.Tags&&this.resourceDetails.Tags.push(e),this.announce(`Failed to remove tag`),t}}},getCurrentTags(){return this.resourceDetails?.Tags||[]}},ws=`mahresources_quickTags`,Ts=[{name:`QUICK 1`,key:`Z`},{name:`QUICK 2`,key:`X`},{name:`QUICK 3`,key:`C`},{name:`QUICK 4`,key:`V`},{name:`RECENT`,key:`B`}];function Es(e,t){let n=(e||[]).slice(0,t);for(;n.length(e||[]).map(e=>e&&!Array.isArray(e)?[e]:e));t.quickSlots.length<4;)t.quickSlots.push(Array(9).fill(null));t.activeTab===3?t.activeTab=4:t.activeTab===4&&(t.activeTab=0),t.version=3}try{Array.isArray(t.quickSlots)&&(this.quickSlots=[Es(t.quickSlots[0],9),Es(t.quickSlots[1],9),Es(t.quickSlots[2],9),Es(t.quickSlots[3],9)])}catch(e){console.warn(`Failed to load quickSlots from storage:`,e)}typeof t.drawerOpen==`boolean`&&(this.quickTagPanelOpen=t.drawerOpen),typeof t.activeTab==`number`&&t.activeTab>=0&&t.activeTab<=4&&(this.activeTab=t.activeTab),Array.isArray(t.recentTags)&&(this.recentTags=Es(t.recentTags,9))}catch(e){console.warn(`Failed to load quick tags from storage:`,e)}},_saveQuickTagsToStorage(){let e=JSON.stringify({version:3,quickSlots:this.quickSlots,drawerOpen:this.quickTagPanelOpen,activeTab:this.activeTab,recentTags:this.recentTags});try{localStorage.setItem(ws,e)}catch(t){console.warn(`Failed to save quick tags to localStorage:`,t);try{let t=new Date().toISOString().slice(0,10);localStorage.setItem(`${ws}_recover_${t}`,e)}catch{}}},_initStorageSync(){window.addEventListener(`storage`,e=>{e.key===ws&&this._loadQuickTagsFromStorage()})},switchTab(e){e<0||e>4||(this.expandedSlotIndex!==null&&(this.expandedSlotIndex=null,this._cancelLongPress()),this.activeTab=e,this.editingSlotIndex=null,this._saveQuickTagsToStorage(),this.announce(`Switched to ${Ts[e].name} tab`))},getActiveTabSlots(){return this.activeTab<4?this.quickSlots[this.activeTab]:this.recentTags},isQuickTab(){return this.activeTab<4},openQuickTagPanel(){window.innerWidth<1024&&this.editPanelOpen&&this.closeEditPanel(),this.quickTagPanelOpen=!0,this._saveQuickTagsToStorage(),this.announce(`Edit tags panel opened`),this.fetchResourceDetails()},closeQuickTagPanel(){this.editingSlotIndex=null,this.expandedSlotIndex=null,this._cancelLongPress(),this.quickTagPanelOpen=!1,this._saveQuickTagsToStorage(),!this.editPanelOpen&&this.needsRefreshOnClose&&(this.needsRefreshOnClose=!1,this.refreshPageContent()),this.editPanelOpen||(this.detailsAborter&&=(this.detailsAborter(),null),this.resourceDetails=null),this.announce(`Edit tags panel closed`)},addTagToSlot(e,t){if(!this.isQuickTab())return;let n=this.activeTab;if(!t)return;let r={id:t.ID,name:t.Name},i=this.quickSlots[n][e];if(i){if(i.some(e=>e.id===t.ID))return;i.push(r)}else this.quickSlots[n][e]=[r];this.quickSlots=[...this.quickSlots];let a=this.recentTags.findIndex(e=>e&&e.id===t.ID);a!==-1&&(this.recentTags[a]=null,this.recentTags=[...this.recentTags]),this._saveQuickTagsToStorage(),document.querySelectorAll(`[data-quick-tag-panel] [popover]`).forEach(e=>{try{e.hidePopover()}catch{}})},removeTagFromSlot(e,t){if(!this.isQuickTab())return;let n=this.activeTab,r=this.quickSlots[n][e];if(!r)return;let i=r.filter(e=>e.id!==t);this.quickSlots[n][e]=i.length>0?i:null,this.quickSlots=[...this.quickSlots],this._saveQuickTagsToStorage()},clearQuickTagSlot(e){if(!this.isQuickTab())return;let t=this.activeTab;this.quickSlots[t][e]=null,this.quickSlots=[...this.quickSlots],this._saveQuickTagsToStorage()},recordRecentTag(e){if(this.quickSlots.some(t=>t.some(t=>t&&t.some(t=>t.id===e.ID))))return;let t=Date.now(),n=this.recentTags.findIndex(t=>t&&t.id===e.ID);if(n!==-1){this.recentTags[n]={id:e.ID,name:e.Name,ts:t},this.recentTags=[...this.recentTags],this._saveQuickTagsToStorage();return}let r=this.recentTags.indexOf(null);if(r===-1){r=0;for(let e=1;et.ID===e)},slotMatchState(e){let t=this.getActiveTabSlots()[e];if(!t||!this.resourceDetails)return`none`;let n=Array.isArray(t)?t:[t];if(n.length===0)return`none`;let r=n.filter(e=>this.isTagOnResource(e.id??e.ID)).length;return r===n.length?`all`:r>0?`some`:`none`},async toggleTabTag(e){let t=this.getActiveTabSlots()[e];if(t&&this._quickTagTogglingSlot!==e){this._quickTagTogglingSlot=e;try{let n=(Array.isArray(t)?t:[t]).map(e=>({ID:e.id??e.ID,Name:e.name??e.Name}));if(this.slotMatchState(e)===`all`)await this._batchToggleTags(n,`remove`);else{let e=n.filter(e=>!this.isTagOnResource(e.ID));e.length>0&&await this._batchToggleTags(e,`add`)}}finally{this._quickTagTogglingSlot=null}}},async _batchToggleTags(e,t){let n=this.getCurrentItem()?.id;if(!n)return;let r=t===`add`?`/v1/resources/addTags`:`/v1/resources/removeTags`;if(this.resourceDetails){this.resourceDetails.Tags||(this.resourceDetails.Tags=[]);for(let n of e)if(t===`add`)this.resourceDetails.Tags.some(e=>e.ID===n.ID)||this.resourceDetails.Tags.push(n);else{let e=this.resourceDetails.Tags.findIndex(e=>e.ID===n.ID);e!==-1&&this.resourceDetails.Tags.splice(e,1)}}try{let i=new FormData;i.append(`ID`,n);for(let t of e)i.append(`EditedId`,t.ID);let a=await fetch(r,{method:`POST`,body:i,headers:{Accept:`application/json`}});if(!a.ok)throw Error(`Failed to ${t} tags: ${a.status}`);this.resourceDetails&&this.detailsCache.set(n,{...this.resourceDetails}),this.needsRefreshOnClose=!0;let o=e.map(e=>e.Name).join(`, `);if(this.announce(`${t===`add`?`Added`:`Removed`} tags: ${o}`),t===`add`)for(let t of e)this.recordRecentTag(t)}catch(e){console.error(`Failed to ${t} tags:`,e),this.detailsCache.delete(n),await this.fetchResourceDetails(),this.announce(`Failed to ${t} tags`)}},onQuickTagResourceChange(){this.quickTagPanelOpen&&(this.expandedSlotIndex!==null&&(this.expandedSlotIndex=null,this._cancelLongPress()),this.fetchResourceDetails())},async focusTagEditor(){this.quickTagPanelOpen||this.openQuickTagPanel(),await this.fetchResourceDetails();let e=()=>document.querySelector(`[data-quick-tag-panel]`)?.querySelector(`[data-tag-editor-input]`),t=e();if(t){t.focus();return}let n=t=>{let r=e();r?r.focus():t>0&&requestAnimationFrame(()=>n(t-1))};requestAnimationFrame(()=>n(10))},_numpadOrder:[6,7,8,3,4,5,0,1,2],numpadIndex(e){return this._numpadOrder[e]},quickTagKeyLabel(e){return String(e+1)},_mediaMaxWidthClass(){let e=this.editPanelOpen&&this.quickTagPanelOpen,t=this.editPanelOpen&&!this.quickTagPanelOpen,n=!this.editPanelOpen&&this.quickTagPanelOpen;return e?`lg:max-w-[calc(100vw-690px)] max-w-[90vw]`:t||n?`lg:max-w-[calc(100vw-450px)] max-w-[90vw]`:`max-w-[90vw]`},isExpanded(){return this.expandedSlotIndex!==null},expandedTags(){if(this.expandedSlotIndex===null)return[];let e=this.getActiveTabSlots()[this.expandedSlotIndex];return e?(Array.isArray(e)?e:[e]).slice(0,9):[]},collapseExpanded(){this.expandedSlotIndex!==null&&(this.expandedSlotIndex=null,this._cancelLongPress(),this._expandedClickOutsideHandler&&=(document.removeEventListener(`click`,this._expandedClickOutsideHandler,!0),null),this.announce(`Back to quick slots`))},_expandSlot(e){this.expandedSlotIndex=e,this._longPressTimer=null,this._longPressSlotIdx=null;let t=this.expandedTags(),n=this.quickTagKeyLabel(e);this.announce(`Expanded slot ${n}: ${t.length} tags. Press Escape to go back.`)},_cancelLongPress(){this._longPressTimer&&=(clearTimeout(this._longPressTimer),null),this._longPressSlotIdx=null},_slotTagCount(e){let t=this.getActiveTabSlots()[e];return t?Array.isArray(t)?t.length:1:0},async toggleExpandedTag(e){let t=this.expandedTags();if(e>=t.length)return;let n=t[e],r={ID:n.id??n.ID,Name:n.name??n.Name},i=this.isTagOnResource(r.ID);await this._batchToggleTags([r],i?`remove`:`add`)},handleSlotKeydown(e,t){if(!t.repeat){if(this.isExpanded()){this.toggleExpandedTag(e);return}if(this._slotTagCount(e)<=1){this.toggleTabTag(e);return}this._longPressSlotIdx=e,this._longPressTimer=setTimeout(()=>{this._expandSlot(e)},this._longPressThreshold)}},handleSlotKeyup(e){this.isExpanded()||this._slotTagCount(e)<=1||this._longPressTimer&&(this._cancelLongPress(),this.toggleTabTag(e))},handleSlotMousedown(e){this.isExpanded()||this._slotTagCount(e)<=1||(this._longPressSlotIdx=e,this._longPressTimer=setTimeout(()=>{this._expandSlot(e)},this._longPressThreshold))},handleSlotMouseup(e){this.isExpanded()||this._slotTagCount(e)<=1||this._longPressTimer&&(this._cancelLongPress(),this.toggleTabTag(e))},handleSlotMouseleave(e){this._longPressTimer&&this._cancelLongPress()},_setupExpandedClickOutside(){this._expandedClickOutsideHandler&&=(document.removeEventListener(`click`,this._expandedClickOutsideHandler,!0),null),this.isExpanded()&&(this._expandedClickOutsideHandler=e=>{let t=document.querySelector(`[data-quick-tag-panel]`);t&&!t.contains(e.target)&&this.collapseExpanded()},setTimeout(()=>{this._expandedClickOutsideHandler&&document.addEventListener(`click`,this._expandedClickOutsideHandler,!0)},0))}};function ks(e){e.store(`lightbox`,{...gs,...vs,...bs,...Ss,...Ds,_liveRegion:null,liveRegion:null,init(){this._liveRegion||(this._loadQuickTagsFromStorage(),this._initStorageSync(),this._liveRegion=Go(),this.liveRegion=this._liveRegion.element,this._handleFullscreenChange=()=>{this.isFullscreen=!!(document.fullscreenElement||document.webkitFullscreenElement),this.announce(this.isFullscreen?`Entered fullscreen`:`Exited fullscreen`)},document.addEventListener(`fullscreenchange`,this._handleFullscreenChange),document.addEventListener(`webkitfullscreenchange`,this._handleFullscreenChange),this._handleWheelEvent=e=>{this.isOpen&&(e.target.closest(`[data-edit-panel]`)||e.target.closest(`[data-quick-tag-panel]`)||this.handleWheel(e))},document.addEventListener(`wheel`,this._handleWheelEvent,{passive:!1}))},destroy(){this._handleFullscreenChange&&(document.removeEventListener(`fullscreenchange`,this._handleFullscreenChange),document.removeEventListener(`webkitfullscreenchange`,this._handleFullscreenChange)),this._handleWheelEvent&&document.removeEventListener(`wheel`,this._handleWheelEvent),this._liveRegion&&(this._liveRegion.destroy(),this._liveRegion=null,this.liveRegion=null),this.animationTimeout&&clearTimeout(this.animationTimeout)},announce(e){this._liveRegion?.announce(e)},..._s,...ys,...xs,...Cs,...Os})}var As={resource:{entityType:`resource`,entityLabel:`Resources`,searchEndpoint:`/v1/resources`,maxResults:50,searchParams:(e,t,n={},r)=>{let i=new URLSearchParams({MaxResults:String(r)});return e&&i.set(`name`,e),t.tags&&t.tags.forEach(e=>i.append(`Tags`,e)),t.group&&i.set(`Groups`,t.group),n.content_types&&n.content_types.forEach(e=>i.append(`ContentTypes`,e)),i},filters:[{key:`tags`,label:`Tags`,endpoint:`/v1/tags`,multi:!0},{key:`group`,label:`Group`,endpoint:`/v1/groups`,multi:!1}],tabs:[{id:`note`,label:`Note's Resources`},{id:`all`,label:`All Resources`}],renderItem:`thumbnail`,gridColumns:`grid-cols-3 sm:grid-cols-4 md:grid-cols-5`,getItemId:e=>e.ID,getItemLabel:e=>e.Name||`Resource ${e.ID}`},group:{entityType:`group`,entityLabel:`Groups`,searchEndpoint:`/v1/groups`,maxResults:50,searchParams:(e,t,n={},r)=>{let i=new URLSearchParams({MaxResults:String(r)});return e&&i.set(`name`,e),t.category&&i.set(`categoryId`,t.category),n.category_ids&&n.category_ids.forEach(e=>i.append(`Categories`,e)),i},filters:[{key:`category`,label:`Category`,endpoint:`/v1/categories`,multi:!1}],tabs:null,renderItem:`groupCard`,gridColumns:`grid-cols-2 md:grid-cols-3 lg:grid-cols-4`,getItemId:e=>e.ID,getItemLabel:e=>e.Name||`Group ${e.ID}`},note:{entityType:`note`,entityLabel:`Notes`,searchEndpoint:`/v1/notes`,maxResults:50,searchParams:(e,t,n={},r)=>{let i=new URLSearchParams({MaxResults:String(r)});return e&&i.set(`name`,e),t.tags&&t.tags.forEach(e=>i.append(`Tags`,e)),n.note_type_ids&&n.note_type_ids.forEach(e=>i.append(`NoteTypeIds`,e)),i},filters:[{key:`tags`,label:`Tags`,endpoint:`/v1/tags`,multi:!0}],tabs:null,renderItem:`noteCard`,gridColumns:`grid-cols-2 md:grid-cols-3 lg:grid-cols-4`,getItemId:e=>e.ID,getItemLabel:e=>e.Name||`Note ${e.ID}`}};function js(e){let t=As[e];if(!t)throw Error(`Unknown entity type: ${e}`);return t}function Ms(e){e.store(`entityPicker`,{config:null,isOpen:!1,activeTab:null,loading:!1,error:null,noteId:null,searchQuery:``,filterValues:{},results:[],tabResults:{},selectedIds:new Set,existingIds:new Set,lockedFilters:{},multiSelect:!0,onConfirm:null,searchDebounceTimer:null,requestAborter:null,open({entityType:e,noteId:t=null,existingIds:n=[],lockedFilters:r={},multiSelect:i=!0,onConfirm:a}){this.config=js(e),this.noteId=t,this.existingIds=new Set(n),this.lockedFilters=r,this.multiSelect=i,this.onConfirm=a,this.selectedIds=new Set,this.searchQuery=``,this.filterValues={},this.error=null,this.results=[],this.tabResults={},this.isOpen=!0,this.config.tabs?(this.activeTab=t?this.config.tabs[0].id:this.config.tabs[1]?.id||this.config.tabs[0].id,this.activeTab===`note`&&t&&this.loadNoteResources()):this.activeTab=null,this.loadResults()},close(){this.isOpen=!1,this.results=[],this.tabResults={},this.selectedIds=new Set,this.lockedFilters={},this.multiSelect=!0,this.config=null,this.searchDebounceTimer&&=(clearTimeout(this.searchDebounceTimer),null),this.requestAborter&&=(this.requestAborter(),null),window.dispatchEvent(new CustomEvent(`entity-picker-closed`))},confirm(){this.onConfirm&&this.selectedIds.size>0&&this.onConfirm([...this.selectedIds]),this.close()},async loadNoteResources(){if(this.noteId)try{let e=await fetch(`/v1/resources?ownerId=${this.noteId}&MaxResults=100`);if(!e.ok)throw Error(`Failed to load note resources`);this.tabResults.note=await e.json(),this.tabResults.note.length===0&&this.activeTab===`note`&&(this.activeTab=`all`)}catch(e){console.error(`Error loading note resources:`,e)}},async loadResults(){this.requestAborter&&this.requestAborter(),this.loading=!0,this.error=null;let e=this.config.maxResults||50,t=this.config.searchParams(this.searchQuery.trim(),this.filterValues,this.lockedFilters,e),{abort:n,ready:r}=M(`${this.config.searchEndpoint}?${t}`);this.requestAborter=n;try{let e=await r;if(!e.ok)throw Error(`Failed to load ${this.config.entityLabel.toLowerCase()}`);let t=await e.json();this.results=t,this.config.tabs&&(this.tabResults.all=t)}catch(e){e.name!==`AbortError`&&(this.error=e.message||`Failed to load ${this.config.entityLabel.toLowerCase()}`,console.error(`Error loading results:`,e))}finally{this.loading=!1}},onSearchInput(){this.searchDebounceTimer&&clearTimeout(this.searchDebounceTimer),this.searchDebounceTimer=setTimeout(()=>{this.loadResults()},200)},setFilter(e,t){t==null?delete this.filterValues[e]:this.filterValues[e]=t,this.loadResults()},addToFilter(e,t){this.filterValues[e]||(this.filterValues[e]=[]),this.filterValues[e].includes(t)||(this.filterValues[e]=[...this.filterValues[e],t],this.loadResults())},removeFromFilter(e,t){this.filterValues[e]&&(this.filterValues[e]=this.filterValues[e].filter(e=>e!==t),this.filterValues[e].length===0&&delete this.filterValues[e],this.loadResults())},toggleSelection(e){if(!this.existingIds.has(e)){if(!this.multiSelect){this.selectedIds=new Set([e]),this.confirm();return}this.selectedIds.has(e)?this.selectedIds.delete(e):this.selectedIds.add(e),this.selectedIds=new Set(this.selectedIds)}},isSelected(e){return this.selectedIds.has(e)},isAlreadyAdded(e){return this.existingIds.has(e)},setActiveTab(e){this.activeTab=e},get displayResults(){return this.config?.tabs&&this.activeTab===`note`?this.tabResults.note||[]:this.results},get hasTabResults(){return this.tabResults.note?.length>0},get selectionCount(){return this.selectedIds.size}})}var Ns=5,Ps=2,Fs=500,Is=300*1e3,Ls=new Map;function Rs(e,t){let n=`${e}:${t}`,r=Ls.get(n);return r&&Date.now()-r.timestampsetTimeout(t,e))}async function Vs(e,t=Ps){let n;for(let r=0;r<=t;r++){try{let t=await fetch(e);if(t.ok)return await t.json();if(t.status>=400&&t.status<500)return null;n=Error(`HTTP ${t.status}`)}catch(e){n=e}re()));n.push(...a)}return n}async function Us(e,t){if(!t||t.length===0)return{};let n={resource:Ws,group:Gs}[e];return n?n(t):(console.warn(`No metadata fetcher for entity type: ${e}`),{})}async function Ws(e){let t={},n=[];for(let r of e){if(r==null)continue;let e=Rs(`resource`,r);e?t[r]=e:n.push(r)}if(n.length===0)return t;try{(await Hs(n.map(e=>async()=>{try{return{id:e,res:await Vs(`/v1/resource?id=${e}`)}}catch(t){return console.warn(`Failed to fetch resource ${e} after retries:`,t),{id:e,res:null}}}))).forEach(({id:e,res:n})=>{if(n){let r={contentType:n.ContentType||``,name:n.Name||``,hash:n.Hash||``};t[e]=r,zs(`resource`,e,r)}})}catch(e){console.warn(`Failed to fetch resource metadata:`,e)}return t}async function Gs(e){let t={},n=[];for(let r of e){if(r==null)continue;let e=Rs(`group`,r);e?t[r]=e:n.push(r)}if(n.length===0)return t;try{(await Hs(n.map(e=>async()=>{try{return{id:e,res:await Vs(`/v1/group?id=${e}`)}}catch(t){return console.warn(`Failed to fetch group ${e} after retries:`,t),{id:e,res:null}}}))).forEach(({id:e,res:n})=>{if(n){let r={name:n.Name||``,breadcrumb:Ks(n),resourceCount:n.ResourceCount||0,noteCount:n.NoteCount||0,mainResourceId:n.MainResource?.ID||null,categoryName:n.Category?.Name||``};t[e]=r,zs(`group`,e,r)}})}catch(e){console.warn(`Failed to fetch group metadata:`,e)}return t}function Ks(e){let t=[],n=e.Owner,r=0;for(;n&&r<3;)t.unshift(n.Name),n=n.Owner,r++;return n&&t.unshift(`...`),t.join(` > `)}function qs(e,t){return`${e}-${new Date().toISOString().replace(/\.\d{3}Z$/,``).replace(/:/g,`-`)}.${t}`}function Js(e){return e?e.startsWith(`image/`)?`image`:e===`text/html`?`html`:e.startsWith(`text/`)?`text`:`file`:`file`}function Ys(e,t=120){let n=e.replace(/<[^>]*>/g,` `).replace(/\s+/g,` `).trim();return n.length>t?n.slice(0,t)+`โ€ฆ`:n}function Xs(e,t){let n=e||`Upload failed (HTTP ${t})`,r=null;try{let t=JSON.parse(e),i=t.details?.[0];i?(n=i.error,i.existingResourceId!=null&&(r=i.existingResourceId)):t.error&&(n=t.error)}catch{}return n.length>0&&(n=n.charAt(0).toUpperCase()+n.slice(1)),{message:n,resourceId:r}}function Zs(e){if(!e)return[];if(e.files&&e.files.length>0){let t=[];for(let n of e.files){let e=n.type.startsWith(`image/`),r=n.name&&n.name!==``?n.name:qs(`pasted-file`,n.type.split(`/`)[1]||`bin`);t.push({file:n,name:r,previewUrl:e?URL.createObjectURL(n):null,type:Js(n.type),error:null,errorResourceId:null,_snippet:null})}return t}if(e.items){let t=[];for(let n of e.items)if(n.kind===`file`&&n.type.startsWith(`image/`)){let e=n.getAsFile();if(!e)continue;let r=qs(`pasted-image`,n.type.split(`/`)[1]||`png`);t.push({file:e,name:r,previewUrl:URL.createObjectURL(e),type:`image`,error:null,errorResourceId:null,_snippet:null})}if(t.length>0)return t}let t=e.getData(`text/html`);if(t){let e=new Blob([t],{type:`text/html`}),n=new File([e],qs(`pasted-html`,`html`),{type:`text/html`});return[{file:n,name:n.name,previewUrl:null,type:`html`,error:null,errorResourceId:null,_snippet:Ys(t)}]}let n=e.getData(`text/plain`);if(n){let e=new Blob([n],{type:`text/plain`}),t=new File([e],qs(`pasted-text`,`txt`),{type:`text/plain`});return[{file:t,name:t.name,previewUrl:null,type:`text`,error:null,errorResourceId:null,_snippet:Ys(n)}]}return[]}var Qs=null,$s=null;function ec(){window.addEventListener(`paste`,async e=>{let t=document.querySelector(`input[type='file']`);if(t&&e.clipboardData?.files&&e.clipboardData.files.length>0){e.preventDefault();let n=new DataTransfer;for(let e of t.files)n.items.add(e);for(let t of e.clipboardData.files)n.items.add(t);t.files=n.files,t.dispatchEvent(new Event(`change`,{bubbles:!0})),t.closest(`.flex`)?.classList.add(`ring-2`,`ring-indigo-500`,`rounded-md`),setTimeout(()=>t.closest(`.flex`)?.classList.remove(`ring-2`,`ring-indigo-500`,`rounded-md`),1500);return}let n=document.activeElement;if(n){let e=n.tagName;if(e===`INPUT`||e===`TEXTAREA`||n.isContentEditable)return}let r=Zs(e.clipboardData);if(r.length===0)return;e.preventDefault();let i=window.Alpine?.store(`pasteUpload`);if(!i)return;let a=document.querySelector(`[data-paste-context]`);if(a){try{let e=JSON.parse(a.getAttribute(`data-paste-context`));i.open(r,e)}catch(e){console.error(`Failed to parse data-paste-context:`,e),i.showInfo(`Invalid paste context on this page.`);for(let e of r)e.previewUrl&&URL.revokeObjectURL(e.previewUrl)}return}let o=new URLSearchParams(window.location.search).get(`ownerId`);if(o){try{let e=await fetch(`/v1/group.json?id=${encodeURIComponent(o)}`);if(!e.ok)throw Error(`HTTP ${e.status}`);let t=await e.json();i.open(r,{type:`group`,id:t.ID,name:t.Name})}catch(e){console.error(`Failed to fetch owner group:`,e),i.showInfo(`Could not determine the owner group for pasted content.`);for(let e of r)e.previewUrl&&URL.revokeObjectURL(e.previewUrl)}return}i.showInfo(`To paste and upload, navigate to a group or note detail page, or filter a list by owner.`);for(let e of r)e.previewUrl&&URL.revokeObjectURL(e.previewUrl)})}function tc(e){e.store(`pasteUpload`,{isOpen:!1,items:[],context:null,tags:[],categoryId:null,seriesId:null,state:`idle`,uploadProgress:``,errorMessage:``,infoMessage:``,open(e,t){if(!(!e||e.length===0)){if(this.isOpen&&this.state!==`uploading`){$s&&=(clearTimeout($s),null);for(let e of this.items)e.error===`done`&&e.previewUrl&&URL.revokeObjectURL(e.previewUrl);this.items=this.items.filter(e=>e.error!==`done`),this.items.push(...e),this.state=`preview`,this.errorMessage=``;return}for(let e of this.items)e.previewUrl&&URL.revokeObjectURL(e.previewUrl);this.items=e,this.context=t||null,this.tags=[],this.categoryId=null,this.seriesId=null,this.state=`preview`,this.uploadProgress=``,this.errorMessage=``,this.infoMessage=``,this.isOpen=!0}},close(){$s&&=(clearTimeout($s),null),Qs&&=(clearTimeout(Qs),null);for(let e of this.items)e.previewUrl&&URL.revokeObjectURL(e.previewUrl);this.items=[],this.context=null,this.tags=[],this.categoryId=null,this.seriesId=null,this.state=`idle`,this.uploadProgress=``,this.errorMessage=``,this.infoMessage=``,this.isOpen=!1},removeItem(e){if(e<0||e>=this.items.length)return;let[t]=this.items.splice(e,1);t&&t.previewUrl&&URL.revokeObjectURL(t.previewUrl),this.items.length===0&&this.close()},showInfo(e){this.infoMessage=e,Qs&&clearTimeout(Qs),Qs=setTimeout(()=>{this.infoMessage=``,Qs=null},4e3)},async upload(){if(this.items.length===0||!this.context)return;this.state=`uploading`,this.errorMessage=``;let e=this.items.filter(e=>e.error!==`done`).length,t=0,n=0;for(let r of this.items){if(r.error===`done`)continue;n++,this.uploadProgress=`Uploading ${n} of ${e}...`;let i=new FormData;i.append(`resource`,r.file,r.name),this.context.type===`group`?(i.append(`ownerId`,this.context.id),i.append(`groups`,this.context.id)):this.context.type===`note`&&(this.context.ownerId&&i.append(`ownerId`,this.context.ownerId),i.append(`notes`,this.context.id));for(let e of this.tags)i.append(`tags`,e);this.categoryId&&i.append(`resourceCategoryId`,this.categoryId),this.seriesId&&i.append(`SeriesId`,this.seriesId);try{let e=await fetch(`/v1/resource`,{method:`POST`,body:i});if(e.ok)r.error=`done`,r.errorResourceId=null,t++;else{let t=Xs(await e.text(),e.status);r.error=t.message,r.errorResourceId=t.resourceId}}catch(e){r.error=e.message||`Network error`}}if(t===e)this.state=`success`,this.uploadProgress=`Uploaded ${t} file${t===1?``:`s`} successfully.`,$s=setTimeout(()=>{$s=null,this.close(),this._refreshPage()},1200);else if(t>0){for(let e of this.items)e.error===`done`&&e.previewUrl&&URL.revokeObjectURL(e.previewUrl);this.items=this.items.filter(e=>e.error!==`done`),this.state=`error`,this.errorMessage=`${t} succeeded, ${e-t} failed.`}else this.state=`error`,this.errorMessage=`All ${e} upload${e===1?``:`s`} failed.`},async _refreshPage(){try{let e=await fetch(window.location.href,{headers:{Accept:`text/html`}});if(!e.ok){window.location.reload();return}let t=await e.text(),n=new DOMParser().parseFromString(t,`text/html`).querySelector(`.main`),r=document.querySelector(`.main`);r&&n&&(window.Alpine.morph(r,n,{updating(e,t,n,r){e._x_dataStack&&(t._x_dataStack=e._x_dataStack)}}),window.Alpine?.store(`lightbox`)?.initFromDOM())}catch(e){console.error(`Failed to refresh page after upload:`,e),window.location.reload()}}})}function nc({availableColumns:e,name:t}){return{sortColumns:[],availableColumns:e,name:t,init(){let e=new URLSearchParams(window.location.search).getAll(this.name);e.length>0?this.sortColumns=e.map(e=>this.parseSort(e)):this.sortColumns=[{column:``,direction:`desc`,metaKey:``}]},parseSort(e){let t=e.trim().split(/\s+/),n=t[0]||``,r=t[1]||`desc`,i=n.match(/^meta->>'([a-z_]+)'$/);return i?{column:`__meta__`,direction:r,metaKey:i[1]}:{column:n,direction:r,metaKey:``}},formatSort(e){return e.column?e.column===`__meta__`?e.metaKey?`meta->>'${e.metaKey}' ${e.direction}`:``:`${e.column} ${e.direction}`:``},addSort(){this.sortColumns.push({column:``,direction:`desc`,metaKey:``})},removeSort(e){this.sortColumns.length>1?this.sortColumns.splice(e,1):this.sortColumns[0]={column:``,direction:`desc`,metaKey:``}},isValidMetaKey(e){return/^[a-z_]+$/.test(e)},moveUp(e){if(e>0){let t=this.sortColumns[e];this.sortColumns[e]=this.sortColumns[e-1],this.sortColumns[e-1]=t}},moveDown(e){if(et.Value===e);return t?t.Name:e},getAvailableColumnsForRow(e){let t=this.sortColumns.filter((t,n)=>n!==e).map(e=>e.column).filter(e=>e);return this.availableColumns.filter(e=>!t.includes(e.Value))}}}function rc(){return{isOpen:!1,jobs:[],retainedCompletedJobs:[],eventSource:null,connectionStatus:`disconnected`,_liveRegion:null,_keydownHandler:null,_reconnectDelay:1e3,_reconnectAttempts:0,_maxReconnectAttempts:10,_maxReconnectDelay:6e4,speedTracking:{},exportRetentionMs:0,statusIcons:{pending:`โณ`,downloading:`โฌ‡`,processing:`โš™`,running:`โš™`,completed:`โœ…`,failed:`โŒ`,cancelled:`โ›”`,paused:`โธ`},statusLabels:{pending:`Pending`,downloading:`Downloading`,processing:`Processing`,running:`Running`,completed:`Completed`,failed:`Failed`,cancelled:`Cancelled`,paused:`Paused`},init(){this._liveRegion=Go(),this._lastTrigger=null;let e=document.querySelector(`meta[name="x-export-retention-ms"]`);e&&(this.exportRetentionMs=parseInt(e.getAttribute(`content`),10)||0),window.addEventListener(`jobs-panel-open`,()=>{this.isOpen=!0}),this._keydownHandler=e=>{(e.metaKey||e.ctrlKey)&&e.shiftKey&&e.key.toLowerCase()===`d`&&(e.preventDefault(),this.toggle())},document.addEventListener(`keydown`,this._keydownHandler),this.connect(),this.$watch(`isOpen`,e=>{e?(this.announce(`Jobs panel opened. Shows background job progress.`),this.$nextTick(()=>{let e=this.$refs.panel;e&&(e.querySelector(`button:not([disabled]), [href], input:not([disabled]), [tabindex]:not([tabindex="-1"])`)||e).focus()})):this._lastTrigger&&=(this._lastTrigger.focus(),null)})},announce(e){this._liveRegion?.announce(e)},destroy(){this._liveRegion?.destroy(),this._keydownHandler&&document.removeEventListener(`keydown`,this._keydownHandler),this.disconnect()},toggle(e){!this.isOpen&&e?.currentTarget&&(this._lastTrigger=e.currentTarget),this.isOpen=!this.isOpen},close(){this.isOpen=!1},connect(){this.eventSource||(this.connectionStatus=`connecting`,this.eventSource=new EventSource(`/v1/jobs/events`),this.eventSource.addEventListener(`init`,e=>{let t=JSON.parse(e.data);this.jobs=t.jobs||[];let n=(t.actionJobs||[]).map(e=>({...e,_isAction:!0}));this.jobs=[...this.jobs,...n],this.retainedCompletedJobs=[],this.connectionStatus=`connected`,this._reconnectDelay=1e3,this._reconnectAttempts=0}),this.eventSource.addEventListener(`added`,e=>{let{job:t}=JSON.parse(e.data);this.jobs.push(t),this.announce(`Download queued: ${this.truncateUrl(t.url,30)}`)}),this.eventSource.addEventListener(`updated`,e=>{let{job:t}=JSON.parse(e.data),n=this.jobs.findIndex(e=>e.id===t.id);if(n!==-1&&(this.jobs[n]=t),t.status===`downloading`&&t.progress>0){let e=Date.now(),n=this.speedTracking[t.id];if(n&&n.lastProgress0&&(n.speed=i/r),n.lastProgress=t.progress,n.lastTime=e}else n||(this.speedTracking[t.id]={lastProgress:t.progress,lastTime:e,speed:0})}t.status===`completed`?(delete this.speedTracking[t.id],this.announce(`Download completed: ${this.truncateUrl(t.url,30)}`),window.dispatchEvent(new CustomEvent(`download-completed`,{detail:t}))):t.status===`failed`?(delete this.speedTracking[t.id],this.announce(`Download failed: ${this.truncateUrl(t.url,30)}`)):t.status===`paused`&&(delete this.speedTracking[t.id],this.announce(`Download paused: ${this.truncateUrl(t.url,30)}`))}),this.eventSource.addEventListener(`removed`,e=>{let{job:t}=JSON.parse(e.data),n=this.jobs.find(e=>e.id===t.id);n&&!this.isActive(n)&&(this.retainedCompletedJobs.some(e=>e.id===n.id)||(this.retainedCompletedJobs.unshift(n),this.retainedCompletedJobs.length>5&&(this.retainedCompletedJobs=this.retainedCompletedJobs.slice(0,5)))),this.jobs=this.jobs.filter(e=>e.id!==t.id)}),this.eventSource.addEventListener(`action_added`,e=>{let{job:t}=JSON.parse(e.data);t._isAction=!0,this.jobs.push(t),this.isOpen=!0,this.announce(`Action started: ${t.label}`)}),this.eventSource.addEventListener(`action_updated`,e=>{let{job:t}=JSON.parse(e.data);t._isAction=!0;let n=this.jobs.findIndex(e=>e.id===t.id);n!==-1&&(this.jobs[n]=t),t.status===`completed`?(this.announce(`Action completed: ${t.label}`),window.dispatchEvent(new CustomEvent(`plugin-action-completed`,{detail:t}))):t.status===`failed`&&this.announce(`Action failed: ${t.label}`)}),this.eventSource.addEventListener(`action_removed`,e=>{let{job:t}=JSON.parse(e.data),n=this.jobs.find(e=>e.id===t.id);n&&(n.status===`completed`||n.status===`failed`)&&(this.retainedCompletedJobs.some(e=>e.id===n.id)||(n._isAction=!0,this.retainedCompletedJobs.unshift(n),this.retainedCompletedJobs.length>5&&(this.retainedCompletedJobs=this.retainedCompletedJobs.slice(0,5)))),this.jobs=this.jobs.filter(e=>e.id!==t.id)}),this.eventSource.onerror=()=>{this.connectionStatus=`disconnected`,this.disconnect(),this._reconnectAttempts++,this._reconnectAttempts<=this._maxReconnectAttempts&&(setTimeout(()=>{this.connect()},this._reconnectDelay),this._reconnectDelay=Math.min(this._reconnectDelay*2,this._maxReconnectDelay))})},disconnect(){this.eventSource&&=(this.eventSource.close(),null),this.connectionStatus=`disconnected`},cancelJob(e){fetch(`/v1/jobs/cancel`,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:`id=${encodeURIComponent(e)}`}).catch(e=>console.error(`Cancel failed:`,e))},pauseJob(e){fetch(`/v1/jobs/pause`,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:`id=${encodeURIComponent(e)}`}).catch(e=>console.error(`Pause failed:`,e))},resumeJob(e){fetch(`/v1/jobs/resume`,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:`id=${encodeURIComponent(e)}`}).catch(e=>console.error(`Resume failed:`,e))},retryJob(e){fetch(`/v1/jobs/retry`,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:`id=${encodeURIComponent(e)}`}).catch(e=>console.error(`Retry failed:`,e))},formatProgress(e){return e.totalSize>0?`${this.formatBytes(e.progress)} / ${this.formatBytes(e.totalSize)} (${Math.min(100,e.progressPercent).toFixed(1)}%)`:e.progress>0?`${this.formatBytes(e.progress)} downloaded`:``},formatBytes(e){if(e===0)return`0 B`;let t=1024,n=[`B`,`KB`,`MB`,`GB`],r=Math.floor(Math.log(e)/Math.log(t));return parseFloat((e/t**+r).toFixed(1))+` `+n[r]},getSpeed(e){let t=this.speedTracking[e.id];return t?t.speed:0},formatSpeed(e){let t=this.getSpeed(e);return t<=0?``:this.formatBytes(t)+`/s`},formatRelativeTime(e){let t=e-Date.now();if(t<=0)return`now (tar may already be gone)`;let n=Math.floor(t/6e4);if(n<60)return`in ${n} min`;let r=Math.floor(n/60);if(r<24)return`in ${r} h ${n%60} min`;let i=Math.floor(r/24);return`in ${i} day${i===1?``:`s`}`},getProgressPercent(e){return e.totalSize>0&&e.progress>0?Math.min(100,e.progress/e.totalSize*100):0},isActive(e){return[`pending`,`downloading`,`processing`,`running`].includes(e.status)},canPause(e){return[`pending`,`downloading`].includes(e.status)},canResume(e){return e.status===`paused`},canRetry(e){return[`failed`,`cancelled`].includes(e.status)},get activeCount(){return this.jobs.filter(e=>this.isActive(e)).length},get hasActiveJobs(){return this.activeCount>0},get displayJobs(){let e=new Set(this.jobs.map(e=>e.id)),t=this.retainedCompletedJobs.filter(t=>!e.has(t.id));return[...this.jobs,...t]},truncateUrl(e,t=40){return e?e.length<=t?e:e.substring(0,t-3)+`...`:``},getJobTitle(e){return e._isAction?e.label||e.actionId:e.source===`group-export`?e.name||`Group export`:this.getFilename(e.url)||e.name||`Download`},getJobSubtitle(e){return e._isAction?e.message||``:this.truncateUrl(e.url,50)},getFilename(e){if(!e)return``;try{return new URL(e).pathname.split(`/`).pop()||e}catch{return e.split(`/`).pop()||e}}}}function ic(e){return{r1:e.r1,v1:e.v1,r2:e.r2,v2:e.v2,init(){},updateUrl(){let e=new URL(window.location);e.searchParams.set(`r1`,this.r1),e.searchParams.set(`v1`,this.v1),e.searchParams.set(`r2`,this.r2),e.searchParams.set(`v2`,this.v2),window.location.href=e.toString()},async fetchVersions(e){let t=await fetch(`/v1/resource/versions?resourceId=${e}`);return t.ok?t.json():(console.error(`Failed to fetch versions:`,t.statusText),[])},async onResource1Change(e){this.r1=e;let t=await this.fetchVersions(e);t.length>0&&(this.v1=t[0].versionNumber),this.updateUrl()},async onResource2Change(e){this.r2=e;let t=await this.fetchVersions(e);t.length>0&&(this.v2=t[0].versionNumber),this.updateUrl()},onVersion1Change(e){this.v1=e,this.updateUrl()},onVersion2Change(e){this.v2=e,this.updateUrl()},swapSides(){[this.r1,this.r2]=[this.r2,this.r1],[this.v1,this.v2]=[this.v2,this.v1],this.updateUrl()}}}function ac(e){return{g1:e.g1,g2:e.g2,init(){},updateUrl(){let e=new URL(window.location);e.searchParams.set(`g1`,this.g1),e.searchParams.set(`g2`,this.g2),window.location.href=e.toString()},onGroup1Change(e){this.g1=e,this.updateUrl()},onGroup2Change(e){this.g2=e,this.updateUrl()},swapSides(){[this.g1,this.g2]=[this.g2,this.g1],this.updateUrl()}}}function oc({leftUrl:e,rightUrl:t,leftLabel:n,rightLabel:r}){return{mode:`side-by-side`,leftUrl:e,rightUrl:t,leftLabel:n||``,rightLabel:r||``,sliderPos:50,opacity:50,showLeft:!0,isDragging:!1,_keyHandler:null,init(){this._keyHandler=e=>{if(e.target.tagName===`INPUT`||e.target.tagName===`TEXTAREA`||e.target.tagName===`SELECT`)return;let t=e.shiftKey?10:2;this.mode===`slider`?e.key===`ArrowLeft`?(this.sliderPos=Math.max(1,this.sliderPos-t),e.preventDefault()):e.key===`ArrowRight`&&(this.sliderPos=Math.min(99,this.sliderPos+t),e.preventDefault()):this.mode===`onion`&&(e.key===`ArrowLeft`?(this.opacity=Math.max(0,this.opacity-t),e.preventDefault()):e.key===`ArrowRight`&&(this.opacity=Math.min(100,this.opacity+t),e.preventDefault()))},document.addEventListener(`keydown`,this._keyHandler)},destroy(){this._keyHandler&&document.removeEventListener(`keydown`,this._keyHandler)},swapSides(){[this.leftUrl,this.rightUrl]=[this.rightUrl,this.leftUrl],[this.leftLabel,this.rightLabel]=[this.rightLabel,this.leftLabel]},toggleSide(){this.showLeft=!this.showLeft},onRadiogroupKeydown(e,t,n){if(e.key!==`ArrowRight`&&e.key!==`ArrowLeft`&&e.key!==`Home`&&e.key!==`End`)return;e.preventDefault();let r=n.indexOf(this[t]),i=r;e.key===`ArrowRight`?i=(r+1)%n.length:e.key===`ArrowLeft`?i=(r-1+n.length)%n.length:e.key===`Home`?i=0:e.key===`End`&&(i=n.length-1),this[t]=n[i];let a=e.currentTarget;this.$nextTick(()=>{let e=a.querySelector(`[role="radio"][aria-checked="true"]`);e instanceof HTMLElement&&e.focus()})},startSliderDrag(e){e.preventDefault(),this.isDragging=!0;let t=e.target.closest(`.relative`);document.body.style.userSelect=`none`,document.body.style.cursor=`ew-resize`;let n=e=>{if(!this.isDragging)return;e.preventDefault();let n=t.getBoundingClientRect(),r=(e.clientX||e.touches?.[0]?.clientX)-n.left;this.sliderPos=Math.max(1,Math.min(99,r/n.width*100))},r=()=>{this.isDragging=!1,document.body.style.userSelect=``,document.body.style.cursor=``,document.removeEventListener(`mousemove`,n),document.removeEventListener(`mouseup`,r),document.removeEventListener(`touchmove`,n),document.removeEventListener(`touchend`,r)};document.addEventListener(`mousemove`,n),document.addEventListener(`mouseup`,r),document.addEventListener(`touchmove`,n,{passive:!1}),document.addEventListener(`touchend`,r)}}}function sc({resourceId:e,imageUrl:t,initialWidth:n=0,initialHeight:r=0}){return{resourceId:e,imageUrl:t,naturalW:n||0,naturalH:r||0,rect:{x:0,y:0,width:0,height:0},aspect:`free`,comment:``,isSubmitting:!1,errorMessage:``,decodeFailed:!1,_drag:null,onImageLoad(){let e=this.$refs.image;if(e){if(!e.naturalWidth||!e.naturalHeight){this.decodeFailed=!0;return}this.decodeFailed=!1,this.naturalW=e.naturalWidth||this.naturalW,this.naturalH=e.naturalHeight||this.naturalH}},onImageError(){this.decodeFailed=!0},_imageRect(){return this.$refs.image?this.$refs.image.getBoundingClientRect():null},_eventToNatural(e){let t=this._imageRect();if(!t||t.width<=0||t.height<=0||!this.naturalW||!this.naturalH)return null;let n=Math.max(0,Math.min(t.width,e.clientX-t.left)),r=Math.max(0,Math.min(t.height,e.clientY-t.top));return{x:Math.round(n/t.width*this.naturalW),y:Math.round(r/t.height*this.naturalH)}},onPointerDown(e){if(e.button!==void 0&&e.button!==0)return;let t=this._eventToNatural(e);if(t&&(this.errorMessage=``,this._drag={startX:t.x,startY:t.y},this.rect={x:t.x,y:t.y,width:0,height:0},e.target&&e.target.setPointerCapture&&e.pointerId!==void 0))try{e.target.setPointerCapture(e.pointerId)}catch{}},onPointerMove(e){if(!this._drag)return;let t=this._eventToNatural(e);if(!t)return;let n=Math.min(this._drag.startX,t.x),r=Math.min(this._drag.startY,t.y),i=Math.max(this._drag.startX,t.x),a=Math.max(this._drag.startY,t.y),o=i-n,s=a-r,c=this._aspectRatio();if(c){let e=o,t=s/c,n=Math.max(e,t);o=Math.round(n),s=Math.round(n*c)}this.rect={x:n,y:r,width:o,height:s},this.clampRect()},onPointerUp(e){if(this._drag&&(this._drag=null,e&&e.target&&e.target.releasePointerCapture&&e.pointerId!==void 0))try{e.target.releasePointerCapture(e.pointerId)}catch{}},_aspectRatio(){switch(this.aspect){case`1:1`:return 1;case`16:9`:return 9/16;case`4:3`:return 3/4;case`original`:return this.naturalW>0&&this.naturalH>0?this.naturalH/this.naturalW:null;default:return null}},applyAspect(){let e=this._aspectRatio();if(!e||!this.hasSelection())return;let t=this.rect.x+this.rect.width/2,n=this.rect.y+this.rect.height/2,r=this.rect.width,i=this.rect.height/e,a=Math.max(r,i),o=Math.round(a),s=Math.round(a*e);this.rect={x:Math.round(t-o/2),y:Math.round(n-s/2),width:o,height:s},this.clampRect()},clampRect(e=`auto`){if(!this.naturalW||!this.naturalH)return;let{x:t,y:n,width:r,height:i}=this.rect;t=Math.max(0,Math.min(this.naturalW-1,Math.floor(t||0))),n=Math.max(0,Math.min(this.naturalH-1,Math.floor(n||0))),r=Math.max(0,Math.floor(r||0)),i=Math.max(0,Math.floor(i||0));let a=this._aspectRatio();if(a&&r>0&&i>0){let o=Math.max(0,this.naturalW-t),s=Math.max(0,this.naturalH-n);if(e===`h`){let e=o*a;i=Math.floor(Math.min(i,s,e)),r=Math.floor(i/a)}else{let e=s/a;r=Math.floor(Math.min(r,o,e)),i=Math.floor(r*a)}}else t+r>this.naturalW&&(r=this.naturalW-t),n+i>this.naturalH&&(i=this.naturalH-n);this.rect={x:t,y:n,width:r,height:i}},hasSelection(){return this.rect.width>0&&this.rect.height>0},selectionStyle(){let e=this._imageRect();if(!e||!this.naturalW||!this.naturalH)return`display: none`;let t=e.width/this.naturalW,n=e.height/this.naturalH;return`left: ${this.rect.x*t}px; top: ${this.rect.y*n}px; width: ${this.rect.width*t}px; height: ${this.rect.height*n}px; outline: 2px dashed #fff; box-shadow: 0 0 0 2px rgba(0,0,0,0.6); background: rgba(255,255,255,0.1);`},async submit(){if(!this.isSubmitting&&!(this.decodeFailed||!this.naturalW||!this.naturalH)){if(!this.hasSelection()){this.errorMessage=`Select a crop area first.`;return}this.errorMessage=``,this.isSubmitting=!0;try{let e=new URLSearchParams;e.set(`id`,String(this.resourceId)),e.set(`x`,String(this.rect.x)),e.set(`y`,String(this.rect.y)),e.set(`width`,String(this.rect.width)),e.set(`height`,String(this.rect.height)),this.comment&&this.comment.trim()&&e.set(`comment`,this.comment.trim());let t=await fetch(`/v1/resources/crop`,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`,Accept:`application/json`},body:e.toString()});if(!t.ok){let e=`Crop failed (HTTP ${t.status})`;try{let n=await t.text();n&&(e=n)}catch{}this.errorMessage=e,this.isSubmitting=!1;return}window.location.reload()}catch(e){this.errorMessage=e&&e.message?e.message:`Crop failed.`,this.isSubmitting=!1}}},close(){let e=this.$root;e&&typeof e.close==`function`&&e.close()},reset(){this.rect={x:0,y:0,width:0,height:0},this.aspect=`free`,this.comment=``,this.errorMessage=``,this.isSubmitting=!1,this._drag=null}}}function cc({leftUrl:t=null,rightUrl:n=null,leftText:r=null,rightText:i=null}){return{mode:`unified`,loading:!0,error:null,leftText:r??``,rightText:i??``,unifiedDiff:[],splitLeft:[],splitRight:[],stats:{added:0,removed:0},async init(){try{if(r!==null&&i!==null){this.computeDiff();return}let[e,a]=await Promise.all([fetch(t),fetch(n)]);if(!e.ok||!a.ok)throw Error(`Failed to load files`);this.leftText=await e.text(),this.rightText=await a.text(),this.computeDiff()}catch(e){this.error=e.message}finally{this.loading=!1}},computeDiff(){let t=e(this.leftText,this.rightText);this.unifiedDiff=[],this.splitLeft=[],this.splitRight=[];let n=0,r=0,i=0,a=0;for(let e of t){let t=e.value.split(` + }`),t.setAttribute(`x-show`,`$store.bulkSelection.isActiveEditor($el)`),t.setAttribute(`x-collapse`,``),t.setAttribute(`:class`,`$store.bulkSelection.isActiveEditor($el) && 'active'`),t.insertAdjacentElement(`beforebegin`,n),this.editors.push(t),!t.classList.contains(`no-ajax`)&&t.addEventListener(`submit`,async n=>{n.preventDefault();try{t.parentElement.classList.add(`pointer-events-none`);let n=await fetch(t.action,{method:`POST`,body:new FormData(t)});if(!n.ok)throw Error(`Server error: ${n.status}`);let r=new URL(window.location);r.pathname+=`.body`;let i=await fetch(r.toString()).then(e=>e.text());t.reset(),this.deselectAll(),e.morph(document.querySelector(`.list-container, .items-container`),i),this.announce(`Bulk operation completed successfully`)}catch(e){this.announce(`Bulk operation failed: ${e.message}`),alert(`Bulk operation failed: ${e.message}`)}finally{t.parentElement.classList.remove(`pointer-events-none`)}})}})}function os(){return{init(){this.$root.querySelectorAll(`form`).forEach(e=>this.$store.bulkSelection.registerForm(e))}}}function ss({itemNo:e,itemId:t}={}){return{init(){let n=this.$root.querySelector(`input[type='checkbox']`);this.$store.bulkSelection.registerOption({itemNo:e,itemId:t,el:n})},selected(){return this.$store.bulkSelection.isSelected(t)},events:{"@click"(e){if(e.shiftKey){this.$store.bulkSelection.selectUntil(t);return}this.$store.bulkSelection.toggle(t)},"@contextmenu"(e){e.preventDefault(),this.$store.bulkSelection.selectUntil(t)},"@keydown.space.prevent"(){this.$store.bulkSelection.toggle(t)},"@keydown.enter.prevent"(){this.$store.bulkSelection.toggle(t)}}}}function cs(){document.addEventListener(`keypress`,function(e){if(e.key!==` `)return;let t=new Set,n=window.getSelection(),r=n.rangeCount;if(n.type===`Range`){e.preventDefault();for(let e=0;e{e.addEventListener(`click`,async function(t){if(!t.target.classList.contains(`edit-in-list`))return;t.preventDefault();let n=t.target.dataset.entityType,r=t.target.closest(`[x-data]`),i=[];if(r&&window.Alpine){let e=window.Alpine.$data(r);e?.entity?.Tags&&(i=e.entity.Tags)}let a=await(async function(){let e=new URL(`${window.location.origin}/partials/autocompleter`);return e.searchParams.append(`selectedItems`,JSON.stringify(i)),e.searchParams.append(`title`,`Edit tags`),e.searchParams.append(`sortBy`,`most_used_${n}`),e.searchParams.append(`id`,`tagEditor_${Math.random()}`),e.searchParams.append(`elName`,`editedId`),e.searchParams.append(`url`,`/v1/tags`),e.searchParams.append(`addUrl`,`/v1/tag`),fetch(e.toString()).then(e=>e.text())})(),o=document.createElement(`form`);o.dataset.inlineEditor=`true`,o.addEventListener(`submit`,e=>{e.preventDefault()}),o.addEventListener(`multiple-input`,e=>{fetch(`/v1/`+n+`s/replaceTags`,{method:`POST`,body:new FormData(o)})}),o.className=`mb-6 p-4 active`;let s=document.createElement(`input`);s.setAttribute(`:value`,`entity.ID`),s.name=`ID`,s.type=`hidden`;let c=new DOMParser().parseFromString(a,`text/html`);o.replaceChildren(...c.body.childNodes),o.appendChild(s),e.innerHTML=``,e.appendChild(o),window.Alpine.initTree(o),setTimeout(()=>o.querySelector(`[x-ref='autocompleter']`)?.focus(),10)})})}function ls(e){try{return JSON.parse(e||`{}`)}catch{return{}}}function us(e){e.store(`savedSetting`,{sessionSettings:ls(sessionStorage.getItem(`settings`)),localSettings:ls(localStorage.getItem(`settings`)),registerEl(e,t=!0,n=!0){let r=t?this.localSettings:this.sessionSettings,i=t?localStorage:sessionStorage;e.checked===void 0?e.value=r[e.name]??n:So(e,(r[e.name]??n)?.toString()===`true`),e.addEventListener(`change`,()=>{let t=e.checked??e.value;r[e.name]=t,i.setItem(`settings`,JSON.stringify(r))})}})}var N=new Map,ds=3e4,fs=50;function ps(e){let t=e.toLowerCase(),n=N.get(t);return n&&Date.now()-n.timestamp=fs){let e=N.keys().next().value;N.delete(e)}N.set(n,{results:t,timestamp:Date.now()})}function hs(){return{isOpen:!1,query:``,results:[],selectedIndex:0,loading:!1,requestAborter:null,debounceTimer:null,_liveRegion:null,typeIcons:{resource:`๐Ÿ“„`,note:`๐Ÿ“`,group:`๐Ÿ‘ฅ`,tag:`๐Ÿท`,category:`๐Ÿ“`,resourceCategory:`๐Ÿ“‚`,query:`๐Ÿ”`,relationType:`๐Ÿ”—`,noteType:`๐Ÿ“‹`},typeLabels:{resource:`Resource`,note:`Note`,group:`Group`,tag:`Tag`,category:`Category`,resourceCategory:`Resource Category`,query:`Query`,relationType:`Relation Type`,noteType:`Note Type`},init(){this._liveRegion=Go(),this._keydownHandler=e=>{(e.metaKey||e.ctrlKey)&&e.key===`k`&&(e.preventDefault(),this.toggle())},document.addEventListener(`keydown`,this._keydownHandler),this.$watch(`isOpen`,e=>{e&&(this.$nextTick(()=>{this.$refs.searchInput?.focus()}),this.announce(`Search dialog opened. Type to search resources, notes, groups, and tags.`))})},announce(e){this._liveRegion?.announce(e)},destroy(){this._liveRegion?.destroy(),this._keydownHandler&&document.removeEventListener(`keydown`,this._keydownHandler),this.debounceTimer&&clearTimeout(this.debounceTimer),this.requestAborter&&=(this.requestAborter(),null)},toggle(){this.isOpen=!this.isOpen,this.isOpen&&(this.query=``,this.results=[],this.selectedIndex=0)},close(){this.isOpen=!1,this.query=``,this.results=[]},search(){this.debounceTimer&&clearTimeout(this.debounceTimer),this.requestAborter&&=(this.requestAborter(),null);let e=this.query.trim();if(e.length<2){this.results=[];return}let t=ps(e);if(t){this.results=t,this.selectedIndex=0,this.results.length>0?this.announce(`${this.results.length} result${this.results.length===1?``:`s`} found. Use arrow keys to navigate.`):this.announce(`No results found.`);return}let n=e.length<3?300:150;this.debounceTimer=setTimeout(()=>{this.loading=!0;let{abort:t,ready:n}=M(`/v1/search?q=${encodeURIComponent(e)}&limit=15`);this.requestAborter=t,n.then(e=>e.json()).then(t=>{this.query.trim()===e&&(this.results=t.results||[],this.selectedIndex=0,ms(e,this.results),this.results.length>0?this.announce(`${this.results.length} result${this.results.length===1?``:`s`} found. Use arrow keys to navigate.`):this.announce(`No results found.`))}).catch(e=>{e.name!==`AbortError`&&console.error(`Search error:`,e)}).finally(()=>{this.loading=!1})},n)},navigateUp(){this.results.length!==0&&(this.selectedIndex=this.selectedIndex===0?this.results.length-1:this.selectedIndex-1,this.scrollToSelected(),this.announceSelectedResult())},navigateDown(){this.results.length!==0&&(this.selectedIndex=(this.selectedIndex+1)%this.results.length,this.scrollToSelected(),this.announceSelectedResult())},announceSelectedResult(){let e=this.results[this.selectedIndex];if(e){let t=this.getLabel(e.type);this.announce(`${e.name}, ${t}, ${this.selectedIndex+1} of ${this.results.length}`)}},scrollToSelected(){this.$nextTick(()=>{let e=this.$refs.resultsList?.querySelector(`[data-selected="true"]`);e&&e.scrollIntoView({block:`nearest`})})},selectResult(){let e=this.results[this.selectedIndex];e&&this.navigateTo(e.url)},navigateTo(e){if(e&&(e.startsWith(`/`)||e.startsWith(`?`)||e.startsWith(`#`)))this.close(),window.location.href=e;else try{new URL(e,window.location.origin).origin===window.location.origin&&(this.close(),window.location.href=e)}catch{}},getIcon(e){return this.typeIcons[e]||`๐Ÿ“Œ`},getLabel(e){return this.typeLabels[e]||e},highlightMatch(e,t){if(!e||!t)return e;let n=this.escapeHTML(e),r=this.escapeHTML(t),i=RegExp(`(${this.escapeRegex(r)})`,`gi`);return n.replace(i,`$1`)},escapeHTML(e){let t=document.createElement(`div`);return t.textContent=e,t.innerHTML},escapeRegex(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}}}var gs={isOpen:!1,currentIndex:0,items:[],loading:!1,pageLoading:!1,currentPage:1,hasNextPage:!1,hasPrevPage:!1,baseUrl:``,pageSize:50,loadedPages:new Set,requestAborter:null,triggerElement:null,_preloadedUrls:new Set,_preloadedImages:[],_preloadAheadCount:5},_s={_extractItemsFromLinks(e){return Array.from(e).map(e=>{let t=e.dataset.resourceHash||``,n=t?`&v=${t}`:``;return{id:parseInt(e.dataset.resourceId,10),viewUrl:`/v1/resource/view?id=${e.dataset.resourceId}${n}`,contentType:e.dataset.contentType||``,name:e.dataset.resourceName||e.querySelector(`img`)?.alt||``,hash:t,width:parseInt(e.dataset.resourceWidth,10)||0,height:parseInt(e.dataset.resourceHeight,10)||0,ownerName:e.dataset.ownerName||``,ownerId:parseInt(e.dataset.ownerId,10)||0}}).filter(e=>e.contentType?.startsWith(`image/`)||e.contentType?.startsWith(`video/`))},initFromDOM(){let e=document.querySelectorAll(`.list-container, .gallery, .dashboard-grid`);if(e.length===0)return;let t=[];e.forEach(e=>{let n=e.querySelectorAll(`[data-lightbox-item]`);t.push(...this._extractItemsFromLinks(n))}),this.items=t;let n=new URLSearchParams(window.location.search);this.currentPage=parseInt(n.get(`page`),10)||1,this.baseUrl=window.location.pathname+window.location.search;let r=document.querySelector(`nav[aria-label="Pagination"]`);r?(this.hasNextPage=r.dataset.hasNext===`true`,this.hasPrevPage=r.dataset.hasPrev===`true`):(this.hasPrevPage=this.currentPage>1,this.hasNextPage=!1),this.loadedPages.add(this.currentPage);let i=e[0].dataset.pageSize;i?this.pageSize=parseInt(i,10)||50:window.location.pathname.includes(`/simple`)&&(this.pageSize=200)},openFromClick(e,t,n){if(!n?.startsWith(`image/`)&&!n?.startsWith(`video/`)){window.location.href=e.currentTarget.href;return}e.preventDefault(),this.triggerElement=e.currentTarget;let r=e.currentTarget.closest(`[data-lightbox-source]`);if(r){this._openFromSourceContainer(r,t);return}let i=this.items.findIndex(e=>e.id===t);i!==-1&&this.open(i)},_openFromSourceContainer(e,t){let n=e.querySelectorAll(`[data-lightbox-item]`),r=this._extractItemsFromLinks(n);if(r.length===0)return;let i=e.dataset.lightboxSource,a=e.dataset.lightboxParamName,o=e.dataset.lightboxParamValue,s=new URL(i,window.location.origin);s.searchParams.set(a,o),this.items=r,this.baseUrl=s.pathname+s.search,this.currentPage=1,this.loadedPages=new Set([1]),this.pageSize=50,this.hasNextPage=r.length>=5,this.hasPrevPage=!1;let c=r.findIndex(e=>e.id===t);c!==-1&&this.open(c)},open(e){this._savedScrollY=window.scrollY,document.body.style.position=`fixed`,document.body.style.top=`-${this._savedScrollY}px`,document.body.style.left=`0`,document.body.style.right=`0`,document.body.style.overflow=`hidden`,this.currentIndex=e,this.isOpen=!0,this.loading=!0,document.activeElement&&document.activeElement!==document.body&&document.activeElement.blur();let t=this.getCurrentItem(),n=this.isVideo(t?.contentType)?`video`:this.isSvg(t?.contentType)?`SVG`:`image`;this.announce(`Opened ${n}: ${t?.name||`media`}. ${this.currentIndex+1} of ${this.items.length}`),this.scheduleMediaCheck(),this._preloadUpcoming(),this.quickTagPanelOpen&&this.fetchResourceDetails()},_preloadUpcoming(){let e=this._preloadAheadCount||5,t=Math.min(this.items.length,this.currentIndex+1+e);for(let e=this.currentIndex+1;en&&this._preloadedImages.splice(0,this._preloadedImages.length-n)},close(){this.pauseCurrentVideo(),this.isFullscreen&&=(document.exitFullscreen?document.exitFullscreen().catch(()=>{}):document.webkitExitFullscreen&&document.webkitExitFullscreen(),!1),this.editPanelOpen&&this.closeEditPanel(),this.quickTagPanelOpen&&this.closeQuickTagPanel(),this.isOpen=!1,this.loading=!1,this.resetZoom();let e=this._savedScrollY;document.body.style.position=``,document.body.style.top=``,document.body.style.left=``,document.body.style.right=``,document.body.style.overflow=``,window.scrollTo(0,e),this.requestAborter&&=(this.requestAborter(),null),this.triggerElement&&=(this.triggerElement.focus({preventScroll:!0}),null),this.announce(`Media viewer closed`),requestAnimationFrame(()=>{window.scrollTo(0,e)})},async next(){this.pageLoading||(this.pauseCurrentVideo(),this.resetZoom(),this.currentIndex0)this.currentIndex--,this.loading=!0,this.announcePosition(),this.scheduleMediaCheck(),this._preloadUpcoming(),this.onResourceChange();else if(this.hasPrevPage){let e=await this.loadPrevPage();e>0&&(this.currentIndex=e-1,this.loading=!0,this.announcePosition(),this.scheduleMediaCheck(),this._preloadUpcoming(),this.onResourceChange())}}},announcePosition(){let e=this.getCurrentItem();this.announce(`${e?.name||`Media`}, ${this.currentIndex+1} of ${this.items.length}`)},async loadNextPage(){let e=this.currentPage+1;if(this.loadedPages.has(e)){this.currentPage=e;return}this.pageLoading=!0,this.announce(`Loading more items...`);try{let{items:t,hasNextPage:n}=await this.fetchPage(e);if(t.length===0){this.hasNextPage=!1,this.announce(`No more items`);return}this.items=[...this.items,...t],this.loadedPages.add(e),this.currentPage=e,this.hasNextPage=n,this.announce(`Loaded ${t.length} more items`)}catch(e){e.name!==`AbortError`&&(console.error(`Failed to load next page:`,e),this.announce(`Failed to load more items`))}finally{this.pageLoading=!1}},async loadPrevPage(){if(this.currentPage<=1)return 0;let e=this.currentPage-1;if(this.loadedPages.has(e))return this.currentPage=e,this.hasPrevPage=e>1,0;this.pageLoading=!0,this.announce(`Loading previous items...`);try{let{items:t}=await this.fetchPage(e),n=t.length;return this.items=[...t,...this.items],this.currentIndex+=n,this.loadedPages.add(e),this.hasPrevPage=e>1,this.announce(`Loaded ${n} previous items`),n}catch(e){return e.name!==`AbortError`&&(console.error(`Failed to load previous page:`,e),this.announce(`Failed to load previous items`)),0}finally{this.pageLoading=!1}},async fetchPage(e){this.requestAborter&&this.requestAborter();let t=new URL(this.baseUrl,window.location.origin);t.searchParams.set(`page`,e);let{abort:n,ready:r}=M(t.pathname+`.json`+t.search);this.requestAborter=n;let i=await r;if(!i.ok)throw Error(`Failed to fetch page: ${i.status}`);let a=await i.json();this.requestAborter=null;let o=a.resources||[],s=(a.pagination||{}).NextLink?.Selected===!0;return{items:o.filter(e=>e.ContentType?.startsWith(`image/`)||e.ContentType?.startsWith(`video/`)).map(e=>{let t=e.Hash?`&v=${e.Hash}`:``;return{id:e.ID,viewUrl:`/v1/resource/view?id=${e.ID}${t}`,contentType:e.ContentType,name:e.Name||``,hash:e.Hash||``,width:e.Width||0,height:e.Height||0,ownerName:e.Owner?.Name||``,ownerId:e.Owner?.ID||0}}),hasNextPage:s}},isImage(e){return e?.startsWith(`image/`)&&!this.isSvg(e)},isSvg(e){return e===`image/svg+xml`},isVideo(e){return e?.startsWith(`video/`)},getCurrentItem(){return this.items[this.currentIndex]},onMediaLoaded(){this.loading=!1},checkIfMediaLoaded(e){if(e){if(e.tagName===`IMG`&&e.complete&&(this.isSvg(this.getCurrentItem()?.contentType)||e.naturalWidth>0)){this.loading=!1;return}if(e.tagName===`OBJECT`&&e.contentDocument){this.loading=!1;return}e.tagName===`VIDEO`&&e.readyState>=3&&(this.loading=!1)}},scheduleMediaCheck(){requestAnimationFrame(()=>{requestAnimationFrame(()=>{let e=document.querySelector(`[role="dialog"] img, [role="dialog"] video, [role="dialog"] object`);e&&this.checkIfMediaLoaded(e)})})},restartVideo(){let e=document.querySelector(`[role="dialog"] video`);e&&(e.currentTime=0,e.play())},pauseCurrentVideo(){let e=document.querySelector(`[x-show="$store.lightbox.isOpen"] video`);e&&!e.paused&&e.pause()}},vs={isFullscreen:!1,zoomLevel:1,minZoom:1,maxZoom:5,panX:0,panY:0,imageRect:null,containerRect:null,animationsDisabled:!1,animationTimeout:null},ys={fullscreenSupported(){return!!(document.fullscreenEnabled||document.webkitFullscreenEnabled)},async toggleFullscreen(){if(!this.fullscreenSupported())return;let e=document.querySelector(`[role="dialog"][aria-modal="true"]`);if(e)try{this.isFullscreen?document.exitFullscreen?await document.exitFullscreen():document.webkitExitFullscreen&&await document.webkitExitFullscreen():e.requestFullscreen?await e.requestFullscreen():e.webkitRequestFullscreen&&await e.webkitRequestFullscreen()}catch(e){console.error(`Fullscreen toggle failed:`,e)}},isZoomed(){return this.zoomLevel>1},setZoomLevel(e){let t=this.zoomLevel;this.zoomLevel=Math.max(this.minZoom,Math.min(this.maxZoom,e)),this.zoomLevel!==t&&this.zoomLevel===1&&(this.panX=0,this.panY=0)},resetZoom(){this.zoomLevel=1,this.panX=0,this.panY=0,this.hideZoomPresets()},hideZoomPresets(){let e=document.getElementById(`zoom-preset-popover`);e?.matches(`:popover-open`)&&e.hidePopover()},showZoomPresets(e){let t=document.getElementById(`zoom-preset-popover`);if(!t)return;if(t.matches(`:popover-open`)){t.hidePopover();return}let n=this.zoomPresets();if(!n.length)return;let r=this;t.innerHTML=``,Object.assign(t.style,{background:`rgba(0,0,0,0.8)`,backdropFilter:`blur(8px)`,border:`1px solid rgba(255,255,255,0.1)`,borderRadius:`0.375rem`,padding:`0.25rem 0`,margin:`0`,minWidth:`7rem`,textAlign:`center`,color:`white`,fontSize:`0.875rem`});for(let e of n){let n=document.createElement(`button`);n.textContent=e.label,n.style.cssText=`display:block;width:100%;padding:0.375rem 0.75rem;transition:background 150ms;font-variant-numeric:tabular-nums;background:none;border:none;color:inherit;cursor:pointer;font-size:inherit;`,n.addEventListener(`mouseenter`,()=>n.style.background=`rgba(255,255,255,0.2)`),n.addEventListener(`mouseleave`,()=>n.style.background=`none`),n.addEventListener(`click`,t=>{t.stopPropagation(),r.setNativeZoom(e.nativePct)}),t.appendChild(n)}let i=e.getBoundingClientRect();t.showPopover();let a=t.getBoundingClientRect();t.style.position=`fixed`,t.style.left=i.left+i.width/2-a.width/2+`px`,t.style.top=i.top-a.height-4+`px`,t.style.bottom=`auto`,t.style.right=`auto`},announceZoom(){this.zoomLevel===1?this.announce(`Zoom reset to 100%`):this.announce(`Zoomed to ${Math.round(this.zoomLevel*100)}%`)},nativeZoomPercent(){let e=this.loading,t=this.zoomLevel,n=this.getCurrentItem();if(!n||this.isVideo(n.contentType)||e)return null;let r=this.getMediaElement();if(!r)return null;let i=r.element,a=i.naturalWidth,o=i.clientWidth;if(!a||!o)return null;let s=t*o/a*100;return Math.round(s)+`%`},zoomPresets(){let e=this.getMediaElement();if(!e)return[];let t=e.element,n=t.naturalWidth,r=t.clientWidth,i=t.clientHeight;if(!n||!r)return[];let a=Math.round(r/n*100),o=[25,50,100,200,300,500],s=[{label:`Fit (`+a+`%)`,nativePct:null}],c=window.innerWidth*.9,l=window.innerHeight*.9;if(r&&i){let e=Math.min(c/r,l/i);if(e>1.01&&e<=this.maxZoom){let t=Math.round(e*r/n*100);s.push({label:`Stretch (`+t+`%)`,nativePct:`stretch`})}}for(let e of o){let t=e/100*(n/r);t>=this.minZoom&&t<=this.maxZoom&&e!==a&&s.push({label:e+`%`,nativePct:e})}return s},setNativeZoom(e){if(this.hideZoomPresets(),e===null){this.setZoomLevel(1),this.announceZoom();return}let t=this.getMediaElement();if(!t)return;let n=t.element,r=n.clientWidth,i=n.clientHeight;if(!r||!i)return;let a;if(e===`stretch`){let e=window.innerWidth*.9,t=window.innerHeight*.9;a=Math.min(e/r,t/i)}else{let t=n.naturalWidth;if(!t)return;a=e/100*(t/r)}this.panX=0,this.panY=0,this.setZoomLevel(a),this.constrainPan(),this.announceZoom()},getMediaElement(){let e=document.querySelector(`[role="dialog"] img, [role="dialog"] object`);return e?{element:e,rect:e.getBoundingClientRect()}:null},getContainerRect(){return document.querySelector(`[role="dialog"] .relative.max-h-\\[90vh\\]`)?.getBoundingClientRect()||null},constrainPan(){if(this.zoomLevel<=1){this.panX=0,this.panY=0;return}let e=this.getMediaElement(),t=this.getContainerRect();if(!e||!t)return;let n=e.element,r=n.clientWidth,i=n.clientHeight,a=r*this.zoomLevel,o=i*this.zoomLevel,s=Math.max(0,(a-t.width)/2/this.zoomLevel),c=Math.max(0,(o-t.height)/2/this.zoomLevel);this.panX=Math.max(-s,Math.min(s,this.panX)),this.panY=Math.max(-c,Math.min(c,this.panY))},disableAnimations(){this.animationsDisabled=!0,this.animationTimeout&&clearTimeout(this.animationTimeout),this.animationTimeout=setTimeout(()=>{this.animationsDisabled=!1,this.animationTimeout=null},100)}},bs={touchStartX:null,touchStartY:null,pinchStartDistance:null,pinchStartZoom:null,pinchStartCenterX:null,pinchStartCenterY:null,pinchCenterX:null,pinchCenterY:null,pinchOriginX:null,pinchOriginY:null,pinchImageX:null,pinchImageY:null,isDragging:!1,dragStartX:null,dragStartY:null,dragStartPanX:null,dragStartPanY:null,dragVelocityX:0,dragVelocityY:0,lastDragTime:null,lastDragX:null,lastDragY:null,_navDebounce:!1,_wheelDebounceTimer:null,_wheelNavDirection:0,_wheelNavTime:0,_prevWheelAbsDelta:0,_wheelIncreaseCount:0},xs={getPinchDistance(e){let t=e[0].clientX-e[1].clientX,n=e[0].clientY-e[1].clientY;return Math.sqrt(t*t+n*n)},getPinchCenter(e){return{x:(e[0].clientX+e[1].clientX)/2,y:(e[0].clientY+e[1].clientY)/2}},handleTouchStart(e){if(e.target.closest(`[data-edit-panel]`)){this.touchStartX=null;return}if(e.touches.length===2){e.preventDefault(),this.pinchStartDistance=this.getPinchDistance(e.touches),this.pinchStartZoom=this.zoomLevel;let t=this.getPinchCenter(e.touches);this.pinchStartCenterX=t.x,this.pinchStartCenterY=t.y,this.pinchCenterX=t.x,this.pinchCenterY=t.y;let n=this.getMediaElement();if(n){let e=n.rect,r=e.left+e.width/2,i=e.top+e.height/2;this.pinchOriginX=r-this.zoomLevel*this.panX,this.pinchOriginY=i-this.zoomLevel*this.panY,this.pinchImageX=(t.x-this.pinchOriginX)/this.zoomLevel-this.panX,this.pinchImageY=(t.y-this.pinchOriginY)/this.zoomLevel-this.panY}else this.pinchOriginX=null,this.pinchOriginY=null,this.pinchImageX=null,this.pinchImageY=null}else e.touches.length===1&&(this.touchStartX=e.touches[0].clientX,this.touchStartY=e.touches[0].clientY,this.isZoomed()&&(this.dragStartPanX=this.panX,this.dragStartPanY=this.panY))},handleTouchMove(e){if(!this.isVideo(this.getCurrentItem()?.contentType)){if(e.touches.length===2){e.preventDefault();let t=this.getPinchCenter(e.touches);if(this.pinchStartDistance!==null){this.disableAnimations();let n=this.getPinchDistance(e.touches)/this.pinchStartDistance;this.setZoomLevel(this.pinchStartZoom*n),this.pinchOriginX!==null&&(this.panX=(t.x-this.pinchOriginX)/this.zoomLevel-this.pinchImageX,this.panY=(t.y-this.pinchOriginY)/this.zoomLevel-this.pinchImageY,this.constrainPan()),this.pinchCenterX=t.x,this.pinchCenterY=t.y}}else if(e.touches.length===1&&this.isZoomed()&&this.touchStartX!==null){e.preventDefault(),this.disableAnimations();let t=e.touches[0].clientX-this.touchStartX,n=e.touches[0].clientY-this.touchStartY;this.panX=(this.dragStartPanX||0)+t/this.zoomLevel,this.panY=(this.dragStartPanY||0)+n/this.zoomLevel,this.constrainPan()}}},handleTouchEnd(e){if(this.pinchStartDistance!==null){if(this.zoomLevel50&&!this._navDebounce&&(this._navDebounce=!0,setTimeout(()=>{this._navDebounce=!1},300),e>0?this.next():this.prev())}this.pinchStartDistance=null,this.pinchStartZoom=null,this.pinchStartCenterX=null,this.pinchStartCenterY=null,this.pinchCenterX=null,this.pinchCenterY=null,this.pinchOriginX=null,this.pinchOriginY=null,this.pinchImageX=null,this.pinchImageY=null,this.announceZoom();return}if(this.touchStartX===null)return;let t=e.changedTouches[0].clientX,n=e.changedTouches[0].clientY,r=this.touchStartX-t,i=this.touchStartY-n;if(Math.abs(r)>Math.abs(i)&&Math.abs(r)>50&&!this.isZoomed()){if(this._navDebounce)return;this._navDebounce=!0,setTimeout(()=>{this._navDebounce=!1},300),r>0?this.next():this.prev()}this.touchStartX=null,this.touchStartY=null},handleWheel(e){if(!this.isVideo(this.getCurrentItem()?.contentType)){if(e.ctrlKey){e.preventDefault(),this.disableAnimations();let t=this.getMediaElement(),n=this.zoomLevel,r=this.panX,i=this.panY,a=1.002**-e.deltaY;this.setZoomLevel(this.zoomLevel*a);let o=this.zoomLevel;if(o!==n&&t){let a=t.rect,s=a.left+a.width/2,c=a.top+a.height/2,l=s-n*r,u=c-n*i,d=e.clientX-l,f=e.clientY-u;this.panX=r+d*(1/o-1/n),this.panY=i+f*(1/o-1/n),this.constrainPan()}this._zoomAnnounceDebounce||(this._zoomAnnounceDebounce=!0,setTimeout(()=>{this.announceZoom(),this._zoomAnnounceDebounce=!1},500));return}if(this.isZoomed())e.preventDefault(),this.disableAnimations(),this.panX-=e.deltaX/this.zoomLevel,this.panY-=e.deltaY/this.zoomLevel,this.constrainPan();else{let t=Math.abs(e.deltaX),n=Math.abs(e.deltaY)>t?e.deltaY:e.deltaX,r=Math.abs(n);if(r>10){if(e.preventDefault(),this._wheelDebounce){let e=Math.sign(n)!==this._wheelNavDirection,t=performance.now()-this._wheelNavTime;if(r>this._prevWheelAbsDelta?this._wheelIncreaseCount++:this._wheelIncreaseCount=0,this._prevWheelAbsDelta=r,e||t>150&&this._wheelIncreaseCount>=3)clearTimeout(this._wheelDebounceTimer),this._wheelDebounce=!1,this._navDebounce=!1;else{clearTimeout(this._wheelDebounceTimer),this._wheelDebounceTimer=setTimeout(()=>{this._wheelDebounce=!1,this._navDebounce=!1,this._wheelIncreaseCount=0,this._prevWheelAbsDelta=0},300);return}}if(this._navDebounce)return;this._wheelDebounce=!0,this._navDebounce=!0,this._wheelNavDirection=Math.sign(n),this._wheelNavTime=performance.now(),this._prevWheelAbsDelta=r,this._wheelIncreaseCount=0,this._wheelDebounceTimer=setTimeout(()=>{this._wheelDebounce=!1,this._navDebounce=!1,this._wheelIncreaseCount=0,this._prevWheelAbsDelta=0},300),n>0?this.next():this.prev()}}}},handleDoubleClick(e){if(!this.isVideo(this.getCurrentItem()?.contentType))if(e.preventDefault(),this.zoomLevel===1){let t=this.getMediaElement();if(!t)return;let n=t.element,r=n.clientWidth,i=n.clientHeight,a=n.naturalWidth||r,o=n.naturalHeight||i,s=Math.max(a/r,o/i),c=Math.max(this.minZoom+.01,Math.min(this.maxZoom,s)),l=t.rect,u=e.clientX-(l.left+l.width/2),d=e.clientY-(l.top+l.height/2);this.panX=-u,this.panY=-d,this.setZoomLevel(c),this.constrainPan(),this.announceZoom()}else this.setZoomLevel(1),this.announceZoom()},handleMouseDown(e){this.isVideo(this.getCurrentItem()?.contentType)||e.target.closest(`button`)||e.target.closest(`[data-edit-panel]`)||(e.preventDefault(),this.isDragging=!0,this.dragStartX=e.clientX,this.dragStartY=e.clientY,this.dragStartPanX=this.panX,this.dragStartPanY=this.panY,this.lastDragX=e.clientX,this.lastDragY=e.clientY,this.lastDragTime=performance.now(),this.dragVelocityX=0,this.dragVelocityY=0)},handleMouseMove(e){if(!this.isDragging)return;let t=performance.now(),n=t-this.lastDragTime;if(n>0&&(this.dragVelocityX=(e.clientX-this.lastDragX)/n,this.dragVelocityY=(e.clientY-this.lastDragY)/n),this.lastDragX=e.clientX,this.lastDragY=e.clientY,this.lastDragTime=t,this.isZoomed()){this.disableAnimations();let t=e.clientX-this.dragStartX,n=e.clientY-this.dragStartY;this.panX=this.dragStartPanX+t/this.zoomLevel,this.panY=this.dragStartPanY+n/this.zoomLevel,this.constrainPan()}},handleMouseUp(e){if(!this.isDragging)return;let t=e.clientX-this.dragStartX,n=e.clientY-this.dragStartY,r=Math.sqrt(t*t+n*n),i=Math.sqrt(this.dragVelocityX**2+this.dragVelocityY**2);this.isDragging=!1,!this.isZoomed()&&Math.abs(this.dragVelocityX)>Math.abs(this.dragVelocityY)&&(i>.3||r>30)&&!this._navDebounce&&(this._navDebounce=!0,setTimeout(()=>{this._navDebounce=!1},300),t<0?this.next():t>0&&this.prev()),this.dragStartX=null,this.dragStartY=null;let a=document.querySelector(`[role="dialog"][aria-modal="true"]`);a&&a.focus()}},Ss={editPanelOpen:!1,resourceDetails:null,detailsLoading:!1,detailsCache:new Map,detailsAborter:null,_savingTagIds:new Set,needsRefreshOnClose:!1},Cs={handleEscape(){return this.close(),!0},async openEditPanel(){window.innerWidth<1024&&this.quickTagPanelOpen&&this.closeQuickTagPanel(),this.editPanelOpen=!0,this.announce(`Info panel opened`),await this.fetchResourceDetails(),requestAnimationFrame(()=>{let e=document.querySelector(`[data-edit-panel]`);if(e){let t=e.querySelector(`input, textarea`);t&&t.focus()}})},closeEditPanel(){this.editPanelOpen=!1,this.quickTagPanelOpen||(this.detailsAborter&&=(this.detailsAborter(),null),this.resourceDetails=null),!this.quickTagPanelOpen&&this.needsRefreshOnClose&&(this.needsRefreshOnClose=!1,this.refreshPageContent()),this.announce(`Info panel closed`)},formatBytes(e){let t=Number(e);if(!Number.isFinite(t)||t<=0)return``;let n=1024,r=[`B`,`KB`,`MB`,`GB`,`TB`],i=Math.min(r.length-1,Math.floor(Math.log(t)/Math.log(n)));return parseFloat((t/n**+i).toFixed(1))+` `+r[i]},formatDateTime(e){if(!e)return``;let t=e instanceof Date?e:new Date(e);if(Number.isNaN(t.getTime()))return``;try{return t.toLocaleString(void 0,{dateStyle:`medium`,timeStyle:`short`})}catch{return t.toLocaleString()}},async refreshPageContent(){let e=document.querySelector(`.list-container, .items-container`);if(e)try{let t=new URL(window.location);t.pathname+=`.body`;let n=await fetch(t.toString());if(!n.ok)return;let r=await n.text(),i=new DOMParser().parseFromString(r,`text/html`).querySelector(`.list-container, .items-container`);if(i&&window.Alpine){let t=window.scrollX,n=window.scrollY;window.Alpine.morph(e,i,{updating(e,t,n,r){e._x_dataStack&&(t._x_dataStack=e._x_dataStack)}}),window.scrollTo(t,n),this.updateItemsFromDOM()}}catch(e){console.error(`Failed to refresh page content:`,e)}},updateItemsFromDOM(){let e=document.querySelector(`.list-container, .gallery`);if(!e)return;let t=e.querySelectorAll(`[data-lightbox-item]`),n=new Map;t.forEach(e=>{let t=parseInt(e.dataset.resourceId,10),r=e.dataset.contentType||``;if(r.startsWith(`image/`)||r.startsWith(`video/`)){let i=e.dataset.resourceHash||``,a=i?`&v=${i}`:``;n.set(t,{id:t,viewUrl:`/v1/resource/view?id=${t}${a}`,contentType:r,name:e.dataset.resourceName||e.querySelector(`img`)?.alt||``,hash:i})}});for(let e=0;e100&&this.detailsCache.delete(this.detailsCache.keys().next().value),this.detailsLoading=!0,this.detailsAborter&&this.detailsAborter();try{let{abort:e,ready:n}=M(`/resource.json?id=${t}`);this.detailsAborter=e;let r=await n;if(!r.ok)throw Error(`Failed to fetch resource: ${r.status}`);let i=await r.json(),a=i.resource||i;this.getCurrentItem()?.id===t&&(this.resourceDetails=a,this.detailsCache.set(t,a)),this.detailsAborter=null}catch(e){e.name!==`AbortError`&&(console.error(`Failed to fetch resource details:`,e),this.announce(`Failed to load resource details`))}finally{this.detailsLoading=!1}},async onResourceChange(){if(!this.editPanelOpen&&!this.quickTagPanelOpen)return;let e=document.activeElement,t=document.querySelector(`[data-edit-panel]`),n=null;e&&t?.contains(e)&&(e.id?n=`#${e.id}`:e.matches(`input[placeholder]`)&&(n=`input[placeholder="${e.getAttribute(`placeholder`)}"]`)),this.resourceDetails=null;let r=this.getCurrentItem()?.id;r&&this.detailsCache.delete(r),await this.fetchResourceDetails(),n&&requestAnimationFrame(()=>{let e=document.querySelector(`[data-edit-panel] ${n}`);e&&e.focus()}),this.onQuickTagResourceChange()},async updateName(e){let t=this.getCurrentItem()?.id;if(!t||!this.resourceDetails)return;let n=this.resourceDetails.Name;if(e===n)return;this.resourceDetails.Name=e;let r=this.items[this.currentIndex];r&&(r.name=e);try{let n=new FormData;n.append(`Name`,e);let r=await fetch(`/v1/resource/editName?id=${t}`,{method:`POST`,body:n,headers:{Accept:`application/json`}});if(!r.ok)throw Error(`Failed to update name: ${r.status}`);this.detailsCache.set(t,{...this.resourceDetails}),this.needsRefreshOnClose=!0,this.announce(`Name updated`)}catch(e){console.error(`Failed to update name:`,e),this.resourceDetails.Name=n,r&&(r.name=n),this.announce(`Failed to update name`)}},async updateDescription(e){let t=this.getCurrentItem()?.id;if(!t||!this.resourceDetails)return;let n=this.resourceDetails.Description;if(e!==n){this.resourceDetails.Description=e;try{let n=new FormData;n.append(`Description`,e);let r=await fetch(`/v1/resource/editDescription?id=${t}`,{method:`POST`,body:n,headers:{Accept:`application/json`}});if(!r.ok)throw Error(`Failed to update description: ${r.status}`);this.detailsCache.set(t,{...this.resourceDetails}),this.needsRefreshOnClose=!0,this.announce(`Description updated`)}catch(e){console.error(`Failed to update description:`,e),this.resourceDetails.Description=n,this.announce(`Failed to update description`)}}},async saveTagAddition(e){let t=this.getCurrentItem()?.id;if(!(!t||this._savingTagIds.has(e.ID))){this._savingTagIds.add(e.ID),this.resourceDetails&&(this.resourceDetails.Tags||(this.resourceDetails.Tags=[]),this.resourceDetails.Tags.some(t=>t.ID===e.ID)||this.resourceDetails.Tags.push(e));try{let n=new FormData;n.append(`ID`,t),n.append(`EditedId`,e.ID);let r=await fetch(`/v1/resources/addTags`,{method:`POST`,body:n,headers:{Accept:`application/json`}});if(!r.ok)throw Error(`Failed to add tag: ${r.status}`);this.resourceDetails&&this.detailsCache.set(t,{...this.resourceDetails}),this.needsRefreshOnClose=!0,this.announce(`Added tag: ${e.Name}`),this.recordRecentTag(e)}catch(t){if(console.error(`Failed to add tag:`,t),this.resourceDetails?.Tags){let t=this.resourceDetails.Tags.findIndex(t=>t.ID===e.ID);t!==-1&&this.resourceDetails.Tags.splice(t,1)}throw this.announce(`Failed to add tag`),t}finally{this._savingTagIds.delete(e.ID)}}},async saveTagRemoval(e){let t=this.getCurrentItem()?.id;if(t){if(this.resourceDetails?.Tags){let t=this.resourceDetails.Tags.findIndex(t=>t.ID===e.ID);t!==-1&&this.resourceDetails.Tags.splice(t,1)}try{let n=new FormData;n.append(`ID`,t),n.append(`EditedId`,e.ID);let r=await fetch(`/v1/resources/removeTags`,{method:`POST`,body:n,headers:{Accept:`application/json`}});if(!r.ok)throw Error(`Failed to remove tag: ${r.status}`);this.resourceDetails&&this.detailsCache.set(t,{...this.resourceDetails}),this.needsRefreshOnClose=!0,this.announce(`Removed tag: ${e.Name}`)}catch(t){throw console.error(`Failed to remove tag:`,t),this.resourceDetails?.Tags&&this.resourceDetails.Tags.push(e),this.announce(`Failed to remove tag`),t}}},getCurrentTags(){return this.resourceDetails?.Tags||[]}},ws=`mahresources_quickTags`,Ts=[{name:`QUICK 1`,key:`Z`},{name:`QUICK 2`,key:`X`},{name:`QUICK 3`,key:`C`},{name:`QUICK 4`,key:`V`},{name:`RECENT`,key:`B`}];function Es(e,t){let n=(e||[]).slice(0,t);for(;n.length(e||[]).map(e=>e&&!Array.isArray(e)?[e]:e));t.quickSlots.length<4;)t.quickSlots.push(Array(9).fill(null));t.activeTab===3?t.activeTab=4:t.activeTab===4&&(t.activeTab=0),t.version=3}try{Array.isArray(t.quickSlots)&&(this.quickSlots=[Es(t.quickSlots[0],9),Es(t.quickSlots[1],9),Es(t.quickSlots[2],9),Es(t.quickSlots[3],9)])}catch(e){console.warn(`Failed to load quickSlots from storage:`,e)}typeof t.drawerOpen==`boolean`&&(this.quickTagPanelOpen=t.drawerOpen),typeof t.activeTab==`number`&&t.activeTab>=0&&t.activeTab<=4&&(this.activeTab=t.activeTab),Array.isArray(t.recentTags)&&(this.recentTags=Es(t.recentTags,9))}catch(e){console.warn(`Failed to load quick tags from storage:`,e)}},_saveQuickTagsToStorage(){let e=JSON.stringify({version:3,quickSlots:this.quickSlots,drawerOpen:this.quickTagPanelOpen,activeTab:this.activeTab,recentTags:this.recentTags});try{localStorage.setItem(ws,e)}catch(t){console.warn(`Failed to save quick tags to localStorage:`,t);try{let t=new Date().toISOString().slice(0,10);localStorage.setItem(`${ws}_recover_${t}`,e)}catch{}}},_initStorageSync(){window.addEventListener(`storage`,e=>{e.key===ws&&this._loadQuickTagsFromStorage()})},switchTab(e){e<0||e>4||(this.expandedSlotIndex!==null&&(this.expandedSlotIndex=null,this._cancelLongPress()),this.activeTab=e,this.editingSlotIndex=null,this._saveQuickTagsToStorage(),this.announce(`Switched to ${Ts[e].name} tab`))},getActiveTabSlots(){return this.activeTab<4?this.quickSlots[this.activeTab]:this.recentTags},isQuickTab(){return this.activeTab<4},openQuickTagPanel(){window.innerWidth<1024&&this.editPanelOpen&&this.closeEditPanel(),this.quickTagPanelOpen=!0,this._saveQuickTagsToStorage(),this.announce(`Edit tags panel opened`),this.fetchResourceDetails()},closeQuickTagPanel(){this.editingSlotIndex=null,this.expandedSlotIndex=null,this._cancelLongPress(),this.quickTagPanelOpen=!1,this._saveQuickTagsToStorage(),!this.editPanelOpen&&this.needsRefreshOnClose&&(this.needsRefreshOnClose=!1,this.refreshPageContent()),this.editPanelOpen||(this.detailsAborter&&=(this.detailsAborter(),null),this.resourceDetails=null),this.announce(`Edit tags panel closed`)},addTagToSlot(e,t){if(!this.isQuickTab())return;let n=this.activeTab;if(!t)return;let r={id:t.ID,name:t.Name},i=this.quickSlots[n][e];if(i){if(i.some(e=>e.id===t.ID))return;i.push(r)}else this.quickSlots[n][e]=[r];this.quickSlots=[...this.quickSlots];let a=this.recentTags.findIndex(e=>e&&e.id===t.ID);a!==-1&&(this.recentTags[a]=null,this.recentTags=[...this.recentTags]),this._saveQuickTagsToStorage(),document.querySelectorAll(`[data-quick-tag-panel] [popover]`).forEach(e=>{try{e.hidePopover()}catch{}})},removeTagFromSlot(e,t){if(!this.isQuickTab())return;let n=this.activeTab,r=this.quickSlots[n][e];if(!r)return;let i=r.filter(e=>e.id!==t);this.quickSlots[n][e]=i.length>0?i:null,this.quickSlots=[...this.quickSlots],this._saveQuickTagsToStorage()},clearQuickTagSlot(e){if(!this.isQuickTab())return;let t=this.activeTab;this.quickSlots[t][e]=null,this.quickSlots=[...this.quickSlots],this._saveQuickTagsToStorage()},recordRecentTag(e){if(this.quickSlots.some(t=>t.some(t=>t&&t.some(t=>t.id===e.ID))))return;let t=Date.now(),n=this.recentTags.findIndex(t=>t&&t.id===e.ID);if(n!==-1){this.recentTags[n]={id:e.ID,name:e.Name,ts:t},this.recentTags=[...this.recentTags],this._saveQuickTagsToStorage();return}let r=this.recentTags.indexOf(null);if(r===-1){r=0;for(let e=1;et.ID===e)},slotMatchState(e){let t=this.getActiveTabSlots()[e];if(!t||!this.resourceDetails)return`none`;let n=Array.isArray(t)?t:[t];if(n.length===0)return`none`;let r=n.filter(e=>this.isTagOnResource(e.id??e.ID)).length;return r===n.length?`all`:r>0?`some`:`none`},async toggleTabTag(e){let t=this.getActiveTabSlots()[e];if(t&&this._quickTagTogglingSlot!==e){this._quickTagTogglingSlot=e;try{let n=(Array.isArray(t)?t:[t]).map(e=>({ID:e.id??e.ID,Name:e.name??e.Name}));if(this.slotMatchState(e)===`all`)await this._batchToggleTags(n,`remove`);else{let e=n.filter(e=>!this.isTagOnResource(e.ID));e.length>0&&await this._batchToggleTags(e,`add`)}}finally{this._quickTagTogglingSlot=null}}},async _batchToggleTags(e,t){let n=this.getCurrentItem()?.id;if(!n)return;let r=t===`add`?`/v1/resources/addTags`:`/v1/resources/removeTags`;if(this.resourceDetails){this.resourceDetails.Tags||(this.resourceDetails.Tags=[]);for(let n of e)if(t===`add`)this.resourceDetails.Tags.some(e=>e.ID===n.ID)||this.resourceDetails.Tags.push(n);else{let e=this.resourceDetails.Tags.findIndex(e=>e.ID===n.ID);e!==-1&&this.resourceDetails.Tags.splice(e,1)}}try{let i=new FormData;i.append(`ID`,n);for(let t of e)i.append(`EditedId`,t.ID);let a=await fetch(r,{method:`POST`,body:i,headers:{Accept:`application/json`}});if(!a.ok)throw Error(`Failed to ${t} tags: ${a.status}`);this.resourceDetails&&this.detailsCache.set(n,{...this.resourceDetails}),this.needsRefreshOnClose=!0;let o=e.map(e=>e.Name).join(`, `);if(this.announce(`${t===`add`?`Added`:`Removed`} tags: ${o}`),t===`add`)for(let t of e)this.recordRecentTag(t)}catch(e){console.error(`Failed to ${t} tags:`,e),this.detailsCache.delete(n),await this.fetchResourceDetails(),this.announce(`Failed to ${t} tags`)}},onQuickTagResourceChange(){this.quickTagPanelOpen&&(this.expandedSlotIndex!==null&&(this.expandedSlotIndex=null,this._cancelLongPress()),this.fetchResourceDetails())},async focusTagEditor(){this.quickTagPanelOpen||this.openQuickTagPanel(),await this.fetchResourceDetails();let e=()=>document.querySelector(`[data-quick-tag-panel]`)?.querySelector(`[data-tag-editor-input]`),t=e();if(t){t.focus();return}let n=t=>{let r=e();r?r.focus():t>0&&requestAnimationFrame(()=>n(t-1))};requestAnimationFrame(()=>n(10))},_numpadOrder:[6,7,8,3,4,5,0,1,2],numpadIndex(e){return this._numpadOrder[e]},quickTagKeyLabel(e){return String(e+1)},_mediaMaxWidthClass(){let e=this.editPanelOpen&&this.quickTagPanelOpen,t=this.editPanelOpen&&!this.quickTagPanelOpen,n=!this.editPanelOpen&&this.quickTagPanelOpen;return e?`lg:max-w-[calc(100vw-690px)] max-w-[90vw]`:t||n?`lg:max-w-[calc(100vw-450px)] max-w-[90vw]`:`max-w-[90vw]`},isExpanded(){return this.expandedSlotIndex!==null},expandedTags(){if(this.expandedSlotIndex===null)return[];let e=this.getActiveTabSlots()[this.expandedSlotIndex];return e?(Array.isArray(e)?e:[e]).slice(0,9):[]},collapseExpanded(){this.expandedSlotIndex!==null&&(this.expandedSlotIndex=null,this._cancelLongPress(),this._expandedClickOutsideHandler&&=(document.removeEventListener(`click`,this._expandedClickOutsideHandler,!0),null),this.announce(`Back to quick slots`))},_expandSlot(e){this.expandedSlotIndex=e,this._longPressTimer=null,this._longPressSlotIdx=null;let t=this.expandedTags(),n=this.quickTagKeyLabel(e);this.announce(`Expanded slot ${n}: ${t.length} tags. Press Escape to go back.`)},_cancelLongPress(){this._longPressTimer&&=(clearTimeout(this._longPressTimer),null),this._longPressSlotIdx=null},_slotTagCount(e){let t=this.getActiveTabSlots()[e];return t?Array.isArray(t)?t.length:1:0},async toggleExpandedTag(e){let t=this.expandedTags();if(e>=t.length)return;let n=t[e],r={ID:n.id??n.ID,Name:n.name??n.Name},i=this.isTagOnResource(r.ID);await this._batchToggleTags([r],i?`remove`:`add`)},handleSlotKeydown(e,t){if(!t.repeat){if(this.isExpanded()){this.toggleExpandedTag(e);return}if(this._slotTagCount(e)<=1){this.toggleTabTag(e);return}this._longPressSlotIdx=e,this._longPressTimer=setTimeout(()=>{this._expandSlot(e)},this._longPressThreshold)}},handleSlotKeyup(e){this.isExpanded()||this._slotTagCount(e)<=1||this._longPressTimer&&(this._cancelLongPress(),this.toggleTabTag(e))},handleSlotMousedown(e){this.isExpanded()||this._slotTagCount(e)<=1||(this._longPressSlotIdx=e,this._longPressTimer=setTimeout(()=>{this._expandSlot(e)},this._longPressThreshold))},handleSlotMouseup(e){this.isExpanded()||this._slotTagCount(e)<=1||this._longPressTimer&&(this._cancelLongPress(),this.toggleTabTag(e))},handleSlotMouseleave(e){this._longPressTimer&&this._cancelLongPress()},_setupExpandedClickOutside(){this._expandedClickOutsideHandler&&=(document.removeEventListener(`click`,this._expandedClickOutsideHandler,!0),null),this.isExpanded()&&(this._expandedClickOutsideHandler=e=>{let t=document.querySelector(`[data-quick-tag-panel]`);t&&!t.contains(e.target)&&this.collapseExpanded()},setTimeout(()=>{this._expandedClickOutsideHandler&&document.addEventListener(`click`,this._expandedClickOutsideHandler,!0)},0))}};function ks(e){e.store(`lightbox`,{...gs,...vs,...bs,...Ss,...Ds,_liveRegion:null,liveRegion:null,init(){this._liveRegion||(this._loadQuickTagsFromStorage(),this._initStorageSync(),this._liveRegion=Go(),this.liveRegion=this._liveRegion.element,this._handleFullscreenChange=()=>{this.isFullscreen=!!(document.fullscreenElement||document.webkitFullscreenElement),this.announce(this.isFullscreen?`Entered fullscreen`:`Exited fullscreen`)},document.addEventListener(`fullscreenchange`,this._handleFullscreenChange),document.addEventListener(`webkitfullscreenchange`,this._handleFullscreenChange),this._handleWheelEvent=e=>{this.isOpen&&(e.target.closest(`[data-edit-panel]`)||e.target.closest(`[data-quick-tag-panel]`)||this.handleWheel(e))},document.addEventListener(`wheel`,this._handleWheelEvent,{passive:!1}))},destroy(){this._handleFullscreenChange&&(document.removeEventListener(`fullscreenchange`,this._handleFullscreenChange),document.removeEventListener(`webkitfullscreenchange`,this._handleFullscreenChange)),this._handleWheelEvent&&document.removeEventListener(`wheel`,this._handleWheelEvent),this._liveRegion&&(this._liveRegion.destroy(),this._liveRegion=null,this.liveRegion=null),this.animationTimeout&&clearTimeout(this.animationTimeout)},announce(e){this._liveRegion?.announce(e)},..._s,...ys,...xs,...Cs,...Os})}var As={resource:{entityType:`resource`,entityLabel:`Resources`,searchEndpoint:`/v1/resources`,maxResults:50,searchParams:(e,t,n={},r)=>{let i=new URLSearchParams({MaxResults:String(r)});return e&&i.set(`name`,e),t.tags&&t.tags.forEach(e=>i.append(`Tags`,e)),t.group&&i.set(`Groups`,t.group),n.content_types&&n.content_types.forEach(e=>i.append(`ContentTypes`,e)),i},filters:[{key:`tags`,label:`Tags`,endpoint:`/v1/tags`,multi:!0},{key:`group`,label:`Group`,endpoint:`/v1/groups`,multi:!1}],tabs:[{id:`note`,label:`Note's Resources`},{id:`all`,label:`All Resources`}],renderItem:`thumbnail`,gridColumns:`grid-cols-3 sm:grid-cols-4 md:grid-cols-5`,getItemId:e=>e.ID,getItemLabel:e=>e.Name||`Resource ${e.ID}`},group:{entityType:`group`,entityLabel:`Groups`,searchEndpoint:`/v1/groups`,maxResults:50,searchParams:(e,t,n={},r)=>{let i=new URLSearchParams({MaxResults:String(r)});return e&&i.set(`name`,e),t.category&&i.set(`categoryId`,t.category),n.category_ids&&n.category_ids.forEach(e=>i.append(`Categories`,e)),i},filters:[{key:`category`,label:`Category`,endpoint:`/v1/categories`,multi:!1}],tabs:null,renderItem:`groupCard`,gridColumns:`grid-cols-2 md:grid-cols-3 lg:grid-cols-4`,getItemId:e=>e.ID,getItemLabel:e=>e.Name||`Group ${e.ID}`},note:{entityType:`note`,entityLabel:`Notes`,searchEndpoint:`/v1/notes`,maxResults:50,searchParams:(e,t,n={},r)=>{let i=new URLSearchParams({MaxResults:String(r)});return e&&i.set(`name`,e),t.tags&&t.tags.forEach(e=>i.append(`Tags`,e)),n.note_type_ids&&n.note_type_ids.forEach(e=>i.append(`NoteTypeIds`,e)),i},filters:[{key:`tags`,label:`Tags`,endpoint:`/v1/tags`,multi:!0}],tabs:null,renderItem:`noteCard`,gridColumns:`grid-cols-2 md:grid-cols-3 lg:grid-cols-4`,getItemId:e=>e.ID,getItemLabel:e=>e.Name||`Note ${e.ID}`}};function js(e){let t=As[e];if(!t)throw Error(`Unknown entity type: ${e}`);return t}function Ms(e){e.store(`entityPicker`,{config:null,isOpen:!1,activeTab:null,loading:!1,error:null,noteId:null,searchQuery:``,filterValues:{},results:[],tabResults:{},selectedIds:new Set,existingIds:new Set,lockedFilters:{},multiSelect:!0,onConfirm:null,searchDebounceTimer:null,requestAborter:null,open({entityType:e,noteId:t=null,existingIds:n=[],lockedFilters:r={},multiSelect:i=!0,onConfirm:a}){this.config=js(e),this.noteId=t,this.existingIds=new Set(n),this.lockedFilters=r,this.multiSelect=i,this.onConfirm=a,this.selectedIds=new Set,this.searchQuery=``,this.filterValues={},this.error=null,this.results=[],this.tabResults={},this.isOpen=!0,this.config.tabs?(this.activeTab=t?this.config.tabs[0].id:this.config.tabs[1]?.id||this.config.tabs[0].id,this.activeTab===`note`&&t&&this.loadNoteResources()):this.activeTab=null,this.loadResults()},close(){this.isOpen=!1,this.results=[],this.tabResults={},this.selectedIds=new Set,this.lockedFilters={},this.multiSelect=!0,this.config=null,this.searchDebounceTimer&&=(clearTimeout(this.searchDebounceTimer),null),this.requestAborter&&=(this.requestAborter(),null),window.dispatchEvent(new CustomEvent(`entity-picker-closed`))},confirm(){this.onConfirm&&this.selectedIds.size>0&&this.onConfirm([...this.selectedIds]),this.close()},async loadNoteResources(){if(this.noteId)try{let e=await fetch(`/v1/resources?ownerId=${this.noteId}&MaxResults=100`);if(!e.ok)throw Error(`Failed to load note resources`);this.tabResults.note=await e.json(),this.tabResults.note.length===0&&this.activeTab===`note`&&(this.activeTab=`all`)}catch(e){console.error(`Error loading note resources:`,e)}},async loadResults(){this.requestAborter&&this.requestAborter(),this.loading=!0,this.error=null;let e=this.config.maxResults||50,t=this.config.searchParams(this.searchQuery.trim(),this.filterValues,this.lockedFilters,e),{abort:n,ready:r}=M(`${this.config.searchEndpoint}?${t}`);this.requestAborter=n;try{let e=await r;if(!e.ok)throw Error(`Failed to load ${this.config.entityLabel.toLowerCase()}`);let t=await e.json();this.results=t,this.config.tabs&&(this.tabResults.all=t)}catch(e){e.name!==`AbortError`&&(this.error=e.message||`Failed to load ${this.config.entityLabel.toLowerCase()}`,console.error(`Error loading results:`,e))}finally{this.loading=!1}},onSearchInput(){this.searchDebounceTimer&&clearTimeout(this.searchDebounceTimer),this.searchDebounceTimer=setTimeout(()=>{this.loadResults()},200)},setFilter(e,t){t==null?delete this.filterValues[e]:this.filterValues[e]=t,this.loadResults()},addToFilter(e,t){this.filterValues[e]||(this.filterValues[e]=[]),this.filterValues[e].includes(t)||(this.filterValues[e]=[...this.filterValues[e],t],this.loadResults())},removeFromFilter(e,t){this.filterValues[e]&&(this.filterValues[e]=this.filterValues[e].filter(e=>e!==t),this.filterValues[e].length===0&&delete this.filterValues[e],this.loadResults())},toggleSelection(e){if(!this.existingIds.has(e)){if(!this.multiSelect){this.selectedIds=new Set([e]),this.confirm();return}this.selectedIds.has(e)?this.selectedIds.delete(e):this.selectedIds.add(e),this.selectedIds=new Set(this.selectedIds)}},isSelected(e){return this.selectedIds.has(e)},isAlreadyAdded(e){return this.existingIds.has(e)},setActiveTab(e){this.activeTab=e},get displayResults(){return this.config?.tabs&&this.activeTab===`note`?this.tabResults.note||[]:this.results},get hasTabResults(){return this.tabResults.note?.length>0},get selectionCount(){return this.selectedIds.size}})}var Ns=5,Ps=2,Fs=500,Is=300*1e3,Ls=new Map;function Rs(e,t){let n=`${e}:${t}`,r=Ls.get(n);return r&&Date.now()-r.timestampsetTimeout(t,e))}async function Vs(e,t=Ps){let n;for(let r=0;r<=t;r++){try{let t=await fetch(e);if(t.ok)return await t.json();if(t.status>=400&&t.status<500)return null;n=Error(`HTTP ${t.status}`)}catch(e){n=e}re()));n.push(...a)}return n}async function Us(e,t){if(!t||t.length===0)return{};let n={resource:Ws,group:Gs}[e];return n?n(t):(console.warn(`No metadata fetcher for entity type: ${e}`),{})}async function Ws(e){let t={},n=[];for(let r of e){if(r==null)continue;let e=Rs(`resource`,r);e?t[r]=e:n.push(r)}if(n.length===0)return t;try{(await Hs(n.map(e=>async()=>{try{return{id:e,res:await Vs(`/v1/resource?id=${e}`)}}catch(t){return console.warn(`Failed to fetch resource ${e} after retries:`,t),{id:e,res:null}}}))).forEach(({id:e,res:n})=>{if(n){let r={contentType:n.ContentType||``,name:n.Name||``,hash:n.Hash||``};t[e]=r,zs(`resource`,e,r)}})}catch(e){console.warn(`Failed to fetch resource metadata:`,e)}return t}async function Gs(e){let t={},n=[];for(let r of e){if(r==null)continue;let e=Rs(`group`,r);e?t[r]=e:n.push(r)}if(n.length===0)return t;try{(await Hs(n.map(e=>async()=>{try{return{id:e,res:await Vs(`/v1/group?id=${e}`)}}catch(t){return console.warn(`Failed to fetch group ${e} after retries:`,t),{id:e,res:null}}}))).forEach(({id:e,res:n})=>{if(n){let r={name:n.Name||``,breadcrumb:Ks(n),resourceCount:n.ResourceCount||0,noteCount:n.NoteCount||0,mainResourceId:n.MainResource?.ID||null,categoryName:n.Category?.Name||``};t[e]=r,zs(`group`,e,r)}})}catch(e){console.warn(`Failed to fetch group metadata:`,e)}return t}function Ks(e){let t=[],n=e.Owner,r=0;for(;n&&r<3;)t.unshift(n.Name),n=n.Owner,r++;return n&&t.unshift(`...`),t.join(` > `)}function qs(e,t){return`${e}-${new Date().toISOString().replace(/\.\d{3}Z$/,``).replace(/:/g,`-`)}.${t}`}function Js(e){return e?e.startsWith(`image/`)?`image`:e===`text/html`?`html`:e.startsWith(`text/`)?`text`:`file`:`file`}function Ys(e,t=120){let n=e.replace(/<[^>]*>/g,` `).replace(/\s+/g,` `).trim();return n.length>t?n.slice(0,t)+`โ€ฆ`:n}function Xs(e,t){let n=e||`Upload failed (HTTP ${t})`,r=null;try{let t=JSON.parse(e),i=t.details?.[0];i?(n=i.error,i.existingResourceId!=null&&(r=i.existingResourceId)):t.error&&(n=t.error)}catch{}return n.length>0&&(n=n.charAt(0).toUpperCase()+n.slice(1)),{message:n,resourceId:r}}function Zs(e){if(!e)return[];if(e.files&&e.files.length>0){let t=[];for(let n of e.files){let e=n.type.startsWith(`image/`),r=n.name&&n.name!==``?n.name:qs(`pasted-file`,n.type.split(`/`)[1]||`bin`);t.push({file:n,name:r,previewUrl:e?URL.createObjectURL(n):null,type:Js(n.type),error:null,errorResourceId:null,_snippet:null})}return t}if(e.items){let t=[];for(let n of e.items)if(n.kind===`file`&&n.type.startsWith(`image/`)){let e=n.getAsFile();if(!e)continue;let r=qs(`pasted-image`,n.type.split(`/`)[1]||`png`);t.push({file:e,name:r,previewUrl:URL.createObjectURL(e),type:`image`,error:null,errorResourceId:null,_snippet:null})}if(t.length>0)return t}let t=e.getData(`text/html`);if(t){let e=new Blob([t],{type:`text/html`}),n=new File([e],qs(`pasted-html`,`html`),{type:`text/html`});return[{file:n,name:n.name,previewUrl:null,type:`html`,error:null,errorResourceId:null,_snippet:Ys(t)}]}let n=e.getData(`text/plain`);if(n){let e=new Blob([n],{type:`text/plain`}),t=new File([e],qs(`pasted-text`,`txt`),{type:`text/plain`});return[{file:t,name:t.name,previewUrl:null,type:`text`,error:null,errorResourceId:null,_snippet:Ys(n)}]}return[]}var Qs=null,$s=null;function ec(){window.addEventListener(`paste`,async e=>{let t=document.querySelector(`input[type='file']`);if(t&&e.clipboardData?.files&&e.clipboardData.files.length>0){e.preventDefault();let n=new DataTransfer;for(let e of t.files)n.items.add(e);for(let t of e.clipboardData.files)n.items.add(t);t.files=n.files,t.dispatchEvent(new Event(`change`,{bubbles:!0})),t.closest(`.flex`)?.classList.add(`ring-2`,`ring-indigo-500`,`rounded-md`),setTimeout(()=>t.closest(`.flex`)?.classList.remove(`ring-2`,`ring-indigo-500`,`rounded-md`),1500);return}let n=document.activeElement;if(n){let e=n.tagName;if(e===`INPUT`||e===`TEXTAREA`||n.isContentEditable)return}let r=Zs(e.clipboardData);if(r.length===0)return;e.preventDefault();let i=window.Alpine?.store(`pasteUpload`);if(!i)return;let a=document.querySelector(`[data-paste-context]`);if(a){try{let e=JSON.parse(a.getAttribute(`data-paste-context`));i.open(r,e)}catch(e){console.error(`Failed to parse data-paste-context:`,e),i.showInfo(`Invalid paste context on this page.`);for(let e of r)e.previewUrl&&URL.revokeObjectURL(e.previewUrl)}return}let o=new URLSearchParams(window.location.search).get(`ownerId`);if(o){try{let e=await fetch(`/v1/group.json?id=${encodeURIComponent(o)}`);if(!e.ok)throw Error(`HTTP ${e.status}`);let t=await e.json();i.open(r,{type:`group`,id:t.ID,name:t.Name})}catch(e){console.error(`Failed to fetch owner group:`,e),i.showInfo(`Could not determine the owner group for pasted content.`);for(let e of r)e.previewUrl&&URL.revokeObjectURL(e.previewUrl)}return}i.showInfo(`To paste and upload, navigate to a group or note detail page, or filter a list by owner.`);for(let e of r)e.previewUrl&&URL.revokeObjectURL(e.previewUrl)})}function tc(e){e.store(`pasteUpload`,{isOpen:!1,items:[],context:null,tags:[],categoryId:null,seriesId:null,state:`idle`,uploadProgress:``,errorMessage:``,infoMessage:``,open(e,t){if(!(!e||e.length===0)){if(this.isOpen&&this.state!==`uploading`){$s&&=(clearTimeout($s),null);for(let e of this.items)e.error===`done`&&e.previewUrl&&URL.revokeObjectURL(e.previewUrl);this.items=this.items.filter(e=>e.error!==`done`),this.items.push(...e),this.state=`preview`,this.errorMessage=``;return}for(let e of this.items)e.previewUrl&&URL.revokeObjectURL(e.previewUrl);this.items=e,this.context=t||null,this.tags=[],this.categoryId=null,this.seriesId=null,this.state=`preview`,this.uploadProgress=``,this.errorMessage=``,this.infoMessage=``,this.isOpen=!0}},close(){$s&&=(clearTimeout($s),null),Qs&&=(clearTimeout(Qs),null);for(let e of this.items)e.previewUrl&&URL.revokeObjectURL(e.previewUrl);this.items=[],this.context=null,this.tags=[],this.categoryId=null,this.seriesId=null,this.state=`idle`,this.uploadProgress=``,this.errorMessage=``,this.infoMessage=``,this.isOpen=!1},removeItem(e){if(e<0||e>=this.items.length)return;let[t]=this.items.splice(e,1);t&&t.previewUrl&&URL.revokeObjectURL(t.previewUrl),this.items.length===0&&this.close()},showInfo(e){this.infoMessage=e,Qs&&clearTimeout(Qs),Qs=setTimeout(()=>{this.infoMessage=``,Qs=null},4e3)},async upload(){if(this.items.length===0||!this.context)return;this.state=`uploading`,this.errorMessage=``;let e=this.items.filter(e=>e.error!==`done`).length,t=0,n=0;for(let r of this.items){if(r.error===`done`)continue;n++,this.uploadProgress=`Uploading ${n} of ${e}...`;let i=new FormData;i.append(`resource`,r.file,r.name),this.context.type===`group`?(i.append(`ownerId`,this.context.id),i.append(`groups`,this.context.id)):this.context.type===`note`&&(this.context.ownerId&&i.append(`ownerId`,this.context.ownerId),i.append(`notes`,this.context.id));for(let e of this.tags)i.append(`tags`,e);this.categoryId&&i.append(`resourceCategoryId`,this.categoryId),this.seriesId&&i.append(`SeriesId`,this.seriesId);try{let e=await fetch(`/v1/resource`,{method:`POST`,body:i});if(e.ok)r.error=`done`,r.errorResourceId=null,t++;else{let t=Xs(await e.text(),e.status);r.error=t.message,r.errorResourceId=t.resourceId}}catch(e){r.error=e.message||`Network error`}}if(t===e)this.state=`success`,this.uploadProgress=`Uploaded ${t} file${t===1?``:`s`} successfully.`,$s=setTimeout(()=>{$s=null,this.close(),this._refreshPage()},1200);else if(t>0){for(let e of this.items)e.error===`done`&&e.previewUrl&&URL.revokeObjectURL(e.previewUrl);this.items=this.items.filter(e=>e.error!==`done`),this.state=`error`,this.errorMessage=`${t} succeeded, ${e-t} failed.`}else this.state=`error`,this.errorMessage=`All ${e} upload${e===1?``:`s`} failed.`},async _refreshPage(){try{let e=await fetch(window.location.href,{headers:{Accept:`text/html`}});if(!e.ok){window.location.reload();return}let t=await e.text(),n=new DOMParser().parseFromString(t,`text/html`).querySelector(`.main`),r=document.querySelector(`.main`);r&&n&&(window.Alpine.morph(r,n,{updating(e,t,n,r){e._x_dataStack&&(t._x_dataStack=e._x_dataStack)}}),window.Alpine?.store(`lightbox`)?.initFromDOM())}catch(e){console.error(`Failed to refresh page after upload:`,e),window.location.reload()}}})}function nc({availableColumns:e,name:t}){return{sortColumns:[],availableColumns:e,name:t,init(){let e=new URLSearchParams(window.location.search).getAll(this.name);e.length>0?this.sortColumns=e.map(e=>this.parseSort(e)):this.sortColumns=[{column:``,direction:`desc`,metaKey:``}]},parseSort(e){let t=e.trim().split(/\s+/),n=t[0]||``,r=t[1]||`desc`,i=n.match(/^meta->>'([a-z_]+)'$/);return i?{column:`__meta__`,direction:r,metaKey:i[1]}:{column:n,direction:r,metaKey:``}},formatSort(e){return e.column?e.column===`__meta__`?e.metaKey?`meta->>'${e.metaKey}' ${e.direction}`:``:`${e.column} ${e.direction}`:``},addSort(){this.sortColumns.push({column:``,direction:`desc`,metaKey:``})},removeSort(e){this.sortColumns.length>1?this.sortColumns.splice(e,1):this.sortColumns[0]={column:``,direction:`desc`,metaKey:``}},isValidMetaKey(e){return/^[a-z_]+$/.test(e)},moveUp(e){if(e>0){let t=this.sortColumns[e];this.sortColumns[e]=this.sortColumns[e-1],this.sortColumns[e-1]=t}},moveDown(e){if(et.Value===e);return t?t.Name:e},getAvailableColumnsForRow(e){let t=this.sortColumns.filter((t,n)=>n!==e).map(e=>e.column).filter(e=>e);return this.availableColumns.filter(e=>!t.includes(e.Value))}}}function rc(){return{isOpen:!1,jobs:[],retainedCompletedJobs:[],eventSource:null,connectionStatus:`disconnected`,_liveRegion:null,_keydownHandler:null,_reconnectDelay:1e3,_reconnectAttempts:0,_maxReconnectAttempts:10,_maxReconnectDelay:6e4,speedTracking:{},exportRetentionMs:0,statusIcons:{pending:`โณ`,downloading:`โฌ‡`,processing:`โš™`,running:`โš™`,completed:`โœ…`,failed:`โŒ`,cancelled:`โ›”`,paused:`โธ`},statusLabels:{pending:`Pending`,downloading:`Downloading`,processing:`Processing`,running:`Running`,completed:`Completed`,failed:`Failed`,cancelled:`Cancelled`,paused:`Paused`},init(){this._liveRegion=Go(),this._lastTrigger=null;let e=document.querySelector(`meta[name="x-export-retention-ms"]`);e&&(this.exportRetentionMs=parseInt(e.getAttribute(`content`),10)||0),window.addEventListener(`jobs-panel-open`,()=>{this.isOpen=!0}),this._keydownHandler=e=>{(e.metaKey||e.ctrlKey)&&e.shiftKey&&e.key.toLowerCase()===`d`&&(e.preventDefault(),this.toggle())},document.addEventListener(`keydown`,this._keydownHandler),this.connect(),this.$watch(`isOpen`,e=>{e?(this.announce(`Jobs panel opened. Shows background job progress.`),this.$nextTick(()=>{let e=this.$refs.panel;e&&(e.querySelector(`button:not([disabled]), [href], input:not([disabled]), [tabindex]:not([tabindex="-1"])`)||e).focus()})):this._lastTrigger&&=(this._lastTrigger.focus(),null)})},announce(e){this._liveRegion?.announce(e)},destroy(){this._liveRegion?.destroy(),this._keydownHandler&&document.removeEventListener(`keydown`,this._keydownHandler),this.disconnect()},toggle(e){!this.isOpen&&e?.currentTarget&&(this._lastTrigger=e.currentTarget),this.isOpen=!this.isOpen},close(){this.isOpen=!1},connect(){this.eventSource||(this.connectionStatus=`connecting`,this.eventSource=new EventSource(`/v1/jobs/events`),this.eventSource.addEventListener(`init`,e=>{let t=JSON.parse(e.data);this.jobs=t.jobs||[];let n=(t.actionJobs||[]).map(e=>({...e,_isAction:!0}));this.jobs=[...this.jobs,...n],this.retainedCompletedJobs=[],this.connectionStatus=`connected`,this._reconnectDelay=1e3,this._reconnectAttempts=0}),this.eventSource.addEventListener(`added`,e=>{let{job:t}=JSON.parse(e.data);this.jobs.push(t),this.announce(`Download queued: ${this.truncateUrl(t.url,30)}`)}),this.eventSource.addEventListener(`updated`,e=>{let{job:t}=JSON.parse(e.data),n=this.jobs.findIndex(e=>e.id===t.id);if(n!==-1&&(this.jobs[n]=t),t.status===`downloading`&&t.progress>0){let e=Date.now(),n=this.speedTracking[t.id];if(n&&n.lastProgress0&&(n.speed=i/r),n.lastProgress=t.progress,n.lastTime=e}else n||(this.speedTracking[t.id]={lastProgress:t.progress,lastTime:e,speed:0})}t.status===`completed`?(delete this.speedTracking[t.id],this.announce(`Download completed: ${this.truncateUrl(t.url,30)}`),window.dispatchEvent(new CustomEvent(`download-completed`,{detail:t}))):t.status===`failed`?(delete this.speedTracking[t.id],this.announce(`Download failed: ${this.truncateUrl(t.url,30)}`)):t.status===`paused`&&(delete this.speedTracking[t.id],this.announce(`Download paused: ${this.truncateUrl(t.url,30)}`))}),this.eventSource.addEventListener(`removed`,e=>{let{job:t}=JSON.parse(e.data),n=this.jobs.find(e=>e.id===t.id);n&&!this.isActive(n)&&(this.retainedCompletedJobs.some(e=>e.id===n.id)||(this.retainedCompletedJobs.unshift(n),this.retainedCompletedJobs.length>5&&(this.retainedCompletedJobs=this.retainedCompletedJobs.slice(0,5)))),this.jobs=this.jobs.filter(e=>e.id!==t.id)}),this.eventSource.addEventListener(`action_added`,e=>{let{job:t}=JSON.parse(e.data);t._isAction=!0,this.jobs.push(t),this.isOpen=!0,this.announce(`Action started: ${t.label}`)}),this.eventSource.addEventListener(`action_updated`,e=>{let{job:t}=JSON.parse(e.data);t._isAction=!0;let n=this.jobs.findIndex(e=>e.id===t.id);n!==-1&&(this.jobs[n]=t),t.status===`completed`?(this.announce(`Action completed: ${t.label}`),window.dispatchEvent(new CustomEvent(`plugin-action-completed`,{detail:t}))):t.status===`failed`&&this.announce(`Action failed: ${t.label}`)}),this.eventSource.addEventListener(`action_removed`,e=>{let{job:t}=JSON.parse(e.data),n=this.jobs.find(e=>e.id===t.id);n&&(n.status===`completed`||n.status===`failed`)&&(this.retainedCompletedJobs.some(e=>e.id===n.id)||(n._isAction=!0,this.retainedCompletedJobs.unshift(n),this.retainedCompletedJobs.length>5&&(this.retainedCompletedJobs=this.retainedCompletedJobs.slice(0,5)))),this.jobs=this.jobs.filter(e=>e.id!==t.id)}),this.eventSource.onerror=()=>{this.connectionStatus=`disconnected`,this.disconnect(),this._reconnectAttempts++,this._reconnectAttempts<=this._maxReconnectAttempts&&(setTimeout(()=>{this.connect()},this._reconnectDelay),this._reconnectDelay=Math.min(this._reconnectDelay*2,this._maxReconnectDelay))})},disconnect(){this.eventSource&&=(this.eventSource.close(),null),this.connectionStatus=`disconnected`},cancelJob(e){fetch(`/v1/jobs/cancel`,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:`id=${encodeURIComponent(e)}`}).catch(e=>console.error(`Cancel failed:`,e))},pauseJob(e){fetch(`/v1/jobs/pause`,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:`id=${encodeURIComponent(e)}`}).catch(e=>console.error(`Pause failed:`,e))},resumeJob(e){fetch(`/v1/jobs/resume`,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:`id=${encodeURIComponent(e)}`}).catch(e=>console.error(`Resume failed:`,e))},retryJob(e){fetch(`/v1/jobs/retry`,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:`id=${encodeURIComponent(e)}`}).catch(e=>console.error(`Retry failed:`,e))},formatProgress(e){return e.totalSize>0?`${this.formatBytes(e.progress)} / ${this.formatBytes(e.totalSize)} (${Math.min(100,e.progressPercent).toFixed(1)}%)`:e.progress>0?`${this.formatBytes(e.progress)} downloaded`:``},formatBytes(e){if(e===0)return`0 B`;let t=1024,n=[`B`,`KB`,`MB`,`GB`],r=Math.floor(Math.log(e)/Math.log(t));return parseFloat((e/t**+r).toFixed(1))+` `+n[r]},getSpeed(e){let t=this.speedTracking[e.id];return t?t.speed:0},formatSpeed(e){let t=this.getSpeed(e);return t<=0?``:this.formatBytes(t)+`/s`},formatRelativeTime(e){let t=e-Date.now();if(t<=0)return`now (tar may already be gone)`;let n=Math.floor(t/6e4);if(n<60)return`in ${n} min`;let r=Math.floor(n/60);if(r<24)return`in ${r} h ${n%60} min`;let i=Math.floor(r/24);return`in ${i} day${i===1?``:`s`}`},getProgressPercent(e){return e.totalSize>0&&e.progress>0?Math.min(100,e.progress/e.totalSize*100):0},isActive(e){return[`pending`,`downloading`,`processing`,`running`].includes(e.status)},canPause(e){return[`pending`,`downloading`].includes(e.status)},canResume(e){return e.status===`paused`},canRetry(e){return[`failed`,`cancelled`].includes(e.status)},get activeCount(){return this.jobs.filter(e=>this.isActive(e)).length},get hasActiveJobs(){return this.activeCount>0},get displayJobs(){let e=new Set(this.jobs.map(e=>e.id)),t=this.retainedCompletedJobs.filter(t=>!e.has(t.id));return[...this.jobs,...t]},truncateUrl(e,t=40){return e?e.length<=t?e:e.substring(0,t-3)+`...`:``},getJobTitle(e){return e._isAction?e.label||e.actionId:e.source===`group-export`?e.name||`Group export`:this.getFilename(e.url)||e.name||`Download`},getJobSubtitle(e){return e._isAction?e.message||``:this.truncateUrl(e.url,50)},getFilename(e){if(!e)return``;try{return new URL(e).pathname.split(`/`).pop()||e}catch{return e.split(`/`).pop()||e}}}}function ic(e){return{r1:e.r1,v1:e.v1,r2:e.r2,v2:e.v2,init(){},updateUrl(){let e=new URL(window.location);e.searchParams.set(`r1`,this.r1),e.searchParams.set(`v1`,this.v1),e.searchParams.set(`r2`,this.r2),e.searchParams.set(`v2`,this.v2),window.location.href=e.toString()},async fetchVersions(e){let t=await fetch(`/v1/resource/versions?resourceId=${e}`);return t.ok?t.json():(console.error(`Failed to fetch versions:`,t.statusText),[])},async onResource1Change(e){this.r1=e;let t=await this.fetchVersions(e);t.length>0&&(this.v1=t[0].versionNumber),this.updateUrl()},async onResource2Change(e){this.r2=e;let t=await this.fetchVersions(e);t.length>0&&(this.v2=t[0].versionNumber),this.updateUrl()},onVersion1Change(e){this.v1=e,this.updateUrl()},onVersion2Change(e){this.v2=e,this.updateUrl()},swapSides(){[this.r1,this.r2]=[this.r2,this.r1],[this.v1,this.v2]=[this.v2,this.v1],this.updateUrl()}}}function ac(e){return{g1:e.g1,g2:e.g2,init(){},updateUrl(){let e=new URL(window.location);e.searchParams.set(`g1`,this.g1),e.searchParams.set(`g2`,this.g2),window.location.href=e.toString()},onGroup1Change(e){this.g1=e,this.updateUrl()},onGroup2Change(e){this.g2=e,this.updateUrl()},swapSides(){[this.g1,this.g2]=[this.g2,this.g1],this.updateUrl()}}}function oc({leftUrl:e,rightUrl:t,leftLabel:n,rightLabel:r}){return{mode:`side-by-side`,leftUrl:e,rightUrl:t,leftLabel:n||``,rightLabel:r||``,sliderPos:50,opacity:50,showLeft:!0,isDragging:!1,_keyHandler:null,init(){this._keyHandler=e=>{if(e.target.tagName===`INPUT`||e.target.tagName===`TEXTAREA`||e.target.tagName===`SELECT`)return;let t=e.shiftKey?10:2;this.mode===`slider`?e.key===`ArrowLeft`?(this.sliderPos=Math.max(1,this.sliderPos-t),e.preventDefault()):e.key===`ArrowRight`&&(this.sliderPos=Math.min(99,this.sliderPos+t),e.preventDefault()):this.mode===`onion`&&(e.key===`ArrowLeft`?(this.opacity=Math.max(0,this.opacity-t),e.preventDefault()):e.key===`ArrowRight`&&(this.opacity=Math.min(100,this.opacity+t),e.preventDefault()))},document.addEventListener(`keydown`,this._keyHandler)},destroy(){this._keyHandler&&document.removeEventListener(`keydown`,this._keyHandler)},swapSides(){[this.leftUrl,this.rightUrl]=[this.rightUrl,this.leftUrl],[this.leftLabel,this.rightLabel]=[this.rightLabel,this.leftLabel]},toggleSide(){this.showLeft=!this.showLeft},onRadiogroupKeydown(e,t,n){if(e.key!==`ArrowRight`&&e.key!==`ArrowLeft`&&e.key!==`Home`&&e.key!==`End`)return;e.preventDefault();let r=n.indexOf(this[t]),i=r;e.key===`ArrowRight`?i=(r+1)%n.length:e.key===`ArrowLeft`?i=(r-1+n.length)%n.length:e.key===`Home`?i=0:e.key===`End`&&(i=n.length-1),this[t]=n[i];let a=e.currentTarget;this.$nextTick(()=>{let e=a.querySelector(`[role="radio"][aria-checked="true"]`);e instanceof HTMLElement&&e.focus()})},startSliderDrag(e){e.preventDefault(),this.isDragging=!0;let t=e.target.closest(`.relative`);document.body.style.userSelect=`none`,document.body.style.cursor=`ew-resize`;let n=e=>{if(!this.isDragging)return;e.preventDefault();let n=t.getBoundingClientRect(),r=(e.clientX||e.touches?.[0]?.clientX)-n.left;this.sliderPos=Math.max(1,Math.min(99,r/n.width*100))},r=()=>{this.isDragging=!1,document.body.style.userSelect=``,document.body.style.cursor=``,document.removeEventListener(`mousemove`,n),document.removeEventListener(`mouseup`,r),document.removeEventListener(`touchmove`,n),document.removeEventListener(`touchend`,r)};document.addEventListener(`mousemove`,n),document.addEventListener(`mouseup`,r),document.addEventListener(`touchmove`,n,{passive:!1}),document.addEventListener(`touchend`,r)}}}function sc({resourceId:e,imageUrl:t,initialWidth:n=0,initialHeight:r=0}){return{resourceId:e,imageUrl:t,naturalW:n||0,naturalH:r||0,rect:{x:0,y:0,width:0,height:0},aspect:`free`,comment:``,isSubmitting:!1,errorMessage:``,decodeFailed:!1,_drag:null,onImageLoad(){let e=this.$refs.image;if(e){if(!e.naturalWidth||!e.naturalHeight){this.decodeFailed=!0;return}this.decodeFailed=!1,this.naturalW=e.naturalWidth||this.naturalW,this.naturalH=e.naturalHeight||this.naturalH}},onImageError(){this.decodeFailed=!0},_imageRect(){return this.$refs.image?this.$refs.image.getBoundingClientRect():null},_eventToNatural(e){let t=this._imageRect();if(!t||t.width<=0||t.height<=0||!this.naturalW||!this.naturalH)return null;let n=Math.max(0,Math.min(t.width,e.clientX-t.left)),r=Math.max(0,Math.min(t.height,e.clientY-t.top));return{x:Math.round(n/t.width*this.naturalW),y:Math.round(r/t.height*this.naturalH)}},onPointerDown(e){if(e.button!==void 0&&e.button!==0)return;let t=this._eventToNatural(e);if(t&&(this.errorMessage=``,this._drag={startX:t.x,startY:t.y},this.rect={x:t.x,y:t.y,width:0,height:0},e.target&&e.target.setPointerCapture&&e.pointerId!==void 0))try{e.target.setPointerCapture(e.pointerId)}catch{}},onPointerMove(e){if(!this._drag)return;let t=this._eventToNatural(e);if(!t)return;let n=Math.min(this._drag.startX,t.x),r=Math.min(this._drag.startY,t.y),i=Math.max(this._drag.startX,t.x),a=Math.max(this._drag.startY,t.y),o=i-n,s=a-r,c=this._aspectRatio();if(c){let e=o,t=s/c,n=Math.max(e,t);o=Math.round(n),s=Math.round(n*c)}this.rect={x:n,y:r,width:o,height:s},this.clampRect()},onPointerUp(e){if(this._drag&&(this._drag=null,e&&e.target&&e.target.releasePointerCapture&&e.pointerId!==void 0))try{e.target.releasePointerCapture(e.pointerId)}catch{}},_aspectRatio(){switch(this.aspect){case`1:1`:return 1;case`16:9`:return 9/16;case`4:3`:return 3/4;case`original`:return this.naturalW>0&&this.naturalH>0?this.naturalH/this.naturalW:null;default:return null}},applyAspect(){let e=this._aspectRatio();if(!e||!this.hasSelection())return;let t=this.rect.x+this.rect.width/2,n=this.rect.y+this.rect.height/2,r=this.rect.width,i=this.rect.height/e,a=Math.max(r,i),o=Math.round(a),s=Math.round(a*e);this.rect={x:Math.round(t-o/2),y:Math.round(n-s/2),width:o,height:s},this.clampRect()},clampRect(e=`auto`){if(!this.naturalW||!this.naturalH)return;let{x:t,y:n,width:r,height:i}=this.rect;t=Math.max(0,Math.min(this.naturalW-1,Math.floor(t||0))),n=Math.max(0,Math.min(this.naturalH-1,Math.floor(n||0))),r=Math.max(0,Math.floor(r||0)),i=Math.max(0,Math.floor(i||0));let a=this._aspectRatio();if(a&&r>0&&i>0){let o=Math.max(0,this.naturalW-t),s=Math.max(0,this.naturalH-n);if(e===`h`){let e=o*a;i=Math.floor(Math.min(i,s,e)),r=Math.floor(i/a)}else{let e=s/a;r=Math.floor(Math.min(r,o,e)),i=Math.floor(r*a)}}else t+r>this.naturalW&&(r=this.naturalW-t),n+i>this.naturalH&&(i=this.naturalH-n);this.rect={x:t,y:n,width:r,height:i}},hasSelection(){return this.rect.width>0&&this.rect.height>0},selectionStyle(){let e=this._imageRect();if(!e||!this.naturalW||!this.naturalH)return`display: none`;let t=e.width/this.naturalW,n=e.height/this.naturalH;return`left: ${this.rect.x*t}px; top: ${this.rect.y*n}px; width: ${this.rect.width*t}px; height: ${this.rect.height*n}px; outline: 2px dashed #fff; box-shadow: 0 0 0 2px rgba(0,0,0,0.6); background: rgba(255,255,255,0.1);`},async submit(){if(!this.isSubmitting&&!(this.decodeFailed||!this.naturalW||!this.naturalH)){if(!this.hasSelection()){this.errorMessage=`Select a crop area first.`;return}this.errorMessage=``,this.isSubmitting=!0;try{let e=new URLSearchParams;e.set(`id`,String(this.resourceId)),e.set(`x`,String(this.rect.x)),e.set(`y`,String(this.rect.y)),e.set(`width`,String(this.rect.width)),e.set(`height`,String(this.rect.height)),this.comment&&this.comment.trim()&&e.set(`comment`,this.comment.trim());let t=await fetch(`/v1/resources/crop`,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`,Accept:`application/json`},body:e.toString()});if(!t.ok){let e=`Crop failed (HTTP ${t.status})`;try{let n=await t.text();n&&(e=n)}catch{}this.errorMessage=e,this.isSubmitting=!1;return}window.location.reload()}catch(e){this.errorMessage=e&&e.message?e.message:`Crop failed.`,this.isSubmitting=!1}}},close(){let e=this.$root;e&&typeof e.close==`function`&&e.close()},reset(){this.rect={x:0,y:0,width:0,height:0},this.aspect=`free`,this.comment=``,this.errorMessage=``,this.isSubmitting=!1,this._drag=null}}}function cc({leftUrl:t=null,rightUrl:n=null,leftText:r=null,rightText:i=null}){return{mode:`unified`,loading:!0,error:null,leftText:r??``,rightText:i??``,unifiedDiff:[],splitLeft:[],splitRight:[],stats:{added:0,removed:0},async init(){try{if(r!==null&&i!==null){this.computeDiff();return}let[e,a]=await Promise.all([fetch(t),fetch(n)]);if(!e.ok||!a.ok)throw Error(`Failed to load files`);this.leftText=await e.text(),this.rightText=await a.text(),this.computeDiff()}catch(e){this.error=e.message}finally{this.loading=!1}},computeDiff(){let t=e(this.leftText,this.rightText);this.unifiedDiff=[],this.splitLeft=[],this.splitRight=[];let n=0,r=0,i=0,a=0;for(let e of t){let t=e.value.split(` `);t[t.length-1]===``&&t.pop();for(let o of t)e.added?(r++,i++,this.unifiedDiff.push({type:`added`,prefix:`+`,content:o,leftNum:null,rightNum:r}),this.splitLeft.push({num:null,content:``,changed:!1}),this.splitRight.push({num:r,content:o,changed:!0})):e.removed?(n++,a++,this.unifiedDiff.push({type:`removed`,prefix:`-`,content:o,leftNum:n,rightNum:null}),this.splitLeft.push({num:n,content:o,changed:!0}),this.splitRight.push({num:null,content:``,changed:!1})):(n++,r++,this.unifiedDiff.push({type:`context`,prefix:` `,content:o,leftNum:n,rightNum:r}),this.splitLeft.push({num:n,content:o,changed:!1}),this.splitRight.push({num:r,content:o,changed:!1}))}this.stats={added:i,removed:a}},onRadiogroupKeydown(e,t,n){if(e.key!==`ArrowRight`&&e.key!==`ArrowLeft`&&e.key!==`Home`&&e.key!==`End`)return;e.preventDefault();let r=n.indexOf(this[t]),i=r;e.key===`ArrowRight`?i=(r+1)%n.length:e.key===`ArrowLeft`?i=(r-1+n.length)%n.length:e.key===`Home`?i=0:e.key===`End`&&(i=n.length-1),this[t]=n[i];let a=e.currentTarget;this.$nextTick(()=>{let e=a.querySelector(`[role="radio"][aria-checked="true"]`);e instanceof HTMLElement&&e.focus()})}}}var lc=97,uc=122;function dc(e,t){let n;return function(...r){clearTimeout(n),n=setTimeout(()=>e.apply(this,r),t)}}function fc(e,t=[]){let n=dc(async function(e,t){await this._doUpdateBlockContent(e,t)},500);return{noteId:e,blocks:t,editMode:!1,addBlockPickerOpen:!1,activePickerIndex:0,loading:!1,error:null,_pendingUpdates:{},_blockTypesLoaded:!1,renderMarkdown(e){if(!e)return``;let t=e.replace(/&/g,`&`).replace(//g,`>`).replace(/"/g,`"`).replace(/'/g,`'`);t=t.replace(/\n/g,`
`);let n=[];return t=t.replace(/`([^`]+)`/g,(e,t)=>{let r=`๎€€CODE`+n.length+`๎€`;return n.push(``+t+``),r}),t=t.replace(/\*\*([^*]+)\*\*/g,`$1`),t=t.replace(/\*([^*]+)\*/g,`$1`),t=t.replace(/(^|[^A-Za-z0-9_])_([^_\n]+)_(?=$|[^A-Za-z0-9_])/g,`$1$2`),t=t.replace(/~~([^~\n]+)~~/g,`$1`),t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(e,t,n)=>{let r=n.trim().toLowerCase();return r.startsWith(`javascript:`)||r.startsWith(`data:`)||r.startsWith(`vbscript:`)?t:`${t}`}),t=t.replace(/๎€€CODE(\d+)๎€/g,(e,t)=>n[Number(t)]),t},async init(){this._blockTypesLoaded||await this.loadBlockTypes(),this.blocks.length===0&&this.noteId&&await this.loadBlocks(),this.$watch(`addBlockPickerOpen`,e=>{e&&(this.activePickerIndex=0,this.$nextTick(()=>{let e=this.$el.querySelector(`#add-block-listbox`);if(e){let t=e.querySelector(`[role="option"][tabindex="0"]`);t&&t.focus()}}))});let e=this;window.mahBlock={saveContent(t,n){return e.updateBlockContent(t,n)},updateState(t,n){return e.updateBlockState(t,n)},getBlock(t){return e.blocks.find(e=>e.id===t)||null}}},focusPickerItem(e){this.activePickerIndex=e,this.$nextTick(()=>{let e=this.$el.querySelector(`#add-block-listbox`);if(e){let t=e.querySelector(`[role="option"][tabindex="0"]`);t&&t.focus()}})},async loadBlockTypes(){try{let e=await fetch(`/v1/note/block/types`);e.ok&&(this.blockTypes=(await e.json()).map(e=>({type:e.type,label:e.label||this._formatLabel(e.type),icon:e.icon||this._getIconForType(e.type),description:e.description||``,defaultContent:e.defaultContent,plugin:e.plugin||!1,pluginName:e.pluginName||null,filters:e.filters||null})),this._blockTypesLoaded=!0)}catch(e){console.warn(`Failed to load block types from API, using defaults:`,e)}},_formatLabel(e){return e.charAt(0).toUpperCase()+e.slice(1)},_getIconForType(e){return{text:`๐Ÿ“`,heading:`๐Ÿ”ค`,divider:`โ”€โ”€`,gallery:`๐Ÿ–ผ๏ธ`,references:`๐Ÿ“`,todos:`โ˜‘๏ธ`,table:`๐Ÿ“Š`,calendar:`๐Ÿ“…`}[e]||`๐Ÿ“ฆ`},async loadBlocks(){this.loading=!0,this.error=null;try{let e=await fetch(`/v1/note/blocks?noteId=${this.noteId}`);if(!e.ok)throw Error(`Failed to load blocks: ${e.status}`);this.blocks=await e.json()}catch(e){this.error=e.message,console.error(`Error loading blocks:`,e)}finally{this.loading=!1}},toggleEditMode(){this.editMode=!this.editMode},async addBlock(e,t=null){this.error=null;try{let n=this.calculatePosition(t),r=await fetch(`/v1/note/block`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({noteId:this.noteId,type:e,position:n,content:this.getDefaultContent(e)})});if(!r.ok){let e=await r.json().catch(()=>({}));throw Error(e.error||`Failed to add block: ${r.status}`)}await this.loadBlocks()}catch(e){this.error=e.message,console.error(`Error adding block:`,e)}},updateBlockContentDebounced(e,t){let r=this.blocks.findIndex(t=>t.id===e);r>=0&&(this.blocks[r]={...this.blocks[r],content:t}),this._pendingUpdates[e]=t,n.call(this,e,t)},async updateBlockContent(e,t){delete this._pendingUpdates[e],await this._doUpdateBlockContent(e,t)},async _doUpdateBlockContent(e,t){this.error=null;try{let n=await fetch(`/v1/note/block?id=${e}`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({content:t})});if(!n.ok){let e=await n.json().catch(()=>({}));throw Error(e.error||`Failed to update block: ${n.status}`)}let r=await n.json(),i=this.blocks.findIndex(t=>t.id===e);i>=0&&(this.blocks[i]=r)}catch(e){this.error=e.message,console.error(`Error updating block content:`,e)}},async updateBlockState(e,t){this.error=null;try{let n=await fetch(`/v1/note/block/state?id=${e}`,{method:`PATCH`,headers:{"Content-Type":`application/json`},body:JSON.stringify({state:t})});if(!n.ok){let e=await n.json().catch(()=>({}));throw Error(e.error||`Failed to update block state: ${n.status}`)}let r=await n.json(),i=this.blocks.findIndex(t=>t.id===e);i>=0&&(this.blocks[i]=r)}catch(e){this.error=e.message,console.error(`Error updating block state:`,e)}},async deleteBlock(e){this.error=null;try{let t=await fetch(`/v1/note/block?id=${e}`,{method:`DELETE`});if(!t.ok){let e=await t.json().catch(()=>({}));throw Error(e.error||`Failed to delete block: ${t.status}`)}this.blocks=this.blocks.filter(t=>t.id!==e)}catch(e){this.error=e.message,console.error(`Error deleting block:`,e)}},async moveBlock(e,t){let n=this.blocks.findIndex(t=>t.id===e);if(n<0)return;let r=t===`up`?n-1:n+1;if(!(r<0||r>=this.blocks.length)){this.error=null;try{let e={},i=this.blocks[n],a=this.blocks[r];e[i.id]=a.position,e[a.id]=i.position;let o=await fetch(`/v1/note/blocks/reorder`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({noteId:this.noteId,positions:e})});if(!o.ok){let e=await o.json().catch(()=>({}));throw Error(e.error||`Failed to reorder blocks: ${o.status}`)}await this.loadBlocks();let s=this.$refs&&this.$refs.liveRegion;s&&(s.textContent=`Block ${n+1} moved ${t}`)}catch(e){this.error=e.message,console.error(`Error moving block:`,e)}}},calculatePosition(e){if(!e){if(this.blocks.length===0)return`n`;let e=this.blocks[this.blocks.length-1];return this.positionBetween(e.position,``)}let t=this.blocks.findIndex(t=>t.position===e);return t<0||t===this.blocks.length-1?this.positionBetween(e,``):this.positionBetween(e,this.blocks[t+1].position)},positionBetween(e,t){return e===``&&t===``?`n`:(e===``&&(e=String.fromCharCode(lc)),t===``&&(t=String.fromCharCode(uc+1)),this._generateBetween(e,t))},_generateBetween(e,t){let n=[],r=0;for(;;){let i,a;if(i=ri&&ot.type===e);return t&&t.defaultContent?t.defaultContent:{text:{text:``},heading:{text:``,level:2},divider:{},gallery:{resourceIds:[]},references:{groupIds:[]},todos:{items:[]},table:{columns:[],rows:[]}}[e]||{}},blockTypes:[{type:`text`,label:`Text`,icon:`๐Ÿ“`},{type:`heading`,label:`Heading`,icon:`๐Ÿ”ค`},{type:`divider`,label:`Divider`,icon:`โ”€โ”€`},{type:`gallery`,label:`Gallery`,icon:`๐Ÿ–ผ๏ธ`},{type:`references`,label:`References`,icon:`๐Ÿ“`},{type:`todos`,label:`Todos`,icon:`โ˜‘๏ธ`},{type:`table`,label:`Table`,icon:`๐Ÿ“Š`},{type:`calendar`,label:`Calendar`,icon:`๐Ÿ“…`}]}}function pc(e,t,n){return{block:e,saveFn:t,saveDebouncedFn:n,text:e?.content?.text||``,onBlockInput(){this.saveDebouncedFn&&this.saveDebouncedFn(this.block.id,{text:this.text})},saveBlock(){this.saveFn(this.block.id,{text:this.text})}}}function mc(e,t,n){return{block:e,saveFn:t,saveDebouncedFn:n,text:e?.content?.text||``,level:e?.content?.level||2,onInput(){this.saveDebouncedFn&&this.saveDebouncedFn(this.block.id,{text:this.text,level:this.level})},save(){this.saveFn(this.block.id,{text:this.text,level:this.level})}}}function hc(){return{}}function gc(e,t,n,r){return{block:e,saveContentFn:t,saveStateFn:n,getEditMode:r,items:[...e?.content?.items||[]],checked:[...e?.state?.checked||[]],get editMode(){return this.getEditMode?this.getEditMode():!1},isChecked(e){return this.checked.includes(e)},toggleCheck(e){this.isChecked(e)?this.checked=this.checked.filter(t=>t!==e):this.checked=[...this.checked,e],this.saveStateFn(this.block.id,{checked:this.checked})},saveContent(){this.saveContentFn(this.block.id,{items:this.items})},addItem(){let e={id:crypto.randomUUID(),label:`New item`};this.items=[...this.items,e],this.saveContentFn(this.block.id,{items:this.items})},removeItem(e){let t=this.items[e];this.items=this.items.filter((t,n)=>n!==e),t&&(this.checked=this.checked.filter(e=>e!==t.id)),this.saveContentFn(this.block.id,{items:this.items}),this.saveStateFn(this.block.id,{checked:this.checked})}}}function _c(e,t,n,r){return{block:e,saveContentFn:t,getEditMode:n,noteId:r,resourceIds:[...e?.content?.resourceIds||[]],resourceMeta:{},get editMode(){return this.getEditMode?this.getEditMode():!1},async init(){await this.fetchResourceMeta()},async fetchResourceMeta(){if(this.resourceIds.length===0)return;let e=this.resourceIds.filter(e=>!this.resourceMeta[e]);if(e.length!==0)try{for(let t=0;tfetch(`/v1/resource?id=${e}`).then(t=>t.status===404?{__unavailable:!0,id:e}:t.ok?t.json():null)))).forEach((e,t)=>{e&&e.__unavailable?this.resourceMeta[n[t]]={__unavailable:!0,id:n[t]}:e&&(this.resourceMeta[n[t]]={contentType:e.ContentType||``,name:e.Name||``,hash:e.Hash||``})})}}catch(e){console.warn(`Failed to fetch resource metadata for gallery:`,e)}},openPicker(){let e=Alpine.store(`entityPicker`);if(!e){console.error(`entityPicker store not found`);return}e.open({entityType:`resource`,noteId:this.noteId,existingIds:this.resourceIds,onConfirm:e=>{this.addResources(e)}})},openGalleryLightbox(e){let t=Alpine.store(`lightbox`);if(!t)return;let n=this.resourceIds.map(e=>{let t=this.resourceMeta[e]||{},n=t.hash||``;return{id:e,viewUrl:`/v1/resource/view?id=${e}${n?`&v=${n}`:``}`,contentType:t.contentType||`image/jpeg`,name:t.name||``,hash:n}}).filter(e=>e.contentType?.startsWith(`image/`)||e.contentType?.startsWith(`video/`));n.length!==0&&(t.items=n,t.loadedPages=new Set([1]),t.hasNextPage=!1,t.hasPrevPage=!1,t.open(e))},updateResourceIds(e){this.resourceIds=e.split(`,`).map(e=>parseInt(e.trim(),10)).filter(e=>!isNaN(e)&&e>0),this.saveContentFn(this.block.id,{resourceIds:this.resourceIds}),this.fetchResourceMeta()},addResources(e){this.resourceIds=[...new Set([...this.resourceIds,...e])],this.saveContentFn(this.block.id,{resourceIds:this.resourceIds}),this.fetchResourceMeta()},removeResource(e){this.resourceIds=this.resourceIds.filter(t=>t!==e),this.saveContentFn(this.block.id,{resourceIds:this.resourceIds})}}}function vc(e,t,n){return{block:e,saveContentFn:t,getEditMode:n,groupIds:[...e?.content?.groupIds||[]],groupMeta:{},loadingMeta:!1,get editMode(){return this.getEditMode?this.getEditMode():!1},async init(){await this.fetchGroupMeta()},async fetchGroupMeta(){if(this.groupIds.length!==0){this.loadingMeta=!0;try{let e=await Us(`group`,this.groupIds);for(let t of this.groupIds)e[t]||(e[t]={__unavailable:!0});this.groupMeta=e}catch(e){console.warn(`Failed to fetch group metadata:`,e)}finally{this.loadingMeta=!1}}},openPicker(){let e=Alpine.store(`entityPicker`);if(!e){console.error(`entityPicker store not found`);return}e.open({entityType:`group`,existingIds:this.groupIds,onConfirm:e=>{this.addGroups(e)}})},getGroupDisplay(e){let t=this.groupMeta[e];return t?t.__unavailable?{name:`Group #${e} unavailable`,breadcrumb:``,unavailable:!0}:{name:t.name||`Group ${e}`,breadcrumb:t.breadcrumb||``,unavailable:!1}:{name:`Group ${e}`,breadcrumb:``,unavailable:!1}},addGroups(e){this.groupIds=[...new Set([...this.groupIds,...e])],this.saveContentFn(this.block.id,{groupIds:this.groupIds}),this.fetchGroupMeta()},removeGroup(e){this.groupIds=this.groupIds.filter(t=>t!==e),this.saveContentFn(this.block.id,{groupIds:this.groupIds})}}}var yc=new Map,bc=3e4,xc=1e4,Sc=50;function Cc(e,t,n){return`${e}:${t}:${JSON.stringify(n||{})}`}function wc(e){return yc.get(e)}function Tc(e,t){if(yc.size>=Sc){let e=yc.keys().next().value;yc.delete(e)}yc.set(e,{data:t,timestamp:Date.now()})}function Ec(e){return e&&Date.now()-e.timestamp=xc&&Date.now()-e.timestamptypeof e==`string`?{id:`col_${t}`,label:e}:e)},_normalizeRows(e,t){return!e||!e.length||!Array.isArray(e[0])?e:e.map((e,n)=>{let r={id:`row_${n}`};return t.forEach((t,n)=>{r[t.id]=e[n]===void 0?``:e[n]}),r})},get displayColumns(){let e=this.isQueryMode?this.queryColumns:this.columns;return this._normalizeColumns(e)},get displayRows(){let e=this.isQueryMode?this.queryRows:this.rows,t=this.displayColumns,n=this._normalizeRows(e,t);return!this.sortColumn||!t.find(e=>e.id===this.sortColumn)?n:[...n].sort((e,t)=>{let n=e[this.sortColumn]||``,r=t[this.sortColumn]||``,i=nr?1:0;return this.sortDirection===`asc`?i:-i})},get sortedRows(){return this.displayRows},init(){this.isQueryMode&&this.fetchQueryData()},toggleSort(e){this.sortDirection=this.sortColumn===e&&this.sortDirection===`asc`?`desc`:`asc`,this.sortColumn=e,this.saveStateFn(this.block.id,{sortColumn:this.sortColumn,sortDirection:this.sortDirection})},saveContent(){this.isQueryMode?this.saveContentFn(this.block.id,{queryId:this.queryId,queryParams:this.queryParams,isStatic:this.isStatic}):this.saveContentFn(this.block.id,{columns:this.columns,rows:this.rows})},async fetchQueryData(e=!1){if(!this.queryId)return;let t=Cc(this.block.id,this.queryId,this.queryParams),n=wc(t);if(!e){if(Ec(n)){this.applyQueryData(n.data);return}if(Dc(n)&&!this.isStatic){this.applyQueryData(n.data),this.backgroundRefresh(t);return}if(Dc(n)&&this.isStatic){this.applyQueryData(n.data);return}}this.queryLoading=!0,this.queryError=null;try{let e=await this.fetchFromServer();Tc(t,e),this.applyQueryData(e)}catch(e){this.queryError=e.message||`Failed to load query data`,console.error(`Table block query fetch error:`,e)}finally{this.queryLoading=!1}},async backgroundRefresh(e){if(!this.isRefreshing){this.isRefreshing=!0;try{let t=await this.fetchFromServer();Tc(e,t),this.applyQueryData(t)}catch(e){console.error(`Background refresh failed:`,e)}finally{this.isRefreshing=!1}}},async fetchFromServer(){let e=new URLSearchParams({blockId:this.block.id});for(let[t,n]of Object.entries(this.queryParams||{}))e.append(t,n);let t=await fetch(`/v1/note/block/table/query?${e}`);if(!t.ok){if(t.status===404)throw Error(`Query unavailable`);let e=await t.json().catch(()=>({}));throw Error(e.error||`HTTP ${t.status}`)}return t.json()},applyQueryData(e){this.queryColumns=e.columns||[],this.queryRows=e.rows||[],this.lastFetchTime=e.cachedAt?new Date(e.cachedAt):new Date},async manualRefresh(){await this.fetchQueryData(!0)},get lastFetchTimeFormatted(){if(!this.lastFetchTime)return``;let e=new Date,t=Math.floor((e-this.lastFetchTime)/1e3);return t<60?`just now`:t<3600?`${Math.floor(t/60)}m ago`:this.lastFetchTime.toLocaleTimeString()},selectedQueryName:(e?.content?.queryId,null),selectQuery(e){this.queryId=e.ID||e.id,this.selectedQueryName=e.Name||e.name,this.queryParams={},this.isStatic=!1,this.columns=[],this.rows=[],this.saveContent(),this.fetchQueryData(!0)},clearQuery(){this.queryId=null,this.queryParams={},this.isStatic=!1,this.queryColumns=[],this.queryRows=[],this.queryError=null,this.lastFetchTime=null,this.columns=[],this.rows=[],this.saveContent()},toggleStatic(){this.isStatic=!this.isStatic,this.saveContent()},updateQueryParam(e,t){t===``||t==null?delete this.queryParams[e]:this.queryParams[e]=t,this.saveContent(),this.fetchQueryData(!0)},removeQueryParam(e){delete this.queryParams[e],this.queryParams={...this.queryParams},this.saveContent(),this.fetchQueryData(!0)},addQueryParam(){let e=`param_${Object.keys(this.queryParams).length+1}`;this.queryParams[e]=``,this.queryParams={...this.queryParams}},addColumn(){let e={id:crypto.randomUUID(),label:`New Column`};this.columns=[...this.columns,e],this.saveContent()},removeColumn(e){let t=this.columns[e];this.columns=this.columns.filter((t,n)=>n!==e),t&&(this.rows=this.rows.map(e=>{let n={...e};return delete n[t.id],n})),this.saveContent()},addRow(){let e={id:crypto.randomUUID()};this.rows=[...this.rows,e],this.saveContent()},removeRow(e){this.rows=this.rows.filter((t,n)=>n!==e),this.saveContent()}}}var kc=new Map,Ac=300*1e3,jc=50;function Mc(e,t,n){return`${e}:${t}:${n}`}function Nc(e){return kc.get(e)}function Pc(e,t){if(kc.size>=jc){let e=kc.keys().next().value;kc.delete(e)}kc.set(e,{data:t,timestamp:Date.now()})}function Fc(e){return e&&Date.now()-e.timestamp=Ac}var Lc=[`#3b82f6`,`#10b981`,`#f59e0b`,`#ef4444`,`#8b5cf6`,`#ec4899`,`#06b6d4`,`#f97316`];function Rc(e,t,n,r,i){return{block:e,saveContentFn:t,saveStateFn:n,getEditMode:r,noteId:i,calendars:JSON.parse(JSON.stringify(e?.content?.calendars||[])),view:e?.state?.view||`month`,currentDate:e?.state?.currentDate?new Date(e.state.currentDate):new Date,customEvents:JSON.parse(JSON.stringify(e?.state?.customEvents||[])),events:[],calendarMeta:{},loading:!1,error:null,isRefreshing:!1,lastFetchTime:null,newUrl:``,showColorPicker:null,showEventModal:!1,editingEvent:null,eventForm:{title:``,startDate:``,startTime:`09:00`,endDate:``,endTime:`10:00`,allDay:!1,location:``,description:``},expandedDay:null,get editMode(){return this.getEditMode?this.getEditMode():!1},get currentMonth(){return this.currentDate.toLocaleString(`default`,{month:`long`})},get currentYear(){return this.currentDate.getFullYear()},get dateRange(){let e=new Date(this.currentDate);if(this.view===`month`)return{start:new Date(e.getFullYear(),e.getMonth(),1),end:new Date(e.getFullYear(),e.getMonth()+1,0)};{let e=new Date;e.setHours(0,0,0,0);let t=new Date(e);return t.setFullYear(t.getFullYear()+1),{start:e,end:t}}},formatDate(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-${String(e.getDate()).padStart(2,`0`)}`},async init(){this.calendars.forEach(e=>{this.calendarMeta[e.id]={name:e.name,color:e.color}}),this.customEvents.length>0&&(this.calendarMeta.custom={name:`My Events`,color:`#6366f1`}),(this.calendars.length>0||this.customEvents.length>0)&&await this.fetchEvents()},async fetchEvents(e=!1){if(this.calendars.length===0&&this.customEvents.length===0){this.events=[];return}let{start:t,end:n}=this.dateRange,r=Mc(this.block.id,this.formatDate(t),this.formatDate(n)),i=Nc(r);if(!e){if(Fc(i)){this.applyEventData(i.data);return}if(Ic(i)){this.applyEventData(i.data),this.backgroundRefresh(r,t,n);return}}this.loading=!0,this.error=null;try{let e=await this.fetchFromServer(t,n);Pc(r,e),this.applyEventData(e)}catch(e){this.error=e.message||`Failed to load events`,console.error(`Calendar fetch error:`,e)}finally{this.loading=!1}},async backgroundRefresh(e,t,n){if(!this.isRefreshing){this.isRefreshing=!0;try{let r=await this.fetchFromServer(t,n);Pc(e,r),this.applyEventData(r)}catch(e){console.error(`Background refresh failed:`,e)}finally{this.isRefreshing=!1}}},async fetchFromServer(e,t){let n=new URLSearchParams({blockId:this.block.id,start:this.formatDate(e),end:this.formatDate(t)}),r=await fetch(`/v1/note/block/calendar/events?${n}`);if(!r.ok){let e=await r.json().catch(()=>({}));throw Error(e.error||`HTTP ${r.status}`)}return r.json()},applyEventData(e){this.events=e.events||[],this.lastFetchTime=e.cachedAt?new Date(e.cachedAt):new Date,(e.calendars||[]).forEach(e=>{this.calendarMeta[e.id]={name:e.name,color:e.color}});let t=e.errors||[];t.length>0&&(this.error=`Some calendars failed to load: ${t.map(e=>`${e.calendarId}: ${e.error}`).join(`; `)}`)},prevMonth(){let e=new Date(this.currentDate);e.setMonth(e.getMonth()-1),this.currentDate=e,this.saveState(),this.fetchEvents()},nextMonth(){let e=new Date(this.currentDate);e.setMonth(e.getMonth()+1),this.currentDate=e,this.saveState(),this.fetchEvents()},setView(e){this.view=e,this.saveState(),this.fetchEvents()},async saveState(){return this.saveStateFn(this.block.id,{view:this.view,currentDate:this.currentDate.toISOString().split(`T`)[0],customEvents:this.customEvents})},saveContent(){this.saveContentFn(this.block.id,{calendars:this.calendars})},addCalendarFromUrl(){let e=this.newUrl.trim();if(!e)return;try{new URL(e)}catch{this.error=`Invalid URL format. Please enter a valid URL starting with http:// or https://`;return}let t=crypto.randomUUID(),n=this.calendars.length%Lc.length,r={id:t,name:`Calendar `+(this.calendars.length+1),color:Lc[n],source:{type:`url`,url:e}};this.calendars.push(r),this.calendarMeta[t]={name:r.name,color:r.color},this.newUrl=``,this.error=null,this.saveContent(),this.fetchEvents(!0)},addCalendarFromResource(e,t){let n=crypto.randomUUID(),r=this.calendars.length%Lc.length,i={id:n,name:t||`Calendar `+(this.calendars.length+1),color:Lc[r],source:{type:`resource`,resourceId:e}};this.calendars.push(i),this.calendarMeta[n]={name:i.name,color:i.color},this.saveContent(),this.fetchEvents(!0)},removeCalendar(e){this.calendars=this.calendars.filter(t=>t.id!==e),delete this.calendarMeta[e],this.saveContent(),this.fetchEvents(!0)},updateCalendarName(e,t){let n=this.calendars.find(t=>t.id===e);n&&(n.name=t,this.calendarMeta[e].name=t,this.saveContent())},updateCalendarColor(e,t){let n=this.calendars.find(t=>t.id===e);n&&(n.color=t,this.calendarMeta[e].color=t,this.saveContent()),this.showColorPicker=null},openResourcePicker(){let e=Alpine.store(`entityPicker`);if(!e){console.error(`entityPicker store not found`);return}e.open({entityType:`resource`,noteId:this.noteId,existingIds:[],contentTypeFilter:`text/calendar`,onConfirm:async e=>{let t=await Promise.allSettled(e.map(async e=>{let t=await fetch(`/v1/resource?id=${e}`);if(!t.ok)throw Error(`Failed to fetch resource ${e}: HTTP ${t.status}`);return{id:e,name:(await t.json()).Name}})),n=!1;for(let e of t)if(e.status===`fulfilled`){let t=crypto.randomUUID(),r=this.calendars.length%Lc.length,i={id:t,name:e.value.name||`Calendar `+(this.calendars.length+1),color:Lc[r],source:{type:`resource`,resourceId:e.value.id}};this.calendars.push(i),this.calendarMeta[t]={name:i.name,color:i.color},n=!0}else console.error(`Failed to fetch resource:`,e.reason);n&&(this.saveContent(),this.fetchEvents(!0))}})},get monthDays(){let{start:e,end:t}=this.dateRange,n=[],r=e.getDay();for(let t=0;t{let r=new Date(e.start),i=new Date(e.end);return r<=n&&i>=t})},isToday(e){let t=new Date;return e.getDate()===t.getDate()&&e.getMonth()===t.getMonth()&&e.getFullYear()===t.getFullYear()},getDayKey(e){return this.formatDateInput(e)},isExpanded(e){return this.expandedDay===this.getDayKey(e)},toggleExpandedDay(e){let t=this.getDayKey(e);this.expandedDay=this.expandedDay===t?null:t},closeExpandedDay(){this.expandedDay=null},get agendaEvents(){let e=this.events.slice(0,30),t={};return e.forEach(e=>{let n=new Date(e.start).toDateString();t[n]||(t[n]={date:new Date(e.start),events:[]}),t[n].events.push(e)}),Object.values(t).sort((e,t)=>e.date-t.date)},goToEventMonth(e){this.currentDate=new Date(e.start),this.view=`month`,this.saveState()},formatEventTime(e){return e.allDay?`All day`:new Date(e.start).toLocaleTimeString(`default`,{hour:`numeric`,minute:`2-digit`})},formatAgendaDate(e){return e.toLocaleDateString(`default`,{weekday:`short`,month:`short`,day:`numeric`})},getCalendarColor(e){return this.calendarMeta[e]?.color||`#6b7280`},getCalendarName(e){return this.calendarMeta[e]?.name||`Unknown`},isCustomEvent(e){return e.calendarId===`custom`},openEventModalForDay(e){let t=this.formatDateInput(e);this.editingEvent=null,this.eventForm={title:``,startDate:t,startTime:`09:00`,endDate:t,endTime:`10:00`,allDay:!1,location:``,description:``},this.showEventModal=!0},openEventModalForEdit(e){if(!this.isCustomEvent(e))return;let t=new Date(e.start),n=new Date(e.end);this.editingEvent=e,this.eventForm={title:e.title,startDate:this.formatDateInput(t),startTime:this.formatTimeInput(t),endDate:this.formatDateInput(n),endTime:this.formatTimeInput(n),allDay:e.allDay||!1,location:e.location||``,description:e.description||``},this.showEventModal=!0},closeEventModal(){this.showEventModal=!1,this.editingEvent=null},async saveEvent(){if(!this.eventForm.title.trim())return;let e,t;this.eventForm.allDay?(e=new Date(this.eventForm.startDate+`T00:00:00`),t=new Date(this.eventForm.endDate+`T23:59:59`)):(e=new Date(this.eventForm.startDate+`T`+this.eventForm.startTime),t=new Date(this.eventForm.endDate+`T`+this.eventForm.endTime)),t<=e&&!this.eventForm.allDay&&(t=new Date(e.getTime()+3600*1e3));let n={id:this.editingEvent?.id||crypto.randomUUID(),title:this.eventForm.title.trim(),start:e.toISOString(),end:t.toISOString(),allDay:this.eventForm.allDay,location:this.eventForm.location.trim()||void 0,description:this.eventForm.description.trim()||void 0,calendarId:`custom`};if(this.editingEvent){let e=this.customEvents.findIndex(e=>e.id===n.id);e>=0&&(this.customEvents[e]=n)}else this.customEvents.push(n);await this.saveState(),this.closeEventModal(),await this.fetchEvents(!0)},async deleteEvent(){this.editingEvent&&(this.customEvents=this.customEvents.filter(e=>e.id!==this.editingEvent.id),await this.saveState(),this.closeEventModal(),await this.fetchEvents(!0))},formatDateInput(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-${String(e.getDate()).padStart(2,`0`)}`},formatTimeInput(e){return`${String(e.getHours()).padStart(2,`0`)}:${String(e.getMinutes()).padStart(2,`0`)}`}}}function zc(){return{isOpen:!1,mode:`create`,event:null,title:``,startDate:``,startTime:`09:00`,endDate:``,endTime:`10:00`,allDay:!1,location:``,description:``,onSave:null,onDelete:null,open(e={}){if(this.mode=e.mode||`create`,this.event=e.event||null,this.onSave=e.onSave||null,this.onDelete=e.onDelete||null,this.event){let e=new Date(this.event.start),t=new Date(this.event.end);this.title=this.event.title,this.startDate=this.formatDateInput(e),this.startTime=this.formatTimeInput(e),this.endDate=this.formatDateInput(t),this.endTime=this.formatTimeInput(t),this.allDay=this.event.allDay||!1,this.location=this.event.location||``,this.description=this.event.description||``}else{let t=e.date||this.formatDateInput(new Date);this.title=``,this.startDate=t,this.startTime=`09:00`,this.endDate=t,this.endTime=`10:00`,this.allDay=!1,this.location=``,this.description=``}this.isOpen=!0},close(){this.isOpen=!1,this.event=null,this.onSave=null,this.onDelete=null},save(){if(!this.title.trim())return;let e,t;this.allDay?(e=new Date(this.startDate+`T00:00:00`),t=new Date(this.endDate+`T23:59:59`)):(e=new Date(this.startDate+`T`+this.startTime),t=new Date(this.endDate+`T`+this.endTime)),t<=e&&!this.allDay&&(t=new Date(e.getTime()+3600*1e3));let n={id:this.event?.id||crypto.randomUUID(),title:this.title.trim(),start:e.toISOString(),end:t.toISOString(),allDay:this.allDay,location:this.location.trim()||void 0,description:this.description.trim()||void 0,calendarId:`custom`};this.onSave&&this.onSave(n),this.close()},deleteEvent(){this.onDelete&&this.event&&this.onDelete(this.event.id),this.close()},formatDateInput(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-${String(e.getDate()).padStart(2,`0`)}`},formatTimeInput(e){return`${String(e.getHours()).padStart(2,`0`)}:${String(e.getMinutes()).padStart(2,`0`)}`},onAllDayChange(){this.allDay&&this.endDatet!==e):this.checked=[...this.checked,e],this.saving=!0,this.error=null;try{let e=await fetch(`/s/${this.shareToken}/block/${this.blockId}/state`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({checked:this.checked})});if(!e.ok)throw Error(`Failed to save: ${e.status}`)}catch(n){t?this.checked=[...this.checked,e]:this.checked=this.checked.filter(t=>t!==e),this.error=n.message,console.error(`Failed to save todo state:`,n)}finally{this.saving=!1}}}}var Hc=[`#3b82f6`,`#10b981`,`#f59e0b`,`#ef4444`,`#8b5cf6`,`#ec4899`,`#06b6d4`,`#f97316`];function Uc(e,t,n,r){return{blockId:e,shareToken:r,calendars:t?.calendars||[],view:n?.view||`month`,currentDate:n?.currentDate?new Date(n.currentDate):new Date,customEvents:JSON.parse(JSON.stringify(n?.customEvents||[])),events:[],calendarMeta:{},loading:!1,error:null,isRefreshing:!1,showEventModal:!1,editingEvent:null,eventForm:{title:``,startDate:``,startTime:`09:00`,endDate:``,endTime:`10:00`,allDay:!1,location:``,description:``},expandedDay:null,get currentMonth(){return this.currentDate.toLocaleString(`default`,{month:`long`})},get currentYear(){return this.currentDate.getFullYear()},get dateRange(){let e=new Date(this.currentDate);if(this.view===`month`)return{start:new Date(e.getFullYear(),e.getMonth(),1),end:new Date(e.getFullYear(),e.getMonth()+1,0)};{let e=new Date;e.setHours(0,0,0,0);let t=new Date(e);return t.setFullYear(t.getFullYear()+1),{start:e,end:t}}},formatDate(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-${String(e.getDate()).padStart(2,`0`)}`},async init(){this.calendars.forEach((e,t)=>{this.calendarMeta[e.id]={name:e.name||`Calendar ${t+1}`,color:e.color||Hc[t%Hc.length]}}),this.customEvents.length>0&&(this.calendarMeta.custom={name:`My Events`,color:`#6366f1`}),(this.calendars.length>0||this.customEvents.length>0)&&await this.fetchEvents()},async fetchEvents(e=!1){if(this.calendars.length===0&&this.customEvents.length===0){this.events=[];return}this.loading=!0,this.error=null;try{let{start:e,end:t}=this.dateRange,n=new URLSearchParams({start:this.formatDate(e),end:this.formatDate(t)}),r=await fetch(`/s/${this.shareToken}/block/${this.blockId}/calendar/events?${n}`);if(!r.ok){let e=await r.json().catch(()=>({}));throw Error(e.error||`HTTP ${r.status}`)}let i=await r.json();this.applyEventData(i)}catch(e){this.error=e.message||`Failed to load events`,console.error(`Calendar fetch error:`,e)}finally{this.loading=!1}},applyEventData(e){this.events=e.events||[],(e.calendars||[]).forEach(e=>{this.calendarMeta[e.id]={name:e.name,color:e.color}});let t=e.errors||[];t.length>0&&(this.error=`Some calendars failed to load: ${t.map(e=>`${e.calendarId}: ${e.error}`).join(`; `)}`)},async saveState(){try{await fetch(`/s/${this.shareToken}/block/${this.blockId}/state`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({view:this.view,currentDate:this.formatDate(this.currentDate),customEvents:this.customEvents})})}catch(e){console.error(`Failed to save calendar state:`,e)}},prevMonth(){let e=new Date(this.currentDate);e.setMonth(e.getMonth()-1),this.currentDate=e,this.saveState(),this.fetchEvents()},nextMonth(){let e=new Date(this.currentDate);e.setMonth(e.getMonth()+1),this.currentDate=e,this.saveState(),this.fetchEvents()},setView(e){this.view=e,this.saveState(),this.fetchEvents()},goToEventMonth(e){this.currentDate=new Date(e.start),this.view=`month`,this.saveState()},get monthDays(){let e=new Date(this.currentDate),t=new Date(e.getFullYear(),e.getMonth(),1),n=new Date(e.getFullYear(),e.getMonth()+1,0),r=[],i=t.getDay();for(let e=0;e{let r=new Date(e.start),i=new Date(e.end);return r<=n&&i>=t})},isToday(e){let t=new Date;return e.getDate()===t.getDate()&&e.getMonth()===t.getMonth()&&e.getFullYear()===t.getFullYear()},getDayKey(e){return this.formatDateInput(e)},isExpanded(e){return this.expandedDay===this.getDayKey(e)},toggleExpandedDay(e){let t=this.getDayKey(e);this.expandedDay=this.expandedDay===t?null:t},closeExpandedDay(){this.expandedDay=null},get agendaEvents(){let e=this.events.slice(0,30),t={};return e.forEach(e=>{let n=new Date(e.start).toDateString();t[n]||(t[n]={date:new Date(e.start),events:[]}),t[n].events.push(e)}),Object.values(t).sort((e,t)=>e.date-t.date)},formatEventTime(e){return e.allDay?`All day`:new Date(e.start).toLocaleTimeString(`default`,{hour:`numeric`,minute:`2-digit`})},formatAgendaDate(e){return e.toLocaleDateString(`default`,{weekday:`short`,month:`short`,day:`numeric`})},getCalendarColor(e){return this.calendarMeta[e]?.color||`#6b7280`},getCalendarName(e){return this.calendarMeta[e]?.name||`Unknown`},isCustomEvent(e){return e.calendarId===`custom`},openEventModalForDay(e){let t=this.formatDateInput(e);this.editingEvent=null,this.eventForm={title:``,startDate:t,startTime:`09:00`,endDate:t,endTime:`10:00`,allDay:!1,location:``,description:``},this.showEventModal=!0},openEventModalForEdit(e){if(!this.isCustomEvent(e))return;let t=new Date(e.start),n=new Date(e.end);this.editingEvent=e,this.eventForm={title:e.title,startDate:this.formatDateInput(t),startTime:this.formatTimeInput(t),endDate:this.formatDateInput(n),endTime:this.formatTimeInput(n),allDay:e.allDay||!1,location:e.location||``,description:e.description||``},this.showEventModal=!0},closeEventModal(){this.showEventModal=!1,this.editingEvent=null},async saveEvent(){if(!this.eventForm.title.trim())return;let e,t;this.eventForm.allDay?(e=new Date(this.eventForm.startDate+`T00:00:00`),t=new Date(this.eventForm.endDate+`T23:59:59`)):(e=new Date(this.eventForm.startDate+`T`+this.eventForm.startTime),t=new Date(this.eventForm.endDate+`T`+this.eventForm.endTime)),t<=e&&!this.eventForm.allDay&&(t=new Date(e.getTime()+3600*1e3));let n={id:this.editingEvent?.id||crypto.randomUUID(),title:this.eventForm.title.trim(),start:e.toISOString(),end:t.toISOString(),allDay:this.eventForm.allDay,location:this.eventForm.location.trim()||void 0,description:this.eventForm.description.trim()||void 0,calendarId:`custom`};if(this.editingEvent){let e=this.customEvents.findIndex(e=>e.id===n.id);e>=0&&(this.customEvents[e]=n)}else this.customEvents.push(n),this.calendarMeta.custom||(this.calendarMeta.custom={name:`My Events`,color:`#6366f1`});await this.saveState(),this.closeEventModal(),await this.fetchEvents(!0)},async deleteEvent(){this.editingEvent&&(this.customEvents=this.customEvents.filter(e=>e.id!==this.editingEvent.id),await this.saveState(),this.closeEventModal(),await this.fetchEvents(!0))},formatDateInput(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-${String(e.getDate()).padStart(2,`0`)}`},formatTimeInput(e){return`${String(e.getHours()).padStart(2,`0`)}:${String(e.getMinutes()).padStart(2,`0`)}`}}}function Wc({mode:e=`sql`,dbType:n=`SQLITE`,label:r=``}={}){return{view:null,langCompartment:null,formatError:``,_formatErrorTimer:null,async init(){this.mode=e;let i=this.$refs.hiddenInput,a=this.$refs.editorContainer,o=i.value||``,s=i.getAttribute(`name`)||``,c=r||s,[{EditorView:l,keymap:u,lineNumbers:d,highlightActiveLine:f,highlightActiveLineGutter:p,drawSelection:m},{EditorState:h,Compartment:g},{defaultKeymap:_,history:ee,historyKeymap:te,indentWithTab:ne},{syntaxHighlighting:re,defaultHighlightStyle:ie,bracketMatching:ae,indentOnInput:oe},{autocompletion:se,closeBrackets:ce,closeBracketsKeymap:le}]=await Promise.all([t(()=>import(`./assets/dist-CWxv7SAN.js`).then(e=>e.s),__vite__mapDeps([0,1,2])),t(()=>import(`./assets/dist-CkbxygMd.js`).then(e=>e.x),__vite__mapDeps([2,1])),t(()=>import(`./assets/dist-D_5KILaj.js`),__vite__mapDeps([3,4,2,1,0])),t(()=>import(`./assets/dist-C1mP0eX_.js`),__vite__mapDeps([4,2,1,0])),t(()=>import(`./assets/dist-BARqFM7X.js`).then(e=>e.n),__vite__mapDeps([5,1,4,2,0]))]);this.langCompartment=new g;let ue=[d(),f(),p(),m(),oe(),ae(),ce(),ee(),re(ie,{fallback:!0}),se(),u.of([...le,..._,...te,ne]),this.langCompartment.of([]),l.updateListener.of(e=>{e.docChanged&&(i.value=e.state.doc.toString())}),l.contentAttributes.of({"aria-label":c,"data-language":e}),l.theme({"&":{minHeight:`200px`,maxHeight:`60vh`},".cm-scroller":{overflow:`auto`,minHeight:`200px`},".cm-content":{minHeight:`200px`}})];this.view=new l({state:h.create({doc:o,extensions:ue}),parent:a}),this.view.scrollDOM.tabIndex=0,a._cmView=this.view,e===`sql`?this.loadSQL(n):e===`html`?this.loadHTML():e===`json`&&this.loadJSON()},async loadSQL(e){let{sql:n,SQLite:r,PostgreSQL:i}=await t(async()=>{let{sql:e,SQLite:t,PostgreSQL:n}=await import(`./assets/dist-TwzZQeSF.js`);return{sql:e,SQLite:t,PostgreSQL:n}},__vite__mapDeps([6,5,1,4,2,0,7])),a=e===`POSTGRES`?i:r,o;try{let e=await fetch(`/v1/query/schema`);e.ok&&(o=await e.json())}catch{}this.view.dispatch({effects:this.langCompartment.reconfigure(n({dialect:a,schema:o}))})},async loadHTML(){let{html:e}=await t(async()=>{let{html:e}=await import(`./assets/dist-D8TQvulo.js`);return{html:e}},__vite__mapDeps([8,5,1,4,2,0,7]));this.view.dispatch({effects:this.langCompartment.reconfigure(e({autoCloseTags:!1}))})},async loadJSON(){let{json:e}=await t(async()=>{let{json:e}=await import(`./assets/dist-D4MqxeYB.js`);return{json:e}},__vite__mapDeps([9,4,2,1,0,7]));this.view.dispatch({effects:this.langCompartment.reconfigure(e())})},async formatContent(){if(!this.view)return;let e=this.view.state.doc.toString();if(!e.trim())return;this.formatError=``;let n;try{if(this.mode===`json`)n=JSON.stringify(JSON.parse(e),null,2);else if(this.mode===`html`){let{formatHtml:r}=await t(async()=>{let{formatHtml:e}=await import(`./assets/formatHtml-1-Liwnbs.js`);return{formatHtml:e}},[]);n=r(e)}else return}catch(e){this.formatError=e.message||`Formatting failed`,this._formatErrorTimer&&clearTimeout(this._formatErrorTimer),this._formatErrorTimer=setTimeout(()=>{this.formatError=``},4e3);return}n!==e&&this.view.dispatch({changes:{from:0,to:this.view.state.doc.length,insert:n}})},destroy(){this._formatErrorTimer&&clearTimeout(this._formatErrorTimer),this.view&&=(this.view.destroy(),null)}}}function Gc({initialRows:e=[],highlightedPath:t=null,containingId:n=0,rootId:r=0}){let i=t||[];return{tree:{},expandedNodes:new Set,loadingNodes:new Set,highlightedSet:new Set(i),containingId:n,rootId:r,requestAborters:new Map,init(){this.buildTree(e);for(let e of i)this.expandedNodes.add(e);this.render()},buildTree(e){for(let t of e){let e=t.ownerId||`root`;this.tree[e]||(this.tree[e]=[]),this.tree[e].some(e=>e.id===t.id)||this.tree[e].push(t)}},render(){let e=this.$refs.treeContainer;if(!e)return;let t=this.tree.root||this.tree[0]||[];if(t.length===0){let t=document.createElement(`p`);t.className=`text-gray-500 p-4`,t.textContent=`No groups found.`,e.replaceChildren(t);return}let n=e.querySelector(`li[role="treeitem"][tabindex="0"]`),r=n?n.getAttribute(`data-group-id`):null,i=document.createElement(`ul`);i.className=`tree-chart-list`,i.setAttribute(`role`,`tree`),i.setAttribute(`aria-label`,`Group hierarchy`),t.forEach((e,n)=>{i.appendChild(this.renderNode(e,!0,{level:1,posinset:n+1,setsize:t.length}))}),e.replaceChildren(i),this._applyRovingTabindex(e,r)},_applyRovingTabindex(e,t=null){let n=e.querySelectorAll(`li[role="treeitem"]`);if(n.length===0)return;n.forEach(e=>e.setAttribute(`tabindex`,`-1`));let r=null;t&&(r=e.querySelector(`li[role="treeitem"][data-group-id="${t}"]`)),r||=n[0],r.setAttribute(`tabindex`,`0`)},renderNode(e,t,{level:n=1,posinset:r=1,setsize:i=1}={}){let a=this.highlightedSet.has(e.id),o=e.id===this.containingId,s=this.expandedNodes.has(e.id),c=this.loadingNodes.has(e.id),l=this.tree[e.id]||[],u=e.childCount>0,d=`tree-node-box`;o?d+=` tree-node-box--focused`:a&&(d+=` tree-node-box--path`);let f=document.createElement(`li`);t&&(f.className=`tree-root-node`),f.setAttribute(`role`,`treeitem`),f.setAttribute(`aria-level`,String(n)),f.setAttribute(`aria-posinset`,String(r)),f.setAttribute(`aria-setsize`,String(i)),f.setAttribute(`data-group-id`,String(e.id)),u&&f.setAttribute(`aria-expanded`,s?`true`:`false`);let p=document.createElement(`a`);p.href=`/group?id=${e.id}`,p.className=d,p.title=e.name||``;let m=document.createElement(`span`);if(m.className=`tree-node-name`,m.textContent=e.name||``,p.appendChild(m),e.categoryName){let t=document.createElement(`span`);t.className=`tree-node-category`,t.textContent=e.categoryName,p.appendChild(t)}if(f.appendChild(p),u){let t=e.childCount===1?`1 child`:`${e.childCount} children`;if(c){let t=document.createElement(`button`);t.className=`tree-node-expand`,t.disabled=!0,t.setAttribute(`aria-label`,`Loading children of ${e.name||`group`}`),t.textContent=`Loading...`,f.appendChild(t)}else if(s&&l.length>0){let r=document.createElement(`button`);r.className=`tree-node-expand`,r.dataset.nodeId=e.id,r.dataset.action=`collapse`,r.setAttribute(`aria-expanded`,`true`),r.setAttribute(`aria-label`,`Collapse ${e.name||`group`}, ${t}`);let i=document.createElement(`span`);i.className=`tree-node-arrow tree-node-arrow--down`,i.setAttribute(`aria-hidden`,`true`),r.appendChild(i),r.appendChild(document.createTextNode(` ${e.childCount}`)),f.appendChild(r);let a=document.createElement(`ul`);if(a.className=`tree-chart-list`,a.setAttribute(`role`,`group`),l.forEach((e,t)=>{a.appendChild(this.renderNode(e,!1,{level:n+1,posinset:t+1,setsize:l.length}))}),l.length ul > li[role="treeitem"]`);e&&(a=e)}break}case`ArrowLeft`:{if(t.getAttribute(`aria-expanded`)===`true`){let r=parseInt(t.dataset.groupId,10);if(!Number.isNaN(r)){e.preventDefault(),this.expandedNodes.delete(r),this.render();let t=n.querySelector(`li[role="treeitem"][data-group-id="${r}"]`);t&&t.focus()}return}let r=t.parentElement?.closest(`li[role="treeitem"]`);r&&(a=r);break}default:return}a&&a!==t&&(e.preventDefault(),r.forEach(e=>e.setAttribute(`tabindex`,`-1`)),a.setAttribute(`tabindex`,`0`),a.focus())},async expandNode(e){if(this.expandedNodes.add(e),this.tree[e]&&this.tree[e].length>0){this.render();return}this.loadingNodes.add(e),this.render();try{this.requestAborters.has(e)&&this.requestAborters.get(e)();let{abort:t,ready:n}=M(`/v1/group/tree/children?parentId=${e}&limit=50`);this.requestAborters.set(e,t);let r=await n;if(!r.ok)throw Error(`Failed to load children`);let i=await r.json();this.tree[e]=i}catch(e){e.name!==`AbortError`&&console.error(`Failed to load tree children:`,e)}finally{this.loadingNodes.delete(e),this.requestAborters.delete(e),this.render()}}}}function Kc(e){return{pluginName:e,saved:!1,error:``,async saveSettings(e){this.saved=!1,this.error=``;let t=e.target,n=new FormData(t),r={};for(let[e,t]of n.entries())e!==`name`&&(r[e]=t);t.querySelectorAll(`input[type="checkbox"]`).forEach(e=>{r[e.name]=e.checked}),t.querySelectorAll(`input[type="number"]`).forEach(e=>{r[e.name]!==void 0&&r[e.name]!==``&&(r[e.name]=parseFloat(r[e.name]))});try{let e=await fetch(`/v1/plugin/settings?name=${encodeURIComponent(this.pluginName)}`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(r)});if(!e.ok){if((e.headers.get(`Content-Type`)||``).includes(`application/json`)){let t=await e.json();if(t.errors){this.error=t.errors.map(e=>e.message).join(`, `);return}}this.error=`Failed to save settings (${e.status})`;return}this.saved=!0,setTimeout(()=>{this.saved=!1},3e3)}catch(e){this.error=e.message}}}}function qc(){return{isOpen:!1,action:null,formValues:{},errors:{},submitting:!1,result:null,init(){window.addEventListener(`plugin-action-open`,e=>this.open(e.detail))},open(e){let t={plugin:e.plugin,action:e.action,label:e.label,description:e.description,entityIds:e.entityIds,entityType:e.entityType,async:e.async,params:e.params,confirm:e.confirm,filters:e.filters||{},bulk_max:e.bulk_max};if(this.action=t,this.errors={},this.result=null,this.submitting=!1,this.formValues={},t.params){for(let e of t.params)if(e.type!==`info`){if(e.type===`entity_ref`){this.formValues[e.name]=this.resolveEntityRefDefault(e,t);continue}this.formValues[e.name]=e.default??(e.type===`boolean`?!1:``)}}this.isOpen=!0,this.$nextTick(()=>{let e=this.$root.querySelector(`input, textarea, select`);e&&e.focus()})},resolveEntityRefDefault(e,t){let n=e.default??`trigger`,r=e.entity===t.entityType,i=[];if((n===`trigger`||n===`both`)&&r&&t.entityIds&&i.push(...t.entityIds.map(Number)),(n===`selection`||n===`both`)&&r){let e=window.Alpine?.store(`bulkSelection`);if(e&&e.selectedIds)for(let t of e.selectedIds){let e=Number(t);i.includes(e)||i.push(e)}}return e.multi?i:i.length>0?i[0]:null},effectiveFilters(e){return e.filters||this.action?.filters||{}},openPickerFor(e){let t=e.multi?this.formValues[e.name]||[]:this.formValues[e.name]==null?[]:[this.formValues[e.name]],n=this;Alpine.store(`entityPicker`).open({entityType:e.entity,existingIds:t,lockedFilters:n.effectiveFilters(e),multiSelect:e.multi,onConfirm:t=>{if(e.multi){let r=new Set(n.formValues[e.name]||[]),i=[...n.formValues[e.name]||[]];for(let e of t)r.has(e)||(r.add(e),i.push(e));n.formValues[e.name]=i}else n.formValues[e.name]=t.length>0?t[0]:null}})},removeEntityRefId(e,t){e.multi?this.formValues[e.name]=(this.formValues[e.name]||[]).filter(e=>e!==t):this.formValues[e.name]=null},close(){this.isOpen=!1,this.action=null},isParamVisible(e){if(!e.show_when)return!0;for(let t of Object.keys(e.show_when)){let n=e.show_when[t],r=this.formValues[t];if(Array.isArray(n)){if(!n.includes(r))return!1}else if(r!==n)return!1}return!0},async submit(){if(this.submitting)return;if(this.errors={},this.action.params)for(let e of this.action.params){if(e.type===`info`||!this.isParamVisible(e))continue;let t=this.formValues[e.name];if(e.type===`entity_ref`){let n=e.multi?(t||[]).length:t==null?0:1;e.required&&n===0?this.errors[e.name]=`${e.label} is required`:e.multi&&e.min!=null&&n0&&n>e.max&&(this.errors[e.name]=`${e.label}: at most ${e.max} allowed`);continue}e.required&&!t&&t!==0&&t!==!1&&(this.errors[e.name]=`${e.label} is required`)}if(Object.keys(this.errors).length>0)return;let e={};if(this.action.params)for(let t of this.action.params)t.type!==`info`&&this.isParamVisible(t)&&(e[t.name]=this.formValues[t.name]);else Object.assign(e,this.formValues);this.submitting=!0;try{let t=await fetch(`/v1/jobs/action/run`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({plugin:this.action.plugin,action:this.action.action,entity_ids:this.action.entityIds.map(Number),params:e})}),n=await t.json();if(!t.ok){this.errors._general=n.error||`Action failed`;return}n.job_id||n.job_ids?(this.close(),window.dispatchEvent(new CustomEvent(`jobs-panel-open`))):n.redirect?window.location.href=n.redirect:(this.result=n,setTimeout(()=>{this.close(),window.location.reload()},1500))}catch(e){this.errors._general=e.message}finally{this.submitting=!1}}}}function Jc(){return{open:!1,toggle(){this.open=!this.open},close(){this.open=!1},runAction(e,t,n){this.close(),window.dispatchEvent(new CustomEvent(`plugin-action-open`,{detail:{plugin:e.plugin_name,action:e.id,label:e.label,description:e.description,entityIds:[t],entityType:n,async:e.async,params:e.params,confirm:e.confirm,filters:e.filters,bulk_max:e.bulk_max}}))}}}function Yc(e=``){return{mentionActive:!1,mentionQuery:``,mentionResults:[],mentionSelectedIndex:0,mentionLoading:!1,mentionStart:-1,_requestAborter:null,_debounceTimer:null,_liveRegion:null,typeIcons:{resource:`๐Ÿ“„`,note:`๐Ÿ“`,group:`๐Ÿ‘ฅ`,tag:`๐Ÿท`,category:`๐Ÿ“`},typeLabels:{resource:`Resource`,note:`Note`,group:`Group`,tag:`Tag`,category:`Category`},init(){this._liveRegion=Go()},destroy(){this._liveRegion?.destroy(),this._debounceTimer&&clearTimeout(this._debounceTimer),this._requestAborter&&=(this._requestAborter(),null)},onKeydown(e){!this.mentionActive||this.mentionResults.length===0||(e.key===`ArrowDown`?(e.preventDefault(),this.mentionSelectedIndex=(this.mentionSelectedIndex+1)%this.mentionResults.length,this._scrollToSelected(),this._announceSelected()):e.key===`ArrowUp`?(e.preventDefault(),this.mentionSelectedIndex=this.mentionSelectedIndex===0?this.mentionResults.length-1:this.mentionSelectedIndex-1,this._scrollToSelected(),this._announceSelected()):e.key===`Enter`?(e.preventDefault(),this.selectMention(this.mentionResults[this.mentionSelectedIndex])):e.key===`Escape`&&(e.preventDefault(),this.closeMention()))},onInput(e){let t=this.$refs.mentionInput;if(!t)return;let n=t.value,r=t.selectionStart,i=-1;for(let e=r-1;e>=0;e--){if(n[e]===`@`){(e===0||/\s/.test(n[e-1]))&&(i=e);break}if(n[e]===` `)break}if(i===-1){this.mentionActive&&this.closeMention();return}if(n[i+1]===`[`){let e=n.indexOf(`]`,i);if(e!==-1&&e=2?this._searchMentions(a):this.mentionResults=[]},selectMention(e){if(!e)return;let t=this.$refs.mentionInput;if(!t)return;let n=t.value,r=`@[${e.type}:${e.id}:${e.name}]`,i=n.substring(0,this.mentionStart),a=n.substring(this.mentionStart+1+this.mentionQuery.length);t.value=i+r+a;let o=this.mentionStart+r.length;t.selectionStart=o,t.selectionEnd=o,t.dispatchEvent(new Event(`input`,{bubbles:!0})),this._liveRegion?.announce(`Inserted mention: ${e.name}`),this.closeMention(),t.focus()},closeMention(){this.mentionActive=!1,this.mentionQuery=``,this.mentionResults=[],this.mentionSelectedIndex=0,this.mentionStart=-1,this.mentionLoading=!1,this._debounceTimer&&=(clearTimeout(this._debounceTimer),null),this._requestAborter&&=(this._requestAborter(),null)},getDropdownStyle(){let e=this.$refs.mentionInput;return e?(e.getBoundingClientRect(),e.offsetParent?.getBoundingClientRect(),`position: absolute; top: ${e.offsetTop+e.offsetHeight}px; left: ${e.offsetLeft}px; z-index: 50; min-width: 300px; max-width: 400px;`):``},get activeDescendantId(){if(!this.mentionActive||this.mentionResults.length===0)return``;let e=this.mentionResults[this.mentionSelectedIndex];return e?`mention-option-${e.type}-${e.id}`:``},getIcon(e){return this.typeIcons[e]||`๐Ÿ“Œ`},getLabel(e){return this.typeLabels[e]||e},highlightMatch(e,t){if(!e||!t)return this.escapeHTML(e||``);let n=this.escapeHTML(e),r=this.escapeHTML(t),i=RegExp(`(${this._escapeRegex(r)})`,`gi`);return n.replace(i,`$1`)},escapeHTML(e){if(!e)return``;let t=document.createElement(`div`);return t.textContent=e,t.innerHTML},_escapeRegex(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)},_searchMentions(t){this._debounceTimer&&clearTimeout(this._debounceTimer),this._requestAborter&&=(this._requestAborter(),null);let n=t.length<3?300:150;this._debounceTimer=setTimeout(()=>{this.mentionLoading=!0;let n=`/v1/search?q=${encodeURIComponent(t)}&limit=10`;e&&(n+=`&types=${encodeURIComponent(e)}`);let{abort:r,ready:i}=M(n);this._requestAborter=r,i.then(e=>e.json()).then(e=>{this.mentionQuery===t&&(this.mentionResults=e.results||[],this.mentionSelectedIndex=0,this.mentionResults.length>0?this._liveRegion?.announce(`${this.mentionResults.length} suggestion${this.mentionResults.length===1?``:`s`}. Use arrow keys to navigate.`):this._liveRegion?.announce(`No suggestions found.`))}).catch(e=>{e.name!==`AbortError`&&console.error(`Mention search error:`,e)}).finally(()=>{this.mentionLoading=!1})},n)},_scrollToSelected(){this.$nextTick(()=>{let e=this.$refs.mentionDropdown?.querySelector(`[data-mention-selected="true"]`);e&&e.scrollIntoView({block:`nearest`})})},_announceSelected(){let e=this.mentionResults[this.mentionSelectedIndex];if(e){let t=this.getLabel(e.type);this._liveRegion?.announce(`${e.name}, ${t}, ${this.mentionSelectedIndex+1} of ${this.mentionResults.length}`)}}}}function Xc(e={}){return{selectedGroups:[],groupQuery:``,groupResults:[],scope:{subtree:!0,owned_resources:!0,owned_notes:!0,related_m2m:!0,group_relations:!0},fidelity:{resource_blobs:!0,resource_versions:!1,resource_previews:!1,resource_series:!0},schemaDefs:{categories_and_types:!0,tags:!0,group_relation_types:!0},relatedDepth:0,estimateResult:null,job:null,jobInProgress:!1,downloadUrl:``,eventSource:null,init(){let t=(e.preselectedIds||``).split(`,`).map(e=>e.trim()).filter(Boolean);t.length>0&&Promise.all(t.map(e=>fetch(`/v1/group?id=`+encodeURIComponent(e)).then(e=>e.ok?e.json():null).catch(()=>null))).then(e=>{this.selectedGroups=e.filter(e=>e).map(e=>({id:e.ID||e.id,name:e.Name||e.name}))});let n=localStorage.getItem(`adminExport:currentJobId`);n&&(this.downloadUrl=`/v1/exports/`+encodeURIComponent(n)+`/download`,this.job={id:n,status:`pending`,phase:`rehydrating...`},this.jobInProgress=!0,this.subscribeProgress(n,!0))},addGroup(e){this.selectedGroups.some(t=>t.id===e.id)||this.selectedGroups.push(e),this.groupQuery=``,this.groupResults=[]},removeGroup(e){this.selectedGroups=this.selectedGroups.filter(t=>t.id!==e)},async searchGroups(){if(!this.groupQuery){this.groupResults=[];return}let e=`/v1/groups?name=`+encodeURIComponent(this.groupQuery)+`&maxResults=10`;try{let t=await fetch(e);if(!t.ok)return;let n=await t.json();this.groupResults=(Array.isArray(n)?n:n.items||[]).map(e=>({id:e.ID||e.id,name:e.Name||e.name}))}catch{this.groupResults=[]}},requestBody(){return{rootGroupIds:this.selectedGroups.map(e=>e.id),scope:this.scope,fidelity:this.fidelity,schemaDefs:this.schemaDefs,relatedDepth:this.relatedDepth}},async estimate(){let e=await fetch(`/v1/groups/export/estimate`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(this.requestBody())});if(!e.ok){this.estimateResult=null;return}this.estimateResult=await e.json()},async submit(){this.jobInProgress=!0;let e=await fetch(`/v1/groups/export`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(this.requestBody())});if(!e.ok){this.jobInProgress=!1;return}let t=await e.json();this.job={id:t.jobId,status:`pending`,phase:`queued`},this.downloadUrl=`/v1/exports/`+encodeURIComponent(t.jobId)+`/download`,localStorage.setItem(`adminExport:currentJobId`,t.jobId),this.subscribeProgress(t.jobId,!1)},subscribeProgress(e,t=!1){this.eventSource&&this.eventSource.close(),this.eventSource=new EventSource(`/v1/jobs/events`);let n=(e,t=!1)=>{this.job=e,this.jobInProgress=!1,this.eventSource&&=(this.eventSource.close(),null),t&&this.triggerDownload()},r=r=>{!r.job||r.job.id!==e||(this.job=r.job,r.job.status===`completed`?n(r.job,!t):(r.job.status===`failed`||r.job.status===`cancelled`)&&n(r.job,!1))},i=e=>{try{r(JSON.parse(e.data))}catch{}};this.eventSource.addEventListener(`init`,n=>{try{let i=(JSON.parse(n.data).jobs||[]).find(t=>t.id===e);i?r({job:i}):t&&(localStorage.removeItem(`adminExport:currentJobId`),this.job=null,this.jobInProgress=!1,this.eventSource&&=(this.eventSource.close(),null))}catch{}}),this.eventSource.addEventListener(`added`,i),this.eventSource.addEventListener(`updated`,i),this.eventSource.addEventListener(`removed`,i)},triggerDownload(){let e=document.createElement(`a`);e.href=this.downloadUrl,e.download=``,document.body.appendChild(e),e.click(),document.body.removeChild(e)},humanBytes(e){if(!e||e<0)return`0 B`;let t=[`B`,`KB`,`MB`,`GB`,`TB`],n=e,r=0;for(;n>=1024&&r=10||r===0?0:1)+` `+t[r]},danglingEntries(){return!this.estimateResult||!this.estimateResult.danglingByKind?[]:Object.entries(this.estimateResult.danglingByKind).map(([e,t])=>({kind:e,count:t}))},canCancel(){return this.job?[`pending`,`processing`,`downloading`,`running`,`queued`].includes(this.job.status):!1},async cancel(){if(this.job)try{await fetch(`/v1/jobs/cancel?id=`+encodeURIComponent(this.job.id),{method:`POST`}),localStorage.removeItem(`adminExport:currentJobId`)}catch{}}}}function Zc(){return{selectedFile:null,uploading:!1,jobId:null,job:null,plan:null,error:null,eventSource:null,decisions:{parent_group_id:null,resource_collision_policy:`skip`,guid_collision_policy:`merge`,acknowledge_missing_hashes:!1,mapping_actions:{},dangling_actions:{},excluded_items:[],shell_group_actions:{}},parentGroupQuery:``,parentGroupResults:[],parentGroupName:``,flattenedItems:[],applying:!1,applyJobId:null,applyJob:null,applyPhase:``,applyResult:null,applyEventSource:null,destroy(){this.eventSource&&=(this.eventSource.close(),null),this.closeApplySSE()},async upload(){if(this.selectedFile){this.uploading=!0,this.error=null,this.plan=null,this.jobId=null;try{let e=new FormData;e.append(`file`,this.selectedFile);let t=await fetch(`/v1/groups/import/parse`,{method:`POST`,body:e});if(!t.ok){let e=await t.text();throw Error(e||`HTTP ${t.status}`)}let n=await t.json();this.jobId=n.jobId,this.subscribeProgress(n.jobId)}catch(e){this.error=e.message}finally{this.uploading=!1}}},subscribeProgress(e){this.eventSource&&this.eventSource.close(),this.eventSource=new EventSource(`/v1/jobs/events`);let t=t=>{!t.job||t.job.id!==e||(this.job=t.job,t.job.status===`completed`?(this.onParseComplete(e),this.closeSSE()):(t.job.status===`failed`||t.job.status===`cancelled`)&&(this.error=t.job.error||`Job ${t.job.status}`,this.closeSSE()))},n=e=>{try{t(JSON.parse(e.data))}catch{}};this.eventSource.addEventListener(`init`,n=>{try{let r=(JSON.parse(n.data).jobs||[]).find(t=>t.id===e);r&&t({job:r})}catch{}}),this.eventSource.addEventListener(`added`,n),this.eventSource.addEventListener(`updated`,n),this.eventSource.addEventListener(`removed`,n)},async onParseComplete(e){try{let t=await fetch(`/v1/imports/${encodeURIComponent(e)}/plan`);if(!t.ok)throw Error(`HTTP ${t.status}`);this.plan=await t.json(),this.initDecisionsFromPlan()}catch(e){this.error=`Failed to load import plan: `+e.message}},initDecisionsFromPlan(){if(!this.plan)return;let e=[...this.plan.mappings.categories||[],...this.plan.mappings.note_types||[],...this.plan.mappings.resource_categories||[],...this.plan.mappings.tags||[],...this.plan.mappings.group_relation_types||[]];for(let t of e){let e=t.decision_key;t.suggestion&&!t.ambiguous?this.decisions.mapping_actions[e]={include:!0,action:t.suggestion,destination_id:t.destination_id||null}:this.decisions.mapping_actions[e]={include:!0,action:``,destination_id:null}}for(let e of this.plan.dangling_refs||[])this.decisions.dangling_actions[e.id]={action:`drop`};let t=e=>{for(let n of e)n.shell&&(this.decisions.shell_group_actions[n.export_id]={action:`create`,destination_id:null}),n.children?.length&&t(n.children)};t(this.plan.items||[]),this.flattenedItems=[];let n=(e,t)=>{for(let r of e)this.flattenedItems.push({export_id:r.export_id,name:r.name,depth:t,shell:r.shell||!1,descendant_resource_count:r.descendant_resource_count||0,descendant_note_count:r.descendant_note_count||0,item:r}),r.children?.length&&n(r.children,t+1)};n(this.plan.items||[],0)},closeSSE(){this.eventSource&&=(this.eventSource.close(),null)},getMappingAction(e){let t=e.decision_key;return this.decisions.mapping_actions[t]?.action||(e.ambiguous?``:e.suggestion||`create`)},hasIncompleteDecisions(){if(!this.plan)return!1;if([...this.plan.mappings.categories||[],...this.plan.mappings.note_types||[],...this.plan.mappings.resource_categories||[],...this.plan.mappings.tags||[],...this.plan.mappings.group_relation_types||[]].some(e=>{let t=this.decisions.mapping_actions[e.decision_key];return t?.include===!1?!1:!!(e.ambiguous&&!t?.action||t?.action===`map`&&!t.destination_id)}))return!0;for(let e of this.plan.dangling_refs||[]){let t=this.decisions.dangling_actions[e.id];if(t?.action===`map`&&!t.destination_id)return!0}for(let[e,t]of Object.entries(this.decisions.shell_group_actions))if(!this.decisions.excluded_items.includes(e)&&t.action===`map_to_existing`&&!t.destination_id)return!0;return this.plan.manifest_only_missing_hashes>0&&!this.decisions.acknowledge_missing_hashes},setMappingAction(e,t){let n=e.decision_key;this.decisions.mapping_actions[n]||(this.decisions.mapping_actions[n]={}),this.decisions.mapping_actions[n].action=t,t===`map`&&e.destination_id?this.decisions.mapping_actions[n].destination_id=e.destination_id:t===`create`&&(this.decisions.mapping_actions[n].destination_id=null)},setMappingDest(e,t){let n=e.decision_key;this.decisions.mapping_actions[n]||(this.decisions.mapping_actions[n]={action:`map`}),this.decisions.mapping_actions[n].destination_id=t?parseInt(t,10):null},isMappingIncluded(e){let t=this.decisions.mapping_actions[e.decision_key];return t?t.include!==!1:!0},toggleMappingInclude(e,t){let n=e.decision_key;this.decisions.mapping_actions[n]?this.decisions.mapping_actions[n].include=t:this.decisions.mapping_actions[n]={include:t,action:e.suggestion||`create`,destination_id:null}},mappingSearchResults:{},mappingDestOverride(e){let t=e.decision_key,n=this.decisions.mapping_actions[t]?.destination_id;return n&&n!==e.destination_id},getMappingDestId(e){return this.decisions.mapping_actions[e.decision_key]?.destination_id},async searchMappingDest(e,t){if(!t){this.mappingSearchResults[e.decision_key]=[];return}let n={categories:`/v1/categories`,note_types:`/v1/note/noteTypes`,resource_categories:`/v1/resourceCategories`,tags:`/v1/tags`,group_relation_types:`/v1/relationTypes`},r=`/v1/categories`;for(let[t,i]of Object.entries(n))if((this.plan.mappings[t]||[]).some(t=>t.decision_key===e.decision_key)){r=i;break}try{let n=await fetch(r+`?name=`+encodeURIComponent(t)+`&maxResults=8`);if(!n.ok)return;let i=await n.json(),a=Array.isArray(i)?i:i.items||[];this.mappingSearchResults[e.decision_key]=a.map(e=>({id:e.ID||e.id,name:e.Name||e.name}))}catch{this.mappingSearchResults[e.decision_key]=[]}},danglingSearchResults:{},danglingDestNames:{},shellGroupSearchResults:{},shellGroupDestNames:{},setDanglingAction(e,t,n){this.decisions.dangling_actions[e]={action:t,destination_id:n||null},t===`drop`&&delete this.danglingDestNames[e]},getDanglingAction(e){return this.decisions.dangling_actions[e]?.action||`drop`},getDanglingDest(e){return this.decisions.dangling_actions[e]?.destination_id},getDanglingDestName(e){return this.danglingDestNames[e]||``},setDanglingDest(e,t,n){this.decisions.dangling_actions[e]||(this.decisions.dangling_actions[e]={action:`map`}),this.decisions.dangling_actions[e].destination_id=t,this.danglingDestNames[e]=n,this.danglingSearchResults[e]=[]},async searchDanglingDest(e,t){let n={related_group:`/v1/groups`,group_relation:`/v1/groups`,related_resource:`/v1/resources`,related_note:`/v1/notes`,resource_series_sibling:`/v1/resources`}[e.kind]||`/v1/groups`;if(!t){this.danglingSearchResults[e.id]=[];return}try{let r=await fetch(n+`?name=`+encodeURIComponent(t)+`&maxResults=8`);if(!r.ok)return;let i=await r.json(),a=Array.isArray(i)?i:i.items||[];this.danglingSearchResults[e.id]=a.map(e=>({id:e.ID||e.id,name:e.Name||e.name}))}catch{this.danglingSearchResults[e.id]=[]}},getShellAction(e){return this.decisions.shell_group_actions[e]?.action||`create`},setShellAction(e,t){this.decisions.shell_group_actions[e]||(this.decisions.shell_group_actions[e]={}),this.decisions.shell_group_actions[e].action=t,t===`create`&&(this.decisions.shell_group_actions[e].destination_id=null,delete this.shellGroupDestNames[e])},setShellDest(e,t,n){this.decisions.shell_group_actions[e]||(this.decisions.shell_group_actions[e]={action:`map_to_existing`}),this.decisions.shell_group_actions[e].destination_id=t,this.shellGroupDestNames[e]=n,this.shellGroupSearchResults[e]=[]},async searchShellDest(e,t){if(!t){this.shellGroupSearchResults[e]=[];return}try{let n=await fetch(`/v1/groups?name=`+encodeURIComponent(t)+`&maxResults=8`);if(!n.ok)return;let r=await n.json(),i=Array.isArray(r)?r:r.items||[];this.shellGroupSearchResults[e]=i.map(e=>({id:e.ID||e.id,name:e.Name||e.name}))}catch{this.shellGroupSearchResults[e]=[]}},isExcluded(e){return this.decisions.excluded_items.includes(e)},toggleItem(e,t){t?this.includeItemRecursive(e):this.excludeItemRecursive(e)},excludeItemRecursive(e){this.decisions.excluded_items.includes(e.export_id)||this.decisions.excluded_items.push(e.export_id);for(let t of e.children||[])this.excludeItemRecursive(t)},includeItemRecursive(e){this.decisions.excluded_items=this.decisions.excluded_items.filter(t=>t!==e.export_id);for(let t of e.children||[])this.includeItemRecursive(t)},async searchParentGroups(){if(!this.parentGroupQuery){this.parentGroupResults=[];return}try{let e=await fetch(`/v1/groups?name=`+encodeURIComponent(this.parentGroupQuery)+`&maxResults=10`);if(!e.ok)return;let t=await e.json();this.parentGroupResults=(Array.isArray(t)?t:t.items||[]).map(e=>({id:e.ID||e.id,name:e.Name||e.name}))}catch{this.parentGroupResults=[]}},humanBytes(e){if(!e||e<0)return`0 B`;let t=[`B`,`KB`,`MB`,`GB`,`TB`],n=e,r=0;for(;n>=1024&&r=10||r===0?0:1)+` `+t[r]},canCancel(){return this.job?[`pending`,`processing`,`downloading`,`running`,`queued`].includes(this.job.status):!1},async cancel(){if(this.job)try{await fetch(`/v1/jobs/cancel?id=`+encodeURIComponent(this.job.id),{method:`POST`})}catch{}},async apply(){if(!(this.hasIncompleteDecisions()||this.applying)){this.applying=!0,this.applyResult=null,this.applyJob=null,this.applyPhase=``,this.error=null;try{let e=await fetch(`/v1/imports/${encodeURIComponent(this.jobId)}/apply`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(this.decisions)});if(!e.ok){let t=await e.text();throw Error(t||`HTTP ${e.status}`)}let t=await e.json();this.applyJobId=t.jobId,this.subscribeApplyProgress(t.jobId)}catch(e){this.error=e.message,this.applying=!1}}},subscribeApplyProgress(e){this.closeApplySSE(),this.applyEventSource=new EventSource(`/v1/jobs/events`);let t=t=>{!t.job||t.job.id!==e||(this.applyJob=t.job,this.applyPhase=t.job.phase||``,t.job.status===`completed`?(this.applying=!1,this.fetchApplyResult(),this.closeApplySSE()):(t.job.status===`failed`||t.job.status===`cancelled`)&&(this.applying=!1,this.error=t.job.error||`Apply job ${t.job.status}`,this.fetchApplyResult(),this.closeApplySSE()))},n=e=>{try{t(JSON.parse(e.data))}catch{}};this.applyEventSource.addEventListener(`init`,n=>{try{let r=(JSON.parse(n.data).jobs||[]).find(t=>t.id===e);r&&t({job:r})}catch{}}),this.applyEventSource.addEventListener(`added`,n),this.applyEventSource.addEventListener(`updated`,n),this.applyEventSource.addEventListener(`removed`,n)},async fetchApplyResult(){try{let e=await fetch(`/v1/imports/${encodeURIComponent(this.jobId)}/result`);if(!e.ok)return;this.applyResult=await e.json()}catch{}},closeApplySSE(){this.applyEventSource&&=(this.applyEventSource.close(),null)},async cancelApply(){if(this.applyJobId)try{await fetch(`/v1/jobs/cancel?id=`+encodeURIComponent(this.applyJobId),{method:`POST`})}catch{}}}}function Qc(){return{serverStats:null,serverStatsLoading:!0,serverStatsError:null,_serverStatsAborter:null,_pollInterval:null,dataStats:null,dataStatsLoading:!0,dataStatsError:null,_dataStatsAborter:null,expensiveStats:null,expensiveStatsLoading:!0,expensiveStatsError:null,_expensiveStatsAborter:null,init(){this.fetchServerStats(),this.fetchDataStats(),this.fetchExpensiveStats(),this._pollInterval=setInterval(()=>{this.fetchServerStats()},1e4)},destroy(){this._pollInterval&&=(clearInterval(this._pollInterval),null),this._serverStatsAborter&&=(this._serverStatsAborter(),null),this._dataStatsAborter&&=(this._dataStatsAborter(),null),this._expensiveStatsAborter&&=(this._expensiveStatsAborter(),null)},fetchServerStats(){this._serverStatsAborter&&this._serverStatsAborter();let{abort:e,ready:t}=M(`/v1/admin/server-stats`);this._serverStatsAborter=e,t.then(e=>{if(!e.ok)throw Error(`HTTP ${e.status}`);return e.json()}).then(e=>{this.serverStats=e,this.serverStatsError=null,this.serverStatsLoading=!1}).catch(e=>{e.name!==`AbortError`&&(this.serverStatsError=e.message||`Failed to load server stats`,this.serverStatsLoading=!1)}).finally(()=>{this._serverStatsAborter=null})},fetchDataStats(){this._dataStatsAborter&&this._dataStatsAborter();let{abort:e,ready:t}=M(`/v1/admin/data-stats`);this._dataStatsAborter=e,t.then(e=>{if(!e.ok)throw Error(`HTTP ${e.status}`);return e.json()}).then(e=>{this.dataStats=e,this.dataStatsError=null,this.dataStatsLoading=!1}).catch(e=>{e.name!==`AbortError`&&(this.dataStatsError=e.message||`Failed to load data stats`,this.dataStatsLoading=!1)}).finally(()=>{this._dataStatsAborter=null})},fetchExpensiveStats(){this._expensiveStatsAborter&&this._expensiveStatsAborter();let{abort:e,ready:t}=M(`/v1/admin/data-stats/expensive`);this._expensiveStatsAborter=e,t.then(e=>{if(!e.ok)throw Error(`HTTP ${e.status}`);return e.json()}).then(e=>{this.expensiveStats=e,this.expensiveStatsError=null,this.expensiveStatsLoading=!1}).catch(e=>{e.name!==`AbortError`&&(this.expensiveStatsError=e.message||`Failed to load detailed statistics`,this.expensiveStatsLoading=!1)}).finally(()=>{this._expensiveStatsAborter=null})},formatNumber(e){return e==null?`0`:e>=1e6?(e/1e6).toFixed(2).replace(/\.?0+$/,``)+`M`:e>=1e3?(e/1e3).toFixed(1).replace(/\.?0+$/,``)+`K`:e.toLocaleString()}}}function $c({apiUrl:e,entityType:t,defaultView:n}){return{apiUrl:e,entityType:t,defaultView:n,timelineMode:`created`,granularity:`month`,anchor:new Date().toISOString().slice(0,10),columns:12,buckets:[],hasMore:{left:!0,right:!1},selectedBar:null,selectedBarType:null,previewHtml:``,previewTitle:``,previewTotalCount:0,loading:!1,error:null,maxCount:0,_resizeObserver:null,_fetchAborter:null,_previewAborter:null,init(){this.calculateColumns(),this.fetchBuckets(),this._resizeObserver=new ResizeObserver(()=>{let e=this.$el?this.$el.clientWidth:720,t=Math.max(5,Math.min(30,Math.floor(e/60)));t!==this.columns&&(this.columns=t,this.fetchBuckets())}),this._resizeObserver.observe(this.$el)},destroy(){this._resizeObserver&&=(this._resizeObserver.disconnect(),null),this._fetchAborter&&=(this._fetchAborter(),null),this._previewAborter&&=(this._previewAborter(),null)},calculateColumns(){let e=this.$el?this.$el.clientWidth:720,t=Math.floor(e/60);return this.columns=Math.max(5,Math.min(30,t)),this.columns},get rangeLabel(){if(!this.buckets||this.buckets.length===0)return``;let e=this.buckets[0].label,t=this.buckets[this.buckets.length-1].label;return e===t?e:e+` โ€” `+t},barHeight(e){return!this.maxCount||this.maxCount===0?`0%`:Math.max(2,e/this.maxCount*100)+`%`},async fetchBuckets(){this._fetchAborter&&=(this._fetchAborter(),null),this.loading=!0,this.error=null;let e=new URLSearchParams(window.location.search);e.set(`granularity`,{year:`yearly`,month:`monthly`,week:`weekly`}[this.granularity]||`monthly`),e.set(`anchor`,this.anchor),e.set(`columns`,String(this.columns));try{let{abort:t,ready:n}=M(this.apiUrl+`?`+e.toString());this._fetchAborter=t;let r=await n;if(!r.ok)throw Error(`HTTP `+r.status);let i=await r.json();this.buckets=i.buckets||[],this.hasMore=i.hasMore||{left:!0,right:!1},this.maxCount=0;let a=this.timelineMode;for(let e of this.buckets){let t=e[a]||0;t>this.maxCount&&(this.maxCount=t)}this.loading=!1,this.renderChart()}catch(e){e.name!==`AbortError`&&(this.error=e.message||`Failed to load timeline data`,this.loading=!1)}finally{this._fetchAborter=null}},setTimelineMode(e){this.timelineMode=e,this.closePreview(),this.maxCount=0;for(let t of this.buckets){let n=t[e]||0;n>this.maxCount&&(this.maxCount=n)}this.renderChart()},setGranularity(e){this.granularity=e,this.anchor=new Date().toISOString().slice(0,10),this.closePreview(),this.fetchBuckets()},prev(){this.buckets.length>0&&(this.anchor=this.buckets[0].start.slice(0,10)),this.closePreview(),this.fetchBuckets()},next(){if(this.hasMore.right){if(this.buckets.length>0){let e=new Date(this.buckets[0].start),t=new Date(this.anchor+`T00:00:00Z`),n=t.getTime()-e.getTime(),r=new Date(t.getTime()+n),i=new Date().toISOString().slice(0,10),a=r.toISOString().slice(0,10);this.anchor=a>i?i:a}this.closePreview(),this.fetchBuckets()}},renderChart(){let e=this.$refs.chart;if(!e)return;if(e.innerHTML=``,this.buckets.length===0||this.maxCount===0){e.innerHTML=`

No activity in this period.

`;return}let t=document.createElement(`div`);t.className=`timeline-chart-row`;let n=document.createElement(`div`);n.className=`timeline-y-axis`,this._yAxisTicks(this.maxCount).forEach(e=>{let t=document.createElement(`div`);t.className=`timeline-y-tick`,t.style.bottom=e.value/this.maxCount*100+`%`;let r=document.createElement(`span`);r.className=`timeline-y-label`,r.textContent=e.label,t.appendChild(r),n.appendChild(t)});let r=document.createElement(`div`);r.className=`timeline-bars-row`,t.appendChild(n),t.appendChild(r);let i=document.createElement(`div`);i.className=`timeline-labels-row`;let a=this.timelineMode,o=a===`created`?`timeline-bar-created`:`timeline-bar-updated`;this.buckets.forEach((e,t)=>{let n=e[a]||0,s=e.label+` โ€” `+n+` `+a,c=document.createElement(`div`);if(c.className=`timeline-bucket-col`,c.title=s,n>0){let e=document.createElement(`button`);e.type=`button`,e.className=`timeline-bar `+o+(this.selectedBar===t?` selected`:``),e.style.height=this.barHeight(n),e.setAttribute(`aria-label`,s),e.addEventListener(`click`,()=>this.selectBar(t,a)),c.appendChild(e)}else{let e=document.createElement(`div`);e.className=`timeline-bar-empty`,c.appendChild(e)}r.appendChild(c);let l=document.createElement(`div`);l.className=`timeline-label-cell`;let u=document.createElement(`span`);u.className=`timeline-label`,u.textContent=this._shortLabel(e.label,t),l.appendChild(u),i.appendChild(l)}),e.appendChild(t),e.appendChild(i)},_buildDateParams(e,t){let n=new URLSearchParams(window.location.search);n.delete(`page`);let r=e.start.slice(0,10),i=e.end.slice(0,10);return t===`created`?(n.set(`CreatedAfter`,r),n.set(`CreatedBefore`,i)):(n.set(`UpdatedAfter`,r),n.set(`UpdatedBefore`,i)),n},get showAllUrl(){if(this.selectedBar===null)return`#`;let e=this.buckets[this.selectedBar];if(!e)return`#`;let t=this._buildDateParams(e,this.selectedBarType);return this.defaultView+`?`+t.toString()},async selectBar(e,t){if(this.selectedBar===e&&this.selectedBarType===t){this._previewAborter&&=(this._previewAborter(),null),this.closePreview(),this.renderChart();return}let n=this.buckets[e];if(!n)return;this.selectedBar=e,this.selectedBarType=t;let r=n[t]||0;this.previewTitle=n.label+` โ€” `+r+` `+t,this.previewTotalCount=r,this.renderChart(),this._previewAborter&&=(this._previewAborter(),null);let i=this._buildDateParams(n,t);i.set(`pageSize`,`20`);try{let{abort:e,ready:t}=M(this.defaultView+`.body?`+i.toString());this._previewAborter=e;let n=await t;if(!n.ok)throw Error(`HTTP `+n.status);this.previewHtml=await n.text(),this.$nextTick(()=>{window.Alpine?.store(`lightbox`)?.initFromDOM()})}catch(e){e.name!==`AbortError`&&(console.error(`Failed to load preview:`,e),this.previewHtml=``)}finally{this._previewAborter=null}},_yAxisTicks(e){if(e<=0)return[];let t=e/4,n=10**Math.floor(Math.log10(t)),r=[1,2,5,10].find(e=>e*n>=t)*n;r=Math.max(1,r);let i=[];for(let t=0;t<=e;t+=r)t!==0&&i.push({value:t,label:t>=1e3?(t/1e3).toFixed(t%1e3==0?0:1)+`k`:String(t)});return i},_shortLabel(e,t){if(this.buckets.length<=10)return e;let n=e.match(/^(\d{4})-(\d{2})$/);if(n){let e=n[1],r=n[2],i=(t>0?this.buckets[t-1].label:``).slice(0,4);return t===0||e!==i?e+`-`+r:r}return e},closePreview(){this.selectedBar=null,this.selectedBarType=null,this.previewHtml=``,this.previewTitle=``,this.previewTotalCount=0}}}function el(e){return e.replace(/~/g,`~0`).replace(/\//g,`~1`)}function tl(e){return e.replace(/~1/g,`/`).replace(/~0/g,`~`)}function P(e,t){if(typeof e!=`string`||!e.startsWith(`#/`))return null;let n=e.split(`/`).slice(1),r=t;for(let e of n){let t=tl(e);if(r&&typeof r==`object`&&t in r)r=r[t];else return null}return r}function F(e,t,n=`intersect`){let r={...e};for(let i in t)if(i===`properties`){let i=e.properties||{},a=t.properties||{};r.properties={...i};for(let e in a)if(i[e]&&a[e]){let t=i[e],o=a[e];if(t.properties&&o.properties||t.required&&o.required)r.properties[e]=F(t,o,n);else{let i=t.type,a=o.type,s=new Set([`number`,`integer`]),c={...t,...o};i&&a&&i!==a&&(c.type=s.has(i)&&s.has(a)?`number`:`string`);let l=t.enum,u=o.enum;if(l&&u)if(n===`union`){let e=[...l];for(let t of u)e.some(e=>e===t&&typeof e==typeof t)||e.push(t);c.enum=e}else c.enum=l.filter(e=>u.some(t=>t===e&&typeof t==typeof e));r.properties[e]=c}}else r.properties[e]=a[e]}else i===`required`?r.required=[...new Set([...e.required||[],...t.required||[]])]:i===`$ref`||([`allOf`,`anyOf`,`oneOf`].includes(i)&&r[i]&&Array.isArray(r[i])?r[i]=[...r[i],...t[i]]:r[i]=t[i]);return r}function nl(e,t){if(!e)return e;if(e.$ref){let n=P(e.$ref,t);if(n){let r={...e};return delete r.$ref,nl(F(n,r),t)}return null}for(let n of[`allOf`,`oneOf`,`anyOf`])if(e[n]&&Array.isArray(e[n])){let r={...e};delete r[n];for(let i of e[n]){let e;if(i.$ref){let n=P(i.$ref,t),r={...i};delete r.$ref,e=n?F(n,r):r}else e=i;e&&(r=F(r,e,n===`allOf`?`intersect`:`union`))}if(n!==`allOf`&&r.properties)for(let[i,a]of Object.entries(r.properties))a.enum&&e[n].some(e=>{let n=e;if(e.$ref){let r=P(e.$ref,t);if(r){let t={...e};delete t.$ref,n=F(r,t)}}let r=n.properties?.[i];return r&&!r.enum})&&delete a.enum;return nl(r,t)}return e}function rl(e){if(Array.isArray(e))return`array`;if(e===null)return`null`;let t=typeof e;return t===`number`?Number.isInteger(e)?`integer`:`number`:t}function il(e){let t=rl(e);if(t===`object`)return{type:`object`,properties:{}};if(t===`array`){let t=e;return{type:`array`,items:t.length?il(t[0]):{type:`string`}}}return{type:t}}function I(e,t,n){if(!e)return!0;if(e.$ref&&n){let r=P(e.$ref,n);if(r){let i={...e};return delete i.$ref,I(F(r,i),t,n)}}if(e.allOf&&Array.isArray(e.allOf)){for(let r of e.allOf)if(!I(r,t,n))return!1}if(e.anyOf&&Array.isArray(e.anyOf)&&!e.anyOf.some(e=>I(e,t,n))||e.oneOf&&Array.isArray(e.oneOf)&&e.oneOf.filter(e=>I(e,t,n)).length!==1||e.not&&I(e.not,t,n)||e.const!==void 0&&t!==e.const||e.enum&&!e.enum.includes(t))return!1;if(e.type){let n=rl(t),r=e.type;if(typeof r==`string`){if(r!==n&&!(r===`number`&&n===`integer`))return!1}else if(Array.isArray(r)&&!r.includes(n)&&!(n===`integer`&&r.includes(`number`)))return!1}if(e.minimum!==void 0&&(typeof t!=`number`||te.maximum)||e.exclusiveMinimum!==void 0&&(typeof t!=`number`||t<=e.exclusiveMinimum)||e.exclusiveMaximum!==void 0&&(typeof t!=`number`||t>=e.exclusiveMaximum)||e.minLength!==void 0&&(typeof t!=`string`||t.lengthe.maxLength))return!1;if(e.pattern&&typeof t==`string`)try{if(!new RegExp(e.pattern).test(t))return!1}catch{}if(e.minItems!==void 0&&(!Array.isArray(t)||t.lengthe.maxItems))return!1;if(e.required&&Array.isArray(e.required)){for(let n of e.required)if(t?.[n]===void 0)return!1}if(e.properties)for(let r in e.properties){let i=e.properties[r],a=t?.[r];if(i.$ref&&n){let e=P(i.$ref,n);if(e){let t={...i};delete t.$ref,i=F(e,t)}}if(a!==void 0){if(i.properties||i.allOf||i.anyOf||i.oneOf||i.not){if(!I(i,a,n))return!1;continue}if(i.const!==void 0&&a!==i.const||i.enum&&!i.enum.includes(a))return!1;if(i.type){let e=rl(a),t=i.type;if(typeof t==`string`){if(t!==e&&!(t===`number`&&e===`integer`))return!1}else if(Array.isArray(t)&&!t.includes(e)&&!(e===`integer`&&t.includes(`number`)))return!1}if(i.minimum!==void 0&&(typeof a!=`number`||ai.maximum)||i.exclusiveMinimum!==void 0&&(typeof a!=`number`||a<=i.exclusiveMinimum)||i.exclusiveMaximum!==void 0&&(typeof a!=`number`||a>=i.exclusiveMaximum)||i.minLength!==void 0&&(typeof a!=`string`||a.lengthi.maxLength))return!1;if(i.pattern&&typeof a==`string`)try{if(!new RegExp(i.pattern).test(a))return!1}catch{}if(i.minItems!==void 0&&(!Array.isArray(a)||a.lengthi.maxItems))return!1}}return!0}function al(e,t,n){if(e.$ref){let t=P(e.$ref,n);if(t){let n={...e};delete n.$ref,e=F(t,n)}}if(e.allOf&&Array.isArray(e.allOf)){let t={...e};delete t.allOf;for(let r of e.allOf){let e=r.$ref?P(r.$ref,n):r;if(e){let n=r.$ref?(()=>{let e={...r};return delete e.$ref,e})():{};t=F(t,r.$ref?F(e,n):e)}}e=t}else for(let r of[`oneOf`,`anyOf`])if(e[r]&&Array.isArray(e[r])){let i={...e};delete i[r];let a=-1;for(let o of e[r]){let e=al(F(i,o.$ref?(()=>{let e=P(o.$ref,n),t={...o};return delete t.$ref,e?F(e,t):t})():o),t,n);e>a&&(a=e)}return a>=0?a:0}if(e.const!==void 0)return e.const===t?100:0;let r=rl(t),i=e.type;if(Array.isArray(i))return i.includes(r)?10:r===`integer`&&i.includes(`number`)?9:r===`null`&&(i.includes(`string`)||i.includes(`number`))?5:0;if(i&&i!==r)return i===`number`&&r===`integer`?9:0;if(r===`object`&&e.properties){let r=Object.keys(t),i=Object.keys(e.properties),a=r.filter(e=>i.includes(e)).length+10;for(let[r,i]of Object.entries(e.properties)){let e=i,o=t[r];if(o===void 0)continue;if(e.const!==void 0)if(o===e.const)a+=50;else return 0;if(e.enum&&Array.isArray(e.enum))if(e.enum.includes(o))a+=20;else return 0;let s=e;if(e.$ref){let t=P(e.$ref,n);if(t){let n={...e};delete n.$ref,s=F(t,n)}}if(s.allOf&&Array.isArray(s.allOf)){let e={...s};delete e.allOf;for(let t of s.allOf){let r=t.$ref?P(t.$ref,n):t;if(r){let n=t.$ref?(()=>{let e={...t};return delete e.$ref,e})():{};e=F(e,t.$ref?F(r,n):r)}}s=e}else if(typeof o==`object`&&o&&!Array.isArray(o)){for(let e of[`oneOf`,`anyOf`])if(s[e]&&Array.isArray(s[e])){let t={...s};delete t[e];let r=[`title`,`description`,`examples`,`deprecated`,`readOnly`,`writeOnly`,`default`,`$comment`];if(Object.keys(t).some(e=>!r.includes(e))){let e=al(t,o,n);if(e===0)return 0;a+=e-10}let i=-1;for(let t of s[e]){let e=al(t,o,n);e>i&&(i=e)}if(i===0)return 0;i>0&&(a+=i-10),s={};break}}if(s.properties&&typeof o==`object`&&o&&!Array.isArray(o)){let e=al(s,o,n);if(e===0)return 0;a+=e-10}}if(e.required&&Array.isArray(e.required))for(let n of e.required)t[n]===void 0&&(a-=5);return a}if(r===`object`&&e.required&&Array.isArray(e.required)){let n=10;for(let r of e.required)t[r]===void 0&&(n-=5);return n}return 10}function L(e,t){if(e.$ref){let n=P(e.$ref,t||e);if(n){let r={...e};return delete r.$ref,L(F(n,r),t)}}if(e.allOf&&Array.isArray(e.allOf)){let n={...e};delete n.allOf;for(let r of e.allOf){let i;if(r.$ref){let n=P(r.$ref,t||e),a={...r};delete a.$ref,i=n?F(n,a):a}else i=r;i&&(n=F(n,i))}return L(n,t)}if(e.if){let n={...e};delete n.if,delete n.then,delete n.else;let r=L(n,t);return L(F(n,I(e.if,r,t)?e.then||{}:e.else||{}),t)}if(e.default!==void 0)return e.default;if(e.const!==void 0)return e.const;if(e.enum&&Array.isArray(e.enum)&&e.enum.length>0)return e.enum[0];if(e.type===`object`){if(!e.properties)return{};let n={};for(let[r,i]of Object.entries(e.properties))n[r]=L(i,t);return n}if(e.type===`array`)return[];if(e.type===`boolean`)return!1;if(e.type===`number`||e.type===`integer`)return 0;if(e.type===`null`)return null;if(Array.isArray(e.type)){if(e.type.includes(`string`))return``;if(e.type.includes(`number`)||e.type.includes(`integer`))return 0;if(e.type.includes(`boolean`))return!1;if(e.type.includes(`object`))return{};if(e.type.includes(`array`))return[];if(e.type.includes(`null`))return null}if(e.oneOf&&e.oneOf.length>0)return z(e)?e.oneOf[0].const:L(e.oneOf[0],t);if(e.anyOf&&e.anyOf.length>0)return L(e.anyOf[0],t);if(e.properties){let n={};for(let[r,i]of Object.entries(e.properties))n[r]=L(i,t);return n}return``}function R(e,t){if(e.$ref){let n=P(e.$ref,t||e);if(n){let r={...e};return delete r.$ref,R(F(n,r),t)}}if(e.allOf&&Array.isArray(e.allOf)){let n={...e};delete n.allOf;for(let r of e.allOf){let i;if(r.$ref){let n=P(r.$ref,t||e),a={...r};delete a.$ref,i=n?F(n,a):a}else i=r;i&&(n=F(n,i))}return R(n,t)}if(e.if){let n={...e};delete n.if,delete n.then,delete n.else;let r=R(n,t);return R(F(n,I(e.if,r,t)?e.then||{}:e.else||{}),t)}if(e.default!==void 0)return e.default;if(e.const!==void 0)return e.const;if(e.enum&&Array.isArray(e.enum)&&e.enum.length>0)return e.enum[0];if(e.type===`object`){if(!e.properties)return{};let n={};for(let[r,i]of Object.entries(e.properties))n[r]=R(i,t);return n}if(e.type===`array`)return[];if(e.type===`boolean`)return!1;if(!(e.type===`number`||e.type===`integer`)&&e.type!==`string`){if(e.type===`null`)return null;if(Array.isArray(e.type))return e.type.includes(`null`)?null:e.type.includes(`boolean`)?!1:e.type.includes(`object`)?{}:e.type.includes(`array`)?[]:void 0;if(e.oneOf&&e.oneOf.length>0)return z(e)?e.oneOf[0].const:R(e.oneOf[0],t);if(e.anyOf&&e.anyOf.length>0)return R(e.anyOf[0],t);if(e.properties){let n={};for(let[r,i]of Object.entries(e.properties))n[r]=R(i,t);return n}}}function ol(e){return e.replace(/([a-z])([A-Z])/g,`$1 $2`).replace(/[_-]/g,` `).replace(/\b\w/g,e=>e.toUpperCase())}function z(e){if(!e.oneOf||!Array.isArray(e.oneOf)||e.oneOf.length===0)return!1;let t=new Set([`type`,`properties`,`items`,`oneOf`,`anyOf`,`allOf`,`if`,`$ref`,`enum`]);return e.oneOf.every(e=>!e||typeof e!=`object`||e.const===void 0?!1:!Object.keys(e).some(e=>t.has(e)))}function sl(e){return e.oneOf?e.oneOf.map(e=>({value:e.const,label:e.title||String(e.const),...e[`x-color`]?{color:e[`x-color`]}:{}})):[]}function cl(e,t=``,n=``,r=0,i=null){if(r>10||!e)return[];let a=i||e,o=nl(e,a);if(!o||!o.properties)return[];let s=[];for(let[e,i]of Object.entries(o.properties)){let o=t?`${t}.${e}`:e,c=nl(i,a)||i,l=c.title||ol(e),u=n?`${n} โ€บ ${l}`:l;if(z(c)){let e=sl(c),t=c.type||`string`;if(Array.isArray(t)&&(t=t.find(e=>e!==`null`)||`string`),!c.type&&e.length>0){let n=e.find(e=>e.value!==null)?.value??e[0].value;n===null?t=`null`:typeof n==`number`?t=Number.isInteger(n)?`integer`:`number`:typeof n==`boolean`&&(t=`boolean`)}s.push({path:o,label:u,type:t,enum:e.map(e=>e.value),enumLabels:e.map(e=>e.label)});continue}if(c.properties)s.push(...cl(c,o,u,r+1,a));else if(c.type===`array`)continue;else{let e=c.type||`string`;if(Array.isArray(e)&&(e=e.find(e=>e!==`null`)||`string`),!c.type&&Array.isArray(c.enum)&&c.enum.length>0){let t=c.enum.find(e=>e!==null)??c.enum[0];t===null?e=`null`:typeof t==`number`?e=Number.isInteger(t)?`integer`:`number`:typeof t==`boolean`&&(e=`boolean`)}s.push({path:o,label:u,type:e,enum:Array.isArray(c.enum)?c.enum:null,enumLabels:null})}}return s}function ll(e){if(e.length===0)return[];if(e.length===1)return e[0];let t=new Map(e[0].map(e=>[e.path,{...e}]));for(let n=1;ne.path));for(let e of t.keys())r.has(e)||t.delete(e);for(let r of e[n]){let e=t.get(r.path);if(!e)continue;let n=new Set([`number`,`integer`]);if(e.type!==r.type)if(n.has(e.type)&&n.has(r.type))e.type=`number`;else{e.type=`string`,e.enum=null,e.enumLabels=null;continue}if(e.enum&&r.enum){let t=[...e.enum].sort(),n=[...r.enum].sort();JSON.stringify(t)===JSON.stringify(n)?(e.enumLabels||r.enumLabels)&&JSON.stringify(e.enumLabels)!==JSON.stringify(r.enumLabels)&&(e.enumLabels=null):(e.enum=null,e.enumLabels=null)}else e.enum!==r.enum&&(e.enum=null,e.enumLabels=null)}}return Array.from(t.values())}function ul(e){try{let t=JSON.parse(e),n=R(t,t),r=JSON.stringify(n);return r===void 0?`{}`:r}catch{return JSON.stringify({})}}function dl(){return{open:!1,tab:`edit`,rawJson:``,rawJsonValid:!0,rawJsonError:``,rawJsonDirty:!1,currentSchema:``,_textareaEl:null,openModal(e){this._textareaEl=document.getElementById(e);let t=this._textareaEl?.value||``;try{let e=JSON.parse(t||`{"type":"object","properties":{}}`);!e||typeof e!=`object`||Array.isArray(e)?(this.currentSchema=t,this.rawJson=t,this.rawJsonValid=!1,this.rawJsonError=`Schema must be a JSON object`,this.rawJsonDirty=!0):(this.currentSchema=JSON.stringify(e),this.rawJson=JSON.stringify(e,null,2),this.rawJsonValid=!0,this.rawJsonError=``,this.rawJsonDirty=!1)}catch(e){this.currentSchema=t,this.rawJson=t,this.rawJsonValid=!1,this.rawJsonError=e instanceof Error?e.message:`Invalid JSON`,this.rawJsonDirty=!0}this.tab=`edit`,this.open=!0,this.$nextTick(()=>{this.$refs.modalContent?.querySelector(`[autofocus], button, input, select`)?.focus()})},closeModal(){this.open=!1,this.$el.querySelector(`.visual-editor-btn`)?.focus()},handleSchemaChange(e){this.currentSchema=e.detail.schema;try{this.rawJson=JSON.stringify(JSON.parse(this.currentSchema),null,2)}catch{this.rawJson=this.currentSchema}this.rawJsonDirty=!1,this.rawJsonValid=!0,this.rawJsonError=``},handleRawChange(){this.rawJsonDirty=!0;try{let e=JSON.parse(this.rawJson);if(!e||typeof e!=`object`||Array.isArray(e)){this.rawJsonValid=!1,this.rawJsonError=`Schema must be a JSON object`;return}this.rawJsonValid=!0,this.rawJsonError=``,this.currentSchema=this.rawJson,this.rawJsonDirty=!1}catch(e){this.rawJsonValid=!1,this.rawJsonError=e instanceof Error?e.message:`Invalid JSON`}},applySchema(){if(this._textareaEl){try{this._textareaEl.value=JSON.stringify(JSON.parse(this.currentSchema))}catch{this._textareaEl.value=this.currentSchema}this._textareaEl.dispatchEvent(new Event(`input`,{bubbles:!0}))}this.closeModal()},handleKeydown(e){e.key===`Escape`&&this.closeModal()},handleTabKeydown(e){let t=[`edit`,`preview`,`raw`],n=t.indexOf(this.tab);e.key===`ArrowRight`&&(e.preventDefault(),this.tab=t[(n+1)%t.length],this.$nextTick(()=>e.target.closest(`[role="tablist"]`)?.querySelector(`[aria-selected="true"]`)?.focus())),e.key===`ArrowLeft`&&(e.preventDefault(),this.tab=t[(n-1+t.length)%t.length],this.$nextTick(()=>e.target.closest(`[role="tablist"]`)?.querySelector(`[aria-selected="true"]`)?.focus())),e.key===`Home`&&(e.preventDefault(),this.tab=`edit`,this.$nextTick(()=>e.target.closest(`[role="tablist"]`)?.querySelector(`[aria-selected="true"]`)?.focus())),e.key===`End`&&(e.preventDefault(),this.tab=`raw`,this.$nextTick(()=>e.target.closest(`[role="tablist"]`)?.querySelector(`[aria-selected="true"]`)?.focus()))},getPreviewValue(){return ul(this.currentSchema)},getPropertyCount(){try{let e=JSON.parse(this.currentSchema),t=e.properties?Object.keys(e.properties).length:0,n=e.required?e.required.length:0;return`${t} propert${t===1?`y`:`ies`} ยท ${n} required`}catch{return``}}}}function fl(e,t){let n=t===`group`?{ownEntities:{state:`default`,ownNotes:!0,ownGroups:!0,ownResources:!0},relatedEntities:{state:`default`,relatedGroups:!0,relatedResources:!0,relatedNotes:!0},relations:{state:`default`,forwardRelations:!0,reverseRelations:!0},tags:!0,timestamps:!0,metaJson:!0,merge:!0,clone:!0,treeLink:!0,owner:!0,breadcrumb:!0,description:!0,metaSchemaDisplay:!0}:t===`note`?{content:!0,groups:!0,resources:!0,timestamps:!0,tags:!0,metaJson:!0,metaSchemaDisplay:!0,owner:!0,noteTypeLink:!0,share:!0}:{technicalDetails:{state:`default`},metadataGrid:!0,timestamps:!0,notes:!0,groups:!0,series:!0,similarResources:!0,versions:!0,tags:!0,metaJson:!0,previewImage:!0,imageOperations:!0,categoryLink:!0,fileSize:!0,owner:!0,breadcrumb:!0,description:!0,metaSchemaDisplay:!0},r={};try{r=e&&JSON.parse(e)||{}}catch{r={}}let i=JSON.parse(JSON.stringify(n));for(let[e,t]of Object.entries(r))typeof t==`object`&&t&&typeof i[e]==`object`?Object.assign(i[e],t):i[e]=t;return{config:i,type:t}}function pl(e){if(!e)return e;let t=/@\[([a-zA-Z]+):(\d+):([^\]]+)\]/g,n={resource:`/resource`,note:`/note`,group:`/group`,tag:`/tag`};return e.replace(t,(t,r,i,a,o)=>{let s=r.toLowerCase(),c=parseInt(i,10);if(!c)return t;let l=hl(a),u=n[s]||`/`+s;return s===`resource`?ml(e,o,t)?`${l}${l}`:`${l}`:`${l}`})}function ml(e,t,n){let r=e.lastIndexOf(` diff --git a/src/components/lightbox/navigation.js b/src/components/lightbox/navigation.js index f8878b16..d489ae47 100644 --- a/src/components/lightbox/navigation.js +++ b/src/components/lightbox/navigation.js @@ -27,6 +27,11 @@ export const navigationState = { // Reference to trigger element for focus restoration triggerElement: null, + + // Cache of preloaded image URLs (kept in-memory by the Image objects we hold) + _preloadedUrls: new Set(), + _preloadedImages: [], + _preloadAheadCount: 5, }; export const navigationMethods = { @@ -157,6 +162,7 @@ export const navigationMethods = { this.announce(`Opened ${mediaType}: ${item?.name || 'media'}. ${this.currentIndex + 1} of ${this.items.length}`); this.scheduleMediaCheck(); + this._preloadUpcoming(); // Restore quick tag panel from localStorage if it was previously open if (this.quickTagPanelOpen) { @@ -164,6 +170,26 @@ export const navigationMethods = { } }, + _preloadUpcoming() { + const ahead = this._preloadAheadCount || 5; + const end = Math.min(this.items.length, this.currentIndex + 1 + ahead); + for (let i = this.currentIndex + 1; i < end; i++) { + const item = this.items[i]; + if (!item || !this.isImage(item.contentType)) continue; + if (this._preloadedUrls.has(item.viewUrl)) continue; + this._preloadedUrls.add(item.viewUrl); + const img = new Image(); + img.decoding = 'async'; + img.src = item.viewUrl; + this._preloadedImages.push(img); + } + // Cap retained references so the cache cannot grow unboundedly during long sessions. + const cap = (this._preloadAheadCount || 5) * 6; + if (this._preloadedImages.length > cap) { + this._preloadedImages.splice(0, this._preloadedImages.length - cap); + } + }, + close() { this.pauseCurrentVideo(); @@ -224,6 +250,7 @@ export const navigationMethods = { this.loading = true; this.announcePosition(); this.scheduleMediaCheck(); + this._preloadUpcoming(); this.onResourceChange(); } else if (this.hasNextPage) { await this.loadNextPage(); @@ -232,6 +259,7 @@ export const navigationMethods = { this.loading = true; this.announcePosition(); this.scheduleMediaCheck(); + this._preloadUpcoming(); this.onResourceChange(); } } @@ -248,6 +276,7 @@ export const navigationMethods = { this.loading = true; this.announcePosition(); this.scheduleMediaCheck(); + this._preloadUpcoming(); this.onResourceChange(); } else if (this.hasPrevPage) { const prevItemCount = await this.loadPrevPage(); @@ -256,6 +285,7 @@ export const navigationMethods = { this.loading = true; this.announcePosition(); this.scheduleMediaCheck(); + this._preloadUpcoming(); this.onResourceChange(); } }