@moonitoring/nidamjs 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/nidam.umd.js CHANGED
@@ -1 +1 @@
1
- (function(f,y){typeof exports=="object"&&typeof module<"u"?y(exports):typeof define=="function"&&define.amd?define(["exports"],y):(f=typeof globalThis<"u"?globalThis:f||self,y(f.Nidam={}))})(this,(function(f){"use strict";class y{static#t=new WeakSet;static initialize(t,e=document,s=null,i=[]){!Array.isArray(i)||i.length===0||i.forEach(({selector:o,init:n,name:a})=>{if(!o||typeof n!="function")return;e.querySelectorAll(o).forEach(l=>{if(!this.#t.has(l))try{const c=n(l,t,s);this.#t.add(l),a&&c&&s&&typeof s.set=="function"&&s.set(a,c)}catch(c){console.warn(`Failed to initialize ${o}:`,c)}})})}}class b{#t=new Map;#e;#s=new Map;constructor(t=document){this.#e=t,this.#i()}#i(){["click","input","change","focusin","focusout","keydown","mousedown","desktop:toggle-matrix","desktop:theme-changed"].forEach(e=>{const s=i=>this.#o(e,i);this.#e.addEventListener(e,s),this.#s.set(e,s)})}#o(t,e){const s=this.#t.get(t);if(!(!s||s.length===0))for(const{selector:i,handler:o}of s){if(!i){o.call(this.#e,e,this.#e);continue}const n=e.target.closest(i);n&&o.call(n,e,n)}}on(t,e,s,i={}){const o=i.group;this.#t.has(t)||this.#t.set(t,[]);const n={selector:e,handler:s,group:o};return this.#t.get(t).push(n),n}off(t,e){const s=this.#t.get(t);if(!s)return;const i=s.indexOf(e);i!==-1&&s.splice(i,1),s.length||this.#t.delete(t)}destroy(){for(const[t,e]of this.#s)this.#e.removeEventListener(t,e);this.#s.clear(),this.#t.clear()}}const R={moveCursorToEnd(r){const t=document.createRange();t.selectNodeContents(r),t.collapse(!1);const e=window.getSelection();e.removeAllRanges(),e.addRange(t)},onEscape(r){const t=e=>{e.key==="Escape"&&(r(),document.removeEventListener("keydown",t))};return document.addEventListener("keydown",t),t},hide(...r){r.forEach(t=>t?.classList.add("hidden"))},show(...r){r.forEach(t=>t?.classList.remove("hidden"))},toggle(...r){r.forEach(t=>t?.classList.toggle("hidden"))}};class W{_root;_elements={};_state={};_utils=R;_delegator=null;constructor(t,e){if(this._root=typeof t=="string"?document.querySelector(t):t,this._delegator=e,!this._root)throw new Error(`Root element not found: ${t}`);this._initialize()}_initialize(){this._elements=this._cacheElements(),this._bindEvents()}_cacheElements(){return{}}_bindEvents(){}_query(t){return this._root.querySelector(t)}_queryAll(t){return this._root.querySelectorAll(t)}_on(t,e,s){this._delegator.on(t,e,(i,o)=>{this._root.contains(o)&&s.call(this,i,o)})}}const T=new WeakMap;function p(r){return!r||r==="auto"||r==="normal"?"":r}function S(r){return Number.isFinite(r)?`${Math.round(r)}px`:""}function C(r,t={}){const e=t.includePosition===!0;let s=null;const i=()=>(s||(s=window.getComputedStyle(r)),s),o=(r.offsetWidth>0?S(r.offsetWidth):"")||p(r.style.width)||p(i().width),n=(r.offsetHeight>0?S(r.offsetHeight):"")||p(r.style.height)||p(i().height);let a="",d="";return e&&(a=S(r.offsetLeft)||p(r.style.left)||p(i().left),d=S(r.offsetTop)||p(r.style.top)||p(i().top)),{width:o||"",height:n||"",left:a,top:d}}function w(r){let t=T.get(r);return t||(t=new Map,T.set(r,t)),t}function D(r,t="prevState",e={}){const s=C(r,e),i=JSON.stringify(s);return r.dataset[t]=i,w(r).set(t,{raw:i,parsed:s}),s}function v(r,t="prevState"){const e=r.dataset[t];if(!e)return null;const s=w(r).get(t);if(s&&s.raw===e)return s.parsed;try{const i=JSON.parse(e);if(!i||typeof i!="object")return w(r).set(t,{raw:e,parsed:null}),null;const o={width:p(i.width),height:p(i.height),left:p(i.left),top:p(i.top)};return w(r).set(t,{raw:e,parsed:o}),o}catch{return w(r).set(t,{raw:e,parsed:null}),null}}function L(r,t,e={}){return!t||typeof t!="object"?!1:(t.width&&r.style.width!==t.width&&(r.style.width=t.width),t.height&&r.style.height!==t.height&&(r.style.height=t.height),e.includePosition&&(t.left&&r.style.left!==t.left&&(r.style.left=t.left),t.top&&r.style.top!==t.top&&(r.style.top=t.top)),!0)}class I extends W{_config={zIndexBase:40,layoutStabilizationMs:450,cascadeOffset:30,cooldownMs:500,maxWindows:10,snapGap:6,taskbarHeight:64,snapThreshold:30,dragThreshold:10,resizeDebounceMs:6,animationDurationMs:400,defaultWidth:800,defaultHeight:600,minMargin:10,edgeDetectionRatio:.4,scrollRestoreTimeoutMs:2e3};_windows=new Map;_zIndexCounter=this._config.zIndexBase;_getModules=null;_notify=null;_fetchWindowContent=null;_initializeContent=null;_resolveEndpoint=null;_lastOpenTimestamps=new Map;_pendingRequests=new Map;_snapIndicator=null;constructor(t,e,s={}){super(t,e);const{getModules:i=null,config:o=null,notify:n=null,fetchWindowContent:a=null,initializeContent:d=null,resolveEndpoint:l=null}=s||{};this._getModules=i,this._notify=n||this._defaultNotify.bind(this),this._fetchWindowContent=a||this._defaultFetchWindowContent.bind(this),this._initializeContent=d||(()=>{}),this._resolveEndpoint=l||this._defaultResolveEndpoint,o&&typeof o=="object"&&(this._config={...this._config,...o}),this._zIndexCounter=this._config.zIndexBase,this._initSnapIndicator()}_initSnapIndicator(){this._snapIndicator=document.createElement("div"),this._snapIndicator.className="snap-indicator",document.body.appendChild(this._snapIndicator)}_cacheElements(){return{}}_bindEvents(){this._delegator.on("click","[data-modal]",this._handleModalTrigger.bind(this)),this._delegator.on("click","[data-maximize]",this._handleMaximizeTrigger.bind(this)),this._delegator.on("click","[data-close]",this._handleCloseTrigger.bind(this)),this._delegator.on("mousedown",".window",this._handleWindowFocus.bind(this)),this._delegator.on("mousedown","[data-bar]",this._handleWindowDragStart.bind(this)),document.addEventListener("keydown",this._handleGlobalKeydown.bind(this));let t;window.addEventListener("resize",()=>{clearTimeout(t),t=setTimeout(()=>this._handleResize(),this._config.resizeDebounceMs)})}_handleModalTrigger(t,e){t.preventDefault(),this.open(e.dataset.modal).catch(s=>{console.debug("Modal trigger failed:",s)})}_handleCloseTrigger(t,e){t.preventDefault();const s=e.closest(".window");s&&this.close(s)}_handleWindowFocus(t,e){if(t.target.closest("[data-close]")||t.target.closest("[data-modal]"))return;const s=e.closest(".window");s&&this._focusWindow(s)}_handleMaximizeTrigger(t,e){t.preventDefault();const s=e.closest(".window");s&&this.toggleMaximize(s)}_handleWindowDragStart(t,e){if(t.target.closest("[data-close]")||t.target.closest("[data-maximize]"))return;t.preventDefault();const s=e.closest(".window");s&&(this._focusWindow(s),this.drag(t,s))}_handleGlobalKeydown(t){t.key==="Escape"&&!t.repeat&&this._closeTopmostWindow()}toggleMaximize(t){const e=t.classList.contains("maximized"),s=t.classList.contains("tiled")&&typeof t.dataset.snapType=="string"&&t.dataset.snapType.length>0;t.classList.add("window-toggling"),!e&&!t.classList.contains("tiled")&&this._ensureRestoreState(t);const i=t.classList.toggle("maximized");let o=!1;if(this._updateMaximizeIcon(t,i),!i)if(s){const n=this._getSnapLayout(t.dataset.snapType,window.innerWidth,window.innerHeight-this._config.taskbarHeight);Object.assign(t.style,n)}else{const n=v(t);L(t,n);const a=this._parseCssPixelValue(n?.width)||this._parseCssPixelValue(t.style.width)||t.offsetWidth,d=this._parseCssPixelValue(n?.height)||this._parseCssPixelValue(t.style.height)||t.offsetHeight;this._repositionWindowFromRatios(t,window.innerWidth,window.innerHeight,{widthPx:a,heightPx:d}),o=!0}setTimeout(()=>{t.classList.remove("window-toggling"),o&&this._savePositionRatios(t)},this._config.animationDurationMs)}async open(t,e=!1,s=null,i=!0){if(this._windows.size>=this._config.maxWindows&&!this._windows.has(t)){const a=document.body.dataset.errorMaxWindows||`Maximum of ${this._config.maxWindows} windows allowed.`;return this._notify("error",a.replace("%s",String(this._config.maxWindows))),Promise.reject(new Error("Max windows reached"))}if(this._windows.has(t)&&!e){const a=this._windows.get(t);return i&&this._focusWindow(a),Promise.resolve(a)}if(this._pendingRequests.has(t))return this._pendingRequests.get(t);const o=Date.now();if(!e&&o-(this._lastOpenTimestamps.get(t)||0)<this._config.cooldownMs)return Promise.resolve();this._lastOpenTimestamps.set(t,o);const n=(async()=>{try{const a=await this._fetchWindowContent(t,{force:e,focusSelector:s,activate:i,manager:this});if(typeof a!="string")throw new TypeError("fetchWindowContent must return an HTML string");if(this._windows.has(t)&&e){const l=this._windows.get(t);return!i&&this._isWindowBusy(l)||(this._refreshWindowContent(l,a),i&&this._focusWindow(l),s&&this._handleFocusSelector(l,s)),l}const d=this._createWindowElement(a,t);if(!d){console.warn(`No .window element found for ${t}`);return}return this._setupNewWindow(d,t,s,i),d}catch(a){console.error("Error opening window:",a);const d=document.body.dataset.errorOpenFailed||"Failed to open window.";throw this._notify("error",d),a}finally{this._pendingRequests.delete(t)}})();return this._pendingRequests.set(t,n),n}close(t){const e=t.dataset.endpoint;this._windows.get(e)===t&&this._windows.delete(e),t.classList.add("animate-disappearance"),t.classList.remove("animate-appearance"),t.addEventListener("animationend",()=>{t.isConnected&&t.remove()},{once:!0})}_focusWindow(t){this._zIndexCounter++,t.style.zIndex=this._zIndexCounter,t.classList.add("focused"),this._windows.forEach(e=>{e!==t&&e.classList.remove("focused")})}_isWindowBusy(t){return t.dataset.isBusy==="true"?!0:t.querySelector('[data-is-busy="true"]')!==null}_refreshWindowContent(t,e){const o=new DOMParser().parseFromString(e,"text/html").querySelector(".window");if(!o)return;const n=t.dataset.snapType,a=t.dataset.prevState,d=t.dataset.xRatio,l=t.dataset.yRatio,c=t.classList.contains("focused"),h=t.classList.contains("maximized"),g=t.classList.contains("tiled"),u=this._captureScrollState(t);t.innerHTML=o.innerHTML,t.className=o.className,n&&(t.dataset.snapType=n),a&&(t.dataset.prevState=a),d&&(t.dataset.xRatio=d),l&&(t.dataset.yRatio=l),c&&t.classList.add("focused"),g&&t.classList.add("tiled"),h&&(t.classList.add("maximized"),this._updateMaximizeIcon(t,!0)),!g&&!h&&(o.style.width&&(t.style.width=o.style.width),o.style.height&&(t.style.height=o.style.height)),t.style.margin="0",t.style.transform="none",this._restoreScrollState(t,u),this._initializeModalContent(t)}_updateMaximizeIcon(t,e){const s=t.querySelector("[data-maximize] i");s&&(s.classList.toggle("fa-expand",!e),s.classList.toggle("fa-compress",e))}_createWindowElement(t,e){const o=new DOMParser().parseFromString(t,"text/html").querySelector(".window");return o&&(o.dataset.endpoint=e),o}_setupNewWindow(t,e,s,i=!0){Object.assign(t.style,{position:"absolute",pointerEvents:"auto",margin:"0",transform:"none",visibility:"hidden"}),this._root.appendChild(t);const o=this._windows.size,n=t.dataset.defaultSnap;if(n){const a=window.innerWidth,d=window.innerHeight-this._config.taskbarHeight;this._snapWindow(t,n,a,d)}else this._positionWindow(t,o),this._ensureRestoreState(t);this._windows.set(e,t),this._initializeModalContent(t),i&&this._focusWindow(t),t.style.visibility="",n||this._stabilizeInitialPlacement(t,o),s&&this._handleFocusSelector(t,s)}_positionWindow(t,e=null){const s=t.offsetWidth||parseInt(t.style.width)||this._config.defaultWidth,i=t.offsetHeight||parseInt(t.style.height)||this._config.defaultHeight,o=window.innerWidth,n=window.innerHeight,a=Number.isFinite(e)&&e>=0?e:this._windows.size,d=a*this._config.cascadeOffset,l=a*this._config.cascadeOffset;let c=(o-s)/2+d,h=(n-i)/2+l;const g=this._config.minMargin;c+s>o&&(c=Math.max(g,o-s-g)),h+i>n&&(h=Math.max(g,n-i-g)),t.style.left=`${Math.round(c)}px`,t.style.top=`${Math.round(h)}px`,this._savePositionRatios(t)}_stabilizeInitialPlacement(t,e){if(!t?.isConnected)return;const s=Number.isFinite(this._config.layoutStabilizationMs)&&this._config.layoutStabilizationMs>0?this._config.layoutStabilizationMs:450,i=typeof performance<"u"?()=>performance.now():()=>Date.now(),o=i();let n=!0,a=null,d=t.offsetWidth,l=t.offsetHeight;const c=()=>{n&&(n=!1,a&&(a.disconnect(),a=null))},h=()=>{if(!n||!t.isConnected){c();return}if(t.classList.contains("tiled")||t.classList.contains("maximized"))return;const u=t.offsetWidth,m=t.offsetHeight;(u!==d||m!==l)&&(d=u,l=m,this._positionWindow(t,e))},g=()=>{if(n){if(h(),i()-o<s){requestAnimationFrame(g);return}c()}};requestAnimationFrame(g),typeof ResizeObserver=="function"&&(a=new ResizeObserver(()=>h()),a.observe(t)),setTimeout(()=>c(),s)}_savePositionRatios(t){if(t.classList.contains("tiled")||t.classList.contains("maximized"))return;const e=t.offsetLeft+t.offsetWidth/2,s=t.offsetTop+t.offsetHeight/2;t.dataset.xRatio=String(e/window.innerWidth),t.dataset.yRatio=String(s/window.innerHeight)}_ensureRestoreState(t){const e=v(t);return e?.width&&e?.height?e:D(t,"prevState",{includePosition:!1})}_parseCssPixelValue(t){if(!t)return null;const e=parseFloat(t);return Number.isFinite(e)?e:null}_repositionWindowFromRatios(t,e,s,i=null){const o=parseFloat(t.dataset.xRatio),n=parseFloat(t.dataset.yRatio);if(isNaN(o)||isNaN(n))return!1;const a=(i&&Number.isFinite(i.widthPx)&&i.widthPx>0?i.widthPx:null)||t.offsetWidth,d=(i&&Number.isFinite(i.heightPx)&&i.heightPx>0?i.heightPx:null)||t.offsetHeight,l=o*e,c=n*s;return t.style.left=`${Math.round(l-a/2)}px`,t.style.top=`${Math.round(c-d/2)}px`,!0}_handleFocusSelector(t,e){const s=t.querySelector(e);s&&((s.type==="radio"||s.type==="checkbox")&&(s.checked=!0),s.focus())}_closeTopmostWindow(){let t=null,e=0;this._windows.forEach(s=>{if(s.classList.contains("animate-disappearance"))return;const i=parseInt(s.style.zIndex||0,10);i>e&&(e=i,t=s)}),t&&this.close(t)}drag(t,e){this._dragState?.active||(this._dragState={active:!0,winElement:e,startX:t.clientX,startY:t.clientY,currentX:t.clientX,currentY:t.clientY,startWinLeft:e.offsetLeft,startWinTop:e.offsetTop,isRestored:!1,restoreXRatio:null,initialState:{tiled:e.classList.contains("tiled"),maximized:e.classList.contains("maximized")},view:{w:window.innerWidth,h:window.innerHeight-this._config.taskbarHeight},snap:null,inhibitSnap:!1,isDragging:!1},this._dragHandlers={move:s=>{this._dragState.currentX=s.clientX,this._dragState.currentY=s.clientY},stop:()=>this._handleDragStop()},document.addEventListener("mousemove",this._dragHandlers.move,{passive:!0}),document.addEventListener("mouseup",this._dragHandlers.stop),requestAnimationFrame(()=>this._dragLoop()))}_dragLoop(){this._dragState?.active&&(this._updateDragPosition(),requestAnimationFrame(()=>this._dragLoop()))}_updateDragPosition(){const t=this._dragState,{winElement:e,currentX:s,currentY:i,startX:o,startY:n}=t,a=s-o,d=i-n;if(!t.isDragging&&(Math.abs(a)>this._config.dragThreshold||Math.abs(d)>this._config.dragThreshold)&&(t.isDragging=!0),!t.isDragging)return;(t.initialState.tiled||t.initialState.maximized)&&!t.isRestored&&t.isDragging&&(t.initialState.maximized?(t.restoreXRatio=o/window.innerWidth,this._restoreWindowInternal(e,t.restoreXRatio),t.startWinTop=0):(t.restoreXRatio=(o-e.offsetLeft)/e.offsetWidth,this._restoreWindowInternal(e,null),t.startWinTop=e.offsetTop),t.startX=s,t.startY=i,t.isRestored=!0);let l,c;if(t.isRestored&&t.restoreXRatio!==null){const h=e.offsetWidth;l=s-t.restoreXRatio*h,c=Math.max(0,t.startWinTop+(i-n))}else l=t.startWinLeft+(t.isRestored?s-t.startX:a),c=Math.max(0,t.startWinTop+(t.isRestored?i-t.startY:d));e.style.left=`${l}px`,e.style.top=`${c}px`,(t.isRestored||!t.initialState.tiled&&!t.initialState.maximized)&&(e.classList.contains("tiled")&&e.classList.remove("tiled"),e.classList.contains("maximized")&&(e.classList.remove("maximized"),this._updateMaximizeIcon(e,!1))),t.isDragging&&this._detectSnapZone(s,i)}_detectSnapZone(t,e){const{view:s}=this._dragState,i=this._config.snapThreshold,o=s.w*this._config.edgeDetectionRatio,n=s.h*this._config.edgeDetectionRatio;let a=null;e<i?t<o?a="tl":t>s.w-o?a="tr":a="maximize":t<i?e<n?a="tl":e>s.h-n?a="bl":a="left":t>s.w-i?e<n?a="tr":e>s.h-n?a="br":a="right":e>s.h-i&&(a=t<s.w/2?"bl":"br"),this._dragState.snap!==a&&(this._dragState.snap=a,this._updateSnapIndicator(a,s.w,s.h))}_handleDragStop(){if(!this._dragState?.active)return;const{winElement:t,snap:e,view:s}=this._dragState;document.removeEventListener("mousemove",this._dragHandlers.move),document.removeEventListener("mouseup",this._dragHandlers.stop),this._snapIndicator.classList.remove("visible"),e?e==="maximize"?this.toggleMaximize(t):this._snapWindow(t,e,s.w,s.h):this._savePositionRatios(t),this._dragState.active=!1,this._dragState=null,this._dragHandlers=null}_restoreWindowInternal(t,e){let s,i;const o=v(t);e===null?o&&(s=o.width,i=o.height):(s=o?.width||t.style.width,i=o?.height||t.style.height),(!s||s==="100%")&&(s=this._config.defaultWidth+"px"),(!i||i==="100%")&&(i=this._config.defaultHeight+"px"),t.classList.remove("maximized","tiled"),this._updateMaximizeIcon(t,!1),t.classList.add("window-toggling","dragging-restore"),L(t,{width:s,height:i}),setTimeout(()=>{t.classList.remove("window-toggling","dragging-restore"),this._savePositionRatios(t)},this._config.animationDurationMs)}_updateSnapIndicator(t,e,s){if(!t){this._snapIndicator.classList.remove("visible");return}let i;t==="maximize"?i={top:"0px",left:"0px",width:`${e}px`,height:`${s}px`}:i=this._getSnapLayout(t,e,s),Object.assign(this._snapIndicator.style,i),this._snapIndicator.classList.add("visible")}_snapWindow(t,e,s,i){t.classList.contains("tiled")||this._ensureRestoreState(t),t.classList.add("window-toggling","tiled"),t.dataset.snapType=e;const o=this._getSnapLayout(e,s,i);Object.assign(t.style,o),setTimeout(()=>t.classList.remove("window-toggling"),this._config.animationDurationMs)}_getSnapLayout(t,e,s){const i=this._config.snapGap,o=(e-i*3)/2,n=(s-i*3)/2,a=s-i*2,d=i,l=o+i*2,c=i,h=n+i*2,u={tl:{top:c,left:d,width:o,height:n},tr:{top:c,left:l,width:o,height:n},bl:{top:h,left:d,width:o,height:n},br:{top:h,left:l,width:o,height:n},left:{top:c,left:d,width:o,height:a},right:{top:c,left:l,width:o,height:a}}[t];return{width:`${u.width}px`,height:`${u.height}px`,top:`${u.top}px`,left:`${u.left}px`}}_handleResize(){const t=window.innerWidth,e=window.innerHeight,s=e-this._config.taskbarHeight;this._windows.forEach(i=>{if(i.classList.contains("tiled")&&i.dataset.snapType){const o=i.dataset.snapType,n=this._getSnapLayout(o,t,s);Object.assign(i.style,n)}else i.classList.contains("maximized")||this._repositionWindowFromRatios(i,t,e)})}_captureScrollState(t){const e=new Map;return(t.scrollTop>0||t.scrollLeft>0)&&e.set("root",{top:t.scrollTop,left:t.scrollLeft}),t.querySelectorAll("*").forEach(s=>{(s.scrollTop>0||s.scrollLeft>0)&&e.set(this._getElementPath(t,s),{top:s.scrollTop,left:s.scrollLeft})}),e}_restoreScrollState(t,e){const s=()=>{e.forEach((n,a)=>{let d;if(a==="root")d=t;else try{d=t.querySelector(`:scope > ${a}`)}catch{d=t.querySelector(a)}d&&(d.scrollTop=n.top,d.scrollLeft=n.left)})};s();const i=t.querySelector(".window-content-scrollable > div")||t,o=new ResizeObserver(()=>s());o.observe(i),setTimeout(()=>o.disconnect(),this._config.scrollRestoreTimeoutMs)}_getElementPath(t,e){let s=[],i=e;for(;i&&i!==t;){let o=Array.prototype.indexOf.call(i.parentNode.children,i);s.unshift(`${i.tagName}:nth-child(${o+1})`),i=i.parentNode}return s.join(" > ")}async _defaultFetchWindowContent(t){return(await fetch(this._resolveEndpoint(t),{headers:{"X-Modal-Request":"1"},cache:"no-cache"})).text()}_defaultResolveEndpoint(t){return`/${String(t||"").replace(/^\/+/,"")}`}_defaultNotify(t,e){(t==="error"?console.error:console.log)(`[nidamjs:${t}]`,e)}_initializeModalContent(t){const e=this._getModules?this._getModules():null;this._initializeContent(t,{delegator:this._delegator,modules:e,manager:this})}}class H{#t;#e;#s=200;constructor(t,{refreshMap:e=null,refreshTimeout:s=200}={}){this.#t=t,this.#e=e||window.window_refresh_map||{},this.#s=s}setRefreshMap(t={}){this.#e=t||{}}handleEvent(t,e){const s=this.#e[t],[i,o]=t.split(":"),n=o==="deleted",a=e?.id||null;this.#t&&Array.from(this.#t._windows.entries()).forEach(([d,l])=>{const c=d.startsWith("/")?d.slice(1):d;if(n&&a&&l.dataset.dependsOn&&l.dataset.dependsOn.split("|").some(u=>{const[m,x]=u.split(":");return i===m&&String(x)===String(a)})){setTimeout(()=>{this.#t.close(l)},this.#s);return}s&&s.forEach(h=>{this.#i(h,c,n?null:a)&&setTimeout(()=>{this.#t.open(d,!0,null,!1)},this.#s)})})}#i(t,e,s=null){if(t===e)return!0;const i=t.split("/"),o=e.split("/");return!(i[i.length-1]==="*")&&i.length!==o.length?!1:i.every((a,d)=>a==="*"?!0:a.startsWith("{")&&a.endsWith("}")?s!==null?String(o[d])===String(s):!0:a===o[d])}}const $=(r,t)=>{(r==="error"?console.error:console.log)(`[nidamjs:${r}]`,t)};class P{#t;#e=new Map;#s=null;constructor(t={}){this.#t={root:document,modalContainer:"#target",pendingModalDatasetKey:"pendingModal",registry:[],refreshMap:null,refreshTimeout:200,notify:$,windowManager:{},...t}}initialize(){return this.#i(),this.#o(),this.#r(),this}getModule(t){return this.#e.get(t)}getModules(){return this.#e}#i(){this.#s=new b(this.#t.root),this.#e.set("delegator",this.#s)}#o(){const t=this.#t.root.querySelector(this.#t.modalContainer);if(!t)return;const e=new I(t,this.#s,{getModules:()=>this.#e,initializeContent:(i,o)=>y.initialize(o.delegator,i,o.modules,this.#t.registry),notify:this.#t.notify,...this.#t.windowManager||{}});this.#e.set("window",e),this.#a(t,e);const s=new H(e,{refreshMap:this.#t.refreshMap,refreshTimeout:this.#t.refreshTimeout});this.#e.set("refresher",s)}#a(t,e){const s=this.#t.pendingModalDatasetKey,i=(t?.dataset?.[s]||"").trim();if(!i)return;const o=i.startsWith("/")?i.slice(1):i;e.open(o)}#r(){y.initialize(this.#s,this.#t.root,this.#e,this.#t.registry)}}const N=(r={})=>new P(r),M={set(r,t){try{const e=JSON.stringify(t);localStorage.setItem(r,e)}catch(e){console.error(`Error saving to localStorage (key: ${r}):`,e)}},get(r,t=null){try{const e=localStorage.getItem(r);return e===null?t:JSON.parse(e)}catch(e){return console.error(`Error reading from localStorage (key: ${r}):`,e),t}},remove(r){try{localStorage.removeItem(r)}catch(t){console.error(`Error removing from localStorage (key: ${r}):`,t)}},clear(){try{localStorage.clear()}catch(r){console.error("Error clearing localStorage:",r)}},has(r){try{return localStorage.getItem(r)!==null}catch{return!1}}};class A extends W{_dragState=null;_storageKey="desktop_grid_layout";_storageNamespace="";_storage=M;constructor(t,e,s={}){super(t,e),this._storageKey=s.storageKey||this._storageKey,this._storageNamespace=s.storageNamespace||"",this._storage=s.storage||M,this._loadLayout()}_getStorageKey(){return this._storageNamespace?`${this._storageNamespace}_${this._storageKey}`:this._storageKey}_loadLayout(){try{const t=this._getStorageKey(),e=this._storage.get(t,[]);if(!e||!Array.isArray(e))return;this._root.querySelectorAll(".desktop-icon").forEach(i=>{const o=i.dataset.modal,n=e.find(a=>a.id===o);if(o&&n&&Array.isArray(n.classes)){const a=Array.from(i.classList).filter(d=>d.startsWith("col-start-")||d.startsWith("row-start-")||d.startsWith("col-end-"));i.classList.remove(...a),i.classList.add(...n.classes)}})}catch(t){console.error("Failed to load desktop layout",t)}}_bindEvents(){this._delegator.on("mousedown",".desktop-icon",this._handleDragStart.bind(this))}_handleDragStart(t,e){if(t.button!==0)return;t.preventDefault();const s=e.closest(".desktop-icon"),i=s.getBoundingClientRect(),o=this._root.getBoundingClientRect(),n=Array.from(s.classList).filter(a=>a.startsWith("col-start-")||a.startsWith("row-start-")||a.startsWith("col-end-"));this._dragState={element:s,startX:t.clientX,startY:t.clientY,initialLeft:i.left-o.left,initialTop:i.top-o.top,containerRect:o,originalClasses:n},s.style.left=`${this._dragState.initialLeft}px`,s.style.top=`${this._dragState.initialTop}px`,s.style.width=`${i.width}px`,s.style.position="absolute",s.classList.remove(...n),s.classList.add("dragging"),this._dragHandlers={move:this._handleDragMove.bind(this),stop:this._handleDragStop.bind(this)},document.addEventListener("mousemove",this._dragHandlers.move),document.addEventListener("mouseup",this._dragHandlers.stop)}_handleDragMove(t){if(!this._dragState)return;const{element:e,startX:s,startY:i,initialLeft:o,initialTop:n,containerRect:a}=this._dragState,d=t.clientX-s,l=t.clientY-i;let c=o+d,h=n+l;const g=a.width-e.offsetWidth,u=a.height-e.offsetHeight;c=Math.max(0,Math.min(c,g)),h=Math.max(0,Math.min(h,u)),e.style.left=`${c}px`,e.style.top=`${h}px`}_handleDragStop(t){if(!this._dragState)return;const{element:e,startX:s,startY:i,originalClasses:o}=this._dragState,n=Math.abs(t.clientX-s),a=Math.abs(t.clientY-i),d=n>5||a>5;if(e.classList.remove("dragging"),e.style.zIndex="",d){const l=c=>{c.preventDefault(),c.stopPropagation()};e.addEventListener("click",l,{capture:!0,once:!0}),this._snapToGrid(e)}else e.style.position="",e.style.left="",e.style.top="",e.style.width="",e.classList.add(...o);this._saveLayout&&this._saveLayout(),document.removeEventListener("mousemove",this._dragHandlers.move),document.removeEventListener("mouseup",this._dragHandlers.stop),this._dragState=null}_snapToGrid(t){const e=this._root.getBoundingClientRect(),s=t.getBoundingClientRect();let i=2;window.innerWidth>=1280?i=10:window.innerWidth>=1024?i=8:window.innerWidth>=768&&(i=6);const o=3,n=e.width/i,a=e.height/o,d=s.left-e.left+s.width/2,l=s.top-e.top+s.height/2;let c=Math.floor(d/n)+1,h=Math.floor(l/a)+1;c=Math.max(1,Math.min(c,i)),h=Math.max(1,Math.min(h,o));const g=`col-start-${c}`,u=`row-start-${h}`;if(Array.from(this._root.querySelectorAll(".desktop-icon")).find(_=>_!==t&&_.classList.contains(g)&&_.classList.contains(u))){if(t.style.position="",t.style.left="",t.style.top="",t.style.width="",this._dragState&&this._dragState.originalClasses){const _=Array.from(t.classList).filter(z=>z.startsWith("col-start-")||z.startsWith("row-start-")||z.startsWith("col-end-"));t.classList.remove(..._),t.classList.add(...this._dragState.originalClasses)}return}t.style.position="",t.style.left="",t.style.top="",t.style.width="";const x=Array.from(t.classList).filter(_=>_.startsWith("col-start-")||_.startsWith("row-start-")||_.startsWith("col-end-"));t.classList.remove(...x),t.classList.add(g,u)}_saveLayout(){const t=[];this._root.querySelectorAll(".desktop-icon").forEach(i=>{const o=i.dataset.modal;if(o){const n=Array.from(i.classList).filter(a=>a.startsWith("col-start-")||a.startsWith("row-start-"));t.push({id:o,classes:n})}});const s=this._getStorageKey();this._storage.set(s,t)}}function X(r,t){if(!r||!t||t.type!=="success"||!t.emit)return;let e=t.emit,s=t.id||null;const i=e.split(":");i.length>=3&&(s=i.pop(),e=i.join(":")),r.handleEvent(e,{...t,emit:e,id:s})}N().initialize(),f.BaseManager=W,f.ContentInitializer=y,f.DOMUtils=R,f.DesktopIconManager=A,f.EventDelegator=b,f.NidamApp=P,f.WindowManager=I,f.WindowRefresher=H,f.applyWindowState=L,f.captureWindowState=C,f.createNidamApp=N,f.handleRefreshEvent=X,f.readWindowState=v,f.saveWindowState=D,f.storageUtil=M,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})}));
1
+ (function(g,b){typeof exports=="object"&&typeof module<"u"?b(exports):typeof define=="function"&&define.amd?define(["exports"],b):(g=typeof globalThis<"u"?globalThis:g||self,b(g.Nidam={}))})(this,(function(g){"use strict";class b{static#e=new WeakSet;static initialize(t,e=document,s=null,i=[]){!Array.isArray(i)||i.length===0||i.forEach(({selector:o,init:r,name:n})=>{if(!o||typeof r!="function")return;e.querySelectorAll(o).forEach(d=>{if(!this.#e.has(d))try{const u=r(d,t,s);this.#e.add(d),n&&u&&s&&typeof s.set=="function"&&s.set(n,u)}catch(u){console.warn(`Failed to initialize ${o}:`,u)}})})}}class W{#e=new Map;#t;#s=new Map;constructor(t=document){this.#t=t,this.#i()}#i(){["click","input","change","focusin","focusout","keydown","mousedown","desktop:toggle-matrix","desktop:theme-changed"].forEach(e=>{const s=i=>this.#o(e,i);this.#t.addEventListener(e,s),this.#s.set(e,s)})}#o(t,e){const s=this.#e.get(t);if(!(!s||s.length===0))for(const{selector:i,handler:o}of s){if(!i){o.call(this.#t,e,this.#t);continue}const r=e.target.closest(i);r&&o.call(r,e,r)}}on(t,e,s,i={}){const o=i.group;this.#e.has(t)||this.#e.set(t,[]);const r={selector:e,handler:s,group:o};return this.#e.get(t).push(r),r}off(t,e){const s=this.#e.get(t);if(!s)return;const i=s.indexOf(e);i!==-1&&s.splice(i,1),s.length||this.#e.delete(t)}destroy(){for(const[t,e]of this.#s)this.#t.removeEventListener(t,e);this.#s.clear(),this.#e.clear()}}const D={moveCursorToEnd(a){const t=document.createRange();t.selectNodeContents(a),t.collapse(!1);const e=window.getSelection();e.removeAllRanges(),e.addRange(t)},onEscape(a){const t=e=>{e.key==="Escape"&&(a(),document.removeEventListener("keydown",t))};return document.addEventListener("keydown",t),t},hide(...a){a.forEach(t=>t?.classList.add("hidden"))},show(...a){a.forEach(t=>t?.classList.remove("hidden"))},toggle(...a){a.forEach(t=>t?.classList.toggle("hidden"))}};class z{_root;_elements={};_state={};_utils=D;_delegator=null;constructor(t,e){if(this._root=typeof t=="string"?document.querySelector(t):t,this._delegator=e,!this._root)throw new Error(`Root element not found: ${t}`);this._initialize()}_initialize(){this._elements=this._cacheElements(),this._bindEvents()}_cacheElements(){return{}}_bindEvents(){}_query(t){return this._root.querySelector(t)}_queryAll(t){return this._root.querySelectorAll(t)}_on(t,e,s){this._delegator.on(t,e,(i,o)=>{this._root.contains(o)&&s.call(this,i,o)})}}function R(a){if(!a)return null;const[t,e]=a.split(":").map(s=>parseInt(s.trim(),10));return Number.isFinite(t)&&Number.isFinite(e)?{col:t,row:e}:null}function G(a,t,e,s){const{cols:i,rows:o}=s,r=e.width/i,n=e.height/o,c=a-e.left,d=t-e.top;let u=Math.floor(c/r)+1,h=Math.floor(d/n)+1;return u=Math.max(1,Math.min(u,i)),h=Math.max(1,Math.min(h,o)),{col:u,row:h,posString:`${u}:${h}`}}function L(a,t,e){return Array.from(a).some(s=>s!==t&&s.getAttribute("nd-icon")===e)}const J=(a,t,e,s)=>{const{col:i,row:o}=R(t),r=Math.max(e,s);for(let n=0;n<=r;n++)for(let c=-n;c<=n;c++)for(let d=-n;d<=n;d++){if(Math.max(Math.abs(c),Math.abs(d))!==n)continue;const u=i+c,h=o+d;if(u>=1&&u<=e&&h>=1&&h<=s){const p=`${u}:${h}`;if(!L(a,null,p))return p}}return t},I={set(a,t){try{const e=JSON.stringify(t);localStorage.setItem(a,e)}catch(e){console.error(`Error saving to localStorage (key: ${a}):`,e)}},get(a,t=null){try{const e=localStorage.getItem(a);return e===null?t:JSON.parse(e)}catch(e){return console.error(`Error reading from localStorage (key: ${a}):`,e),t}},remove(a){try{localStorage.removeItem(a)}catch(t){console.error(`Error removing from localStorage (key: ${a}):`,t)}},clear(){try{localStorage.clear()}catch(a){console.error("Error clearing localStorage:",a)}},has(a){try{return localStorage.getItem(a)!==null}catch{return!1}}};class N extends z{_key="nd-icons-layout";constructor(t,e){super(t,e),this.#e()}#e(){this.#t(),this.#s(),this.#i()}_bindEvents(){this._on("mousedown","[nd-icon]",this._handleStartDrag.bind(this))}#t(){const t=this._root.getAttribute("nd-icons");if(!t)return;const[e,s]=t.split(":").map(Number),i=this._root;e&&s&&(i.style.setProperty("--nd-cols",String(e)),i.style.setProperty("--nd-rows",String(s)))}#s(){const t=I.get(this._key,{});this._queryAll("[nd-icon]").forEach(e=>{const s=e.getAttribute("nd-id");if(!s)return;const i=t[s];i&&e.setAttribute("nd-icon",i)})}#i(){const t=this._root.getAttribute("nd-icons");if(!t)return;const[e,s]=t.split(":").map(Number),i=this._queryAll("[nd-icon]");i.forEach(o=>{const r=o.getAttribute("nd-icon");let n=R(r);if(!n)return;let c=Math.max(1,Math.min(n.col,e)),d=Math.max(1,Math.min(n.row,s)),u=`${c}:${d}`;if(L(i,o,u)){u=J(i,u,e,s);const h=R(u);c=h.col,d=h.row}o.style.gridColumnStart=c.toString(),o.style.gridRowStart=d.toString(),o.setAttribute("nd-icon",u)})}_handleStartDrag(t,e){if(t.button!==0)return;t.preventDefault();const s=200,i=40,o=t.clientX,r=t.clientY;let n,c,d,u,h,p=!1;const m=setTimeout(()=>{u=_=>{const T=_.clientX-o,O=_.clientY-r;!p&&Math.hypot(T,O)<i||(p||(p=!0,n=e.cloneNode(!0),n.classList.add("nd-icon-ghost"),n.removeAttribute("nd-icon"),document.body.appendChild(n),e.classList.add("is-dragging"),c=o,d=r,n.style.left=`${c}px`,n.style.top=`${d}px`),c=_.clientX,d=_.clientY,n.style.left=`${c}px`,n.style.top=`${d}px`)},h=()=>{if(document.removeEventListener("mousemove",u),document.removeEventListener("mouseup",h),n&&n.remove(),e.classList.remove("is-dragging"),!p||c===void 0)return;const _=this._root.getBoundingClientRect(),T=getComputedStyle(this._root),O={cols:parseInt(T.getPropertyValue("--nd-cols"),10),rows:parseInt(T.getPropertyValue("--nd-rows"),10)},{posString:Z}=G(c,d,_,O),dt=this._queryAll("[nd-icon]");L(dt,e,Z)||(e.setAttribute("nd-icon",Z),this.#i(),this.#o())},document.addEventListener("mousemove",u),document.addEventListener("mouseup",h)},s),w=()=>clearTimeout(m);document.addEventListener("mouseup",w,{once:!0})}#o(){const t={};this._queryAll("[nd-icon]").forEach(e=>{const s=e.getAttribute("nd-id");s&&(t[s]=e.getAttribute("nd-icon"))}),I.set(this._key,t)}}class l{static#e=new WeakMap;static capture(t,e={}){const s=e.includePosition===!0;let i=null;const o=()=>(i||(i=window.getComputedStyle(t)),i),r=(t.offsetWidth>0?l.#s(t.offsetWidth):"")||l.#t(t.style.width)||l.#t(o().width),n=(t.offsetHeight>0?l.#s(t.offsetHeight):"")||l.#t(t.style.height)||l.#t(o().height);let c="",d="";return s&&(c=l.#s(t.offsetLeft)||l.#t(t.style.left)||l.#t(o().left),d=l.#s(t.offsetTop)||l.#t(t.style.top)||l.#t(o().top)),{width:r||"",height:n||"",left:c,top:d}}static save(t,e="prevState",s={}){const i=l.capture(t,s),o=JSON.stringify(i);return t.dataset[e]=o,l.#i(t).set(e,{raw:o,parsed:i}),i}static read(t,e="prevState"){const s=t.dataset[e];if(!s)return null;const i=l.#i(t).get(e);if(i&&i.raw===s)return i.parsed;try{const o=JSON.parse(s);if(!o||typeof o!="object")return null;const r={width:l.#t(o.width),height:l.#t(o.height),left:l.#t(o.left),top:l.#t(o.top)};return l.#i(t).set(e,{raw:s,parsed:r}),r}catch{return null}}static apply(t,e,s={}){return!e||typeof e!="object"?!1:(e.width&&t.style.width!==e.width&&(t.style.width=e.width),e.height&&t.style.height!==e.height&&(t.style.height=e.height),s.includePosition&&(e.left&&t.style.left!==e.left&&(t.style.left=e.left),e.top&&t.style.top!==e.top&&(t.style.top=e.top)),!0)}static ensureRestoreState(t){const e=l.read(t);return e?.width&&e?.height?e:l.save(t,"prevState",{includePosition:!1})}static positionWindow(t,e,s){const i=t.offsetWidth||parseInt(t.style.width)||s.defaultWidth,o=t.offsetHeight||parseInt(t.style.height)||s.defaultHeight,r=window.innerWidth,n=window.innerHeight,c=e,d=c*s.cascadeOffset,u=c*s.cascadeOffset;let h=(r-i)/2+d,p=(n-o)/2+u;const m=s.minMargin;h+i>r&&(h=Math.max(m,r-i-m)),p+o>n&&(p=Math.max(m,n-o-m)),t.style.left=`${Math.round(h)}px`,t.style.top=`${Math.round(p)}px`,l.savePositionRatios(t)}static stabilizeInitialPlacement(t,e,s){if(!t?.isConnected)return;const i=Number.isFinite(s.layoutStabilizationMs)&&s.layoutStabilizationMs>0?s.layoutStabilizationMs:450,o=typeof performance<"u"?()=>performance.now():()=>Date.now(),r=o();let n=!0,c=null,d=t.offsetWidth,u=t.offsetHeight;const h=()=>{n&&(n=!1,c&&(c.disconnect(),c=null))},p=()=>{if(!n||!t.isConnected){h();return}if(t.classList.contains("tiled")||t.classList.contains("maximized"))return;const w=t.offsetWidth,_=t.offsetHeight;(w!==d||_!==u)&&(d=w,u=_,l.positionWindow(t,e,s))},m=()=>{if(n){if(p(),o()-r<i){requestAnimationFrame(m);return}h()}};requestAnimationFrame(m),typeof ResizeObserver=="function"&&(c=new ResizeObserver(()=>p()),c.observe(t)),setTimeout(()=>h(),i)}static savePositionRatios(t){if(t.classList.contains("tiled")||t.classList.contains("maximized"))return;const e=t.offsetLeft+t.offsetWidth/2,s=t.offsetTop+t.offsetHeight/2;t.dataset.xRatio=String(e/window.innerWidth),t.dataset.yRatio=String(s/window.innerHeight)}static repositionWindowFromRatios(t,e,s,i=null){const o=parseFloat(t.dataset.xRatio),r=parseFloat(t.dataset.yRatio);if(isNaN(o)||isNaN(r))return!1;const n=(i&&i.widthPx>0?i.widthPx:null)||t.offsetWidth,c=(i&&i.heightPx>0?i.heightPx:null)||t.offsetHeight,d=o*e,u=r*s;return t.style.left=`${Math.round(d-n/2)}px`,t.style.top=`${Math.round(u-c/2)}px`,!0}static captureScrollState(t){const e=new Map;return(t.scrollTop>0||t.scrollLeft>0)&&e.set("root",{top:t.scrollTop,left:t.scrollLeft}),t.querySelectorAll("*").forEach(s=>{(s.scrollTop>0||s.scrollLeft>0)&&e.set(l.getElementPath(t,s),{top:s.scrollTop,left:s.scrollLeft})}),e}static restoreScrollState(t,e,s){const i=()=>{e.forEach((n,c)=>{let d;if(c==="root")d=t;else try{d=t.querySelector(`:scope > ${c}`)}catch{d=t.querySelector(c)}d&&(d.scrollTop=n.top,d.scrollLeft=n.left)})};i();const o=t.querySelector(".window-content-scrollable > div")||t,r=new ResizeObserver(()=>i());r.observe(o),setTimeout(()=>r.disconnect(),s.scrollRestoreTimeoutMs)}static parseCssPixelValue(t){if(!t)return null;const e=parseFloat(t);return Number.isFinite(e)?e:null}static getElementPath(t,e){let s=[],i=e;for(;i&&i!==t;){let o=Array.prototype.indexOf.call(i.parentNode.children,i);s.unshift(`${i.tagName}:nth-child(${o+1})`),i=i.parentNode}return s.join(" > ")}static#t(t){return!t||t==="auto"||t==="normal"?"":t}static#s(t){return Number.isFinite(t)?`${Math.round(t)}px`:""}static#i(t){let e=l.#e.get(t);return e||(e=new Map,l.#e.set(t,e)),e}}const P={root:typeof document<"u"?document:null,modalContainer:"#target",pendingModalDatasetKey:"pendingModal",registry:[],refreshMap:null,refreshTimeout:200,windowManager:{zIndexBase:40,layoutStabilizationMs:450,cascadeOffset:30,cooldownMs:500,maxWindows:10,snapGap:6,taskbarHeight:64,snapThreshold:30,dragThreshold:10,resizeDebounceMs:6,animationDurationMs:400,defaultWidth:800,defaultHeight:600,minMargin:10,edgeDetectionRatio:.4,scrollRestoreTimeoutMs:2e3}};class y{static detectSnapZone(t,e,s,i){const o=t.snapThreshold,r=i.w*t.edgeDetectionRatio,n=i.h*t.edgeDetectionRatio;let c=null;return s<o?e<r?c="tl":e>i.w-r?c="tr":c="maximize":e<o?s<n?c="tl":s>i.h-n?c="bl":c="left":e>i.w-o?s<n?c="tr":s>i.h-n?c="br":c="right":s>i.h-o&&(c=e<i.w/2?"bl":"br"),c}static snapWindow(t,e,s,i){t.classList.contains("tiled")||l.ensureRestoreState(t),t.classList.add("window-toggling","tiled"),t.dataset.snapType=e;const o=y.getSnapLayout(e,s,i.w,i.h);Object.assign(t.style,o),setTimeout(()=>t.classList.remove("window-toggling"),s.animationDurationMs)}static getSnapLayout(t,e,s,i){const o=e.snapGap,r=(s-o*3)/2,n=(i-o*3)/2,c=i-o*2,d=o,u=r+o*2,h=o,p=n+o*2,w={tl:{top:h,left:d,width:r,height:n},tr:{top:h,left:u,width:r,height:n},bl:{top:p,left:d,width:r,height:n},br:{top:p,left:u,width:r,height:n},left:{top:h,left:d,width:r,height:c},right:{top:h,left:u,width:r,height:c}}[t];return w?{width:`${w.width}px`,height:`${w.height}px`,top:`${w.top}px`,left:`${w.left}px`}:{}}static handleResize(t,e,s){const i=window.innerWidth,o=window.innerHeight,r=o-e.taskbarHeight;t.forEach(n=>{if(n.classList.contains("tiled")&&n.dataset.snapType){const c=n.dataset.snapType,d=y.getSnapLayout(c,e,i,r);Object.assign(n.style,d)}else n.classList.contains("maximized")||s.repositionFromRatios(n,i,o)})}static restoreWindowInternal(t,e,s,i){let o,r;const n=l.read(t);e===null?n&&(o=n.width,r=n.height):(o=n?.width||t.style.width,r=n?.height||t.style.height),(!o||o==="100%")&&(o=s.defaultWidth+"px"),(!r||r==="100%")&&(r=s.defaultHeight+"px"),t.classList.remove("maximized","tiled"),i.onUpdateMaximizeIcon(t,!1),t.classList.add("window-toggling","dragging-restore"),l.apply(t,{width:o,height:r}),setTimeout(()=>{t.classList.remove("window-toggling","dragging-restore"),i.onSavePositionRatios(t)},s.animationDurationMs)}}const K="[nd-toast-stack]",Q=new Set(["info","success","error","warning"]),E=new Set(["top-right","top-left","bottom-right","bottom-left"]),tt=220,H={duration:3e3,closable:!0},$=a=>typeof a=="string"&&E.has(a),k=a=>{const t=Number.isFinite(a?.duration)?Number(a.duration):H.duration,e=typeof a?.closable=="boolean"?a.closable:H.closable,s=$(a?.position)?a.position:null;return{duration:t,closable:e,position:s}},et=a=>{if(typeof document>"u")return null;let t=document.querySelector(K);if(!t)return console.warn('[nidamjs:toast] Missing [nd-toast-stack]. Add <div nd-toast-stack data-position="bottom-right"></div> if you want to display toasts.'),null;const e=t.getAttribute("data-position"),s=a||($(e)?e:"top-right");return t.setAttribute("data-position",s),t},x=a=>{if(typeof a=="string")return a.trim()?[a]:[];if(Array.isArray(a))return a.filter(Boolean).flatMap(t=>typeof t=="object"&&t!==null?x(t):String(t).trim()).filter(Boolean);if(a&&typeof a=="object"){const t=a;return t.errors?x(t.errors):Object.values(t).flatMap(e=>x(e)).filter(Boolean)}return[]},st=a=>{const t=document.createElement("div");if(t.className="nd-toast-content",a.length<=1){const s=document.createElement("span");return s.textContent=a[0],t.appendChild(s),t}const e=document.createElement("ul");return e.className="nd-toast-list",a.forEach(s=>{const i=document.createElement("li");i.textContent=s,e.appendChild(i)}),t.appendChild(e),t},q=(a,t)=>{t.setAttribute("data-state","closing"),window.setTimeout(()=>{t.remove(),a.childElementCount||a.remove()},tt)},it=(a,t,e)=>{const s=document.createElement("button");return s.type="button",s.className="nd-toast-close",s.setAttribute("aria-label","Close notification"),s.textContent="x",s.addEventListener("click",()=>{e&&window.clearTimeout(e),q(a,t)}),s},ot=(a,t,e)=>e<=0?0:window.setTimeout(()=>{q(a,t)},e),F=(a,t,e=void 0)=>{if(typeof window>"u"||typeof document>"u")return;const s=x(t);if(!s.length)return;const i=Q.has(a)?a:"info",o=k(e),r=et(o.position);if(!r)return;const n=document.createElement("div");n.className="nd-toast",n.setAttribute("data-type",i),n.setAttribute("data-state","open"),n.appendChild(st(s));const c=ot(r,n,o.duration);return o.closable&&n.appendChild(it(r,n,c)),r.appendChild(n),o.duration},nt=a=>a==="error"?"error":a==="warn"||a==="warning"?"warning":a==="success"?"success":"info",X=(a={})=>{const t=k(a);return(e,s)=>{const i=nt(e);F(i,s,t)}},C=X();class f{static async open(t,e,s){const{pendingRequests:i}=s,o=f._getValidationError(t,e,s);if(o){if(o==="ALREADY_OPEN")return s.windows.get(t);if(o==="COOLDOWN")return Promise.resolve();throw new Error(o)}if(i.has(t))return i.get(t);const r=(async()=>{try{const n=await s.fetchWindowContent(t,e);if(typeof n!="string")throw new TypeError("HTML content must be a string");const c=s.windows.get(t);return c&&e.force?f._refreshExisting(c,n,s,e):f._createAndSetup(t,n,s,e)}catch(n){throw f._handleError(n,s),n}finally{i.delete(t)}})();return i.set(t,r),r}static close(t,e){const s=t.dataset.endpoint;e.get(s)===t&&e.delete(s),t.classList.add("animate-disappearance"),t.classList.remove("animate-appearance"),t.addEventListener("animationend",()=>{t.isConnected&&t.remove()},{once:!0})}static toggleMaximize(t,e){const{config:s,callbacks:i}=e,o=t.classList.contains("maximized"),r=t.classList.contains("tiled")&&t.dataset.snapType;t.classList.add("window-toggling"),!o&&!t.classList.contains("tiled")&&i.saveWindowState(t,"prevState",{includePosition:!1});const n=t.classList.toggle("maximized");let c=!1;if(f.updateMaximizeIcon(t,n),!n)if(r){const d=y.getSnapLayout(t.dataset.snapType,s,window.innerWidth,window.innerHeight-s.taskbarHeight);Object.assign(t.style,d)}else{const d=i.readWindowState(t);i.applyWindowState(t,d);const u={widthPx:l.parseCssPixelValue(d?.width)||t.offsetWidth,heightPx:l.parseCssPixelValue(d?.height)||t.offsetHeight};l.repositionWindowFromRatios(t,window.innerWidth,window.innerHeight,u),c=!0}setTimeout(()=>{t.classList.remove("window-toggling"),c&&l.savePositionRatios(t)},s.animationDurationMs)}static focusWindow(t,e){e.zIndexCounter++,t.style.zIndex=e.zIndexCounter,t.classList.add("focused"),e.windows.forEach(s=>{s!==t&&s.classList.remove("focused")})}static isWindowBusy(t){return t.dataset.isBusy==="true"||t.querySelector('[data-is-busy="true"]')!==null}static updateMaximizeIcon(t,e){const s=t.querySelector("[data-maximize] i");s&&(s.classList.toggle("fa-expand",!e),s.classList.toggle("fa-compress",e))}static closeTopmostWindow(t){let e=null,s=0;t.forEach(i=>{if(i.classList.contains("animate-disappearance"))return;const o=parseInt(i.style.zIndex||0,10);o>s&&(s=o,e=i)}),e&&f.close(e,t)}static _getValidationError(t,e,s){const{windows:i,config:o,lastOpenTimestamps:r}=s;if(i.size>=o.maxWindows&&!i.has(t)){const c=document.body.dataset.errorMaxWindows||`Maximum of ${o.maxWindows} windows allowed.`;return C("error",c.replace("%s",String(o.maxWindows))),"MAX_WINDOWS_REACHED"}if(i.has(t)&&!e.force)return e.activate&&f.focusWindow(i.get(t),s),"ALREADY_OPEN";const n=Date.now();return!e.force&&n-(r.get(t)||0)<o.cooldownMs?"COOLDOWN":(r.set(t,n),null)}static _refreshExisting(t,e,s,i){return!i.activate&&f.isWindowBusy(t)||(f._applyNewContent(t,e,s),i.activate&&f.focusWindow(t,s),i.focusSelector&&f.handleFocusSelector(t,i.focusSelector)),t}static _createAndSetup(t,e,s,i){const o=f._parseHTML(e);if(!o)throw new Error(`No .window element found in content for ${t}`);return o.dataset.endpoint=t,f._initializeNewWindow(o,t,i,s),o}static _parseHTML(t){return new DOMParser().parseFromString(t,"text/html").querySelector(".window")}static _applyNewContent(t,e,s){const i=f._parseHTML(e);if(!i)return;const{config:o,callbacks:r}=s,n={snapType:t.dataset.snapType,xRatio:t.dataset.xRatio,yRatio:t.dataset.yRatio,isFocused:t.classList.contains("focused"),isMaximized:t.classList.contains("maximized"),isTiled:t.classList.contains("tiled"),scroll:l.captureScrollState(t)};t.innerHTML=i.innerHTML,t.className=i.className,n.snapType&&(t.dataset.snapType=n.snapType),n.xRatio&&(t.dataset.xRatio=n.xRatio),n.yRatio&&(t.dataset.yRatio=n.yRatio),n.isFocused&&t.classList.add("focused"),n.isTiled&&t.classList.add("tiled"),n.isMaximized&&(t.classList.add("maximized"),f.updateMaximizeIcon(t,!0)),!n.isTiled&&!n.isMaximized&&(i.style.width&&(t.style.width=i.style.width),i.style.height&&(t.style.height=i.style.height)),l.restoreScrollState(t,n.scroll,o),r.initializeContent(t)}static _initializeNewWindow(t,e,s,i){const{root:o,windows:r,config:n,callbacks:c}=i;Object.assign(t.style,{position:"absolute",pointerEvents:"auto",margin:"0",visibility:"hidden"}),o.appendChild(t);const d=t.dataset.defaultSnap;d?y.snapWindow(t,d,n,{w:window.innerWidth,h:window.innerHeight-n.taskbarHeight}):l.positionWindow(t,r.size,n),r.set(e,t),c.initializeContent(t),s.activate&&f.focusWindow(t,i),t.style.visibility="",d||l.stabilizeInitialPlacement(t,r.size-1,n),s.focusSelector&&f.handleFocusSelector(t,s.focusSelector)}static handleFocusSelector(t,e){const s=t.querySelector(e);s&&((s.type==="radio"||s.type==="checkbox")&&(s.checked=!0),s.focus())}static _handleError(t,e){console.error("Window Lifecycle Error:",t);const s=document.body.dataset.errorOpenFailed||"Failed to open window.";C("error",s)}}class v{static drag(t,e,s,i,o){if(i.active)return;Object.assign(i,{active:!0,winElement:e,startX:t.clientX,startY:t.clientY,currentX:t.clientX,currentY:t.clientY,startWinLeft:e.offsetLeft,startWinTop:e.offsetTop,isRestored:!1,restoreXRatio:null,initialState:{tiled:e.classList.contains("tiled"),maximized:e.classList.contains("maximized")},view:{w:window.innerWidth,h:window.innerHeight-s.taskbarHeight},snap:null,isDragging:!1});const r=c=>{i.currentX=c.clientX,i.currentY=c.clientY},n=()=>v._handleDragStop(s,i,o);i._moveHandler=r,document.addEventListener("mousemove",r,{passive:!0}),document.addEventListener("mouseup",n,{once:!0}),requestAnimationFrame(()=>v._dragLoop(s,i,o))}static _dragLoop(t,e,s){e.active&&(v._updateDragPosition(t,e,s),requestAnimationFrame(()=>v._dragLoop(t,e,s)))}static _updateDragPosition(t,e,s){const{winElement:i,currentX:o,currentY:r,startX:n,startY:c}=e,d=o-n,u=r-c;if(!e.isDragging&&(Math.abs(d)>t.dragThreshold||Math.abs(u)>t.dragThreshold)&&(e.isDragging=!0),!e.isDragging)return;(e.initialState.tiled||e.initialState.maximized)&&!e.isRestored&&(e.initialState.maximized?(e.restoreXRatio=n/window.innerWidth,s.onRestore(i,e.restoreXRatio,!0),e.startWinTop=0):(e.restoreXRatio=(n-i.offsetLeft)/i.offsetWidth,s.onRestore(i,null,!1),e.startWinTop=i.offsetTop),e.startX=o,e.startY=r,e.isRestored=!0);let h,p;e.isRestored&&e.restoreXRatio!==null?(h=o-e.restoreXRatio*i.offsetWidth,p=Math.max(0,e.startWinTop+(r-c))):(h=e.startWinLeft+(e.isRestored?o-n:d),p=Math.max(0,e.startWinTop+(e.isRestored?r-c:u))),i.style.left=`${h}px`,i.style.top=`${p}px`,(e.isRestored||!e.initialState.tiled&&!e.initialState.maximized)&&(i.classList.remove("tiled","maximized"),s.onUpdateMaximizeIcon(i,!1));const m=s.detectSnapZone(o,r,e.view);e.snap!==m&&(e.snap=m,s.updateSnapIndicator(m,e.view))}static _handleDragStop(t,e,s){if(!e.active)return;const{winElement:i,snap:o,view:r}=e;document.removeEventListener("mousemove",e._moveHandler),s.updateSnapIndicator(null,r),o?o==="maximize"?s.onMaximize(i):s.onSnap(i,o,r):s.onSaveState(i),e.active=!1}}class S{static async load(t,e,s){const{isStatic:i,resolveEndpoint:o}=s;if(i){const c=S._getStaticTemplateContent(t);if(c!==null)return c;throw new Error(`Static route not found: ${String(t||"")}`)}const r=(o||S._defaultResolveEndpoint)(t),n=await fetch(r,{headers:{"X-Modal-Request":"1"},cache:"no-cache"});if(!n.ok)throw new Error(`Failed to fetch window content: ${n.statusText}`);return n.text()}static _defaultResolveEndpoint(t){return`/${String(t||"").replace(/^\/+/,"")}`}static _normalizeEndpoint(t){return String(t||"").trim().replace(/^\/+/,"")}static _buildStaticRouteCandidates(t){const e=S._normalizeEndpoint(t),s=[],i=r=>{const n=String(r||"").trim();!n||s.includes(n)||s.push(n)};i(e);const o=e.split("/").pop();return i(o),e.endsWith(".html")&&i(e.slice(0,-5)),o&&o.endsWith(".html")&&i(o.slice(0,-5)),s}static _getStaticTemplateContent(t){const e=document.querySelectorAll("template[data-route]");if(!e.length)return null;const s=new Map;e.forEach(o=>{const r=o.getAttribute("data-route");r&&s.set(r.trim(),o.innerHTML)});const i=S._buildStaticRouteCandidates(t);for(const o of i)if(s.has(o))return s.get(o);return null}}class V extends z{_config={...P.windowManager};_windows=new Map;_zIndexCounter=this._config.zIndexBase;_getModules=null;_fetchWindowContent=null;_initializeContent=null;_resolveEndpoint=null;_static=!1;_lastOpenTimestamps=new Map;_pendingRequests=new Map;_snapIndicator=null;_dragState={active:!1};constructor(t,e,s={}){super(t,e);const{getModules:i=null,config:o=null,fetchWindowContent:r=null,initializeContent:n=null,resolveEndpoint:c=null,static:d=!1}=s||{};this._getModules=i,this._initializeContent=n||(()=>{}),this._resolveEndpoint=c,this._static=!!d,this._fetchWindowContent=r||((u,h)=>S.load(u,h,{isStatic:this._static,resolveEndpoint:this._resolveEndpoint})),o&&typeof o=="object"&&(this._config={...this._config,...o}),this._zIndexCounter=this._config.zIndexBase,this._initSnapIndicator(),this._hydrateExistingWindows()}_hydrateExistingWindows(){this._root.querySelectorAll(".window").forEach(e=>{const s=e,i=s.dataset.endpoint||s.dataset.modal;if(i&&!this._windows.has(i)){s.dataset.endpoint||(s.dataset.endpoint=i),this._windows.set(i,s),this._initializeModalContent(s);const o=parseInt(s.style.zIndex||"0",10);o>this._zIndexCounter&&(this._zIndexCounter=o)}})}_initSnapIndicator(){this._snapIndicator=document.createElement("div"),this._snapIndicator.className="snap-indicator",document.body.appendChild(this._snapIndicator)}_bindEvents(){this._delegator.on("click","[data-modal]",(e,s)=>{s.hasAttribute("nd-taskbar-icon")||(e.preventDefault(),this.open(s.dataset.modal).catch(i=>{i?.message!=="MAX_WINDOWS_REACHED"&&console.error("Modal trigger failed:",i)}))}),this._delegator.on("click","[data-maximize]",(e,s)=>{e.preventDefault();const i=s.closest(".window");i&&this.toggleMaximize(i)}),this._delegator.on("click","[data-close]",(e,s)=>{e.preventDefault();const i=s.closest(".window");i&&this.close(i)}),this._delegator.on("mousedown",".window",(e,s)=>{if(e.target.closest("[data-close]")||e.target.closest("[data-modal]"))return;const i=s.closest(".window");i&&this.focus(i)}),this._delegator.on("mousedown","[data-bar]",(e,s)=>{if(e.target.closest("[data-close]")||e.target.closest("[data-maximize]"))return;e.preventDefault();const i=s.closest(".window");i&&(this.focus(i),this.drag(e,i))}),this._delegator.on("keydown",null,e=>{e.key==="Escape"&&!e.repeat&&this.closeTopmost()});let t;window.addEventListener("resize",()=>{clearTimeout(t),t=setTimeout(()=>{y.handleResize(this._windows,this._config,{repositionFromRatios:(e,s,i)=>l.repositionWindowFromRatios(e,s,i)})},this._config.resizeDebounceMs)})}_getLifecycleContext(){return{root:this._root,windows:this._windows,config:this._config,zIndexCounter:this._zIndexCounter,pendingRequests:this._pendingRequests,lastOpenTimestamps:this._lastOpenTimestamps,fetchWindowContent:this._fetchWindowContent,callbacks:{initializeContent:t=>this._initializeModalContent(t),saveWindowState:(t,e,s)=>l.save(t,e,s),readWindowState:(t,e)=>l.read(t,e),applyWindowState:(t,e,s)=>l.apply(t,e,s)}}}async open(t,e=!1,s=null,i=!0){const o=this._windows.has(t),r=await f.open(t,{force:e,focusSelector:s,activate:i},this._getLifecycleContext());return o?i&&this._root.dispatchEvent(new CustomEvent("window:focused",{detail:{endpoint:t},bubbles:!0})):this._root.dispatchEvent(new CustomEvent("window:opened",{detail:{endpoint:t},bubbles:!0})),r}close(t){const e=t.dataset.endpoint,s=f.close(t,this._windows);return this._root.dispatchEvent(new CustomEvent("window:closed",{detail:{endpoint:e},bubbles:!0})),s}closeTopmost(){let t=null,e=-1;return this._windows.forEach(s=>{if(s.classList.contains("animate-disappearance"))return;const i=parseInt(s.style.zIndex||0,10);i>e&&(e=i,t=s)}),t?this.close(t):null}getWindows(){return Array.from(this._windows.entries())}focus(t){const e=this._getLifecycleContext(),s=t.dataset.endpoint;f.focusWindow(t,e),this._zIndexCounter=e.zIndexCounter,this._root.dispatchEvent(new CustomEvent("window:focused",{detail:{endpoint:s},bubbles:!0}))}drag(t,e){const s={onRestore:(i,o)=>y.restoreWindowInternal(i,o,this._config,{onUpdateMaximizeIcon:(r,n)=>f.updateMaximizeIcon(r,n),onSavePositionRatios:r=>l.savePositionRatios(r)}),onUpdateMaximizeIcon:(i,o)=>f.updateMaximizeIcon(i,o),detectSnapZone:(i,o,r)=>y.detectSnapZone(this._config,i,o,r),updateSnapIndicator:(i,o)=>this._updateSnapIndicator(i,o),onMaximize:i=>this.toggleMaximize(i),onSnap:(i,o,r)=>y.snapWindow(i,o,this._config,r),onSaveState:i=>l.savePositionRatios(i)};return v.drag(t,e,this._config,this._dragState,s)}_updateSnapIndicator(t,e){if(!this._snapIndicator)return;if(!t){this._snapIndicator.classList.remove("visible");return}let s;t==="maximize"?s={top:"0px",left:"0px",width:`${e.w}px`,height:`${e.h}px`}:s=y.getSnapLayout(t,this._config,e.w,e.h),Object.assign(this._snapIndicator.style,s),this._snapIndicator.classList.add("visible")}toggleMaximize(t){return f.toggleMaximize(t,this._getLifecycleContext())}_initializeModalContent(t){const e=this._getModules?this._getModules():null;this._initializeContent(t,{delegator:this._delegator,modules:e,manager:this})}}class Y{static match(t,e,s=null){if(t===e)return!0;const i=t.split("/"),o=e.split("/");return!(i[i.length-1]==="*")&&i.length!==o.length?!1:i.every((n,c)=>n==="*"?!0:n.startsWith("{")&&n.endsWith("}")?s!==null?String(o[c])===String(s):!0:n===o[c])}static normalize(t){return String(t||"").trim().replace(/^\/+/,"")}}class j{#e;#t;constructor(t,{refreshMap:e=null,refreshTimeout:s=200}={}){this._provider=t,this.#e=e||window.window_refresh_map||{},this.#t=s}setRefreshMap(t={}){this.#e=t||{}}handleEvent(t,e){if(!this._provider)return;const[s,i]=t.split(":"),o=i==="deleted",r=e?.id||null,n=this.#e[t]||[];this._provider.getWindows().forEach(([c,d])=>{const u=Y.normalize(c);if(o&&r&&d.dataset.dependsOn&&this._shouldCloseByDependency(d.dataset.dependsOn,s,r)){setTimeout(()=>this._provider.close(d),this.#t);return}n.some(p=>Y.match(p,u,o?null:r))&&setTimeout(()=>{this._provider.open(c,!0,null,!1)},this.#t)})}_shouldCloseByDependency(t,e,s){return t.split("|").some(o=>{const[r,n]=o.split(":");return e===r&&String(n)===String(s)})}}class rt extends z{_windowManager=null;_toastOffsetCssVars={top:"--nd-toast-top-offset",right:"--nd-toast-right-offset",bottom:"--nd-toast-bottom-offset",left:"--nd-toast-left-offset"};_toastOffsetObserver=null;_windowResizeHandler=null;constructor(t,e,s={}){super(t,e),this._windowManager=s.windowManager||null,this._syncWithWindowManager(),this._syncToastViewportOffsets(),this._observeToastViewportOffsets()}_syncWithWindowManager(){!this._windowManager||!this._windowManager._windows||this._windowManager._windows.forEach((t,e)=>{this._updateIconState(e,!0)})}_bindEvents(){this._on("click","[nd-taskbar-icon]",this._handleIconClick.bind(this)),document.addEventListener("window:opened",t=>{const e=t;this._updateIconState(e.detail.endpoint,!0)}),document.addEventListener("window:closed",t=>{const e=t;this._updateIconState(e.detail.endpoint,!1)})}_handleIconClick(t,e){const s=e.dataset.modal;s&&this._windowManager&&this._windowManager.open(s).catch(i=>{i?.message!=="MAX_WINDOWS_REACHED"&&console.error("Taskbar icon trigger failed:",i)})}_observeToastViewportOffsets(){this._windowResizeHandler=()=>this._syncToastViewportOffsets(),window.addEventListener("resize",this._windowResizeHandler),!(typeof ResizeObserver>"u")&&(this._toastOffsetObserver=new ResizeObserver(()=>this._syncToastViewportOffsets()),this._toastOffsetObserver.observe(this._root))}_setToastViewportOffsets(t){const e=document?.documentElement?.style;e&&(e.setProperty(this._toastOffsetCssVars.top,`${t.top}px`),e.setProperty(this._toastOffsetCssVars.right,`${t.right}px`),e.setProperty(this._toastOffsetCssVars.bottom,`${t.bottom}px`),e.setProperty(this._toastOffsetCssVars.left,`${t.left}px`))}_syncToastViewportOffsets(){const t={top:0,right:0,bottom:0,left:0},e=this._root.getBoundingClientRect();if(!e){this._setToastViewportOffsets(t);return}const s=this._root.getAttribute("nd-taskbar")==="extend",i=this._root.getAttribute("nd-taskbar-position")||"bottom",o=window.innerWidth||document.documentElement.clientWidth,r=2;s||i==="bottom"?t.bottom=Math.ceil(e.height||0):i==="left"&&e.left<=r?t.left=Math.ceil(e.width||0):i==="right"&&e.right>=o-r&&(t.right=Math.ceil(e.width||0)),this._setToastViewportOffsets(t)}_updateIconState(t,e){this._queryAll(`[nd-taskbar-icon][data-modal="${t}"]`).forEach(i=>{e?i.classList.add("is-open"):i.classList.remove("is-open")})}}class B{#e;#t=new Map;#s=null;constructor(t={}){const e=this._parseConfig(t);this.#e={...P,...e}}initialize(){return this.#i(),this.#o(),this.#a(),this.#n(),this}getModule(t){return this.#t.get(t)}getModules(){return this.#t}#i(){this.#s=new W(this.#e.root),this.#t.set("delegator",this.#s)}#o(){const t=this.#e.root.querySelector(this.#e.modalContainer);if(!t)return;const e=new V(t,this.#s,{getModules:()=>this.#t,initializeContent:(o,r)=>b.initialize(r.delegator,o,r.modules,this.#e.registry),config:this.#e.windowManager||{}});this.#t.set("window",e),this.#r(t,e);const s=this.#e.root.querySelector("[nd-taskbar]");if(s){const o=new rt(s,this.#s,{windowManager:e});this.#t.set("taskbar",o)}const i=new j(e,{refreshMap:this.#e.refreshMap,refreshTimeout:this.#e.refreshTimeout});this.#t.set("refresher",i)}#n(){const t=this.#e.root.querySelector("[nd-icons]");if(!t)return;const e=new N(t,this.#s);this.#t.set("icon",e)}#r(t,e){const s=this.#e.pendingModalDatasetKey,i=(t?.dataset?.[s]||"").trim();if(!i)return;const o=i.startsWith("/")?i.slice(1):i;e.open(o)}#a(){b.initialize(this.#s,this.#e.root,this.#t,this.#e.registry)}_parseConfig(t){if(typeof t=="string")try{return JSON.parse(t)}catch{return C("error","Parsing error, falling back to default settings."),{}}return t||{}}}const U=(a={})=>new B(a);let M=null;function A(a={}){return M?(console.warn("[nidamjs] App is already initialized."),M):(M=U(a),M.initialize())}function at(){if(typeof document>"u")return;const a=document.querySelector("script[data-nd-init]");!M&&!a&&A()}function ct(a,t){if(!a||!t||t.type!=="success"||!t.emit)return;let e=t.emit,s=t.id||null;const i=e.split(":");i.length>=3&&(s=i.pop(),e=i.join(":")),a.handleEvent(e,{...t,emit:e,id:s})}at(),g.BaseManager=z,g.ContentInitializer=b,g.DOMUtils=D,g.EventDelegator=W,g.IconManager=N,g.NidamApp=B,g.WindowManager=V,g.WindowRefresher=j,g.WindowState=l,g.createNidamApp=U,g.createToastNotify=X,g.default=A,g.handleRefreshEvent=ct,g.initNidamApp=A,g.showToast=F,g.storageUtil=I,g.toastNotify=C,Object.defineProperties(g,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
package/package.json CHANGED
@@ -1,46 +1,46 @@
1
1
  {
2
- "name": "@moonitoring/nidamjs",
3
- "version": "1.0.0",
4
- "type": "module",
5
- "main": "./dist/nidam.cjs",
6
- "module": "./dist/nidam.es.js",
7
- "style": "./dist/nidam.css",
8
- "exports": {
9
- ".": {
10
- "import": "./dist/nidam.es.js",
11
- "require": "./dist/nidam.cjs"
12
- },
13
- "./cjs": "./dist/nidam.cjs",
14
- "./umd": "./dist/nidam.umd.js",
15
- "./nidam.css": "./dist/nidam.css"
2
+ "name": "@moonitoring/nidamjs",
3
+ "version": "1.0.2",
4
+ "main": "./dist/nidam.cjs",
5
+ "module": "./dist/nidam.es.js",
6
+ "devDependencies": {
7
+ "@types/node": "^24.10.13",
8
+ "@vitest/coverage-v8": "3.2.4",
9
+ "express": "^5.2.1",
10
+ "jsdom": "^27.4.0",
11
+ "prettier": "^3.8.1",
12
+ "typescript": "^5.9.3",
13
+ "vite": "^7.3.1",
14
+ "vitest": "^3.2.4"
15
+ },
16
+ "exports": {
17
+ ".": {
18
+ "import": "./dist/nidam.es.js",
19
+ "require": "./dist/nidam.cjs"
16
20
  },
17
- "files": [
18
- "dist",
19
- "readme.md"
20
- ],
21
- "publishConfig": {
22
- "access": "public",
23
- "tag": "beta"
24
- },
25
- "scripts": {
26
- "imports": "bun -e \"await import('./src/index.js')\"",
27
- "test": "vitest run --coverage",
28
- "test:watch": "vitest --coverage",
29
- "lint": "tsc --noEmit",
30
- "format": "prettier -w .",
31
- "quality": "bun run imports && bun run lint && bun run test && bun run format",
32
- "build": "vite build --mode lib && vite build --mode css",
33
- "csr": "bun run build && vite --open /examples/csr/index.html",
34
- "ssr": "bun run build && bun examples/ssr/main.js"
35
- },
36
- "devDependencies": {
37
- "@types/node": "^24.10.13",
38
- "@vitest/coverage-v8": "3.2.4",
39
- "express": "^5.2.1",
40
- "jsdom": "^27.4.0",
41
- "prettier": "^3.8.1",
42
- "typescript": "^5.9.3",
43
- "vite": "^7.3.1",
44
- "vitest": "^3.2.4"
45
- }
21
+ "./cjs": "./dist/nidam.cjs",
22
+ "./umd": "./dist/nidam.umd.js",
23
+ "./nidam.css": "./dist/nidam.css"
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "readme.md"
28
+ ],
29
+ "publishConfig": {
30
+ "access": "public",
31
+ "tag": "beta"
32
+ },
33
+ "scripts": {
34
+ "imports": "bun -e \"await import('./src/index.js')\"",
35
+ "test": "vitest run --coverage",
36
+ "test:watch": "vitest --coverage",
37
+ "lint": "tsc --noEmit",
38
+ "format": "prettier -w .",
39
+ "quality": "bun run imports && bun run lint && bun run test && bun run format",
40
+ "build": "vite build --mode lib && vite build --mode css",
41
+ "csr": "bun run build && vite --open /examples/csr/index.html",
42
+ "ssr": "bun run build && bun examples/ssr/main.js"
43
+ },
44
+ "style": "./dist/nidam.css",
45
+ "type": "module"
46
46
  }
package/readme.md CHANGED
@@ -32,10 +32,7 @@ const app = createNidamApp({
32
32
  modalContainer: "#target",
33
33
  registry: [],
34
34
  windowManager: {
35
- config: {
36
- layoutStabilizationMs: 450,
37
- },
38
- notify: (level, message) => console.log(level, message),
35
+ layoutStabilizationMs: 450,
39
36
  },
40
37
  });
41
38
 
@@ -45,6 +42,12 @@ app.initialize();
45
42
  `layoutStabilizationMs` controls how long the first window can auto-recenter if late CSS changes its rendered size after
46
43
  open.
47
44
 
45
+ ## Toast Notifications
46
+
47
+ - App-level notifications use `toastNotify` by default.
48
+ - Supported positions: `top-right`, `top-left`, `bottom-right`, `bottom-left`.
49
+ - Styling is CSS-variable driven on `[nd-toast-stack]` and `.nd-toast`.
50
+
48
51
  ## Documentation
49
52
 
50
53
  - Porting plan and Code Arena differences: [porting_plan.md](porting_plan.md)