@wcstack/devtools 4.11.0 → 4.12.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/dist/auto.min.js +1 -1
- package/dist/index.esm.js +1 -1
- package/package.json +1 -1
package/dist/auto.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var e="@wcstack/devtools",t="4.11.0";const n="__WCSTACK_DEVTOOLS_HOOK__";function i(){const e=globalThis,t=e[n];if(void 0!==t)return 2!==t.version&&console.warn(`[wcstack/devtools] hook registry version mismatch: found ${t.version}, expected 2. Keeping the existing registry (first-wins).`),t;const i=function(){const e=new Map,t=new Set,n=e=>{if(0===t.size)return void e._setSink(null);const n=e.id;e._setSink(e=>{for(const i of t)i.onEvent?.(n,e)})};return{version:2,sources:e,register(i){if(!e.has(i.id)){e.set(i.id,i),n(i);for(const e of t)e.onSourceRegistered?.(i)}},unregister(n){const i=e.get(n);if(void 0!==i){i._setSink(null),e.delete(n);for(const e of t)e.onSourceUnregistered?.(n)}},addListener(i){t.add(i);for(const t of e.values())n(t),i.onSourceRegistered?.(t);return()=>{if(t.delete(i))for(const t of e.values())n(t)}}}}();return e[n]=i,i}const o=80;function s(e){const t=e.constructor,n=t?.name;return"string"==typeof n&&n.length>0?n:"Object"}function r(e,t=2){switch(typeof e){case"string":return`"${e.length>o?e.slice(0,o)+"…":e}"`;case"number":case"boolean":case"bigint":return String(e);case"symbol":return e.toString();case"undefined":return"undefined";case"function":return"[[Function]]"}if(null===e)return"null";const n=e;if(Array.isArray(n)){if(t<=0)return`[[Array(${n.length})]]`;const e=n.slice(0,3).map(e=>r(e,t-1)),i=n.length>3?`, …(${n.length})`:"";return`[${e.join(", ")}${i}]`}if(function(e){const t=Object.getPrototypeOf(e);return t===Object.prototype||null===t}(n)){if(t<=0)return"[[Object]]";const e=Object.keys(n),i=e.slice(0,3).map(e=>`${e}: ${r(n[e],t-1)}`),o=e.length>3?`, …(${e.length})`:"";return`{${i.join(", ")}${o}}`}return`[[${s(n)}]]`}function a(e){if(null!==e&&"object"==typeof e){const{name:t,message:n}=e;if("string"==typeof n){const i="string"==typeof t&&t.length>0?t:s(e),r=n.length>o?n.slice(0,o)+"…":n;return r.length>0?`${i}: ${r}`:i}}return r(e,1)}function l(e){if(0===e.length)return"";const t=e.slice(0,3).map(e=>{const t=r(e,1);return t.length>o?t.slice(0,o)+"…":t}),n=e.length>3?`, …(${e.length})`:"";return`${t.join(", ")}${n}`}const c=String.fromCharCode(0);function d(e){return e}function h(e,t){return e+c+t}function u(e,t){return e+c+t}function p(e){return"undefined"!=typeof ShadowRoot&&e instanceof ShadowRoot?`<${e.host.tagName.toLowerCase()}>`:9===e.nodeType?"document":e.nodeName.toLowerCase()}function m(e){return!(Number.parseInt(String(e),10)>=4)}function g(e,t,n){return void 0===n?{kind:e,name:t,status:"never",count:0,note:null}:n.zeroSubscriberCount===n.count?{kind:e,name:t,status:"emitted-unheard",count:n.count,note:`all ${n.count} emit(s) had 0 subscribers`}:{kind:e,name:t,status:"emitted",count:n.count,note:n.zeroSubscriberCount>0?`${n.zeroSubscriberCount}/${n.count} emit(s) had 0 subscribers`:null}}class f{_timelineCapacity;_removeListener=null;_sources=new Map;_roster=new Map;_wiringByPathKey=new Map;_wiringEntryByBinding=new WeakMap;_timeline=[];_seq=0;_paused=!1;_changeListeners=new Set;_observingSince=null;_watchFiredStats=new Map;_tokenEmitStats=new Map;_everAttachedKeys=new Set;constructor(e){this._timelineCapacity=e?.timelineCapacity??500}get connected(){return null!==this._removeListener}get paused(){return this._paused}set paused(e){this._paused=e}connect(){if(null!==this._removeListener)return;this._observingSince=performance.now();const e=i();this._removeListener=e.addListener({onSourceRegistered:e=>{this._sources.set(e.id,e),this._refreshRosterOf(e),this._notify("sources")},onSourceUnregistered:e=>{this._sources.delete(e),this._roster.delete(e),this._notify("sources"),this._notify("roster")},onEvent:(e,t)=>{this._ingest(e,t)}})}disconnect(){null!==this._removeListener&&(this._removeListener(),this._removeListener=null,this._sources.clear(),this._roster.clear(),this._wiringByPathKey.clear(),this._wiringEntryByBinding=new WeakMap,this._observingSince=null,this._watchFiredStats.clear(),this._tokenEmitStats.clear(),this._everAttachedKeys.clear(),this._notify("sources"),this._notify("roster"),this._notify("wiring"),this._notify("coverage"))}get observingSince(){return this._observingSince}onChange(e){return this._changeListeners.add(e),()=>{this._changeListeners.delete(e)}}getSources(){return[...this._sources.values()]}getRoster(){const e=[];for(const t of this._roster.values())e.push(...t);return e}refreshRoster(){for(const e of this._sources.values())this._refreshRosterOf(e);this._notify("roster")}getTimeline(){return this._timeline}clearTimeline(){this._timeline=[],this._notify("timeline")}getWiringForPath(e,t){const n=this._wiringByPathKey.get(e);if(void 0===n)return[];const i=this._collectAlive(n);return void 0===t?i:i.filter(e=>null===e.stateElementRef||e.stateElementRef.deref()===t)}getAllWiring(){const e=[];for(const t of this._wiringByPathKey.values())e.push(...this._collectAlive(t));return e}getWiringForNode(e){const t=[];for(const n of this._wiringByPathKey.values())for(const i of this._collectAlive(n)){const n=i.bindingRef.deref();(n.node===e||n.replaceNode===e||e.contains(n.node)||e.contains(n.replaceNode))&&t.push(i)}return t}getCanonicalDeclared(){let e=!1;const t=[],n=new Set;for(const[i,o]of this._sources){if("function"!=typeof o.getDeclaredBindings)continue;e=!0;const s=new Set;for(const e of this._roster.get(i)??[])s.add(e.rootNode);for(const e of s)for(const i of o.getDeclaredBindings(e)){const e=[i.statePathName,i.propName,i.bindingType,i.origin,i.raw].join(c);n.has(e)||(n.add(e),t.push(i))}}return e?t:null}getCoverageReport(e){const t=[];for(const n of this.getRoster()){const i=n.summary;if(void 0!==e&&i.element!==e)continue;const o=m(this._sources.get(n.sourceId).packageVersion);for(const e of i.watchPaths??[]){const n=this._measuredFor(this._watchFiredStats,d(e),i.element)?.count??0;if(n>0){t.push({kind:"watch",name:e,status:"fired",count:n,note:null});continue}if(!o){t.push({kind:"watch",name:e,status:"never",count:0,note:null});continue}const s=void 0!==i.keyedListPaths;let r=null;for(let t=e.indexOf(".*");-1!==t;t=e.indexOf(".*",t+2)){const n=e.slice(0,t);if(!(i.paths.list.has(n)||(i.keyedListPaths?.has(n)??!1))){r=n;break}}null===r?t.push({kind:"watch",name:e,status:"never",count:0,note:null}):t.push({kind:"watch",name:e,status:"prerequisite-missing",count:0,note:s?`list "${r}" has no for binding and no $listKeys declaration — list writes never reach its rows (only explicit-index writes can fire this watch)`:`no for binding observed for list "${r}" (a $listKeys declaration would still let list writes fire it)`})}for(const e of i.commandTokenNames)t.push(g("command",e,this._measuredFor(this._tokenEmitStats,h("command",e),i.element)));for(const e of i.eventTokenNames)t.push(g("eventToken",e,this._measuredFor(this._tokenEmitStats,h("event",e),i.element)))}const n=this.getCanonicalDeclared();if(null!==n){const e=new Set;for(const i of n){if("for"===i.bindingType||"if"===i.bindingType||"elseif"===i.bindingType||"else"===i.bindingType)continue;if(i.propName.startsWith("eventToken."))continue;const n=u(i.statePathName,i.propName);if(e.has(n))continue;e.add(n);const o=this._everAttachedKeys.has(n);t.push({kind:"binding",name:`${i.propName} ← ${i.statePathName}`,status:o?"attached":"never-attached",count:o?1:0,note:"fragment"===i.origin?"template interior (attaches when rows materialize)":null})}}return t}keysOf(e){const t=this._sources.get(e.sourceId);return void 0===t||"function"!=typeof t.keys?[]:t.keys(e.rootNode)}overlaysOf(e){const t=this._sources.get(e.sourceId);return void 0===t||"function"!=typeof t.overlays?null:t.overlays(e.rootNode)}keyedSubscriptionsOf(e){const t=this._sources.get(e.sourceId);return void 0===t||"function"!=typeof t.keyedSubscriptions?null:t.keyedSubscriptions(e.rootNode)}readValue(e,t,n){const i=this._sources.get(e.sourceId);if(void 0!==i)return i.read(e.rootNode,t,n)}writeValue(e,t,n,i){const o=this._sources.get(e.sourceId);void 0!==o&&o.write(e.rootNode,t,n,i)}_notify(e){for(const t of this._changeListeners)t(e)}_refreshRosterOf(e){const t=[],n=new Map;for(const i of e.getStateElements()){const o=p(i.rootNode),s=(n.get(o)??0)+1;n.set(o,s),t.push({sourceId:e.id,label:1===s?o:`${o}#${s}`,rootNode:i.rootNode,summary:i})}this._roster.set(e.id,t)}_statFor(e,t,n){let i=e.get(t);void 0===i&&(i=[],e.set(t,i));const o="object"==typeof n&&null!==n?n:null;for(const e of i)if(null===o?null===e.stateElementRef:e.stateElementRef?.deref()===o)return e;const s={stateElementRef:null===o?null:new WeakRef(o),count:0,zeroSubscriberCount:0};return i.push(s),s}_measuredFor(e,t,n){const i=e.get(t);if(void 0===i)return;let o=0,s=0;for(let e=i.length-1;e>=0;e--){const t=i[e].stateElementRef;null===t||void 0!==t.deref()?null!==t&&t.deref()!==n||(o+=i[e].count,s+=i[e].zeroSubscriberCount):i.splice(e,1)}return 0===i.length&&e.delete(t),0===o?void 0:{count:o,zeroSubscriberCount:s}}_collectAlive(e){const t=[];for(const n of e)void 0!==n.bindingRef.deref()?t.push(n):e.delete(n);return t}_appendTimeline(e){if(this._paused)return;this._timeline.push({...e,seq:this._seq++,time:performance.now()});const t=this._timeline.length-this._timelineCapacity;t>0&&this._timeline.splice(0,t),this._notify("timeline")}_labelOf(e){const t=e.listIndex?.indexes,n=e.absolutePathInfo.pathInfo.path;return void 0!==t?`${n}[${t.join(",")}]`:n}_ingest(e,t){switch(t.type){case"state:element-registered":{const n=this._sources.get(e);return void 0!==n&&(this._refreshRosterOf(n),this._notify("roster")),void this._appendTimeline({sourceId:e,kind:"element-registered",label:p(t.rootNode),detail:"",subscriberCount:null})}case"state:element-unregistered":{const n=this._sources.get(e);return void 0!==n&&(this._refreshRosterOf(n),this._notify("roster")),void this._appendTimeline({sourceId:e,kind:"element-unregistered",label:p(t.rootNode),detail:"",subscriberCount:null})}case"state:write":{const n=t.hasOldValue?`${r(t.value)} (was ${r(t.oldValue)})`:r(t.value);return void this._appendTimeline({sourceId:e,kind:"write",label:this._labelOf(t.absoluteAddress),detail:n,subscriberCount:null})}case"state:update-batch":{const n=[];let i=0;for(const e of t.addresses)i++,n.length<3&&n.push(this._labelOf(e));if(0===i)return;this._notify("values");const o=i>n.length?`, …(${i})`:"";return void this._appendTimeline({sourceId:e,kind:"batch",label:`${i} address${1===i?"":"es"}`,detail:`${n.join(", ")}${o}`,subscriberCount:null})}case"state:binding-added":{const n=t.absoluteAddress.absolutePathInfo.pathInfo.path,i=n;let o=this._wiringByPathKey.get(i);void 0===o&&(o=new Set,this._wiringByPathKey.set(i,o));const s=t.absoluteAddress.absolutePathInfo.stateElement,r={sourceId:e,path:n,propName:t.binding.propName,bindingType:t.binding.bindingType,bindingRef:new WeakRef(t.binding),stateElementRef:"object"==typeof s&&null!==s?new WeakRef(s):null};return o.add(r),this._wiringEntryByBinding.set(t.binding,r),this._everAttachedKeys.add(u(n,t.binding.propName)),this._notify("wiring"),void this._notify("coverage")}case"state:binding-removed":{const e=this._wiringEntryByBinding.get(t.binding);if(void 0===e)return;this._wiringEntryByBinding.delete(t.binding);const n=e.path,i=this._wiringByPathKey.get(n);return void 0!==i&&(i.delete(e),0===i.size&&this._wiringByPathKey.delete(n)),void this._notify("wiring")}case"state:binding-cleared":{const e=t.absoluteAddress.absolutePathInfo.pathInfo.path;return void(this._wiringByPathKey.delete(e)&&this._notify("wiring"))}case"state:token-emit":{const n=this._statFor(this._tokenEmitStats,h(t.kind,t.tokenName),t.stateElement);return n.count+=1,0===t.subscriberCount&&(n.zeroSubscriberCount+=1),this._notify("coverage"),void this._appendTimeline({sourceId:e,kind:t.kind,label:t.tokenName,detail:l(t.args),subscriberCount:t.subscriberCount})}case"state:watch-fired":return this._statFor(this._watchFiredStats,t.path,t.stateElement).count+=1,void this._notify("coverage");case"state:watch-error":return void this._appendTimeline({sourceId:e,kind:"watch-error",label:t.path,detail:`${t.phase}: ${a(t.error)}`,subscriberCount:null});case"state:watch-chain-limit":return void this._appendTimeline({sourceId:e,kind:"watch-chain-limit",label:`depth > ${t.maxDepth}`,detail:t.paths.join(", "),subscriberCount:null});case"state:render-chain-limit":return void this._appendTimeline({sourceId:e,kind:"render-chain-limit",label:`depth > ${t.maxDepth}`,detail:t.paths.join(", "),subscriberCount:null});case"state:path-unresolved":return void this._appendTimeline({sourceId:e,kind:"path-unresolved",label:t.path,detail:`${t.source}: "${t.missingSegment}" is not declared`,subscriberCount:null});case"state:binding-apply-error":return void this._appendTimeline({sourceId:e,kind:"binding-apply-error",label:t.path,detail:`${t.bindingType}: ${a(t.error)}`,subscriberCount:null});case"propagation:suppressed":return void this._appendTimeline({sourceId:e,kind:"propagation-suppressed",label:t.member,detail:`${t.reason} (tx ${t.transactionId}, edge ${t.edgeId})`,subscriberCount:null});case"propagation:coalesced":return void this._appendTimeline({sourceId:e,kind:"propagation-coalesced",label:this._labelOf(t.absoluteAddress),detail:`tx ${t.droppedTransactionId} dropped (winner tx ${t.winnerTransactionId})`,subscriberCount:null});case"propagation:hop-limit":return void this._appendTimeline({sourceId:e,kind:"propagation-hop-limit",label:this._labelOf(t.absoluteAddress),detail:`hop ${t.hop} (tx ${t.transactionId})`,subscriberCount:null});case"contract:drift":{const n=void 0!==t.member?`: ${t.member}`:"",i="event-mismatch"===t.reason?` (sidecar ${t.sidecarEvent??"?"} / live ${t.liveEvent??"?"})`:"";return void this._appendTimeline({sourceId:e,kind:"contract-drift",label:t.tag,detail:`${t.reason}${n}${i}`,subscriberCount:null})}case"contract:manifest-read":case"contract:unsupported-extension":return}}}const _=["wcs-text","wcs-for","wcs-if","wcs-elseif","wcs-else"];function w(e,t,n){const i=t.trim();if(0===i.length)return null;const o=i.indexOf(":");if(o<0)return null;const s=i.slice(0,o).trim(),r=i.slice(o+1).trim();if(0===s.length||0===r.length)return null;const[a,...l]=r.split("|").map(e=>e.trim());return{element:e,propName:s,path:a,filters:l.filter(e=>e.length>0),origin:n,raw:i}}class b extends HTMLElement{static get observedAttributes(){return["open","dock","hotkey"]}_core=null;_removeCoreListener=null;_panel=null;_badge=null;_stateSelect=null;_paneElements={};_wiringView="wiring";_highlightLayer=null;_dirtyPanes=new Set;_renderScheduled=!1;_selectedRosterKey=null;_selectedPath=null;_pickedNode=null;_pickMode=!1;_expanded=new Set;_hotkeyHandler=null;_pickHandler=null;_editInput=null;_statePointerDown=!1;get core(){return this._core}connectedCallback(){if(document.documentElement.hasAttribute("data-wcs-server"))return;null===this.shadowRoot&&this._buildShadow();const e=Number(this.getAttribute("buffer")??"");this._core=new f({timelineCapacity:Number.isFinite(e)&&e>0?e:void 0}),this._removeCoreListener=this._core.onChange(e=>{"roster"===e||"sources"===e?(this._markDirty("state"),this._markDirty("wiring")):"wiring"===e?this._markDirty("wiring"):"coverage"===e?"coverage"===this._wiringView&&this._markDirty("wiring"):"values"===e?this.open&&this._markDirty("state"):this._markDirty("timeline")}),this._core.connect(),this._applyDock(),this._applyOpen(),this._installHotkey(),this._markDirty("state"),this._markDirty("wiring"),this._markDirty("timeline")}disconnectedCallback(){this._removeCoreListener?.(),this._removeCoreListener=null,this._core?.disconnect(),this._core=null,this._uninstallHotkey(),this._exitPickMode()}attributeChangedCallback(e){null!==this.shadowRoot&&("open"===e?this._applyOpen():"dock"===e?this._applyDock():"hotkey"===e&&(this._uninstallHotkey(),this._installHotkey()))}__flushRenderForTest(){this._renderDirty()}_buildShadow(){const e=this.attachShadow({mode:"open"}),t=document.createElement("style");t.textContent='\n:host {\n all: initial;\n position: fixed;\n z-index: 2147483647;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 12px;\n inset: auto 0 0 auto;\n}\n* { box-sizing: border-box; }\n.badge {\n position: fixed;\n right: 12px;\n bottom: 12px;\n width: 40px;\n height: 40px;\n border-radius: 20px;\n border: 1px solid #2b4f78;\n background: #10263f;\n color: #9fd0ff;\n font-weight: 700;\n cursor: pointer;\n}\n.panel {\n position: fixed;\n display: flex;\n flex-direction: column;\n background: #0d1b2a;\n color: #d7e3f4;\n border: 1px solid #2b4f78;\n box-shadow: 0 0 24px rgba(0,0,0,.5);\n}\n.panel.dock-bottom { left: 0; right: 0; bottom: 0; height: 45vh; }\n.panel.dock-right { top: 0; right: 0; bottom: 0; width: 420px; }\n.panel[hidden] { display: none; }\nheader {\n display: flex;\n gap: 6px;\n align-items: center;\n padding: 6px 8px;\n border-bottom: 1px solid #2b4f78;\n background: #10263f;\n}\n/* The header never grows wider than the panel: the title and the middle group shrink (the\n group scrolls sideways when even that is not enough), so dock and × always stay in view —\n the right dock is only 420px wide. */\nheader .title {\n flex: 0 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-weight: 700;\n color: #9fd0ff;\n margin-right: 4px;\n}\nheader .tools {\n flex: 1 1 auto;\n min-width: 0;\n display: flex;\n gap: 6px;\n align-items: center;\n overflow-x: auto;\n}\nheader .tools select { flex: 0 1 auto; min-width: 6em; text-overflow: ellipsis; }\nheader .tools button, header > button { flex: none; white-space: nowrap; }\nheader select, header button {\n font: inherit;\n background: #16324f;\n color: #d7e3f4;\n border: 1px solid #2b4f78;\n border-radius: 4px;\n padding: 2px 8px;\n cursor: pointer;\n}\nheader button[aria-pressed="true"] { background: #2b5d8f; }\n.panes { display: flex; flex: 1; min-height: 0; }\n.pane { flex: 1; min-width: 0; overflow: auto; padding: 6px 8px; border-right: 1px solid #1d3a5c; }\n.pane:last-child { border-right: none; }\n.pane h3 {\n margin: 0 0 6px;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: .08em;\n color: #7ba7d4;\n}\n.tree-row { display: flex; gap: 6px; padding: 1px 0; align-items: baseline; white-space: nowrap; }\n.tree-row .toggle { width: 14px; cursor: pointer; color: #7ba7d4; user-select: none; }\n.tree-row .key { color: #9fd0ff; cursor: pointer; }\n.tree-row .value { color: #ffd9a0; overflow: hidden; text-overflow: ellipsis; }\n.tree-row .value.editable { cursor: pointer; }\n.tree-row input { font: inherit; background: #16324f; color: #ffd9a0; border: 1px solid #2b4f78; }\n.badge-tag {\n display: inline-block;\n padding: 0 4px;\n border-radius: 3px;\n font-size: 10px;\n background: #26456a;\n color: #a8c6e8;\n}\n.badge-tag.warn { background: #6a3326; color: #ffb3a0; }\n.badge-tag.declared { background: #4a4426; color: #efe3a0; }\n.wiring-row, .timeline-row { padding: 1px 0; white-space: nowrap; }\n.wiring-row .prop { color: #b7f0c0; }\n.wiring-row .path { color: #9fd0ff; }\n.timeline-row .t { color: #6f88a3; }\n.timeline-row .label { color: #9fd0ff; }\n.timeline-row .detail { color: #ffd9a0; }\n.timeline-row .kind { display: inline-block; min-width: 52px; text-align: center; }\n.empty { color: #6f88a3; font-style: italic; padding: 4px 0; }\n.notice { color: #efe3a0; padding: 2px 0 6px; }\n.notice button { font: inherit; margin-left: 6px; cursor: pointer; }\n.wiring-row .detail { color: #6f88a3; }\n.overlays-heading { margin-top: 10px; }\n.overlay-row { padding: 1px 0; white-space: nowrap; }\n.overlay-row .prop { color: #b7f0c0; }\n.overlay-row .path { color: #9fd0ff; }\n.overlay-row .detail { color: #6f88a3; }\n.keyed-row { padding: 1px 0; white-space: nowrap; }\n.keyed-row .path { color: #9fd0ff; }\n.keyed-row .detail { color: #6f88a3; }\n.wiring-tabs { padding: 0 0 4px; }\n.wiring-tabs button { font: inherit; cursor: pointer; margin-right: 4px; opacity: 0.6; }\n.wiring-tabs button.active { opacity: 1; font-weight: bold; }\n.hl-box {\n position: fixed;\n pointer-events: none;\n border: 1px solid #58c2ff;\n background: rgba(88,194,255,.18);\n}\n',e.append(t);const n=document.createElement("button");n.className="badge",n.title="wcstack DevTools",n.textContent="WCS",n.addEventListener("click",()=>this.toggle()),e.append(n),this._badge=n;const i=document.createElement("div");i.className="panel dock-bottom",i.hidden=!0;const o=document.createElement("header"),s=document.createElement("span");s.className="title",s.textContent="wcstack devtools",o.append(s);const r=document.createElement("div");r.className="tools",o.append(r);const a=document.createElement("select");a.title="state element",a.addEventListener("change",()=>{this._selectedRosterKey=a.value||null,this._selectedPath=null,this._expanded.clear(),this._markDirty("state"),this._markDirty("wiring")}),r.append(a),this._stateSelect=a;const l=this._headerButton(r,"⌖ pick","pick a page element");l.addEventListener("click",()=>{this._pickMode?this._exitPickMode():this._enterPickMode(),l.setAttribute("aria-pressed",String(this._pickMode))}),l.dataset.role="pick";const c=this._headerButton(r,"⏸","pause timeline");c.addEventListener("click",()=>{const e=this._core;null!==e&&(e.paused=!e.paused,c.setAttribute("aria-pressed",String(e.paused)))}),c.dataset.role="pause";const d=this._headerButton(r,"🗑","clear timeline");d.addEventListener("click",()=>{this._core?.clearTimeline()}),d.dataset.role="clear";const h=this._headerButton(o,"dock","toggle dock position");h.addEventListener("click",()=>{const e="bottom"===(this.getAttribute("dock")??"bottom")?"right":"bottom";this.setAttribute("dock",e)}),h.dataset.role="dock";const u=this._headerButton(o,"×","close");u.addEventListener("click",()=>this.toggle(!1)),u.dataset.role="close",i.append(o);const p=document.createElement("div");p.className="panes";for(const[e,t]of[["state","State"],["wiring","Wiring"],["timeline","Timeline"]]){const n=document.createElement("section");n.className=`pane pane-${e}`;const i=document.createElement("h3");i.textContent=t;const o=document.createElement("div");o.className="pane-body",n.append(i,o),p.append(n),this._paneElements[e]=o}this._paneElements.state.parentElement.addEventListener("pointerdown",()=>{this._holdStateWhilePressed()}),i.append(p),e.append(i),this._panel=i;const m=document.createElement("div");m.className="hl-layer",e.append(m),this._highlightLayer=m}_headerButton(e,t,n){const i=document.createElement("button");return i.textContent=t,i.title=n,i.setAttribute("aria-pressed","false"),e.append(i),i}get open(){return this.hasAttribute("open")}toggle(e){e??!this.open?this.setAttribute("open",""):this.removeAttribute("open")}_applyOpen(){this._panel.hidden=!this.open,this._badge.hidden=this.open,this.open&&(this._markDirty("state"),this._markDirty("wiring"),this._markDirty("timeline"))}_applyDock(){const e="right"===this.getAttribute("dock")?"right":"bottom";this._panel.classList.toggle("dock-right","right"===e),this._panel.classList.toggle("dock-bottom","bottom"===e)}_installHotkey(){const e=this.getAttribute("hotkey")??"Alt+Shift+D";if("none"===e)return;const t=e.split("+").map(e=>e.trim().toLowerCase()),n=t[t.length-1],i=t.includes("alt"),o=t.includes("shift"),s=t.includes("ctrl"),r=t.includes("meta");this._hotkeyHandler=e=>{e.key.toLowerCase()===n&&e.altKey===i&&e.shiftKey===o&&e.ctrlKey===s&&e.metaKey===r&&(e.preventDefault(),this.toggle())},window.addEventListener("keydown",this._hotkeyHandler)}_uninstallHotkey(){null!==this._hotkeyHandler&&(window.removeEventListener("keydown",this._hotkeyHandler),this._hotkeyHandler=null)}_enterPickMode(){this._pickMode=!0,this._pickHandler=e=>{const t=e.target;t.getRootNode()!==this.shadowRoot&&t!==this&&(e.preventDefault(),e.stopPropagation(),this._pickedNode=t,this._selectedPath=null,this._exitPickMode(),this._markDirty("wiring"))},document.addEventListener("click",this._pickHandler,{capture:!0})}_exitPickMode(){null!==this._pickHandler&&(document.removeEventListener("click",this._pickHandler,{capture:!0}),this._pickHandler=null),this._pickMode=!1;const e=this.shadowRoot?.querySelector('button[data-role="pick"]');e?.setAttribute("aria-pressed","false")}_markDirty(e){this._dirtyPanes.add(e),this._renderScheduled||(this._renderScheduled=!0,requestAnimationFrame(()=>{this._renderDirty()}))}_renderDirty(){if(this._renderScheduled=!1,null===this._core||null===this.shadowRoot)return void this._dirtyPanes.clear();const e=this._dirtyPanes;this._dirtyPanes=new Set,e.has("state")&&(this._stateHeld()?this._dirtyPanes.add("state"):this._renderStatePane()),e.has("wiring")&&this._renderWiringPane(),e.has("timeline")&&this._renderTimelinePane()}_stateHeld(){return!!this._statePointerDown||null!==this._editInput&&this.shadowRoot.activeElement===this._editInput}_releaseState(){this._dirtyPanes.has("state")&&this._markDirty("state")}_holdStateWhilePressed(){this._statePointerDown=!0;const e=()=>{window.removeEventListener("pointerup",e,!0),window.removeEventListener("pointercancel",e,!0),this._statePointerDown=!1,this._releaseState()};window.addEventListener("pointerup",e,!0),window.addEventListener("pointercancel",e,!0)}_rosterKey(e){return`${e.sourceId}:${e.label}`}_selectedRoster(){const e=this._core.getRoster();if(0===e.length)return null;return e.find(e=>this._rosterKey(e)===this._selectedRosterKey)??e[0]}_renderStatePane(){this._editInput=null;const e=this._paneElements.state,t=e.parentElement,n=t.scrollTop;this._renderStateBody(e),t.scrollTop=n}_renderStateBody(e){const t=this._core,n=this._stateSelect,i=t.getRoster(),o=this._selectedRoster();if(n.replaceChildren(...i.map(e=>{const t=document.createElement("option");return t.value=this._rosterKey(e),t.textContent=`${e.label} (${e.sourceId.slice(0,12)})`,t.selected=null!==o&&this._rosterKey(e)===this._rosterKey(o),t})),e.replaceChildren(),null===o)return void e.append(this._emptyRow("no <wcs-state> elements observed"));this._selectedRosterKey=this._rosterKey(o);const s=t.keysOf(o);if(0===s.length)return e.append(this._emptyRow("no readable keys (runtime without keys() API?)")),this._renderOverlaysSection(e,o),void this._renderKeyedSection(e,o);for(const t of s)this._renderTreeNode(e,o,{path:t,indexes:[]},t,0);this._renderOverlaysSection(e,o),this._renderKeyedSection(e,o)}_renderKeyedSection(e,t){const n=this._core.keyedSubscriptionsOf(t);if(null===n||0===n.length)return;const i=document.createElement("h3");i.className="overlays-heading",i.textContent=`Keyed selection (${n.length} path${1===n.length?"":"s"})`,e.append(i);for(const t of n)e.append(this._keyedRow(t))}_keyedRow(e){const t=document.createElement("div");t.className="keyed-row";const n=document.createElement("span");if(n.className="path",n.textContent=e.path,t.append(n),e.tracked){const e=document.createElement("span");e.className="badge-tag warn",e.textContent="tracked",e.title="the path is a getter or under one, so $eq cannot subscribe by key: every getter that reads it re-evaluates when it changes",t.append(document.createTextNode(" "),e)}const i=[];e.rows>0&&i.push(`rows ${e.rows} · keys ${e.keys}`),e.lists>0&&i.push(`list watchers ${e.lists}`),e.tracked||i.push(`last ${r(e.lastValue,1)}`);const o=document.createElement("span");return o.className="detail",o.textContent=i.length>0?` ${i.join(" · ")}`:"",t.append(o),t}_renderOverlaysSection(e,t){const n=this._core.overlaysOf(t);if(null===n||0===n.length)return;const i=document.createElement("h3");i.className="overlays-heading",i.textContent=`Overlays (${n.length} mount${1===n.length?"":"s"})`,e.append(i);for(const t of n)e.append(this._overlayRow(t))}_overlayRow(e){const t=document.createElement("div");t.className="overlay-row";const n=document.createElement("span");n.className="badge-tag",n.textContent=e.marker;const i=document.createElement("span");i.className="prop",i.textContent=`<${e.componentTag}>`;const o=document.createElement("span");o.className="path",o.textContent=e.stateProp,t.append(n,document.createTextNode(" "),i,document.createTextNode(" "),o);const s=[];for(const t of e.mountTable)s.push(`${""===t.inner?"(root)":t.inner} → ${t.outer}`);e.delta>0&&s.push(`Δ${e.delta}`),e.privateKeys.length>0&&s.push(`private: ${e.privateKeys.join(", ")}`);const r=e.exports??[];if(r.length>0&&s.push(`exports: ${r.join(", ")}`),e.getterKeys.length>0&&s.push(`getters: ${e.getterKeys.join(", ")}`),s.length>0){const e=document.createElement("span");e.className="detail",e.textContent=` ${s.join(" · ")}`,t.append(e)}return t}_renderTreeNode(e,t,n,i,o){const s=this._core;let a,l=!0;try{a=s.readValue(t,n.path,n.indexes)}catch{l=!1}const c=document.createElement("div");c.className="tree-row",c.style.paddingLeft=14*o+"px";const d=l&&function(e){if(Array.isArray(e))return!0;if(null===e||"object"!=typeof e)return!1;const t=Object.getPrototypeOf(e);return t===Object.prototype||null===t}(a),h=function(e){return`${e.path}#${e.indexes.join(",")}`}(n),u=d&&this._expanded.has(h),p=document.createElement("span");p.className="toggle",p.textContent=d?u?"▾":"▸":"",d&&p.addEventListener("click",()=>{this._expanded.has(h)?this._expanded.delete(h):this._expanded.add(h),this._markDirty("state")}),c.append(p);const m=document.createElement("span");m.className="key",m.textContent=`${i}:`,m.title=n.path,m.addEventListener("click",()=>{this._selectedPath=n.path,this._pickedNode=null,this._markDirty("wiring"),this._highlightPath(t,n.path)}),c.append(m);const g=document.createElement("span");if(g.className="value",l){g.textContent=r(a,1);(null===a||"object"!=typeof a)&&"function"!=typeof a&&(g.classList.add("editable"),g.title="click to edit",g.addEventListener("click",()=>{this._beginEdit(c,g,t,n,a)}))}else g.textContent="(unreadable getter)";if(c.append(g),e.append(c),u)if(Array.isArray(a)){const i=Math.min(a.length,20);for(let s=0;s<i;s++)this._renderTreeNode(e,t,{path:`${n.path}.*`,indexes:[...n.indexes,s]},`[${s}]`,o+1);if(a.length>i){const t=this._emptyRow(`…(${a.length} items)`);t.style.paddingLeft=14*(o+1)+"px",e.append(t)}}else for(const i of Object.keys(a))this._renderTreeNode(e,t,{path:`${n.path}.${i}`,indexes:n.indexes},i,o+1)}_beginEdit(e,t,n,i,o){const s=document.createElement("input");s.value="string"==typeof o?o:String(o);const r=()=>{this._editInput=null,this._core?.writeValue(n,i.path,function(e){const t=e.trim();try{return JSON.parse(t)}catch{return e}}(s.value),i.indexes),this._markDirty("state")};s.addEventListener("keydown",e=>{"Enter"===e.key?r():"Escape"===e.key&&(this._editInput=null,this._markDirty("state"))}),s.addEventListener("blur",()=>{this._releaseState()}),e.replaceChild(s,t),this._editInput=s,s.focus()}_renderWiringPane(){const e=this._core,t=this._paneElements.wiring;t.replaceChildren();const n=document.createElement("div");n.className="wiring-tabs";for(const[e,t]of[["wiring","wiring"],["coverage","coverage"]]){const i=document.createElement("button");i.textContent=t,this._wiringView===e&&i.classList.add("active"),i.addEventListener("click",()=>{this._wiringView=e,this._markDirty("wiring")}),n.append(i)}if(t.append(n),"coverage"===this._wiringView)return void this._renderCoverageView(t);let i,o;if(null!==this._pickedNode){i=e.getWiringForNode(this._pickedNode);const t=this._pickedNode;o=t instanceof Element?`<${t.tagName.toLowerCase()}>`:t.nodeName}else if(null!==this._selectedPath){const t=this._selectedRoster();i=null!==t?e.getWiringForPath(this._selectedPath,t.summary.element):[],o=this._selectedPath}else i=e.getAllWiring(),o="all";const s=document.createElement("div");if(s.textContent=`context: ${o} — ${i.length} live binding${1===i.length?"":"s"}`,t.append(s),i.length>0){for(const e of i)t.append(this._wiringRow(e));return}const r=e.getCanonicalDeclared(),a=this._selectedRoster(),l=null===r&&null!==a?function(e,t="data-wcs"){const n=[];for(const i of e.querySelectorAll(`[${t}]`)){const e=i.getAttribute(t);for(const t of e.split(";")){const e=w(i,t,"attribute");null!==e&&n.push(e)}}const i=(e.ownerDocument??e).createTreeWalker(e,NodeFilter.SHOW_COMMENT);let o=i.nextNode();for(;null!==o;){const e=o.textContent.trim(),t=_.find(t=>e===t||e.startsWith(t+":"));if(void 0!==t){const i=o.parentNode instanceof Element?o.parentNode:null;if(null!==i){const o=e===t?"":e.slice(t.length+1).trim();if(o.length>0){const e="wcs-text"===t?"textContent":t.slice(4);n.push(w(i,`${e}: ${o}`,"comment"))}}}o=i.nextNode()}return n}(this._scanRootOf(a)):[];if(0===(r?.length??0)&&0===l.length)return void t.append(this._emptyRow("no bindings observed"));const c=document.createElement("div");c.className="notice";const d=document.createElement("span");d.className="badge-tag declared",d.textContent=null!==r?"declared (canonical)":"declared",c.append(d,document.createTextNode(" attached late — reload to capture live bindings "));const h=document.createElement("button");if(h.textContent="reload",h.addEventListener("click",()=>{location.reload()}),c.append(h),t.append(c),null!==r)for(const e of r)t.append(this._canonicalDeclaredRow(e));else for(const e of l)t.append(this._declaredRow(e))}_renderCoverageView(e){const t=this._core,n=t.observingSince,i=document.createElement("div"),o=null===n?null:new Date(Date.now()-(performance.now()-n)).toLocaleTimeString();i.textContent=null===o?"not observing":`observing since ${o} (declared vs measured after this point)`,e.append(i);const s=this._selectedRoster(),r=t.getCoverageReport(s?.summary.element);if(0!==r.length)for(const t of r){const n=document.createElement("div");n.className="wiring-row";const i=document.createElement("span");i.className="badge-tag",i.textContent=t.kind;const o=document.createElement("span");o.className="badge-tag",o.textContent=t.count>1?`${t.status} ×${t.count}`:t.status,"never"===t.status||"never-attached"===t.status||"emitted-unheard"===t.status?o.classList.add("warn"):"prerequisite-missing"===t.status&&o.classList.add("declared");const s=document.createElement("span");if(s.className="path",s.textContent=` ${t.name} `,n.append(i,document.createTextNode(" "),s,o),null!==t.note){const e=document.createElement("span");e.className="detail",e.textContent=` ${t.note}`,n.append(e)}e.append(n)}else e.append(this._emptyRow("nothing declared to cover"))}_canonicalDeclaredRow(e){const t=document.createElement("div");t.className="wiring-row";const n=document.createElement("span");n.className="badge-tag declared",n.textContent=e.origin;const i=document.createElement("span");i.className="prop",i.textContent=e.propName;const o=document.createElement("span");o.className="path";const s=e.outFilters.map(e=>` | ${e.filterName}(${e.args.join(",")})`).join("");if(o.textContent=`${e.statePathName}${s}`,t.append(n,document.createTextNode(" "),i,document.createTextNode(" ← "),o),null!==e.node){const n=e.node;t.addEventListener("click",()=>{this._highlightNodes([n])})}return t}_scanRootOf(e){const t=e.rootNode;return t.nodeType===Node.DOCUMENT_NODE||t.nodeType===Node.DOCUMENT_FRAGMENT_NODE?t:document}_wiringRow(e){const t=document.createElement("div");t.className="wiring-row";const n=document.createElement("span");n.className="prop",n.textContent=e.propName;const i=document.createTextNode(" ← "),o=document.createElement("span");o.className="path",o.textContent=e.path;const s=document.createElement("span");return s.className="badge-tag",s.textContent=e.bindingType,t.append(s,document.createTextNode(" "),n,i,o),t.addEventListener("click",()=>{const t=e.bindingRef.deref();void 0!==t&&this._highlightNodes([t.node,t.replaceNode])}),t}_declaredRow(e){const t=document.createElement("div");t.className="wiring-row";const n=document.createElement("span");n.className="badge-tag declared",n.textContent=e.origin;const i=document.createElement("span");i.className="prop",i.textContent=e.propName;const o=document.createElement("span");return o.className="path",o.textContent=e.path,t.append(n,document.createTextNode(" "),i,document.createTextNode(" ← "),o),t.addEventListener("click",()=>{this._highlightNodes([e.element])}),t}_renderTimelinePane(){const e=this._core,t=this._paneElements.timeline,n=e.getTimeline(),i=Math.max(0,n.length-200),o=[];i>0&&o.push(this._emptyRow(`…(${i} earlier entries)`));for(let e=i;e<n.length;e++)o.push(this._timelineRow(n[e]));0===o.length&&o.push(this._emptyRow("no activity yet")),t.replaceChildren(...o),t.scrollTop=t.scrollHeight}_timelineRow(e){const t=document.createElement("div");t.className="timeline-row";const n=document.createElement("span");n.className="t",n.textContent=`${(e.time/1e3).toFixed(3)}s `;const i=document.createElement("span");i.className="badge-tag kind",i.textContent=e.kind,0===e.subscriberCount&&(i.classList.add("warn"),i.title="emitted with no subscribers"),"watch-error"!==e.kind&&"watch-chain-limit"!==e.kind||(i.classList.add("warn"),i.title="watch-error"===e.kind?"a $watch or $scan failure (read, handler, fold or write — see the phase in the detail); the runtime isolated it (console.error only)":"a $watch write chain hit the depth limit and was cut off"),"render-chain-limit"===e.kind&&(i.classList.add("warn"),i.title="writes made while rendering kept starting new batches; the chain hit the depth limit and this batch was not rendered"),"path-unresolved"!==e.kind&&"binding-apply-error"!==e.kind||(i.classList.add("warn"),i.title="path-unresolved"===e.kind?"a wired path does not resolve on the state; its updates are dropped":"a binding threw while applying; the runtime isolated it (console.error only)"),"propagation-hop-limit"!==e.kind&&"contract-drift"!==e.kind||(i.classList.add("warn"),i.title="propagation-hop-limit"===e.kind?"a two-way propagation chain hit the hop limit and was cut off":"sidecar manifest drifted from the live wcBindable declaration (live wins)");const o=document.createElement("span");o.className="label",o.textContent=` ${e.label} `;const s=document.createElement("span");return s.className="detail",s.textContent=e.detail,t.append(n,i,o,s),t}_emptyRow(e){const t=document.createElement("div");return t.className="empty",t.textContent=e,t}_highlightPath(e,t){const n=this._core,i=[];for(const o of n.getWiringForPath(t,e.summary.element)){const e=o.bindingRef.deref();void 0!==e&&i.push(e.node,e.replaceNode)}this._highlightNodes(i)}_highlightNodes(e){const t=this._highlightLayer;t.replaceChildren();const n=new Set;for(const i of e){const e=i instanceof Element?i:i.parentElement;if(null===e||n.has(e)||!e.isConnected)continue;n.add(e);const o=e.getBoundingClientRect(),s=document.createElement("div");s.className="hl-box",s.style.left=`${o.left}px`,s.style.top=`${o.top}px`,s.style.width=`${o.width}px`,s.style.height=`${o.height}px`,t.append(s)}setTimeout(()=>{t.replaceChildren()},2e3)}}const y=Symbol.for("wcstack.package"),v=new WeakSet;function k(e,t){Object.defineProperty(e,y,{value:t,configurable:!0})}function x(e,t,n,i,o){if(void 0!==i&&(n===i||n.prototype instanceof i))return;const s=n[y];if(s===o||v.has(e))return;v.add(e);const r=o.slice(0,o.lastIndexOf("@"));console.warn(`[${r}] [wcs/package-twice] <${t}> is already defined by ${s??`another copy of ${r} that does not name its version`}; this copy, ${o}, does nothing. Load each package once.`)}const E="wcs-devtools";function N(n=customElements){!function(e,t,n){for(const[i,o]of n){const n=e.get(i);void 0===n?(k(o,t),e.define(i,o)):x(e,i,n,o,t)}}(n,`${e}@${t}`,[[E,b]])}function $(){null===document.querySelector(E)&&document.body.appendChild(document.createElement(E))}document.documentElement.hasAttribute("data-wcs-server")||(N(),null!==document.body?$():document.addEventListener("DOMContentLoaded",$,{once:!0}));
|
|
1
|
+
var e="@wcstack/devtools",t="4.12.0";const n="__WCSTACK_DEVTOOLS_HOOK__";function i(){const e=globalThis,t=e[n];if(void 0!==t)return 2!==t.version&&console.warn(`[wcstack/devtools] hook registry version mismatch: found ${t.version}, expected 2. Keeping the existing registry (first-wins).`),t;const i=function(){const e=new Map,t=new Set,n=e=>{if(0===t.size)return void e._setSink(null);const n=e.id;e._setSink(e=>{for(const i of t)i.onEvent?.(n,e)})};return{version:2,sources:e,register(i){if(!e.has(i.id)){e.set(i.id,i),n(i);for(const e of t)e.onSourceRegistered?.(i)}},unregister(n){const i=e.get(n);if(void 0!==i){i._setSink(null),e.delete(n);for(const e of t)e.onSourceUnregistered?.(n)}},addListener(i){t.add(i);for(const t of e.values())n(t),i.onSourceRegistered?.(t);return()=>{if(t.delete(i))for(const t of e.values())n(t)}}}}();return e[n]=i,i}const o=80;function s(e){const t=e.constructor,n=t?.name;return"string"==typeof n&&n.length>0?n:"Object"}function r(e,t=2){switch(typeof e){case"string":return`"${e.length>o?e.slice(0,o)+"…":e}"`;case"number":case"boolean":case"bigint":return String(e);case"symbol":return e.toString();case"undefined":return"undefined";case"function":return"[[Function]]"}if(null===e)return"null";const n=e;if(Array.isArray(n)){if(t<=0)return`[[Array(${n.length})]]`;const e=n.slice(0,3).map(e=>r(e,t-1)),i=n.length>3?`, …(${n.length})`:"";return`[${e.join(", ")}${i}]`}if(function(e){const t=Object.getPrototypeOf(e);return t===Object.prototype||null===t}(n)){if(t<=0)return"[[Object]]";const e=Object.keys(n),i=e.slice(0,3).map(e=>`${e}: ${r(n[e],t-1)}`),o=e.length>3?`, …(${e.length})`:"";return`{${i.join(", ")}${o}}`}return`[[${s(n)}]]`}function a(e){if(null!==e&&"object"==typeof e){const{name:t,message:n}=e;if("string"==typeof n){const i="string"==typeof t&&t.length>0?t:s(e),r=n.length>o?n.slice(0,o)+"…":n;return r.length>0?`${i}: ${r}`:i}}return r(e,1)}function l(e){if(0===e.length)return"";const t=e.slice(0,3).map(e=>{const t=r(e,1);return t.length>o?t.slice(0,o)+"…":t}),n=e.length>3?`, …(${e.length})`:"";return`${t.join(", ")}${n}`}const c=String.fromCharCode(0);function d(e){return e}function h(e,t){return e+c+t}function u(e,t){return e+c+t}function p(e){return"undefined"!=typeof ShadowRoot&&e instanceof ShadowRoot?`<${e.host.tagName.toLowerCase()}>`:9===e.nodeType?"document":e.nodeName.toLowerCase()}function m(e){return!(Number.parseInt(String(e),10)>=4)}function g(e,t,n){return void 0===n?{kind:e,name:t,status:"never",count:0,note:null}:n.zeroSubscriberCount===n.count?{kind:e,name:t,status:"emitted-unheard",count:n.count,note:`all ${n.count} emit(s) had 0 subscribers`}:{kind:e,name:t,status:"emitted",count:n.count,note:n.zeroSubscriberCount>0?`${n.zeroSubscriberCount}/${n.count} emit(s) had 0 subscribers`:null}}class f{_timelineCapacity;_removeListener=null;_sources=new Map;_roster=new Map;_wiringByPathKey=new Map;_wiringEntryByBinding=new WeakMap;_timeline=[];_seq=0;_paused=!1;_changeListeners=new Set;_observingSince=null;_watchFiredStats=new Map;_tokenEmitStats=new Map;_everAttachedKeys=new Set;constructor(e){this._timelineCapacity=e?.timelineCapacity??500}get connected(){return null!==this._removeListener}get paused(){return this._paused}set paused(e){this._paused=e}connect(){if(null!==this._removeListener)return;this._observingSince=performance.now();const e=i();this._removeListener=e.addListener({onSourceRegistered:e=>{this._sources.set(e.id,e),this._refreshRosterOf(e),this._notify("sources")},onSourceUnregistered:e=>{this._sources.delete(e),this._roster.delete(e),this._notify("sources"),this._notify("roster")},onEvent:(e,t)=>{this._ingest(e,t)}})}disconnect(){null!==this._removeListener&&(this._removeListener(),this._removeListener=null,this._sources.clear(),this._roster.clear(),this._wiringByPathKey.clear(),this._wiringEntryByBinding=new WeakMap,this._observingSince=null,this._watchFiredStats.clear(),this._tokenEmitStats.clear(),this._everAttachedKeys.clear(),this._notify("sources"),this._notify("roster"),this._notify("wiring"),this._notify("coverage"))}get observingSince(){return this._observingSince}onChange(e){return this._changeListeners.add(e),()=>{this._changeListeners.delete(e)}}getSources(){return[...this._sources.values()]}getRoster(){const e=[];for(const t of this._roster.values())e.push(...t);return e}refreshRoster(){for(const e of this._sources.values())this._refreshRosterOf(e);this._notify("roster")}getTimeline(){return this._timeline}clearTimeline(){this._timeline=[],this._notify("timeline")}getWiringForPath(e,t){const n=this._wiringByPathKey.get(e);if(void 0===n)return[];const i=this._collectAlive(n);return void 0===t?i:i.filter(e=>null===e.stateElementRef||e.stateElementRef.deref()===t)}getAllWiring(){const e=[];for(const t of this._wiringByPathKey.values())e.push(...this._collectAlive(t));return e}getWiringForNode(e){const t=[];for(const n of this._wiringByPathKey.values())for(const i of this._collectAlive(n)){const n=i.bindingRef.deref();(n.node===e||n.replaceNode===e||e.contains(n.node)||e.contains(n.replaceNode))&&t.push(i)}return t}getCanonicalDeclared(){let e=!1;const t=[],n=new Set;for(const[i,o]of this._sources){if("function"!=typeof o.getDeclaredBindings)continue;e=!0;const s=new Set;for(const e of this._roster.get(i)??[])s.add(e.rootNode);for(const e of s)for(const i of o.getDeclaredBindings(e)){const e=[i.statePathName,i.propName,i.bindingType,i.origin,i.raw].join(c);n.has(e)||(n.add(e),t.push(i))}}return e?t:null}getCoverageReport(e){const t=[];for(const n of this.getRoster()){const i=n.summary;if(void 0!==e&&i.element!==e)continue;const o=m(this._sources.get(n.sourceId).packageVersion);for(const e of i.watchPaths??[]){const n=this._measuredFor(this._watchFiredStats,d(e),i.element)?.count??0;if(n>0){t.push({kind:"watch",name:e,status:"fired",count:n,note:null});continue}if(!o){t.push({kind:"watch",name:e,status:"never",count:0,note:null});continue}const s=void 0!==i.keyedListPaths;let r=null;for(let t=e.indexOf(".*");-1!==t;t=e.indexOf(".*",t+2)){const n=e.slice(0,t);if(!(i.paths.list.has(n)||(i.keyedListPaths?.has(n)??!1))){r=n;break}}null===r?t.push({kind:"watch",name:e,status:"never",count:0,note:null}):t.push({kind:"watch",name:e,status:"prerequisite-missing",count:0,note:s?`list "${r}" has no for binding and no $listKeys declaration — list writes never reach its rows (only explicit-index writes can fire this watch)`:`no for binding observed for list "${r}" (a $listKeys declaration would still let list writes fire it)`})}for(const e of i.commandTokenNames)t.push(g("command",e,this._measuredFor(this._tokenEmitStats,h("command",e),i.element)));for(const e of i.eventTokenNames)t.push(g("eventToken",e,this._measuredFor(this._tokenEmitStats,h("event",e),i.element)))}const n=this.getCanonicalDeclared();if(null!==n){const e=new Set;for(const i of n){if("for"===i.bindingType||"if"===i.bindingType||"elseif"===i.bindingType||"else"===i.bindingType)continue;if(i.propName.startsWith("eventToken."))continue;const n=u(i.statePathName,i.propName);if(e.has(n))continue;e.add(n);const o=this._everAttachedKeys.has(n);t.push({kind:"binding",name:`${i.propName} ← ${i.statePathName}`,status:o?"attached":"never-attached",count:o?1:0,note:"fragment"===i.origin?"template interior (attaches when rows materialize)":null})}}return t}keysOf(e){const t=this._sources.get(e.sourceId);return void 0===t||"function"!=typeof t.keys?[]:t.keys(e.rootNode)}overlaysOf(e){const t=this._sources.get(e.sourceId);return void 0===t||"function"!=typeof t.overlays?null:t.overlays(e.rootNode)}keyedSubscriptionsOf(e){const t=this._sources.get(e.sourceId);return void 0===t||"function"!=typeof t.keyedSubscriptions?null:t.keyedSubscriptions(e.rootNode)}readValue(e,t,n){const i=this._sources.get(e.sourceId);if(void 0!==i)return i.read(e.rootNode,t,n)}writeValue(e,t,n,i){const o=this._sources.get(e.sourceId);void 0!==o&&o.write(e.rootNode,t,n,i)}_notify(e){for(const t of this._changeListeners)t(e)}_refreshRosterOf(e){const t=[],n=new Map;for(const i of e.getStateElements()){const o=p(i.rootNode),s=(n.get(o)??0)+1;n.set(o,s),t.push({sourceId:e.id,label:1===s?o:`${o}#${s}`,rootNode:i.rootNode,summary:i})}this._roster.set(e.id,t)}_statFor(e,t,n){let i=e.get(t);void 0===i&&(i=[],e.set(t,i));const o="object"==typeof n&&null!==n?n:null;for(const e of i)if(null===o?null===e.stateElementRef:e.stateElementRef?.deref()===o)return e;const s={stateElementRef:null===o?null:new WeakRef(o),count:0,zeroSubscriberCount:0};return i.push(s),s}_measuredFor(e,t,n){const i=e.get(t);if(void 0===i)return;let o=0,s=0;for(let e=i.length-1;e>=0;e--){const t=i[e].stateElementRef;null===t||void 0!==t.deref()?null!==t&&t.deref()!==n||(o+=i[e].count,s+=i[e].zeroSubscriberCount):i.splice(e,1)}return 0===i.length&&e.delete(t),0===o?void 0:{count:o,zeroSubscriberCount:s}}_collectAlive(e){const t=[];for(const n of e)void 0!==n.bindingRef.deref()?t.push(n):e.delete(n);return t}_appendTimeline(e){if(this._paused)return;this._timeline.push({...e,seq:this._seq++,time:performance.now()});const t=this._timeline.length-this._timelineCapacity;t>0&&this._timeline.splice(0,t),this._notify("timeline")}_labelOf(e){const t=e.listIndex?.indexes,n=e.absolutePathInfo.pathInfo.path;return void 0!==t?`${n}[${t.join(",")}]`:n}_ingest(e,t){switch(t.type){case"state:element-registered":{const n=this._sources.get(e);return void 0!==n&&(this._refreshRosterOf(n),this._notify("roster")),void this._appendTimeline({sourceId:e,kind:"element-registered",label:p(t.rootNode),detail:"",subscriberCount:null})}case"state:element-unregistered":{const n=this._sources.get(e);return void 0!==n&&(this._refreshRosterOf(n),this._notify("roster")),void this._appendTimeline({sourceId:e,kind:"element-unregistered",label:p(t.rootNode),detail:"",subscriberCount:null})}case"state:write":{const n=t.hasOldValue?`${r(t.value)} (was ${r(t.oldValue)})`:r(t.value);return void this._appendTimeline({sourceId:e,kind:"write",label:this._labelOf(t.absoluteAddress),detail:n,subscriberCount:null})}case"state:update-batch":{const n=[];let i=0;for(const e of t.addresses)i++,n.length<3&&n.push(this._labelOf(e));if(0===i)return;this._notify("values");const o=i>n.length?`, …(${i})`:"";return void this._appendTimeline({sourceId:e,kind:"batch",label:`${i} address${1===i?"":"es"}`,detail:`${n.join(", ")}${o}`,subscriberCount:null})}case"state:binding-added":{const n=t.absoluteAddress.absolutePathInfo.pathInfo.path,i=n;let o=this._wiringByPathKey.get(i);void 0===o&&(o=new Set,this._wiringByPathKey.set(i,o));const s=t.absoluteAddress.absolutePathInfo.stateElement,r={sourceId:e,path:n,propName:t.binding.propName,bindingType:t.binding.bindingType,bindingRef:new WeakRef(t.binding),stateElementRef:"object"==typeof s&&null!==s?new WeakRef(s):null};return o.add(r),this._wiringEntryByBinding.set(t.binding,r),this._everAttachedKeys.add(u(n,t.binding.propName)),this._notify("wiring"),void this._notify("coverage")}case"state:binding-removed":{const e=this._wiringEntryByBinding.get(t.binding);if(void 0===e)return;this._wiringEntryByBinding.delete(t.binding);const n=e.path,i=this._wiringByPathKey.get(n);return void 0!==i&&(i.delete(e),0===i.size&&this._wiringByPathKey.delete(n)),void this._notify("wiring")}case"state:binding-cleared":{const e=t.absoluteAddress.absolutePathInfo.pathInfo.path;return void(this._wiringByPathKey.delete(e)&&this._notify("wiring"))}case"state:token-emit":{const n=this._statFor(this._tokenEmitStats,h(t.kind,t.tokenName),t.stateElement);return n.count+=1,0===t.subscriberCount&&(n.zeroSubscriberCount+=1),this._notify("coverage"),void this._appendTimeline({sourceId:e,kind:t.kind,label:t.tokenName,detail:l(t.args),subscriberCount:t.subscriberCount})}case"state:watch-fired":return this._statFor(this._watchFiredStats,t.path,t.stateElement).count+=1,void this._notify("coverage");case"state:watch-error":return void this._appendTimeline({sourceId:e,kind:"watch-error",label:t.path,detail:`${t.phase}: ${a(t.error)}`,subscriberCount:null});case"state:watch-chain-limit":return void this._appendTimeline({sourceId:e,kind:"watch-chain-limit",label:`depth > ${t.maxDepth}`,detail:t.paths.join(", "),subscriberCount:null});case"state:render-chain-limit":return void this._appendTimeline({sourceId:e,kind:"render-chain-limit",label:`depth > ${t.maxDepth}`,detail:t.paths.join(", "),subscriberCount:null});case"state:path-unresolved":return void this._appendTimeline({sourceId:e,kind:"path-unresolved",label:t.path,detail:`${t.source}: "${t.missingSegment}" is not declared`,subscriberCount:null});case"state:binding-apply-error":return void this._appendTimeline({sourceId:e,kind:"binding-apply-error",label:t.path,detail:`${t.bindingType}: ${a(t.error)}`,subscriberCount:null});case"propagation:suppressed":return void this._appendTimeline({sourceId:e,kind:"propagation-suppressed",label:t.member,detail:`${t.reason} (tx ${t.transactionId}, edge ${t.edgeId})`,subscriberCount:null});case"propagation:coalesced":return void this._appendTimeline({sourceId:e,kind:"propagation-coalesced",label:this._labelOf(t.absoluteAddress),detail:`tx ${t.droppedTransactionId} dropped (winner tx ${t.winnerTransactionId})`,subscriberCount:null});case"propagation:hop-limit":return void this._appendTimeline({sourceId:e,kind:"propagation-hop-limit",label:this._labelOf(t.absoluteAddress),detail:`hop ${t.hop} (tx ${t.transactionId})`,subscriberCount:null});case"contract:drift":{const n=void 0!==t.member?`: ${t.member}`:"",i="event-mismatch"===t.reason?` (sidecar ${t.sidecarEvent??"?"} / live ${t.liveEvent??"?"})`:"";return void this._appendTimeline({sourceId:e,kind:"contract-drift",label:t.tag,detail:`${t.reason}${n}${i}`,subscriberCount:null})}case"contract:manifest-read":case"contract:unsupported-extension":return}}}const _=["wcs-text","wcs-for","wcs-if","wcs-elseif","wcs-else"];function w(e,t,n){const i=t.trim();if(0===i.length)return null;const o=i.indexOf(":");if(o<0)return null;const s=i.slice(0,o).trim(),r=i.slice(o+1).trim();if(0===s.length||0===r.length)return null;const[a,...l]=r.split("|").map(e=>e.trim());return{element:e,propName:s,path:a,filters:l.filter(e=>e.length>0),origin:n,raw:i}}class b extends HTMLElement{static get observedAttributes(){return["open","dock","hotkey"]}_core=null;_removeCoreListener=null;_panel=null;_badge=null;_stateSelect=null;_paneElements={};_wiringView="wiring";_highlightLayer=null;_dirtyPanes=new Set;_renderScheduled=!1;_selectedRosterKey=null;_selectedPath=null;_pickedNode=null;_pickMode=!1;_expanded=new Set;_hotkeyHandler=null;_pickHandler=null;_editInput=null;_statePointerDown=!1;get core(){return this._core}connectedCallback(){if(document.documentElement.hasAttribute("data-wcs-server"))return;null===this.shadowRoot&&this._buildShadow();const e=Number(this.getAttribute("buffer")??"");this._core=new f({timelineCapacity:Number.isFinite(e)&&e>0?e:void 0}),this._removeCoreListener=this._core.onChange(e=>{"roster"===e||"sources"===e?(this._markDirty("state"),this._markDirty("wiring")):"wiring"===e?this._markDirty("wiring"):"coverage"===e?"coverage"===this._wiringView&&this._markDirty("wiring"):"values"===e?this.open&&this._markDirty("state"):this._markDirty("timeline")}),this._core.connect(),this._applyDock(),this._applyOpen(),this._installHotkey(),this._markDirty("state"),this._markDirty("wiring"),this._markDirty("timeline")}disconnectedCallback(){this._removeCoreListener?.(),this._removeCoreListener=null,this._core?.disconnect(),this._core=null,this._uninstallHotkey(),this._exitPickMode()}attributeChangedCallback(e){null!==this.shadowRoot&&("open"===e?this._applyOpen():"dock"===e?this._applyDock():"hotkey"===e&&(this._uninstallHotkey(),this._installHotkey()))}__flushRenderForTest(){this._renderDirty()}_buildShadow(){const e=this.attachShadow({mode:"open"}),t=document.createElement("style");t.textContent='\n:host {\n all: initial;\n position: fixed;\n z-index: 2147483647;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 12px;\n inset: auto 0 0 auto;\n}\n* { box-sizing: border-box; }\n.badge {\n position: fixed;\n right: 12px;\n bottom: 12px;\n width: 40px;\n height: 40px;\n border-radius: 20px;\n border: 1px solid #2b4f78;\n background: #10263f;\n color: #9fd0ff;\n font-weight: 700;\n cursor: pointer;\n}\n.panel {\n position: fixed;\n display: flex;\n flex-direction: column;\n background: #0d1b2a;\n color: #d7e3f4;\n border: 1px solid #2b4f78;\n box-shadow: 0 0 24px rgba(0,0,0,.5);\n}\n.panel.dock-bottom { left: 0; right: 0; bottom: 0; height: 45vh; }\n.panel.dock-right { top: 0; right: 0; bottom: 0; width: 420px; }\n.panel[hidden] { display: none; }\nheader {\n display: flex;\n gap: 6px;\n align-items: center;\n padding: 6px 8px;\n border-bottom: 1px solid #2b4f78;\n background: #10263f;\n}\n/* The header never grows wider than the panel: the title and the middle group shrink (the\n group scrolls sideways when even that is not enough), so dock and × always stay in view —\n the right dock is only 420px wide. */\nheader .title {\n flex: 0 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-weight: 700;\n color: #9fd0ff;\n margin-right: 4px;\n}\nheader .tools {\n flex: 1 1 auto;\n min-width: 0;\n display: flex;\n gap: 6px;\n align-items: center;\n overflow-x: auto;\n}\nheader .tools select { flex: 0 1 auto; min-width: 6em; text-overflow: ellipsis; }\nheader .tools button, header > button { flex: none; white-space: nowrap; }\nheader select, header button {\n font: inherit;\n background: #16324f;\n color: #d7e3f4;\n border: 1px solid #2b4f78;\n border-radius: 4px;\n padding: 2px 8px;\n cursor: pointer;\n}\nheader button[aria-pressed="true"] { background: #2b5d8f; }\n.panes { display: flex; flex: 1; min-height: 0; }\n.pane { flex: 1; min-width: 0; overflow: auto; padding: 6px 8px; border-right: 1px solid #1d3a5c; }\n.pane:last-child { border-right: none; }\n.pane h3 {\n margin: 0 0 6px;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: .08em;\n color: #7ba7d4;\n}\n.tree-row { display: flex; gap: 6px; padding: 1px 0; align-items: baseline; white-space: nowrap; }\n.tree-row .toggle { width: 14px; cursor: pointer; color: #7ba7d4; user-select: none; }\n.tree-row .key { color: #9fd0ff; cursor: pointer; }\n.tree-row .value { color: #ffd9a0; overflow: hidden; text-overflow: ellipsis; }\n.tree-row .value.editable { cursor: pointer; }\n.tree-row input { font: inherit; background: #16324f; color: #ffd9a0; border: 1px solid #2b4f78; }\n.badge-tag {\n display: inline-block;\n padding: 0 4px;\n border-radius: 3px;\n font-size: 10px;\n background: #26456a;\n color: #a8c6e8;\n}\n.badge-tag.warn { background: #6a3326; color: #ffb3a0; }\n.badge-tag.declared { background: #4a4426; color: #efe3a0; }\n.wiring-row, .timeline-row { padding: 1px 0; white-space: nowrap; }\n.wiring-row .prop { color: #b7f0c0; }\n.wiring-row .path { color: #9fd0ff; }\n.timeline-row .t { color: #6f88a3; }\n.timeline-row .label { color: #9fd0ff; }\n.timeline-row .detail { color: #ffd9a0; }\n.timeline-row .kind { display: inline-block; min-width: 52px; text-align: center; }\n.empty { color: #6f88a3; font-style: italic; padding: 4px 0; }\n.notice { color: #efe3a0; padding: 2px 0 6px; }\n.notice button { font: inherit; margin-left: 6px; cursor: pointer; }\n.wiring-row .detail { color: #6f88a3; }\n.overlays-heading { margin-top: 10px; }\n.overlay-row { padding: 1px 0; white-space: nowrap; }\n.overlay-row .prop { color: #b7f0c0; }\n.overlay-row .path { color: #9fd0ff; }\n.overlay-row .detail { color: #6f88a3; }\n.keyed-row { padding: 1px 0; white-space: nowrap; }\n.keyed-row .path { color: #9fd0ff; }\n.keyed-row .detail { color: #6f88a3; }\n.wiring-tabs { padding: 0 0 4px; }\n.wiring-tabs button { font: inherit; cursor: pointer; margin-right: 4px; opacity: 0.6; }\n.wiring-tabs button.active { opacity: 1; font-weight: bold; }\n.hl-box {\n position: fixed;\n pointer-events: none;\n border: 1px solid #58c2ff;\n background: rgba(88,194,255,.18);\n}\n',e.append(t);const n=document.createElement("button");n.className="badge",n.title="wcstack DevTools",n.textContent="WCS",n.addEventListener("click",()=>this.toggle()),e.append(n),this._badge=n;const i=document.createElement("div");i.className="panel dock-bottom",i.hidden=!0;const o=document.createElement("header"),s=document.createElement("span");s.className="title",s.textContent="wcstack devtools",o.append(s);const r=document.createElement("div");r.className="tools",o.append(r);const a=document.createElement("select");a.title="state element",a.addEventListener("change",()=>{this._selectedRosterKey=a.value||null,this._selectedPath=null,this._expanded.clear(),this._markDirty("state"),this._markDirty("wiring")}),r.append(a),this._stateSelect=a;const l=this._headerButton(r,"⌖ pick","pick a page element");l.addEventListener("click",()=>{this._pickMode?this._exitPickMode():this._enterPickMode(),l.setAttribute("aria-pressed",String(this._pickMode))}),l.dataset.role="pick";const c=this._headerButton(r,"⏸","pause timeline");c.addEventListener("click",()=>{const e=this._core;null!==e&&(e.paused=!e.paused,c.setAttribute("aria-pressed",String(e.paused)))}),c.dataset.role="pause";const d=this._headerButton(r,"🗑","clear timeline");d.addEventListener("click",()=>{this._core?.clearTimeline()}),d.dataset.role="clear";const h=this._headerButton(o,"dock","toggle dock position");h.addEventListener("click",()=>{const e="bottom"===(this.getAttribute("dock")??"bottom")?"right":"bottom";this.setAttribute("dock",e)}),h.dataset.role="dock";const u=this._headerButton(o,"×","close");u.addEventListener("click",()=>this.toggle(!1)),u.dataset.role="close",i.append(o);const p=document.createElement("div");p.className="panes";for(const[e,t]of[["state","State"],["wiring","Wiring"],["timeline","Timeline"]]){const n=document.createElement("section");n.className=`pane pane-${e}`;const i=document.createElement("h3");i.textContent=t;const o=document.createElement("div");o.className="pane-body",n.append(i,o),p.append(n),this._paneElements[e]=o}this._paneElements.state.parentElement.addEventListener("pointerdown",()=>{this._holdStateWhilePressed()}),i.append(p),e.append(i),this._panel=i;const m=document.createElement("div");m.className="hl-layer",e.append(m),this._highlightLayer=m}_headerButton(e,t,n){const i=document.createElement("button");return i.textContent=t,i.title=n,i.setAttribute("aria-pressed","false"),e.append(i),i}get open(){return this.hasAttribute("open")}toggle(e){e??!this.open?this.setAttribute("open",""):this.removeAttribute("open")}_applyOpen(){this._panel.hidden=!this.open,this._badge.hidden=this.open,this.open&&(this._markDirty("state"),this._markDirty("wiring"),this._markDirty("timeline"))}_applyDock(){const e="right"===this.getAttribute("dock")?"right":"bottom";this._panel.classList.toggle("dock-right","right"===e),this._panel.classList.toggle("dock-bottom","bottom"===e)}_installHotkey(){const e=this.getAttribute("hotkey")??"Alt+Shift+D";if("none"===e)return;const t=e.split("+").map(e=>e.trim().toLowerCase()),n=t[t.length-1],i=t.includes("alt"),o=t.includes("shift"),s=t.includes("ctrl"),r=t.includes("meta");this._hotkeyHandler=e=>{e.key.toLowerCase()===n&&e.altKey===i&&e.shiftKey===o&&e.ctrlKey===s&&e.metaKey===r&&(e.preventDefault(),this.toggle())},window.addEventListener("keydown",this._hotkeyHandler)}_uninstallHotkey(){null!==this._hotkeyHandler&&(window.removeEventListener("keydown",this._hotkeyHandler),this._hotkeyHandler=null)}_enterPickMode(){this._pickMode=!0,this._pickHandler=e=>{const t=e.target;t.getRootNode()!==this.shadowRoot&&t!==this&&(e.preventDefault(),e.stopPropagation(),this._pickedNode=t,this._selectedPath=null,this._exitPickMode(),this._markDirty("wiring"))},document.addEventListener("click",this._pickHandler,{capture:!0})}_exitPickMode(){null!==this._pickHandler&&(document.removeEventListener("click",this._pickHandler,{capture:!0}),this._pickHandler=null),this._pickMode=!1;const e=this.shadowRoot?.querySelector('button[data-role="pick"]');e?.setAttribute("aria-pressed","false")}_markDirty(e){this._dirtyPanes.add(e),this._renderScheduled||(this._renderScheduled=!0,requestAnimationFrame(()=>{this._renderDirty()}))}_renderDirty(){if(this._renderScheduled=!1,null===this._core||null===this.shadowRoot)return void this._dirtyPanes.clear();const e=this._dirtyPanes;this._dirtyPanes=new Set,e.has("state")&&(this._stateHeld()?this._dirtyPanes.add("state"):this._renderStatePane()),e.has("wiring")&&this._renderWiringPane(),e.has("timeline")&&this._renderTimelinePane()}_stateHeld(){return!!this._statePointerDown||null!==this._editInput&&this.shadowRoot.activeElement===this._editInput}_releaseState(){this._dirtyPanes.has("state")&&this._markDirty("state")}_holdStateWhilePressed(){this._statePointerDown=!0;const e=()=>{window.removeEventListener("pointerup",e,!0),window.removeEventListener("pointercancel",e,!0),this._statePointerDown=!1,this._releaseState()};window.addEventListener("pointerup",e,!0),window.addEventListener("pointercancel",e,!0)}_rosterKey(e){return`${e.sourceId}:${e.label}`}_selectedRoster(){const e=this._core.getRoster();if(0===e.length)return null;return e.find(e=>this._rosterKey(e)===this._selectedRosterKey)??e[0]}_renderStatePane(){this._editInput=null;const e=this._paneElements.state,t=e.parentElement,n=t.scrollTop;this._renderStateBody(e),t.scrollTop=n}_renderStateBody(e){const t=this._core,n=this._stateSelect,i=t.getRoster(),o=this._selectedRoster();if(n.replaceChildren(...i.map(e=>{const t=document.createElement("option");return t.value=this._rosterKey(e),t.textContent=`${e.label} (${e.sourceId.slice(0,12)})`,t.selected=null!==o&&this._rosterKey(e)===this._rosterKey(o),t})),e.replaceChildren(),null===o)return void e.append(this._emptyRow("no <wcs-state> elements observed"));this._selectedRosterKey=this._rosterKey(o);const s=t.keysOf(o);if(0===s.length)return e.append(this._emptyRow("no readable keys (runtime without keys() API?)")),this._renderOverlaysSection(e,o),void this._renderKeyedSection(e,o);for(const t of s)this._renderTreeNode(e,o,{path:t,indexes:[]},t,0);this._renderOverlaysSection(e,o),this._renderKeyedSection(e,o)}_renderKeyedSection(e,t){const n=this._core.keyedSubscriptionsOf(t);if(null===n||0===n.length)return;const i=document.createElement("h3");i.className="overlays-heading",i.textContent=`Keyed selection (${n.length} path${1===n.length?"":"s"})`,e.append(i);for(const t of n)e.append(this._keyedRow(t))}_keyedRow(e){const t=document.createElement("div");t.className="keyed-row";const n=document.createElement("span");if(n.className="path",n.textContent=e.path,t.append(n),e.tracked){const e=document.createElement("span");e.className="badge-tag warn",e.textContent="tracked",e.title="the path is a getter or under one, so $eq cannot subscribe by key: every getter that reads it re-evaluates when it changes",t.append(document.createTextNode(" "),e)}const i=[];e.rows>0&&i.push(`rows ${e.rows} · keys ${e.keys}`),e.lists>0&&i.push(`list watchers ${e.lists}`),e.tracked||i.push(`last ${r(e.lastValue,1)}`);const o=document.createElement("span");return o.className="detail",o.textContent=i.length>0?` ${i.join(" · ")}`:"",t.append(o),t}_renderOverlaysSection(e,t){const n=this._core.overlaysOf(t);if(null===n||0===n.length)return;const i=document.createElement("h3");i.className="overlays-heading",i.textContent=`Overlays (${n.length} mount${1===n.length?"":"s"})`,e.append(i);for(const t of n)e.append(this._overlayRow(t))}_overlayRow(e){const t=document.createElement("div");t.className="overlay-row";const n=document.createElement("span");n.className="badge-tag",n.textContent=e.marker;const i=document.createElement("span");i.className="prop",i.textContent=`<${e.componentTag}>`;const o=document.createElement("span");o.className="path",o.textContent=e.stateProp,t.append(n,document.createTextNode(" "),i,document.createTextNode(" "),o);const s=[];for(const t of e.mountTable)s.push(`${""===t.inner?"(root)":t.inner} → ${t.outer}`);e.delta>0&&s.push(`Δ${e.delta}`),e.privateKeys.length>0&&s.push(`private: ${e.privateKeys.join(", ")}`);const r=e.exports??[];if(r.length>0&&s.push(`exports: ${r.join(", ")}`),e.getterKeys.length>0&&s.push(`getters: ${e.getterKeys.join(", ")}`),s.length>0){const e=document.createElement("span");e.className="detail",e.textContent=` ${s.join(" · ")}`,t.append(e)}return t}_renderTreeNode(e,t,n,i,o){const s=this._core;let a,l=!0;try{a=s.readValue(t,n.path,n.indexes)}catch{l=!1}const c=document.createElement("div");c.className="tree-row",c.style.paddingLeft=14*o+"px";const d=l&&function(e){if(Array.isArray(e))return!0;if(null===e||"object"!=typeof e)return!1;const t=Object.getPrototypeOf(e);return t===Object.prototype||null===t}(a),h=function(e){return`${e.path}#${e.indexes.join(",")}`}(n),u=d&&this._expanded.has(h),p=document.createElement("span");p.className="toggle",p.textContent=d?u?"▾":"▸":"",d&&p.addEventListener("click",()=>{this._expanded.has(h)?this._expanded.delete(h):this._expanded.add(h),this._markDirty("state")}),c.append(p);const m=document.createElement("span");m.className="key",m.textContent=`${i}:`,m.title=n.path,m.addEventListener("click",()=>{this._selectedPath=n.path,this._pickedNode=null,this._markDirty("wiring"),this._highlightPath(t,n.path)}),c.append(m);const g=document.createElement("span");if(g.className="value",l){g.textContent=r(a,1);(null===a||"object"!=typeof a)&&"function"!=typeof a&&(g.classList.add("editable"),g.title="click to edit",g.addEventListener("click",()=>{this._beginEdit(c,g,t,n,a)}))}else g.textContent="(unreadable getter)";if(c.append(g),e.append(c),u)if(Array.isArray(a)){const i=Math.min(a.length,20);for(let s=0;s<i;s++)this._renderTreeNode(e,t,{path:`${n.path}.*`,indexes:[...n.indexes,s]},`[${s}]`,o+1);if(a.length>i){const t=this._emptyRow(`…(${a.length} items)`);t.style.paddingLeft=14*(o+1)+"px",e.append(t)}}else for(const i of Object.keys(a))this._renderTreeNode(e,t,{path:`${n.path}.${i}`,indexes:n.indexes},i,o+1)}_beginEdit(e,t,n,i,o){const s=document.createElement("input");s.value="string"==typeof o?o:String(o);const r=()=>{this._editInput=null,this._core?.writeValue(n,i.path,function(e){const t=e.trim();try{return JSON.parse(t)}catch{return e}}(s.value),i.indexes),this._markDirty("state")};s.addEventListener("keydown",e=>{"Enter"===e.key?r():"Escape"===e.key&&(this._editInput=null,this._markDirty("state"))}),s.addEventListener("blur",()=>{this._releaseState()}),e.replaceChild(s,t),this._editInput=s,s.focus()}_renderWiringPane(){const e=this._core,t=this._paneElements.wiring;t.replaceChildren();const n=document.createElement("div");n.className="wiring-tabs";for(const[e,t]of[["wiring","wiring"],["coverage","coverage"]]){const i=document.createElement("button");i.textContent=t,this._wiringView===e&&i.classList.add("active"),i.addEventListener("click",()=>{this._wiringView=e,this._markDirty("wiring")}),n.append(i)}if(t.append(n),"coverage"===this._wiringView)return void this._renderCoverageView(t);let i,o;if(null!==this._pickedNode){i=e.getWiringForNode(this._pickedNode);const t=this._pickedNode;o=t instanceof Element?`<${t.tagName.toLowerCase()}>`:t.nodeName}else if(null!==this._selectedPath){const t=this._selectedRoster();i=null!==t?e.getWiringForPath(this._selectedPath,t.summary.element):[],o=this._selectedPath}else i=e.getAllWiring(),o="all";const s=document.createElement("div");if(s.textContent=`context: ${o} — ${i.length} live binding${1===i.length?"":"s"}`,t.append(s),i.length>0){for(const e of i)t.append(this._wiringRow(e));return}const r=e.getCanonicalDeclared(),a=this._selectedRoster(),l=null===r&&null!==a?function(e,t="data-wcs"){const n=[];for(const i of e.querySelectorAll(`[${t}]`)){const e=i.getAttribute(t);for(const t of e.split(";")){const e=w(i,t,"attribute");null!==e&&n.push(e)}}const i=(e.ownerDocument??e).createTreeWalker(e,NodeFilter.SHOW_COMMENT);let o=i.nextNode();for(;null!==o;){const e=o.textContent.trim(),t=_.find(t=>e===t||e.startsWith(t+":"));if(void 0!==t){const i=o.parentNode instanceof Element?o.parentNode:null;if(null!==i){const o=e===t?"":e.slice(t.length+1).trim();if(o.length>0){const e="wcs-text"===t?"textContent":t.slice(4);n.push(w(i,`${e}: ${o}`,"comment"))}}}o=i.nextNode()}return n}(this._scanRootOf(a)):[];if(0===(r?.length??0)&&0===l.length)return void t.append(this._emptyRow("no bindings observed"));const c=document.createElement("div");c.className="notice";const d=document.createElement("span");d.className="badge-tag declared",d.textContent=null!==r?"declared (canonical)":"declared",c.append(d,document.createTextNode(" attached late — reload to capture live bindings "));const h=document.createElement("button");if(h.textContent="reload",h.addEventListener("click",()=>{location.reload()}),c.append(h),t.append(c),null!==r)for(const e of r)t.append(this._canonicalDeclaredRow(e));else for(const e of l)t.append(this._declaredRow(e))}_renderCoverageView(e){const t=this._core,n=t.observingSince,i=document.createElement("div"),o=null===n?null:new Date(Date.now()-(performance.now()-n)).toLocaleTimeString();i.textContent=null===o?"not observing":`observing since ${o} (declared vs measured after this point)`,e.append(i);const s=this._selectedRoster(),r=t.getCoverageReport(s?.summary.element);if(0!==r.length)for(const t of r){const n=document.createElement("div");n.className="wiring-row";const i=document.createElement("span");i.className="badge-tag",i.textContent=t.kind;const o=document.createElement("span");o.className="badge-tag",o.textContent=t.count>1?`${t.status} ×${t.count}`:t.status,"never"===t.status||"never-attached"===t.status||"emitted-unheard"===t.status?o.classList.add("warn"):"prerequisite-missing"===t.status&&o.classList.add("declared");const s=document.createElement("span");if(s.className="path",s.textContent=` ${t.name} `,n.append(i,document.createTextNode(" "),s,o),null!==t.note){const e=document.createElement("span");e.className="detail",e.textContent=` ${t.note}`,n.append(e)}e.append(n)}else e.append(this._emptyRow("nothing declared to cover"))}_canonicalDeclaredRow(e){const t=document.createElement("div");t.className="wiring-row";const n=document.createElement("span");n.className="badge-tag declared",n.textContent=e.origin;const i=document.createElement("span");i.className="prop",i.textContent=e.propName;const o=document.createElement("span");o.className="path";const s=e.outFilters.map(e=>` | ${e.filterName}(${e.args.join(",")})`).join("");if(o.textContent=`${e.statePathName}${s}`,t.append(n,document.createTextNode(" "),i,document.createTextNode(" ← "),o),null!==e.node){const n=e.node;t.addEventListener("click",()=>{this._highlightNodes([n])})}return t}_scanRootOf(e){const t=e.rootNode;return t.nodeType===Node.DOCUMENT_NODE||t.nodeType===Node.DOCUMENT_FRAGMENT_NODE?t:document}_wiringRow(e){const t=document.createElement("div");t.className="wiring-row";const n=document.createElement("span");n.className="prop",n.textContent=e.propName;const i=document.createTextNode(" ← "),o=document.createElement("span");o.className="path",o.textContent=e.path;const s=document.createElement("span");return s.className="badge-tag",s.textContent=e.bindingType,t.append(s,document.createTextNode(" "),n,i,o),t.addEventListener("click",()=>{const t=e.bindingRef.deref();void 0!==t&&this._highlightNodes([t.node,t.replaceNode])}),t}_declaredRow(e){const t=document.createElement("div");t.className="wiring-row";const n=document.createElement("span");n.className="badge-tag declared",n.textContent=e.origin;const i=document.createElement("span");i.className="prop",i.textContent=e.propName;const o=document.createElement("span");return o.className="path",o.textContent=e.path,t.append(n,document.createTextNode(" "),i,document.createTextNode(" ← "),o),t.addEventListener("click",()=>{this._highlightNodes([e.element])}),t}_renderTimelinePane(){const e=this._core,t=this._paneElements.timeline,n=e.getTimeline(),i=Math.max(0,n.length-200),o=[];i>0&&o.push(this._emptyRow(`…(${i} earlier entries)`));for(let e=i;e<n.length;e++)o.push(this._timelineRow(n[e]));0===o.length&&o.push(this._emptyRow("no activity yet")),t.replaceChildren(...o),t.scrollTop=t.scrollHeight}_timelineRow(e){const t=document.createElement("div");t.className="timeline-row";const n=document.createElement("span");n.className="t",n.textContent=`${(e.time/1e3).toFixed(3)}s `;const i=document.createElement("span");i.className="badge-tag kind",i.textContent=e.kind,0===e.subscriberCount&&(i.classList.add("warn"),i.title="emitted with no subscribers"),"watch-error"!==e.kind&&"watch-chain-limit"!==e.kind||(i.classList.add("warn"),i.title="watch-error"===e.kind?"a $watch or $scan failure (read, handler, fold or write — see the phase in the detail); the runtime isolated it (console.error only)":"a $watch write chain hit the depth limit and was cut off"),"render-chain-limit"===e.kind&&(i.classList.add("warn"),i.title="writes made while rendering kept starting new batches; the chain hit the depth limit and this batch was not rendered"),"path-unresolved"!==e.kind&&"binding-apply-error"!==e.kind||(i.classList.add("warn"),i.title="path-unresolved"===e.kind?"a wired path does not resolve on the state; its updates are dropped":"a binding threw while applying; the runtime isolated it (console.error only)"),"propagation-hop-limit"!==e.kind&&"contract-drift"!==e.kind||(i.classList.add("warn"),i.title="propagation-hop-limit"===e.kind?"a two-way propagation chain hit the hop limit and was cut off":"sidecar manifest drifted from the live wcBindable declaration (live wins)");const o=document.createElement("span");o.className="label",o.textContent=` ${e.label} `;const s=document.createElement("span");return s.className="detail",s.textContent=e.detail,t.append(n,i,o,s),t}_emptyRow(e){const t=document.createElement("div");return t.className="empty",t.textContent=e,t}_highlightPath(e,t){const n=this._core,i=[];for(const o of n.getWiringForPath(t,e.summary.element)){const e=o.bindingRef.deref();void 0!==e&&i.push(e.node,e.replaceNode)}this._highlightNodes(i)}_highlightNodes(e){const t=this._highlightLayer;t.replaceChildren();const n=new Set;for(const i of e){const e=i instanceof Element?i:i.parentElement;if(null===e||n.has(e)||!e.isConnected)continue;n.add(e);const o=e.getBoundingClientRect(),s=document.createElement("div");s.className="hl-box",s.style.left=`${o.left}px`,s.style.top=`${o.top}px`,s.style.width=`${o.width}px`,s.style.height=`${o.height}px`,t.append(s)}setTimeout(()=>{t.replaceChildren()},2e3)}}const y=Symbol.for("wcstack.package"),v=new WeakSet;function k(e,t){Object.defineProperty(e,y,{value:t,configurable:!0})}function x(e,t,n,i,o){if(void 0!==i&&(n===i||n.prototype instanceof i))return;const s=n[y];if(s===o||v.has(e))return;v.add(e);const r=o.slice(0,o.lastIndexOf("@"));console.warn(`[${r}] [wcs/package-twice] <${t}> is already defined by ${s??`another copy of ${r} that does not name its version`}; this copy, ${o}, does nothing. Load each package once.`)}const E="wcs-devtools";function N(n=customElements){!function(e,t,n){for(const[i,o]of n){const n=e.get(i);void 0===n?(k(o,t),e.define(i,o)):x(e,i,n,o,t)}}(n,`${e}@${t}`,[[E,b]])}function $(){null===document.querySelector(E)&&document.body.appendChild(document.createElement(E))}document.documentElement.hasAttribute("data-wcs-server")||(N(),null!==document.body?$():document.addEventListener("DOMContentLoaded",$,{once:!0}));
|
|
2
2
|
//# sourceMappingURL=auto.min.js.map
|
package/dist/index.esm.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wcstack/devtools",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.12.0",
|
|
4
4
|
"description": "In-page DevTools overlay for wcstack. Inspect state trees, bindings/wiring and update timelines via the DevTools Hook Protocol - one script tag, no build step.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.esm.js",
|