@deijose/nix-js 2.0.0 → 2.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.
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./signals.cjs"),t=require("./lifecycle.cjs"),n=require("./router.cjs");var r={enabled:!1,activeTab:"signals",refreshId:null,root:null,panel:null,content:null,dispose:null,renderKeys:{signals:"",components:"",router:""},scrollMemo:{signals:{top:0,left:0},components:{top:0,left:0},router:{top:0,left:0}}},i=new Set,a=new WeakMap,o=1,s=new WeakMap,c=new Map,l=[],u=1;function d(e){return typeof WeakRef<"u"?new WeakRef(e):{deref:()=>e}}function f(e,t){let n=a.get(e);if(n)return n;let l=Date.now(),r={id:o++,createdAt:l,lastUpdated:l,history:[{at:l,value:t}]};return a.set(e,r),i.add(d(e)),r}function p(){let e=[];for(let t of Array.from(i)){let n=t.deref();if(!n){i.delete(t);continue}let o=a.get(n);if(!o)continue;let l=n._subs?.size??0;e.push({id:o.id,value:n.peek(),subscriberCount:l,createdAt:o.createdAt,lastUpdated:o.lastUpdated,history:o.history.slice()})}return e.sort((e,t)=>t.lastUpdated-e.lastUpdated),e}function m(e){let t=e._debugName;if(t&&t.trim())return t;let n=e.constructor;return n?.name&&n.name.trim()?n.name:"AnonymousComponent"}function h(e){let t=e._slots;return t instanceof Map?Array.from(t.keys()).map(e=>String(e)):[]}function g(e){let t={};for(let n of Object.keys(e)){if("__isNixComponent"===n||"children"===n||"_debugName"===n||n.startsWith("_"))continue;let o=e[n];"function"!=typeof o&&(t[n]=o)}return t}function _(e){if(!e)return[];if("*"===e)return["*"];let t=e.split("/").filter(Boolean),n=[],o="";for(let e of t)o+="/"+e,n.push(o);return n.length>0?n:["/"]}function v(){let e=Array.from(c.values()).map(e=>({id:e.id,parentId:e.parentId,debugName:e.debugName,mountedAt:e.mountedAt,hasDefaultSlot:e.hasDefaultSlot,slotNames:[...e.slotNames],props:{...e.props}}));return e.sort((e,t)=>e.id-t.id),e}function y(){i.clear(),a=new WeakMap,o=1,s=new WeakMap,c.clear(),l.length=0,u=1}function b(e){if("string"==typeof e)return e;if("number"==typeof e||"boolean"==typeof e||null==e)return String(e);try{return JSON.stringify(e)}catch{return Object.prototype.toString.call(e)}}function x(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\"/g,"&quot;").replace(/'/g,"&#39;")}function S(e,t=90){let n=b(e);return n.length<=t?n:n.slice(0,t-1)+"…"}function C(e){if(!e)return"-";let t=Date.now()-e;return t<1e3?`${t}ms ago`:t<6e4?`${Math.floor(t/1e3)}s ago`:`${Math.floor(t/6e4)}m ago`}function w(e){let t=p(),n=`${t.length}:${t.map(e=>`${e.id}-${e.lastUpdated}-${e.subscriberCount}`).join("|")}`;if(r.renderKeys.signals===n)return;r.renderKeys.signals=n;let o=t.map(e=>{let t=b(e.value),n=S(e.value,120);return`<tr data-nix-devtools-signal-id="${e.id}">\n <td style="padding:6px 8px;white-space:nowrap;">${e.id}</td>\n <td style="padding:6px 8px;max-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace, SFMono-Regular, Menlo, monospace;" title="${x(t)}">${x(n)}</td>\n <td>${e.subscriberCount}</td>\n <td>${C(e.lastUpdated)}</td>\n </tr>`}).join("");e.innerHTML=`\n <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;">\n <strong>Signals</strong>\n <span style="opacity:.8">${t.length} active</span>\n </div>\n <div data-nix-devtools-scroll="signals" style="max-height:260px;overflow:auto;overscroll-behavior:contain;border:1px solid #2f2f35;border-radius:8px;">\n <table style="width:100%;border-collapse:collapse;font-size:12px;table-layout:fixed;">\n <thead>\n <tr style="background:#1f1f24;">\n <th style="text-align:left;padding:6px 8px;width:42px;">ID</th>\n <th style="text-align:left;padding:6px 8px;">Value</th>\n <th style="text-align:left;padding:6px 8px;width:50px;">Subs</th>\n <th style="text-align:left;padding:6px 8px;width:84px;">Updated</th>\n </tr>\n </thead>\n <tbody>${o}</tbody>\n </table>\n </div>\n <p style="margin:8px 0 0 0;font-size:11px;opacity:.75;">Click a row to log full history in console.</p>\n `;for(let n of e.querySelectorAll("tr[data-nix-devtools-signal-id]"))n.style.cursor="pointer",n.addEventListener("click",()=>{let e=Number(n.dataset.nixDevtoolsSignalId),o=t.find(t=>t.id===e);o&&(console.group(`[Nix DevTools] Signal #${o.id}`),console.log("Current value:",o.value),console.log("Subscribers:",o.subscriberCount),console.table(o.history.map(e=>({at:new Date(e.at).toISOString(),value:e.value}))),console.groupEnd())})}function T(e){let t=new Map,n=[];for(let n of e)t.set(n.id,{...n,children:[]});for(let e of t.values()){if(null==e.parentId){n.push(e);continue}let o=t.get(e.parentId);o?o.children.push(e):n.push(e)}return n}function E(e,t){let n=10+14*t,o=Object.keys(e.props).length>0?b(e.props):"{}",l=e.slotNames.length>0?e.slotNames.join(", "):"none";return`<div style="padding:6px 8px 6px ${n}px;border-bottom:1px solid #24242b;">\n <div><strong>${x(e.debugName)}</strong> <span style="opacity:.7">#${e.id}</span></div>\n <div style="font-size:11px;opacity:.8;">slots: ${l} | default-slot: ${e.hasDefaultSlot?"yes":"no"}</div>\n <div style="font-size:11px;opacity:.8;">props: ${x(S(o,180))}</div>\n </div>`+e.children.map(e=>E(e,t+1)).join("")}function D(e){let t=v(),n=`${t.length}:${t.map(e=>`${e.id}-${e.parentId}-${e.debugName}`).join("|")}`;if(r.renderKeys.components===n)return;r.renderKeys.components=n;let o=T(t);e.innerHTML=`\n <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;">\n <strong>Component Tree</strong>\n <span style="opacity:.8">${t.length} mounted</span>\n </div>\n <div data-nix-devtools-scroll="components" style="max-height:280px;overflow:auto;overscroll-behavior:contain;border:1px solid #2f2f35;border-radius:8px;">\n ${o.length>0?o.map(e=>E(e,0)).join(""):"<div style='padding:10px;opacity:.75'>No mounted components tracked. Enable devtools before your first mount() to capture initial tree.</div>"}\n </div>\n `}function O(e){let t=n._debugGetRouterInternal(),o=t?`${t.mode}|${t.base}|${t.currentPath}|${JSON.stringify(t.params)}|${JSON.stringify(t.query)}|${t.matchedPath}|${t.activeGuards.names.join(",")}`:"none";if(r.renderKeys.router===o)return;if(r.renderKeys.router=o,!t)return void(e.innerHTML='\n <strong>Router State</strong>\n <div style="margin-top:8px;opacity:.75">No active Nix router instance. Ensure your app uses createRouter()/RouterView from @deijose/nix-js/router.</div>\n ');let l=_(t.matchedPath);e.innerHTML=`\n <strong>Router State</strong>\n <div data-nix-devtools-scroll="router" style="margin-top:8px;font-size:12px;line-height:1.55;max-height:280px;overflow:auto;overscroll-behavior:contain;border:1px solid #2f2f35;border-radius:8px;padding:8px;">\n <div><b>mode</b>: ${t.mode}</div>\n <div><b>base</b>: ${t.base}</div>\n <div><b>current</b>: ${x(t.currentPath)}</div>\n <div><b>params</b>: ${x(b(t.params))}</div>\n <div><b>query</b>: ${x(b(t.query))}</div>\n <div><b>matched</b>: ${x(t.matchedPath??"none")}</div>\n <div><b>matched chain</b>: ${l.length>0?x(l.join(" -> ")):"none"}</div>\n <div><b>guards</b>: ${t.activeGuards.names.length>0?x(t.activeGuards.names.join(", ")):"none"}</div>\n </div>\n `}function k(e){if(!r.content)return;let t=r.content.querySelector(`[data-nix-devtools-scroll='${e}']`);t&&(r.scrollMemo[e]={top:t.scrollTop,left:t.scrollLeft})}function A(e){if(!r.content)return;let t=r.content.querySelector(`[data-nix-devtools-scroll='${e}']`);if(!t)return;let n=r.scrollMemo[e];t.scrollTop=n.top,t.scrollLeft=n.left,"1"!==t.dataset.nixDevtoolsScrollBound&&(t.addEventListener("scroll",()=>{r.scrollMemo[e]={top:t.scrollTop,left:t.scrollLeft}},{passive:!0}),t.dataset.nixDevtoolsScrollBound="1")}function j(e=!1){if(!r.content)return;let t=r.activeTab;return e||k(t),"signals"===r.activeTab?(w(r.content),void A("signals")):"components"===r.activeTab?(D(r.content),void A("components")):(O(r.content),void A("router"))}function M(e){let t=document.createElement("div");t.setAttribute("data-nix-devtools-root",""),t.style.position="fixed",t.style.zIndex="2147483647",t.style.bottom="16px",t.style.right="bottom-right"===e.position?"16px":"auto",t.style.left="bottom-left"===e.position?"16px":"auto",t.style.fontFamily="ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif";let n=document.createElement("button");n.type="button",n.textContent="Nix DevTools",n.setAttribute("data-nix-devtools-button",""),n.style.background="#111827",n.style.color="#f9fafb",n.style.border="1px solid #374151",n.style.borderRadius="999px",n.style.padding="8px 12px",n.style.cursor="pointer",n.style.boxShadow="0 6px 18px rgba(0,0,0,.3)";let o=document.createElement("div");o.setAttribute("data-nix-devtools-panel",""),o.style.marginTop="8px",o.style.width="460px",o.style.maxWidth="min(92vw, 460px)",o.style.background="#15151b",o.style.color="#e5e7eb",o.style.border="1px solid #2f2f35",o.style.borderRadius="12px",o.style.padding="10px",o.style.display="none",o.style.boxShadow="0 14px 28px rgba(0,0,0,.35)";let l=document.createElement("div");l.style.display="flex",l.style.gap="6px",l.style.marginBottom="10px";let s=document.createElement("div");s.setAttribute("data-nix-devtools-content","");let i=(e,t)=>{let n=document.createElement("button");return n.type="button",n.textContent=t,n.setAttribute("data-nix-devtools-tab",e),n.style.border="1px solid #353543",n.style.borderRadius="8px",n.style.padding="6px 9px",n.style.background="#1f1f24",n.style.color="#d1d5db",n.style.cursor="pointer",n.addEventListener("click",()=>{r.activeTab=e;for(let t of l.querySelectorAll("button[data-nix-devtools-tab]"))t.style.background=t.dataset.nixDevtoolsTab===e?"#2d4c7a":"#1f1f24";j(!0)}),n};l.appendChild(i("signals","Signals")),l.appendChild(i("components","Components")),l.appendChild(i("router","Router")),n.addEventListener("click",()=>{o.style.display="none"===o.style.display?"block":"none","block"===o.style.display&&j()}),o.appendChild(l),o.appendChild(s),t.appendChild(n),t.appendChild(o),document.body.appendChild(t),r.root=t,r.panel=o,r.content=s}function N(){r.enabled&&(r.enabled=!1,null!=r.refreshId&&(clearInterval(r.refreshId),r.refreshId=null),e._setSignalDebugHooks(null),t._setComponentDebugHooks(null),y(),r.root?.parentNode&&r.root.parentNode.removeChild(r.root),r.root=null,r.panel=null,r.content=null,r.dispose=null,r.renderKeys={signals:"",components:"",router:""},r.scrollMemo={signals:{top:0,left:0},components:{top:0,left:0},router:{top:0,left:0}})}function P(n={}){if(typeof document>"u")return{disable:()=>{}};if(r.enabled&&r.dispose)return{disable:r.dispose};let o=Math.max(100,n.refreshMs??350),i=Math.max(1,n.historyLimit??50),a=n.position??"bottom-right";r.enabled=!0,r.activeTab="signals",e._setSignalDebugHooks({onCreate(e,t){f(e,t)},onWrite(e,t){let n=f(e,t),o=Date.now();n.lastUpdated=o,n.history.push({at:o,value:t}),n.history.length>i&&n.history.splice(0,n.history.length-i)}}),t._setComponentDebugHooks({onMountStart(e){let t=s.get(e);t??(t=u++,s.set(e,t));let n=l.length>0?l[l.length-1]:null;c.set(t,{id:t,parentId:n,debugName:m(e),mountedAt:Date.now(),hasDefaultSlot:null!=e.children,slotNames:h(e),props:g(e)}),l.push(t)},onMountEnd(e){let t=s.get(e);if(null==t)return;let n=c.get(t);if(n&&(n.debugName=m(e),n.hasDefaultSlot=null!=e.children,n.slotNames=h(e),n.props=g(e)),l[l.length-1]===t)return void l.pop();let o=l.lastIndexOf(t);o>=0&&l.splice(o,1)},onUnmount(e){let t=s.get(e);if(null==t)return;c.delete(t);for(let[e,n]of c)n.parentId===t&&c.delete(e);let n=l.lastIndexOf(t);n>=0&&l.splice(n,1)}}),M({position:a}),r.refreshId=setInterval(()=>{"block"===r.panel?.style.display&&j()},o),n.initiallyOpen&&r.panel&&(r.panel.style.display="block",j());let d=()=>N();return r.dispose=d,{disable:d}}exports.disableDevTools=N,exports.enableDevTools=P;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./signals.cjs"),t=require("./lifecycle.cjs"),n=require("./router.cjs");var r={enabled:!1,activeTab:"signals",renderedTab:null,refreshId:null,root:null,panel:null,content:null,dispose:null,renderKeys:{signals:"",components:"",router:""},scrollMemo:{signals:{top:0,left:0},components:{top:0,left:0},router:{top:0,left:0}}},i=new Set,a=new WeakMap,o=1,s=new WeakMap,c=new Map,l=[],u=1;function d(e){return typeof WeakRef<"u"?new WeakRef(e):{deref:()=>e}}function f(e){return typeof WeakRef<"u"?new WeakRef(e):{deref:()=>e}}function p(e,t){let n=a.get(e);if(n)return n;let r=Date.now(),l={id:o++,createdAt:r,lastUpdated:r,history:[{at:r,value:t}]};return a.set(e,l),i.add(d(e)),l}function m(){let e=[];for(let t of Array.from(i)){let n=t.deref();if(!n){i.delete(t);continue}let o=a.get(n);if(!o)continue;let r=n._subs?.size??0;e.push({id:o.id,value:n.peek(),subscriberCount:r,createdAt:o.createdAt,lastUpdated:o.lastUpdated,history:o.history.slice()})}return e.sort((e,t)=>t.lastUpdated-e.lastUpdated),e}function h(e){let t=e._debugName;if(t&&t.trim())return t;let n=e.constructor;return n?.name&&n.name.trim()?n.name:"AnonymousComponent"}function g(e){let t=e._slots;return t instanceof Map?Array.from(t.keys()).map(e=>String(e)):[]}function _(e){let t={};for(let n of Object.keys(e)){if("__isNixComponent"===n||"children"===n||"_debugName"===n||n.startsWith("_"))continue;let o=e[n];"function"!=typeof o&&(t[n]=o)}return t}function v(e){if(!e)return[];if("*"===e)return["*"];let t=e.split("/").filter(Boolean),n=[],o="";for(let e of t)o+="/"+e,n.push(o);return n.length>0?n:["/"]}function y(){let e=[];for(let[t,n]of c){let o=n.ref.deref();o?(n.debugName=h(o),n.hasDefaultSlot=null!=o.children,n.slotNames=g(o),n.props=_(o),e.push({id:n.id,parentId:n.parentId,debugName:n.debugName,mountedAt:n.mountedAt,hasDefaultSlot:n.hasDefaultSlot,slotNames:[...n.slotNames],props:{...n.props}})):c.delete(t)}return e.sort((e,t)=>e.id-t.id),e}function b(e){let t=[e];for(;t.length>0;){let e=t.pop();for(let[n,o]of c)o.parentId===e&&t.push(n);c.delete(e)}}function x(){i.clear(),a=new WeakMap,o=1,s=new WeakMap,c.clear(),l.length=0,u=1}function S(e){if("string"==typeof e)return e;if("number"==typeof e||"boolean"==typeof e||null==e)return String(e);try{return JSON.stringify(e)}catch{return Object.prototype.toString.call(e)}}function C(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\"/g,"&quot;").replace(/'/g,"&#39;")}function w(e,t=90){let n=S(e);return n.length<=t?n:n.slice(0,t-1)+"…"}function T(e){if(!e)return"-";let t=Date.now()-e;return t<1e3?`${t}ms ago`:t<6e4?`${Math.floor(t/1e3)}s ago`:`${Math.floor(t/6e4)}m ago`}function E(e){let t=m(),n=`${t.length}:${t.map(e=>`${e.id}-${e.lastUpdated}-${e.subscriberCount}`).join("|")}`;if("signals"===r.renderedTab&&r.renderKeys.signals===n)return;r.renderKeys.signals=n,r.renderedTab="signals";let o=t.map(e=>{let t=S(e.value),n=w(e.value,120);return`<tr data-nix-devtools-signal-id="${e.id}">\n <td style="padding:6px 8px;white-space:nowrap;">${e.id}</td>\n <td style="padding:6px 8px;max-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace, SFMono-Regular, Menlo, monospace;" title="${C(t)}">${C(n)}</td>\n <td>${e.subscriberCount}</td>\n <td>${T(e.lastUpdated)}</td>\n </tr>`}).join("");e.innerHTML=`\n <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;">\n <strong>Signals</strong>\n <span style="opacity:.8">${t.length} active</span>\n </div>\n <div data-nix-devtools-scroll="signals" style="max-height:260px;overflow:auto;overscroll-behavior:contain;border:1px solid #2f2f35;border-radius:8px;">\n <table style="width:100%;border-collapse:collapse;font-size:12px;table-layout:fixed;">\n <thead>\n <tr style="background:#1f1f24;">\n <th style="text-align:left;padding:6px 8px;width:42px;">ID</th>\n <th style="text-align:left;padding:6px 8px;">Value</th>\n <th style="text-align:left;padding:6px 8px;width:50px;">Subs</th>\n <th style="text-align:left;padding:6px 8px;width:84px;">Updated</th>\n </tr>\n </thead>\n <tbody>${o}</tbody>\n </table>\n </div>\n <p style="margin:8px 0 0 0;font-size:11px;opacity:.75;">Click a row to log full history in console.</p>\n `;for(let n of e.querySelectorAll("tr[data-nix-devtools-signal-id]"))n.style.cursor="pointer",n.addEventListener("click",()=>{let e=Number(n.dataset.nixDevtoolsSignalId),o=t.find(t=>t.id===e);o&&(console.group(`[Nix DevTools] Signal #${o.id}`),console.log("Current value:",o.value),console.log("Subscribers:",o.subscriberCount),console.table(o.history.map(e=>({at:new Date(e.at).toISOString(),value:e.value}))),console.groupEnd())})}function D(e){let t=new Map,n=[];for(let n of e)t.set(n.id,{...n,children:[]});for(let e of t.values()){if(null==e.parentId){n.push(e);continue}let o=t.get(e.parentId);o?o.children.push(e):n.push(e)}return n}function O(e,t){let n=10+14*t,o=Object.keys(e.props).length>0?S(e.props):"{}",r=e.slotNames.length>0?e.slotNames.join(", "):"none";return`<div style="padding:6px 8px 6px ${n}px;border-bottom:1px solid #24242b;">\n <div><strong>${C(e.debugName)}</strong> <span style="opacity:.7">#${e.id}</span></div>\n <div style="font-size:11px;opacity:.8;">slots: ${r} | default-slot: ${e.hasDefaultSlot?"yes":"no"}</div>\n <div style="font-size:11px;opacity:.8;">props: ${C(w(o,180))}</div>\n </div>`+e.children.map(e=>O(e,t+1)).join("")}function k(e){let t=y(),o=n._debugGetRouterInternal(),l=`${o?`${o.currentPath}|${o.matchedPath??""}`:"no-router"}:${t.length}:${t.map(e=>`${e.id}-${e.parentId}-${e.debugName}-${e.hasDefaultSlot}-${e.slotNames.join(",")}-${S(e.props)}`).join("|")}`;if("components"===r.renderedTab&&r.renderKeys.components===l)return;r.renderKeys.components=l,r.renderedTab="components";let a=D(t);e.innerHTML=`\n <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;">\n <strong>Component Tree</strong>\n <span style="opacity:.8">${t.length} mounted</span>\n </div>\n <div style="font-size:11px;opacity:.82;margin-bottom:8px;display:flex;gap:8px;flex-wrap:wrap;">\n <span><b>current:</b> ${C(o?.currentPath??"-")}</span>\n <span><b>matched:</b> ${C(o?.matchedPath??"none")}</span>\n </div>\n <div data-nix-devtools-scroll="components" style="max-height:280px;overflow:auto;overscroll-behavior:contain;border:1px solid #2f2f35;border-radius:8px;">\n ${a.length>0?a.map(e=>O(e,0)).join(""):"<div style='padding:10px;opacity:.75'>No mounted components tracked. Enable devtools before your first mount() to capture initial tree.</div>"}\n </div>\n `}function A(e){let t=n._debugGetRouterInternal(),o=t?`${t.mode}|${t.base}|${t.currentPath}|${JSON.stringify(t.params)}|${JSON.stringify(t.query)}|${t.matchedPath}|${t.activeGuards.names.join(",")}`:"none";if("router"===r.renderedTab&&r.renderKeys.router===o)return;if(r.renderKeys.router=o,r.renderedTab="router",!t)return void(e.innerHTML='\n <strong>Router State</strong>\n <div style="margin-top:8px;opacity:.75">No active Nix router instance. Ensure your app uses createRouter()/RouterView from @deijose/nix-js/router.</div>\n ');let l=v(t.matchedPath);e.innerHTML=`\n <strong>Router State</strong>\n <div data-nix-devtools-scroll="router" style="margin-top:8px;font-size:12px;line-height:1.55;max-height:280px;overflow:auto;overscroll-behavior:contain;border:1px solid #2f2f35;border-radius:8px;padding:8px;">\n <div><b>mode</b>: ${t.mode}</div>\n <div><b>base</b>: ${t.base}</div>\n <div><b>current</b>: ${C(t.currentPath)}</div>\n <div><b>params</b>: ${C(S(t.params))}</div>\n <div><b>query</b>: ${C(S(t.query))}</div>\n <div><b>matched</b>: ${C(t.matchedPath??"none")}</div>\n <div><b>matched chain</b>: ${l.length>0?C(l.join(" -> ")):"none"}</div>\n <div><b>guards</b>: ${t.activeGuards.names.length>0?C(t.activeGuards.names.join(", ")):"none"}</div>\n </div>\n `}function j(e){if(!r.content)return;let t=r.content.querySelector(`[data-nix-devtools-scroll='${e}']`);t&&(r.scrollMemo[e]={top:t.scrollTop,left:t.scrollLeft})}function M(e){if(!r.content)return;let t=r.content.querySelector(`[data-nix-devtools-scroll='${e}']`);if(!t)return;let n=r.scrollMemo[e];t.scrollTop=n.top,t.scrollLeft=n.left,"1"!==t.dataset.nixDevtoolsScrollBound&&(t.addEventListener("scroll",()=>{r.scrollMemo[e]={top:t.scrollTop,left:t.scrollLeft}},{passive:!0}),t.dataset.nixDevtoolsScrollBound="1")}function N(e=!1){if(!r.content)return;let t=r.activeTab;return e||j(t),"signals"===r.activeTab?(E(r.content),void M("signals")):"components"===r.activeTab?(k(r.content),void M("components")):(A(r.content),void M("router"))}function P(){if(r.panel)for(let e of r.panel.querySelectorAll("button[data-nix-devtools-tab]")){let t=e.dataset.nixDevtoolsTab===r.activeTab;e.style.background=t?"#2d4c7a":"#1f1f24"}}function F(e){let t=document.createElement("div");t.setAttribute("data-nix-devtools-root",""),t.style.position="fixed",t.style.zIndex="2147483647",t.style.bottom="16px",t.style.right="bottom-right"===e.position?"16px":"auto",t.style.left="bottom-left"===e.position?"16px":"auto",t.style.fontFamily="ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif";let n=document.createElement("button");n.type="button",n.textContent="Nix DevTools",n.setAttribute("data-nix-devtools-button",""),n.style.background="#111827",n.style.color="#f9fafb",n.style.border="1px solid #374151",n.style.borderRadius="999px",n.style.padding="8px 12px",n.style.cursor="pointer",n.style.boxShadow="0 6px 18px rgba(0,0,0,.3)";let o=document.createElement("div");o.setAttribute("data-nix-devtools-panel",""),o.style.marginTop="8px",o.style.width="460px",o.style.maxWidth="min(92vw, 460px)",o.style.background="#15151b",o.style.color="#e5e7eb",o.style.border="1px solid #2f2f35",o.style.borderRadius="12px",o.style.padding="10px",o.style.display="none",o.style.boxShadow="0 14px 28px rgba(0,0,0,.35)";let l=document.createElement("div");l.style.display="flex",l.style.gap="6px",l.style.marginBottom="10px";let a=document.createElement("div");a.setAttribute("data-nix-devtools-content","");let s=(e,t)=>{let n=document.createElement("button");return n.type="button",n.textContent=t,n.setAttribute("data-nix-devtools-tab",e),n.style.border="1px solid #353543",n.style.borderRadius="8px",n.style.padding="6px 9px",n.style.background="#1f1f24",n.style.color="#d1d5db",n.style.cursor="pointer",n.addEventListener("click",()=>{r.activeTab=e,P(),N(!0)}),n};l.appendChild(s("signals","Signals")),l.appendChild(s("components","Components")),l.appendChild(s("router","Router")),n.addEventListener("click",()=>{o.style.display="none"===o.style.display?"block":"none","block"===o.style.display&&(P(),N(!0))}),o.appendChild(l),o.appendChild(a),t.appendChild(n),t.appendChild(o),document.body.appendChild(t),r.root=t,r.panel=o,r.content=a}function I(){r.enabled&&(r.enabled=!1,null!=r.refreshId&&(clearInterval(r.refreshId),r.refreshId=null),e._setSignalDebugHooks(null),t._setComponentDebugHooks(null),x(),r.root?.parentNode&&r.root.parentNode.removeChild(r.root),r.root=null,r.panel=null,r.content=null,r.dispose=null,r.renderedTab=null,r.renderKeys={signals:"",components:"",router:""},r.scrollMemo={signals:{top:0,left:0},components:{top:0,left:0},router:{top:0,left:0}})}function L(n={}){if(typeof document>"u")return{disable:()=>{}};if(r.enabled&&r.dispose)return{disable:r.dispose};let o=Math.max(100,n.refreshMs??350),a=Math.max(1,n.historyLimit??50),i=n.position??"bottom-right";r.enabled=!0,r.activeTab="signals",e._setSignalDebugHooks({onCreate(e,t){p(e,t)},onWrite(e,t){let n=p(e,t),o=Date.now();n.lastUpdated=o,n.history.push({at:o,value:t}),n.history.length>a&&n.history.splice(0,n.history.length-a)}}),t._setComponentDebugHooks({onMountStart(e){let t=s.get(e);t??(t=u++,s.set(e,t));let n=l.length>0?l[l.length-1]:null;c.set(t,{id:t,parentId:n,debugName:h(e),mountedAt:Date.now(),hasDefaultSlot:null!=e.children,slotNames:g(e),props:_(e),ref:f(e)}),l.push(t)},onMountEnd(e){let t=s.get(e);if(null==t)return;let n=c.get(t);if(n&&(n.debugName=h(e),n.hasDefaultSlot=null!=e.children,n.slotNames=g(e),n.props=_(e)),l[l.length-1]===t)return void l.pop();let o=l.lastIndexOf(t);o>=0&&l.splice(o,1)},onUnmount(e){let t=s.get(e);if(null==t)return;b(t);let n=l.lastIndexOf(t);n>=0&&l.splice(n,1)}}),F({position:i}),r.refreshId=setInterval(()=>{"block"===r.panel?.style.display&&N()},o),n.initiallyOpen&&r.panel&&(r.panel.style.display="block",P(),N(!0));let d=()=>I();return r.dispose=d,{disable:d}}exports.disableDevTools=I,exports.enableDevTools=L;
@@ -1 +1 @@
1
- import{_setSignalDebugHooks as e}from"./signals.js";import{_setComponentDebugHooks as t}from"./lifecycle.js";import{_debugGetRouterInternal as n}from"./router.js";var r={enabled:!1,activeTab:"signals",refreshId:null,root:null,panel:null,content:null,dispose:null,renderKeys:{signals:"",components:"",router:""},scrollMemo:{signals:{top:0,left:0},components:{top:0,left:0},router:{top:0,left:0}}},i=new Set,a=new WeakMap,o=1,s=new WeakMap,c=new Map,l=[],u=1;function d(e){return typeof WeakRef<"u"?new WeakRef(e):{deref:()=>e}}function f(e,t){let n=a.get(e);if(n)return n;let l=Date.now(),r={id:o++,createdAt:l,lastUpdated:l,history:[{at:l,value:t}]};return a.set(e,r),i.add(d(e)),r}function p(){let e=[];for(let t of Array.from(i)){let n=t.deref();if(!n){i.delete(t);continue}let o=a.get(n);if(!o)continue;let l=n._subs?.size??0;e.push({id:o.id,value:n.peek(),subscriberCount:l,createdAt:o.createdAt,lastUpdated:o.lastUpdated,history:o.history.slice()})}return e.sort((e,t)=>t.lastUpdated-e.lastUpdated),e}function m(e){let t=e._debugName;if(t&&t.trim())return t;let n=e.constructor;return n?.name&&n.name.trim()?n.name:"AnonymousComponent"}function h(e){let t=e._slots;return t instanceof Map?Array.from(t.keys()).map(e=>String(e)):[]}function g(e){let t={};for(let n of Object.keys(e)){if("__isNixComponent"===n||"children"===n||"_debugName"===n||n.startsWith("_"))continue;let o=e[n];"function"!=typeof o&&(t[n]=o)}return t}function _(e){if(!e)return[];if("*"===e)return["*"];let t=e.split("/").filter(Boolean),n=[],o="";for(let e of t)o+="/"+e,n.push(o);return n.length>0?n:["/"]}function v(){let e=Array.from(c.values()).map(e=>({id:e.id,parentId:e.parentId,debugName:e.debugName,mountedAt:e.mountedAt,hasDefaultSlot:e.hasDefaultSlot,slotNames:[...e.slotNames],props:{...e.props}}));return e.sort((e,t)=>e.id-t.id),e}function y(){i.clear(),a=new WeakMap,o=1,s=new WeakMap,c.clear(),l.length=0,u=1}function b(e){if("string"==typeof e)return e;if("number"==typeof e||"boolean"==typeof e||null==e)return String(e);try{return JSON.stringify(e)}catch{return Object.prototype.toString.call(e)}}function x(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\"/g,"&quot;").replace(/'/g,"&#39;")}function S(e,t=90){let n=b(e);return n.length<=t?n:n.slice(0,t-1)+"…"}function C(e){if(!e)return"-";let t=Date.now()-e;return t<1e3?`${t}ms ago`:t<6e4?`${Math.floor(t/1e3)}s ago`:`${Math.floor(t/6e4)}m ago`}function w(e){let t=p(),n=`${t.length}:${t.map(e=>`${e.id}-${e.lastUpdated}-${e.subscriberCount}`).join("|")}`;if(r.renderKeys.signals===n)return;r.renderKeys.signals=n;let o=t.map(e=>{let t=b(e.value),n=S(e.value,120);return`<tr data-nix-devtools-signal-id="${e.id}">\n <td style="padding:6px 8px;white-space:nowrap;">${e.id}</td>\n <td style="padding:6px 8px;max-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace, SFMono-Regular, Menlo, monospace;" title="${x(t)}">${x(n)}</td>\n <td>${e.subscriberCount}</td>\n <td>${C(e.lastUpdated)}</td>\n </tr>`}).join("");e.innerHTML=`\n <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;">\n <strong>Signals</strong>\n <span style="opacity:.8">${t.length} active</span>\n </div>\n <div data-nix-devtools-scroll="signals" style="max-height:260px;overflow:auto;overscroll-behavior:contain;border:1px solid #2f2f35;border-radius:8px;">\n <table style="width:100%;border-collapse:collapse;font-size:12px;table-layout:fixed;">\n <thead>\n <tr style="background:#1f1f24;">\n <th style="text-align:left;padding:6px 8px;width:42px;">ID</th>\n <th style="text-align:left;padding:6px 8px;">Value</th>\n <th style="text-align:left;padding:6px 8px;width:50px;">Subs</th>\n <th style="text-align:left;padding:6px 8px;width:84px;">Updated</th>\n </tr>\n </thead>\n <tbody>${o}</tbody>\n </table>\n </div>\n <p style="margin:8px 0 0 0;font-size:11px;opacity:.75;">Click a row to log full history in console.</p>\n `;for(let n of e.querySelectorAll("tr[data-nix-devtools-signal-id]"))n.style.cursor="pointer",n.addEventListener("click",()=>{let e=Number(n.dataset.nixDevtoolsSignalId),o=t.find(t=>t.id===e);o&&(console.group(`[Nix DevTools] Signal #${o.id}`),console.log("Current value:",o.value),console.log("Subscribers:",o.subscriberCount),console.table(o.history.map(e=>({at:new Date(e.at).toISOString(),value:e.value}))),console.groupEnd())})}function T(e){let t=new Map,n=[];for(let n of e)t.set(n.id,{...n,children:[]});for(let e of t.values()){if(null==e.parentId){n.push(e);continue}let o=t.get(e.parentId);o?o.children.push(e):n.push(e)}return n}function E(e,t){let n=10+14*t,o=Object.keys(e.props).length>0?b(e.props):"{}",l=e.slotNames.length>0?e.slotNames.join(", "):"none";return`<div style="padding:6px 8px 6px ${n}px;border-bottom:1px solid #24242b;">\n <div><strong>${x(e.debugName)}</strong> <span style="opacity:.7">#${e.id}</span></div>\n <div style="font-size:11px;opacity:.8;">slots: ${l} | default-slot: ${e.hasDefaultSlot?"yes":"no"}</div>\n <div style="font-size:11px;opacity:.8;">props: ${x(S(o,180))}</div>\n </div>`+e.children.map(e=>E(e,t+1)).join("")}function D(e){let t=v(),n=`${t.length}:${t.map(e=>`${e.id}-${e.parentId}-${e.debugName}`).join("|")}`;if(r.renderKeys.components===n)return;r.renderKeys.components=n;let o=T(t);e.innerHTML=`\n <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;">\n <strong>Component Tree</strong>\n <span style="opacity:.8">${t.length} mounted</span>\n </div>\n <div data-nix-devtools-scroll="components" style="max-height:280px;overflow:auto;overscroll-behavior:contain;border:1px solid #2f2f35;border-radius:8px;">\n ${o.length>0?o.map(e=>E(e,0)).join(""):"<div style='padding:10px;opacity:.75'>No mounted components tracked. Enable devtools before your first mount() to capture initial tree.</div>"}\n </div>\n `}function O(e){let t=n(),o=t?`${t.mode}|${t.base}|${t.currentPath}|${JSON.stringify(t.params)}|${JSON.stringify(t.query)}|${t.matchedPath}|${t.activeGuards.names.join(",")}`:"none";if(r.renderKeys.router===o)return;if(r.renderKeys.router=o,!t)return void(e.innerHTML='\n <strong>Router State</strong>\n <div style="margin-top:8px;opacity:.75">No active Nix router instance. Ensure your app uses createRouter()/RouterView from @deijose/nix-js/router.</div>\n ');let l=_(t.matchedPath);e.innerHTML=`\n <strong>Router State</strong>\n <div data-nix-devtools-scroll="router" style="margin-top:8px;font-size:12px;line-height:1.55;max-height:280px;overflow:auto;overscroll-behavior:contain;border:1px solid #2f2f35;border-radius:8px;padding:8px;">\n <div><b>mode</b>: ${t.mode}</div>\n <div><b>base</b>: ${t.base}</div>\n <div><b>current</b>: ${x(t.currentPath)}</div>\n <div><b>params</b>: ${x(b(t.params))}</div>\n <div><b>query</b>: ${x(b(t.query))}</div>\n <div><b>matched</b>: ${x(t.matchedPath??"none")}</div>\n <div><b>matched chain</b>: ${l.length>0?x(l.join(" -> ")):"none"}</div>\n <div><b>guards</b>: ${t.activeGuards.names.length>0?x(t.activeGuards.names.join(", ")):"none"}</div>\n </div>\n `}function k(e){if(!r.content)return;let t=r.content.querySelector(`[data-nix-devtools-scroll='${e}']`);t&&(r.scrollMemo[e]={top:t.scrollTop,left:t.scrollLeft})}function A(e){if(!r.content)return;let t=r.content.querySelector(`[data-nix-devtools-scroll='${e}']`);if(!t)return;let n=r.scrollMemo[e];t.scrollTop=n.top,t.scrollLeft=n.left,"1"!==t.dataset.nixDevtoolsScrollBound&&(t.addEventListener("scroll",()=>{r.scrollMemo[e]={top:t.scrollTop,left:t.scrollLeft}},{passive:!0}),t.dataset.nixDevtoolsScrollBound="1")}function j(e=!1){if(!r.content)return;let t=r.activeTab;return e||k(t),"signals"===r.activeTab?(w(r.content),void A("signals")):"components"===r.activeTab?(D(r.content),void A("components")):(O(r.content),void A("router"))}function M(e){let t=document.createElement("div");t.setAttribute("data-nix-devtools-root",""),t.style.position="fixed",t.style.zIndex="2147483647",t.style.bottom="16px",t.style.right="bottom-right"===e.position?"16px":"auto",t.style.left="bottom-left"===e.position?"16px":"auto",t.style.fontFamily="ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif";let n=document.createElement("button");n.type="button",n.textContent="Nix DevTools",n.setAttribute("data-nix-devtools-button",""),n.style.background="#111827",n.style.color="#f9fafb",n.style.border="1px solid #374151",n.style.borderRadius="999px",n.style.padding="8px 12px",n.style.cursor="pointer",n.style.boxShadow="0 6px 18px rgba(0,0,0,.3)";let o=document.createElement("div");o.setAttribute("data-nix-devtools-panel",""),o.style.marginTop="8px",o.style.width="460px",o.style.maxWidth="min(92vw, 460px)",o.style.background="#15151b",o.style.color="#e5e7eb",o.style.border="1px solid #2f2f35",o.style.borderRadius="12px",o.style.padding="10px",o.style.display="none",o.style.boxShadow="0 14px 28px rgba(0,0,0,.35)";let l=document.createElement("div");l.style.display="flex",l.style.gap="6px",l.style.marginBottom="10px";let s=document.createElement("div");s.setAttribute("data-nix-devtools-content","");let i=(e,t)=>{let n=document.createElement("button");return n.type="button",n.textContent=t,n.setAttribute("data-nix-devtools-tab",e),n.style.border="1px solid #353543",n.style.borderRadius="8px",n.style.padding="6px 9px",n.style.background="#1f1f24",n.style.color="#d1d5db",n.style.cursor="pointer",n.addEventListener("click",()=>{r.activeTab=e;for(let t of l.querySelectorAll("button[data-nix-devtools-tab]"))t.style.background=t.dataset.nixDevtoolsTab===e?"#2d4c7a":"#1f1f24";j(!0)}),n};l.appendChild(i("signals","Signals")),l.appendChild(i("components","Components")),l.appendChild(i("router","Router")),n.addEventListener("click",()=>{o.style.display="none"===o.style.display?"block":"none","block"===o.style.display&&j()}),o.appendChild(l),o.appendChild(s),t.appendChild(n),t.appendChild(o),document.body.appendChild(t),r.root=t,r.panel=o,r.content=s}function N(){r.enabled&&(r.enabled=!1,null!=r.refreshId&&(clearInterval(r.refreshId),r.refreshId=null),e(null),t(null),y(),r.root?.parentNode&&r.root.parentNode.removeChild(r.root),r.root=null,r.panel=null,r.content=null,r.dispose=null,r.renderKeys={signals:"",components:"",router:""},r.scrollMemo={signals:{top:0,left:0},components:{top:0,left:0},router:{top:0,left:0}})}function P(n={}){if(typeof document>"u")return{disable:()=>{}};if(r.enabled&&r.dispose)return{disable:r.dispose};let o=Math.max(100,n.refreshMs??350),i=Math.max(1,n.historyLimit??50),a=n.position??"bottom-right";r.enabled=!0,r.activeTab="signals",e({onCreate(e,t){f(e,t)},onWrite(e,t){let n=f(e,t),o=Date.now();n.lastUpdated=o,n.history.push({at:o,value:t}),n.history.length>i&&n.history.splice(0,n.history.length-i)}}),t({onMountStart(e){let t=s.get(e);t??(t=u++,s.set(e,t));let n=l.length>0?l[l.length-1]:null;c.set(t,{id:t,parentId:n,debugName:m(e),mountedAt:Date.now(),hasDefaultSlot:null!=e.children,slotNames:h(e),props:g(e)}),l.push(t)},onMountEnd(e){let t=s.get(e);if(null==t)return;let n=c.get(t);if(n&&(n.debugName=m(e),n.hasDefaultSlot=null!=e.children,n.slotNames=h(e),n.props=g(e)),l[l.length-1]===t)return void l.pop();let o=l.lastIndexOf(t);o>=0&&l.splice(o,1)},onUnmount(e){let t=s.get(e);if(null==t)return;c.delete(t);for(let[e,n]of c)n.parentId===t&&c.delete(e);let n=l.lastIndexOf(t);n>=0&&l.splice(n,1)}}),M({position:a}),r.refreshId=setInterval(()=>{"block"===r.panel?.style.display&&j()},o),n.initiallyOpen&&r.panel&&(r.panel.style.display="block",j());let d=()=>N();return r.dispose=d,{disable:d}}export{N as disableDevTools,P as enableDevTools};
1
+ import{_setSignalDebugHooks as e}from"./signals.js";import{_setComponentDebugHooks as t}from"./lifecycle.js";import{_debugGetRouterInternal as n}from"./router.js";var r={enabled:!1,activeTab:"signals",renderedTab:null,refreshId:null,root:null,panel:null,content:null,dispose:null,renderKeys:{signals:"",components:"",router:""},scrollMemo:{signals:{top:0,left:0},components:{top:0,left:0},router:{top:0,left:0}}},i=new Set,a=new WeakMap,o=1,s=new WeakMap,c=new Map,l=[],u=1;function d(e){return typeof WeakRef<"u"?new WeakRef(e):{deref:()=>e}}function f(e){return typeof WeakRef<"u"?new WeakRef(e):{deref:()=>e}}function p(e,t){let n=a.get(e);if(n)return n;let r=Date.now(),l={id:o++,createdAt:r,lastUpdated:r,history:[{at:r,value:t}]};return a.set(e,l),i.add(d(e)),l}function m(){let e=[];for(let t of Array.from(i)){let n=t.deref();if(!n){i.delete(t);continue}let o=a.get(n);if(!o)continue;let r=n._subs?.size??0;e.push({id:o.id,value:n.peek(),subscriberCount:r,createdAt:o.createdAt,lastUpdated:o.lastUpdated,history:o.history.slice()})}return e.sort((e,t)=>t.lastUpdated-e.lastUpdated),e}function h(e){let t=e._debugName;if(t&&t.trim())return t;let n=e.constructor;return n?.name&&n.name.trim()?n.name:"AnonymousComponent"}function g(e){let t=e._slots;return t instanceof Map?Array.from(t.keys()).map(e=>String(e)):[]}function _(e){let t={};for(let n of Object.keys(e)){if("__isNixComponent"===n||"children"===n||"_debugName"===n||n.startsWith("_"))continue;let o=e[n];"function"!=typeof o&&(t[n]=o)}return t}function v(e){if(!e)return[];if("*"===e)return["*"];let t=e.split("/").filter(Boolean),n=[],o="";for(let e of t)o+="/"+e,n.push(o);return n.length>0?n:["/"]}function y(){let e=[];for(let[t,n]of c){let o=n.ref.deref();o?(n.debugName=h(o),n.hasDefaultSlot=null!=o.children,n.slotNames=g(o),n.props=_(o),e.push({id:n.id,parentId:n.parentId,debugName:n.debugName,mountedAt:n.mountedAt,hasDefaultSlot:n.hasDefaultSlot,slotNames:[...n.slotNames],props:{...n.props}})):c.delete(t)}return e.sort((e,t)=>e.id-t.id),e}function b(e){let t=[e];for(;t.length>0;){let e=t.pop();for(let[n,o]of c)o.parentId===e&&t.push(n);c.delete(e)}}function x(){i.clear(),a=new WeakMap,o=1,s=new WeakMap,c.clear(),l.length=0,u=1}function S(e){if("string"==typeof e)return e;if("number"==typeof e||"boolean"==typeof e||null==e)return String(e);try{return JSON.stringify(e)}catch{return Object.prototype.toString.call(e)}}function C(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\"/g,"&quot;").replace(/'/g,"&#39;")}function w(e,t=90){let n=S(e);return n.length<=t?n:n.slice(0,t-1)+"…"}function T(e){if(!e)return"-";let t=Date.now()-e;return t<1e3?`${t}ms ago`:t<6e4?`${Math.floor(t/1e3)}s ago`:`${Math.floor(t/6e4)}m ago`}function E(e){let t=m(),n=`${t.length}:${t.map(e=>`${e.id}-${e.lastUpdated}-${e.subscriberCount}`).join("|")}`;if("signals"===r.renderedTab&&r.renderKeys.signals===n)return;r.renderKeys.signals=n,r.renderedTab="signals";let o=t.map(e=>{let t=S(e.value),n=w(e.value,120);return`<tr data-nix-devtools-signal-id="${e.id}">\n <td style="padding:6px 8px;white-space:nowrap;">${e.id}</td>\n <td style="padding:6px 8px;max-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace, SFMono-Regular, Menlo, monospace;" title="${C(t)}">${C(n)}</td>\n <td>${e.subscriberCount}</td>\n <td>${T(e.lastUpdated)}</td>\n </tr>`}).join("");e.innerHTML=`\n <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;">\n <strong>Signals</strong>\n <span style="opacity:.8">${t.length} active</span>\n </div>\n <div data-nix-devtools-scroll="signals" style="max-height:260px;overflow:auto;overscroll-behavior:contain;border:1px solid #2f2f35;border-radius:8px;">\n <table style="width:100%;border-collapse:collapse;font-size:12px;table-layout:fixed;">\n <thead>\n <tr style="background:#1f1f24;">\n <th style="text-align:left;padding:6px 8px;width:42px;">ID</th>\n <th style="text-align:left;padding:6px 8px;">Value</th>\n <th style="text-align:left;padding:6px 8px;width:50px;">Subs</th>\n <th style="text-align:left;padding:6px 8px;width:84px;">Updated</th>\n </tr>\n </thead>\n <tbody>${o}</tbody>\n </table>\n </div>\n <p style="margin:8px 0 0 0;font-size:11px;opacity:.75;">Click a row to log full history in console.</p>\n `;for(let n of e.querySelectorAll("tr[data-nix-devtools-signal-id]"))n.style.cursor="pointer",n.addEventListener("click",()=>{let e=Number(n.dataset.nixDevtoolsSignalId),o=t.find(t=>t.id===e);o&&(console.group(`[Nix DevTools] Signal #${o.id}`),console.log("Current value:",o.value),console.log("Subscribers:",o.subscriberCount),console.table(o.history.map(e=>({at:new Date(e.at).toISOString(),value:e.value}))),console.groupEnd())})}function D(e){let t=new Map,n=[];for(let n of e)t.set(n.id,{...n,children:[]});for(let e of t.values()){if(null==e.parentId){n.push(e);continue}let o=t.get(e.parentId);o?o.children.push(e):n.push(e)}return n}function O(e,t){let n=10+14*t,o=Object.keys(e.props).length>0?S(e.props):"{}",r=e.slotNames.length>0?e.slotNames.join(", "):"none";return`<div style="padding:6px 8px 6px ${n}px;border-bottom:1px solid #24242b;">\n <div><strong>${C(e.debugName)}</strong> <span style="opacity:.7">#${e.id}</span></div>\n <div style="font-size:11px;opacity:.8;">slots: ${r} | default-slot: ${e.hasDefaultSlot?"yes":"no"}</div>\n <div style="font-size:11px;opacity:.8;">props: ${C(w(o,180))}</div>\n </div>`+e.children.map(e=>O(e,t+1)).join("")}function k(e){let t=y(),o=n(),l=`${o?`${o.currentPath}|${o.matchedPath??""}`:"no-router"}:${t.length}:${t.map(e=>`${e.id}-${e.parentId}-${e.debugName}-${e.hasDefaultSlot}-${e.slotNames.join(",")}-${S(e.props)}`).join("|")}`;if("components"===r.renderedTab&&r.renderKeys.components===l)return;r.renderKeys.components=l,r.renderedTab="components";let a=D(t);e.innerHTML=`\n <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;">\n <strong>Component Tree</strong>\n <span style="opacity:.8">${t.length} mounted</span>\n </div>\n <div style="font-size:11px;opacity:.82;margin-bottom:8px;display:flex;gap:8px;flex-wrap:wrap;">\n <span><b>current:</b> ${C(o?.currentPath??"-")}</span>\n <span><b>matched:</b> ${C(o?.matchedPath??"none")}</span>\n </div>\n <div data-nix-devtools-scroll="components" style="max-height:280px;overflow:auto;overscroll-behavior:contain;border:1px solid #2f2f35;border-radius:8px;">\n ${a.length>0?a.map(e=>O(e,0)).join(""):"<div style='padding:10px;opacity:.75'>No mounted components tracked. Enable devtools before your first mount() to capture initial tree.</div>"}\n </div>\n `}function A(e){let t=n(),o=t?`${t.mode}|${t.base}|${t.currentPath}|${JSON.stringify(t.params)}|${JSON.stringify(t.query)}|${t.matchedPath}|${t.activeGuards.names.join(",")}`:"none";if("router"===r.renderedTab&&r.renderKeys.router===o)return;if(r.renderKeys.router=o,r.renderedTab="router",!t)return void(e.innerHTML='\n <strong>Router State</strong>\n <div style="margin-top:8px;opacity:.75">No active Nix router instance. Ensure your app uses createRouter()/RouterView from @deijose/nix-js/router.</div>\n ');let l=v(t.matchedPath);e.innerHTML=`\n <strong>Router State</strong>\n <div data-nix-devtools-scroll="router" style="margin-top:8px;font-size:12px;line-height:1.55;max-height:280px;overflow:auto;overscroll-behavior:contain;border:1px solid #2f2f35;border-radius:8px;padding:8px;">\n <div><b>mode</b>: ${t.mode}</div>\n <div><b>base</b>: ${t.base}</div>\n <div><b>current</b>: ${C(t.currentPath)}</div>\n <div><b>params</b>: ${C(S(t.params))}</div>\n <div><b>query</b>: ${C(S(t.query))}</div>\n <div><b>matched</b>: ${C(t.matchedPath??"none")}</div>\n <div><b>matched chain</b>: ${l.length>0?C(l.join(" -> ")):"none"}</div>\n <div><b>guards</b>: ${t.activeGuards.names.length>0?C(t.activeGuards.names.join(", ")):"none"}</div>\n </div>\n `}function j(e){if(!r.content)return;let t=r.content.querySelector(`[data-nix-devtools-scroll='${e}']`);t&&(r.scrollMemo[e]={top:t.scrollTop,left:t.scrollLeft})}function M(e){if(!r.content)return;let t=r.content.querySelector(`[data-nix-devtools-scroll='${e}']`);if(!t)return;let n=r.scrollMemo[e];t.scrollTop=n.top,t.scrollLeft=n.left,"1"!==t.dataset.nixDevtoolsScrollBound&&(t.addEventListener("scroll",()=>{r.scrollMemo[e]={top:t.scrollTop,left:t.scrollLeft}},{passive:!0}),t.dataset.nixDevtoolsScrollBound="1")}function N(e=!1){if(!r.content)return;let t=r.activeTab;return e||j(t),"signals"===r.activeTab?(E(r.content),void M("signals")):"components"===r.activeTab?(k(r.content),void M("components")):(A(r.content),void M("router"))}function P(){if(r.panel)for(let e of r.panel.querySelectorAll("button[data-nix-devtools-tab]")){let t=e.dataset.nixDevtoolsTab===r.activeTab;e.style.background=t?"#2d4c7a":"#1f1f24"}}function F(e){let t=document.createElement("div");t.setAttribute("data-nix-devtools-root",""),t.style.position="fixed",t.style.zIndex="2147483647",t.style.bottom="16px",t.style.right="bottom-right"===e.position?"16px":"auto",t.style.left="bottom-left"===e.position?"16px":"auto",t.style.fontFamily="ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif";let n=document.createElement("button");n.type="button",n.textContent="Nix DevTools",n.setAttribute("data-nix-devtools-button",""),n.style.background="#111827",n.style.color="#f9fafb",n.style.border="1px solid #374151",n.style.borderRadius="999px",n.style.padding="8px 12px",n.style.cursor="pointer",n.style.boxShadow="0 6px 18px rgba(0,0,0,.3)";let o=document.createElement("div");o.setAttribute("data-nix-devtools-panel",""),o.style.marginTop="8px",o.style.width="460px",o.style.maxWidth="min(92vw, 460px)",o.style.background="#15151b",o.style.color="#e5e7eb",o.style.border="1px solid #2f2f35",o.style.borderRadius="12px",o.style.padding="10px",o.style.display="none",o.style.boxShadow="0 14px 28px rgba(0,0,0,.35)";let l=document.createElement("div");l.style.display="flex",l.style.gap="6px",l.style.marginBottom="10px";let a=document.createElement("div");a.setAttribute("data-nix-devtools-content","");let s=(e,t)=>{let n=document.createElement("button");return n.type="button",n.textContent=t,n.setAttribute("data-nix-devtools-tab",e),n.style.border="1px solid #353543",n.style.borderRadius="8px",n.style.padding="6px 9px",n.style.background="#1f1f24",n.style.color="#d1d5db",n.style.cursor="pointer",n.addEventListener("click",()=>{r.activeTab=e,P(),N(!0)}),n};l.appendChild(s("signals","Signals")),l.appendChild(s("components","Components")),l.appendChild(s("router","Router")),n.addEventListener("click",()=>{o.style.display="none"===o.style.display?"block":"none","block"===o.style.display&&(P(),N(!0))}),o.appendChild(l),o.appendChild(a),t.appendChild(n),t.appendChild(o),document.body.appendChild(t),r.root=t,r.panel=o,r.content=a}function I(){r.enabled&&(r.enabled=!1,null!=r.refreshId&&(clearInterval(r.refreshId),r.refreshId=null),e(null),t(null),x(),r.root?.parentNode&&r.root.parentNode.removeChild(r.root),r.root=null,r.panel=null,r.content=null,r.dispose=null,r.renderedTab=null,r.renderKeys={signals:"",components:"",router:""},r.scrollMemo={signals:{top:0,left:0},components:{top:0,left:0},router:{top:0,left:0}})}function L(n={}){if(typeof document>"u")return{disable:()=>{}};if(r.enabled&&r.dispose)return{disable:r.dispose};let o=Math.max(100,n.refreshMs??350),a=Math.max(1,n.historyLimit??50),i=n.position??"bottom-right";r.enabled=!0,r.activeTab="signals",e({onCreate(e,t){p(e,t)},onWrite(e,t){let n=p(e,t),o=Date.now();n.lastUpdated=o,n.history.push({at:o,value:t}),n.history.length>a&&n.history.splice(0,n.history.length-a)}}),t({onMountStart(e){let t=s.get(e);t??(t=u++,s.set(e,t));let n=l.length>0?l[l.length-1]:null;c.set(t,{id:t,parentId:n,debugName:h(e),mountedAt:Date.now(),hasDefaultSlot:null!=e.children,slotNames:g(e),props:_(e),ref:f(e)}),l.push(t)},onMountEnd(e){let t=s.get(e);if(null==t)return;let n=c.get(t);if(n&&(n.debugName=h(e),n.hasDefaultSlot=null!=e.children,n.slotNames=g(e),n.props=_(e)),l[l.length-1]===t)return void l.pop();let o=l.lastIndexOf(t);o>=0&&l.splice(o,1)},onUnmount(e){let t=s.get(e);if(null==t)return;b(t);let n=l.lastIndexOf(t);n>=0&&l.splice(n,1)}}),F({position:i}),r.refreshId=setInterval(()=>{"block"===r.panel?.style.display&&N()},o),n.initiallyOpen&&r.panel&&(r.panel.style.display="block",P(),N(!0));let d=()=>I();return r.dispose=d,{disable:d}}export{I as disableDevTools,L as enableDevTools};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deijose/nix-js",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "A lightweight, fully reactive micro-framework — no virtual DOM, no compiler, just signals and tagged templates.",
5
5
  "license": "MIT",
6
6
  "author": "Deiver Vasquez",