@moonitoring/nidamjs 1.0.0
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/LICENSE +21 -0
- package/dist/nidam.cjs +1 -0
- package/dist/nidam.css +1 -0
- package/dist/nidam.es.js +1096 -0
- package/dist/nidam.umd.js +1 -0
- package/package.json +46 -0
- package/readme.md +175 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Technique informatique du Cégep de Sorel-Tracy
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/nidam.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class W{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(d=>{if(!this.#t.has(d))try{const c=n(d,t,s);this.#t.add(d),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 M{_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 z=new WeakMap;function u(r){return!r||r==="auto"||r==="normal"?"":r}function w(r){return Number.isFinite(r)?`${Math.round(r)}px`:""}function T(r,t={}){const e=t.includePosition===!0;let s=null;const i=()=>(s||(s=window.getComputedStyle(r)),s),o=(r.offsetWidth>0?w(r.offsetWidth):"")||u(r.style.width)||u(i().width),n=(r.offsetHeight>0?w(r.offsetHeight):"")||u(r.style.height)||u(i().height);let a="",l="";return e&&(a=w(r.offsetLeft)||u(r.style.left)||u(i().left),l=w(r.offsetTop)||u(r.style.top)||u(i().top)),{width:o||"",height:n||"",left:a,top:l}}function y(r){let t=z.get(r);return t||(t=new Map,z.set(r,t)),t}function C(r,t="prevState",e={}){const s=T(r,e),i=JSON.stringify(s);return r.dataset[t]=i,y(r).set(t,{raw:i,parsed:s}),s}function m(r,t="prevState"){const e=r.dataset[t];if(!e)return null;const s=y(r).get(t);if(s&&s.raw===e)return s.parsed;try{const i=JSON.parse(e);if(!i||typeof i!="object")return y(r).set(t,{raw:e,parsed:null}),null;const o={width:u(i.width),height:u(i.height),left:u(i.left),top:u(i.top)};return y(r).set(t,{raw:e,parsed:o}),o}catch{return y(r).set(t,{raw:e,parsed:null}),null}}function x(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 D extends M{_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:l=null,resolveEndpoint:d=null}=s||{};this._getModules=i,this._notify=n||this._defaultNotify.bind(this),this._fetchWindowContent=a||this._defaultFetchWindowContent.bind(this),this._initializeContent=l||(()=>{}),this._resolveEndpoint=d||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=m(t);x(t,n);const a=this._parseCssPixelValue(n?.width)||this._parseCssPixelValue(t.style.width)||t.offsetWidth,l=this._parseCssPixelValue(n?.height)||this._parseCssPixelValue(t.style.height)||t.offsetHeight;this._repositionWindowFromRatios(t,window.innerWidth,window.innerHeight,{widthPx:a,heightPx:l}),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 d=this._windows.get(t);return!i&&this._isWindowBusy(d)||(this._refreshWindowContent(d,a),i&&this._focusWindow(d),s&&this._handleFocusSelector(d,s)),d}const l=this._createWindowElement(a,t);if(!l){console.warn(`No .window element found for ${t}`);return}return this._setupNewWindow(l,t,s,i),l}catch(a){console.error("Error opening window:",a);const l=document.body.dataset.errorOpenFailed||"Failed to open window.";throw this._notify("error",l),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,l=t.dataset.xRatio,d=t.dataset.yRatio,c=t.classList.contains("focused"),h=t.classList.contains("maximized"),f=t.classList.contains("tiled"),g=this._captureScrollState(t);t.innerHTML=o.innerHTML,t.className=o.className,n&&(t.dataset.snapType=n),a&&(t.dataset.prevState=a),l&&(t.dataset.xRatio=l),d&&(t.dataset.yRatio=d),c&&t.classList.add("focused"),f&&t.classList.add("tiled"),h&&(t.classList.add("maximized"),this._updateMaximizeIcon(t,!0)),!f&&!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,g),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,l=window.innerHeight-this._config.taskbarHeight;this._snapWindow(t,n,a,l)}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,l=a*this._config.cascadeOffset,d=a*this._config.cascadeOffset;let c=(o-s)/2+l,h=(n-i)/2+d;const f=this._config.minMargin;c+s>o&&(c=Math.max(f,o-s-f)),h+i>n&&(h=Math.max(f,n-i-f)),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,l=t.offsetWidth,d=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 g=t.offsetWidth,_=t.offsetHeight;(g!==l||_!==d)&&(l=g,d=_,this._positionWindow(t,e))},f=()=>{if(n){if(h(),i()-o<s){requestAnimationFrame(f);return}c()}};requestAnimationFrame(f),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=m(t);return e?.width&&e?.height?e:C(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,l=(i&&Number.isFinite(i.heightPx)&&i.heightPx>0?i.heightPx:null)||t.offsetHeight,d=o*e,c=n*s;return t.style.left=`${Math.round(d-a/2)}px`,t.style.top=`${Math.round(c-l/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,l=i-n;if(!t.isDragging&&(Math.abs(a)>this._config.dragThreshold||Math.abs(l)>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 d,c;if(t.isRestored&&t.restoreXRatio!==null){const h=e.offsetWidth;d=s-t.restoreXRatio*h,c=Math.max(0,t.startWinTop+(i-n))}else d=t.startWinLeft+(t.isRestored?s-t.startX:a),c=Math.max(0,t.startWinTop+(t.isRestored?i-t.startY:l));e.style.left=`${d}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=m(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"),x(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,l=i,d=o+i*2,c=i,h=n+i*2,g={tl:{top:c,left:l,width:o,height:n},tr:{top:c,left:d,width:o,height:n},bl:{top:h,left:l,width:o,height:n},br:{top:h,left:d,width:o,height:n},left:{top:c,left:l,width:o,height:a},right:{top:c,left:d,width:o,height:a}}[t];return{width:`${g.width}px`,height:`${g.height}px`,top:`${g.top}px`,left:`${g.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 l;if(a==="root")l=t;else try{l=t.querySelector(`:scope > ${a}`)}catch{l=t.querySelector(a)}l&&(l.scrollTop=n.top,l.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 I{#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(([l,d])=>{const c=l.startsWith("/")?l.slice(1):l;if(n&&a&&d.dataset.dependsOn&&d.dataset.dependsOn.split("|").some(g=>{const[_,S]=g.split(":");return i===_&&String(S)===String(a)})){setTimeout(()=>{this.#t.close(d)},this.#s);return}s&&s.forEach(h=>{this.#i(h,c,n?null:a)&&setTimeout(()=>{this.#t.open(l,!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,l)=>a==="*"?!0:a.startsWith("{")&&a.endsWith("}")?s!==null?String(o[l])===String(s):!0:a===o[l])}}const N=(r,t)=>{(r==="error"?console.error:console.log)(`[nidamjs:${r}]`,t)};class H{#t;#e=new Map;#s=null;constructor(t={}){this.#t={root:document,modalContainer:"#target",pendingModalDatasetKey:"pendingModal",registry:[],refreshMap:null,refreshTimeout:200,notify:N,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 D(t,this.#s,{getModules:()=>this.#e,initializeContent:(i,o)=>W.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 I(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(){W.initialize(this.#s,this.#t.root,this.#e,this.#t.registry)}}const P=(r={})=>new H(r),L={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 $ extends M{_dragState=null;_storageKey="desktop_grid_layout";_storageNamespace="";_storage=L;constructor(t,e,s={}){super(t,e),this._storageKey=s.storageKey||this._storageKey,this._storageNamespace=s.storageNamespace||"",this._storage=s.storage||L,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(l=>l.startsWith("col-start-")||l.startsWith("row-start-")||l.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,l=t.clientX-s,d=t.clientY-i;let c=o+l,h=n+d;const f=a.width-e.offsetWidth,g=a.height-e.offsetHeight;c=Math.max(0,Math.min(c,f)),h=Math.max(0,Math.min(h,g)),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),l=n>5||a>5;if(e.classList.remove("dragging"),e.style.zIndex="",l){const d=c=>{c.preventDefault(),c.stopPropagation()};e.addEventListener("click",d,{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,l=s.left-e.left+s.width/2,d=s.top-e.top+s.height/2;let c=Math.floor(l/n)+1,h=Math.floor(d/a)+1;c=Math.max(1,Math.min(c,i)),h=Math.max(1,Math.min(h,o));const f=`col-start-${c}`,g=`row-start-${h}`;if(Array.from(this._root.querySelectorAll(".desktop-icon")).find(p=>p!==t&&p.classList.contains(f)&&p.classList.contains(g))){if(t.style.position="",t.style.left="",t.style.top="",t.style.width="",this._dragState&&this._dragState.originalClasses){const p=Array.from(t.classList).filter(v=>v.startsWith("col-start-")||v.startsWith("row-start-")||v.startsWith("col-end-"));t.classList.remove(...p),t.classList.add(...this._dragState.originalClasses)}return}t.style.position="",t.style.left="",t.style.top="",t.style.width="";const S=Array.from(t.classList).filter(p=>p.startsWith("col-start-")||p.startsWith("row-start-")||p.startsWith("col-end-"));t.classList.remove(...S),t.classList.add(f,g)}_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 A(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})}const X=P();X.initialize();exports.BaseManager=M;exports.ContentInitializer=W;exports.DOMUtils=R;exports.DesktopIconManager=$;exports.EventDelegator=b;exports.NidamApp=H;exports.WindowManager=D;exports.WindowRefresher=I;exports.applyWindowState=x;exports.captureWindowState=T;exports.createNidamApp=P;exports.handleRefreshEvent=A;exports.readWindowState=m;exports.saveWindowState=C;exports.storageUtil=L;
|
package/dist/nidam.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*{box-sizing:border-box}.toolbar-btn{border:1px solid rgba(148,163,184,.65);border-radius:.7rem;padding:.45rem .75rem;background:#0f172ac7;color:#e2e8f0;font-size:.85rem;transition:all .16s ease}.toolbar-btn:hover{border-color:#7dd3fc;transform:translateY(-1px);background:#1e293be6}.mini-btn{border:1px solid rgba(148,163,184,.7);border-radius:.45rem;background:#0f172ac7;color:#f1f5f9;padding:.05rem .45rem;font-size:.72rem;cursor:pointer}.mini-btn:hover{border-color:#7dd3fc}.window{transform-origin:center}.window.animate-appearance{animation:window-appear .18s ease-out forwards}.window.animate-disappearance{animation:window-disappear .14s ease-in forwards}.window [data-bar]{cursor:move}.window.focused [data-bar]{background:linear-gradient(90deg,#1e40af,#0e7490)}.window.maximized{top:0!important;left:0!important;width:100%!important;height:100%!important;max-width:none!important;max-height:none!important;border-radius:0!important}.window.maximized [data-bar]{border-radius:0!important}.window.tiled{max-width:none!important;max-height:none!important}.window-toggling{transition:top .22s ease,left .22s ease,width .22s ease,height .22s ease,max-width .22s ease,max-height .22s ease,border-radius .22s ease}.window-toggling.dragging-restore{transition:width .22s ease,height .22s ease,max-width .22s ease,max-height .22s ease,border-radius .22s ease}.snap-indicator{position:fixed;border:2px dashed rgba(56,189,248,.9);border-radius:.85rem;background:#0ea5e92e;opacity:0;pointer-events:none;transition:opacity .11s ease;z-index:9999}.snap-indicator.visible{opacity:1}@keyframes window-appear{0%{opacity:0;transform:scale(.97)}to{opacity:1;transform:scale(1)}}@keyframes window-disappear{0%{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.98)}}
|