@wcstack/devtools 1.32.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +3 -5
- package/README.md +3 -5
- package/dist/auto.min.js +1 -1
- package/dist/auto.min.js.map +1 -1
- package/dist/index.d.ts +33 -33
- package/dist/index.esm.js +98 -155
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
package/README.ja.md
CHANGED
|
@@ -31,16 +31,15 @@ auto エントリは `<wcs-devtools>` を定義し、ページに無ければ `<
|
|
|
31
31
|
1 つ挿入する。配置や属性を制御したい場合は自分でタグを書く:
|
|
32
32
|
|
|
33
33
|
```html
|
|
34
|
-
<wcs-devtools open dock="right" hotkey="Ctrl+Shift+X" buffer="1000"
|
|
35
|
-
hidden-states="analytics"></wcs-devtools>
|
|
34
|
+
<wcs-devtools open dock="right" hotkey="Ctrl+Shift+X" buffer="1000"></wcs-devtools>
|
|
36
35
|
```
|
|
37
36
|
|
|
38
37
|
## ペイン
|
|
39
38
|
|
|
40
39
|
| ペイン | 内容 |
|
|
41
40
|
|---|---|
|
|
42
|
-
| **State** |
|
|
43
|
-
| **Wiring** | ライブ binding 台帳: binding ごとの `property ← path
|
|
41
|
+
| **State** | 各ルート state ツリー(root node ごとに 1 本・ラベルはルート由来 — v2 に名前次元は無い)のトップレベルキー、配列/オブジェクトの展開、computed getter。値クリックでインライン編集 — 書き込みは通常のリアクティブパイプライン(set トラップ → 更新バッチ → DOM)を通るため、アプリコードが書いたのと同じようにページが反応する。**パス**クリックで束縛ノードをハイライト。 |
|
|
42
|
+
| **Wiring** | ライブ binding 台帳: binding ごとの `property ← path` 行と型バッジ(`text` / `prop` / `for` / …)。**⌖ pick** でページ要素をクリックするとその要素の配線だけに絞れる。行クリックで束縛ノードをハイライト。 |
|
|
44
43
|
| **Timeline** | ring buffer(既定 500 件): `write`(旧値が取れた場合は併記)、`batch`(drain ごとの dedup 済み更新アドレス)、`command` / `event` トークン発火(引数要約 + 購読者数 — **購読者ゼロの空撃ちには警告バッジ**。whenDefined 前配線レースの検出に効く)、state 要素の登録/解除。⏸ で一時停止、🗑 でクリア。 |
|
|
45
44
|
|
|
46
45
|
## 属性
|
|
@@ -51,7 +50,6 @@ auto エントリは `<wcs-devtools>` を定義し、ページに無ければ `<
|
|
|
51
50
|
| `dock` | `bottom` | `bottom` または `right` |
|
|
52
51
|
| `hotkey` | `Alt+Shift+D` | 開閉ショートカット。`none` で無効 |
|
|
53
52
|
| `buffer` | `500` | タイムライン ring buffer 件数(接続時に読む) |
|
|
54
|
-
| `hidden-states` | — | 非表示にする state 名(カンマ区切り。`wcs-devtools` 始まりは常に非表示) |
|
|
55
53
|
|
|
56
54
|
## 遅延アタッチ
|
|
57
55
|
|
package/README.md
CHANGED
|
@@ -33,16 +33,15 @@ does not already contain one. To control placement/attributes, write the tag
|
|
|
33
33
|
yourself:
|
|
34
34
|
|
|
35
35
|
```html
|
|
36
|
-
<wcs-devtools open dock="right" hotkey="Ctrl+Shift+X" buffer="1000"
|
|
37
|
-
hidden-states="analytics"></wcs-devtools>
|
|
36
|
+
<wcs-devtools open dock="right" hotkey="Ctrl+Shift+X" buffer="1000"></wcs-devtools>
|
|
38
37
|
```
|
|
39
38
|
|
|
40
39
|
## Panes
|
|
41
40
|
|
|
42
41
|
| Pane | What it shows |
|
|
43
42
|
|---|---|
|
|
44
|
-
| **State** | Every
|
|
45
|
-
| **Wiring** | The live binding ledger: `property ← path
|
|
43
|
+
| **State** | Every root state tree (one per root node, labelled by its root — v2 has no name dimension): top-level keys, expandable arrays/objects, computed getters. Click a value to edit it inline — the write goes through the normal reactive pipeline (set trap → update batch → DOM), so the page reacts exactly as if application code had written it. Click a **path** to highlight the DOM nodes bound to it. |
|
|
44
|
+
| **Wiring** | The live binding ledger: `property ← path` rows per binding, with type badges (`text` / `prop` / `for` / …). Use **⌖ pick** to click a page element and see only its bindings. Rows highlight their bound nodes on click. |
|
|
46
45
|
| **Timeline** | A ring buffer (default 500) of `write` (with old value when available), `batch` (deduplicated update addresses per drain), `command` / `event` token emissions (with argument summaries and subscriber counts — **zero-subscriber emissions get a warning badge**, catching wired-before-`whenDefined` races), and state element registration. ⏸ pauses, 🗑 clears. |
|
|
47
46
|
|
|
48
47
|
## Attributes
|
|
@@ -53,7 +52,6 @@ yourself:
|
|
|
53
52
|
| `dock` | `bottom` | `bottom` or `right` |
|
|
54
53
|
| `hotkey` | `Alt+Shift+D` | Toggle shortcut; `none` disables |
|
|
55
54
|
| `buffer` | `500` | Timeline ring-buffer capacity (read at connect) |
|
|
56
|
-
| `hidden-states` | — | Comma-separated state names to hide (names starting with `wcs-devtools` are always hidden) |
|
|
57
55
|
|
|
58
56
|
## Late attach
|
|
59
57
|
|
package/dist/auto.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e="__WCSTACK_DEVTOOLS_HOOK__";function t(){const t=globalThis,n=t[e];if(void 0!==n)return 1!==n.version&&console.warn(`[wcstack/devtools] hook registry version mismatch: found ${n.version}, expected 1. Keeping the existing registry (first-wins).`),n;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:1,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 t[e]=i,i}const n=80;function i(e){const t=e.constructor,n=t?.name;return"string"==typeof n&&n.length>0?n:"Object"}function s(e,t=2){switch(typeof e){case"string":return`"${e.length>n?e.slice(0,n)+"…":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 o=e;if(Array.isArray(o)){if(t<=0)return`[[Array(${o.length})]]`;const e=o.slice(0,3).map(e=>s(e,t-1)),n=o.length>3?`, …(${o.length})`:"";return`[${e.join(", ")}${n}]`}if(function(e){const t=Object.getPrototypeOf(e);return t===Object.prototype||null===t}(o)){if(t<=0)return"[[Object]]";const e=Object.keys(o),n=e.slice(0,3).map(e=>`${e}: ${s(o[e],t-1)}`),i=e.length>3?`, …(${e.length})`:"";return`{${n.join(", ")}${i}}`}return`[[${i(o)}]]`}function o(e){if(null!==e&&"object"==typeof e){const{name:t,message:s}=e;if("string"==typeof s){const o="string"==typeof t&&t.length>0?t:i(e),r=s.length>n?s.slice(0,n)+"…":s;return r.length>0?`${o}: ${r}`:o}}return s(e,1)}function r(e){if(0===e.length)return"";const t=e.slice(0,3).map(e=>{const t=s(e,1);return t.length>n?t.slice(0,n)+"…":t}),i=e.length>3?`, …(${e.length})`:"";return`${t.join(", ")}${i}`}const a=String.fromCharCode(0);function d(e,t){return e+a+t}function c(e,t,n){return e+a+t+a+n}function l(e,t,n){return d(e,t)+a+n}function h(e,t,n,i){return void 0===i?{stateName:e,kind:t,name:n,status:"never",count:0,note:null}:i.zeroSubscriberCount===i.count?{stateName:e,kind:t,name:n,status:"emitted-unheard",count:i.count,note:`all ${i.count} emit(s) had 0 subscribers`}:{stateName:e,kind:t,name:n,status:"emitted",count:i.count,note:i.zeroSubscriberCount>0?`${i.zeroSubscriberCount}/${i.count} emit(s) had 0 subscribers`:null}}class u{_timelineCapacity;_hiddenStateNames;_removeListener=null;_sources=new Map;_roster=new Map;_wiringByPathKey=new Map;_wiringEntryByBinding=new WeakMap;_timeline=[];_seq=0;_paused=!1;_changeListeners=new Set;_observingSince=null;_watchFiredCounts=new Map;_tokenEmitCounts=new Map;_everAttachedKeys=new Set;constructor(e){this._timelineCapacity=e?.timelineCapacity??500,this._hiddenStateNames=new Set(e?.hiddenStateNames??[])}get connected(){return null!==this._removeListener}get paused(){return this._paused}set paused(e){this._paused=e}isHiddenStateName(e){return null!==e&&(e.startsWith("wcs-devtools")||this._hiddenStateNames.has(e))}connect(){if(null!==this._removeListener)return;this._observingSince=performance.now();const e=t();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._watchFiredCounts.clear(),this._tokenEmitCounts.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(d(e,t));return void 0===n?[]:this._collectAlive(n)}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,s]of this._sources){if("function"!=typeof s.getDeclaredBindings)continue;e=!0;const o=new Set;for(const e of this._roster.get(i)??[])o.add(e.rootNode);for(const e of o)for(const i of s.getDeclaredBindings(e)){if(this.isHiddenStateName(i.stateName))continue;const e=[i.stateName,i.statePathName,i.propName,i.bindingType,i.origin,i.raw].join(a);n.has(e)||(n.add(e),t.push(i))}}return e?t:null}getCoverageReport(){const e=[];for(const t of this.getRoster()){const n=t.summary;for(const i of n.watchPaths??[]){const s=this._watchFiredCounts.get(d(t.name,i))??0;if(s>0){e.push({stateName:t.name,kind:"watch",name:i,status:"fired",count:s,note:null});continue}const o=void 0!==n.keyedListPaths;let r=null;for(let e=i.indexOf(".*");-1!==e;e=i.indexOf(".*",e+2)){const t=i.slice(0,e);if(!(n.paths.list.has(t)||(n.keyedListPaths?.has(t)??!1))){r=t;break}}null===r?e.push({stateName:t.name,kind:"watch",name:i,status:"never",count:0,note:null}):e.push({stateName:t.name,kind:"watch",name:i,status:"prerequisite-missing",count:0,note:o?`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 i of n.commandTokenNames)e.push(h(t.name,"command",i,this._tokenEmitCounts.get(c(t.name,"command",i))));for(const i of n.eventTokenNames)e.push(h(t.name,"eventToken",i,this._tokenEmitCounts.get(c(t.name,"event",i))))}const t=this.getCanonicalDeclared();if(null!==t){const n=new Set;for(const i of t){if("for"===i.bindingType||"if"===i.bindingType||"elseif"===i.bindingType||"else"===i.bindingType)continue;if(i.propName.startsWith("eventToken."))continue;const t=l(i.stateName,i.statePathName,i.propName);if(n.has(t))continue;n.add(t);const s=this._everAttachedKeys.has(t);e.push({stateName:i.stateName,kind:"binding",name:`${i.propName} ← ${i.statePathName}`,status:s?"attached":"never-attached",count:s?1:0,note:"fragment"===i.origin?"template interior (attaches when rows materialize)":null})}}return e}keysOf(e){const t=this._sources.get(e.sourceId);return void 0===t||"function"!=typeof t.keys?[]:t.keys(e.name,e.rootNode)}readValue(e,t,n){const i=this._sources.get(e.sourceId);if(void 0!==i)return i.read(e.name,e.rootNode,t,n)}writeValue(e,t,n,i){const s=this._sources.get(e.sourceId);void 0!==s&&s.write(e.name,e.rootNode,t,n,i)}_notify(e){for(const t of this._changeListeners)t(e)}_refreshRosterOf(e){const t=[];for(const n of e.getStateElements())this.isHiddenStateName(n.name)||t.push({sourceId:e.id,name:n.name,rootNode:n.rootNode,summary:n});this._roster.set(e.id,t)}_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":{if(this.isHiddenStateName(t.name))return;const n=this._sources.get(e);return void 0!==n&&(this._refreshRosterOf(n),this._notify("roster")),void this._appendTimeline({sourceId:e,kind:"element-registered",stateName:t.name,label:t.name,detail:"",subscriberCount:null})}case"state:element-unregistered":{if(this.isHiddenStateName(t.name))return;const n=this._sources.get(e);return void 0!==n&&(this._refreshRosterOf(n),this._notify("roster")),void this._appendTimeline({sourceId:e,kind:"element-unregistered",stateName:t.name,label:t.name,detail:"",subscriberCount:null})}case"state:write":{const n=t.absoluteAddress.absolutePathInfo.stateName;if(this.isHiddenStateName(n))return;const i=t.hasOldValue?`${s(t.value)} (was ${s(t.oldValue)})`:s(t.value);return void this._appendTimeline({sourceId:e,kind:"write",stateName:n,label:this._labelOf(t.absoluteAddress),detail:i,subscriberCount:null})}case"state:update-batch":{const n=[];let i=0;for(const e of t.addresses)this.isHiddenStateName(e.absolutePathInfo.stateName)||(i++,n.length<3&&n.push(this._labelOf(e)));if(0===i)return;const s=i>n.length?`, …(${i})`:"";return void this._appendTimeline({sourceId:e,kind:"batch",stateName:null,label:`${i} address${1===i?"":"es"}`,detail:`${n.join(", ")}${s}`,subscriberCount:null})}case"state:binding-added":{const n=t.absoluteAddress.absolutePathInfo.stateName;if(this.isHiddenStateName(n))return;const i=t.absoluteAddress.absolutePathInfo.pathInfo.path,s=d(n,i);let o=this._wiringByPathKey.get(s);void 0===o&&(o=new Set,this._wiringByPathKey.set(s,o));const r={sourceId:e,stateName:n,path:i,propName:t.binding.propName,bindingType:t.binding.bindingType,bindingRef:new WeakRef(t.binding)};return o.add(r),this._wiringEntryByBinding.set(t.binding,r),this._everAttachedKeys.add(l(n,i,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=d(e.stateName,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=d(t.absoluteAddress.absolutePathInfo.stateName,t.absoluteAddress.absolutePathInfo.pathInfo.path);return void(this._wiringByPathKey.delete(e)&&this._notify("wiring"))}case"state:token-emit":if(this.isHiddenStateName(t.stateName))return;if(null!==t.stateName){const e=c(t.stateName,t.kind,t.tokenName),n=this._tokenEmitCounts.get(e);void 0===n?this._tokenEmitCounts.set(e,{count:1,zeroSubscriberCount:0===t.subscriberCount?1:0}):(n.count+=1,0===t.subscriberCount&&(n.zeroSubscriberCount+=1)),this._notify("coverage")}return void this._appendTimeline({sourceId:e,kind:t.kind,stateName:t.stateName,label:t.tokenName,detail:r(t.args),subscriberCount:t.subscriberCount});case"state:watch-fired":{if(this.isHiddenStateName(t.stateName))return;const e=d(t.stateName,t.path);return this._watchFiredCounts.set(e,(this._watchFiredCounts.get(e)??0)+1),void this._notify("coverage")}case"state:watch-error":if(this.isHiddenStateName(t.stateName))return;return void this._appendTimeline({sourceId:e,kind:"watch-error",stateName:t.stateName,label:t.path,detail:`${t.phase}: ${o(t.error)}`,subscriberCount:null});case"state:watch-chain-limit":return void this._appendTimeline({sourceId:e,kind:"watch-chain-limit",stateName:null,label:`depth > ${t.maxDepth}`,detail:t.paths.join(", "),subscriberCount:null});case"state:path-unresolved":if(this.isHiddenStateName(t.stateName))return;return void this._appendTimeline({sourceId:e,kind:"path-unresolved",stateName:t.stateName,label:t.path,detail:`${t.source}: "${t.missingSegment}" is not declared`,subscriberCount:null});case"state:binding-apply-error":if(this.isHiddenStateName(t.stateName))return;return void this._appendTimeline({sourceId:e,kind:"binding-apply-error",stateName:t.stateName,label:t.path,detail:`${t.bindingType}: ${o(t.error)}`,subscriberCount:null});case"propagation:suppressed":return void this._appendTimeline({sourceId:e,kind:"propagation-suppressed",stateName:null,label:t.member,detail:`${t.reason} (tx ${t.transactionId}, edge ${t.edgeId})`,subscriberCount:null});case"propagation:coalesced":{const n=t.absoluteAddress.absolutePathInfo.stateName;if(this.isHiddenStateName(n))return;return void this._appendTimeline({sourceId:e,kind:"propagation-coalesced",stateName:n,label:this._labelOf(t.absoluteAddress),detail:`tx ${t.droppedTransactionId} dropped (winner tx ${t.winnerTransactionId})`,subscriberCount:null})}case"propagation:hop-limit":{const n=t.absoluteAddress.absolutePathInfo.stateName;if(this.isHiddenStateName(n))return;return void this._appendTimeline({sourceId:e,kind:"propagation-hop-limit",stateName:n,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",stateName:null,label:t.tag,detail:`${t.reason}${n}${i}`,subscriberCount:null})}case"contract:manifest-read":case"contract:unsupported-extension":return}}}const p=["wcs-text","wcs-for","wcs-if","wcs-elseif","wcs-else"];function m(e,t,n){const i=t.trim();if(0===i.length)return null;const s=i.indexOf(":");if(s<0)return null;const o=i.slice(0,s).trim(),r=i.slice(s+1).trim();if(0===o.length||0===r.length)return null;const[a,...d]=r.split("|").map(e=>e.trim());let c=a,l="default";const h=a.lastIndexOf("@");return h>0&&(c=a.slice(0,h).trim(),l=a.slice(h+1).trim()),{element:e,propName:o,path:c,stateName:l,filters:d.filter(e=>e.length>0),origin:n,raw:i}}class g 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;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")??""),t=(this.getAttribute("hidden-states")??"").split(",").map(e=>e.trim()).filter(e=>e.length>0);this._core=new u({timelineCapacity:Number.isFinite(e)&&e>0?e:void 0,hiddenStateNames:t}),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"):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}\nheader .title { font-weight: 700; color: #9fd0ff; margin-right: 4px; }\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; }\nheader .spacer { flex: 1; }\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.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 s=document.createElement("header"),o=document.createElement("span");o.className="title",o.textContent="wcstack devtools",s.append(o);const r=document.createElement("select");r.title="state element",r.addEventListener("change",()=>{this._selectedRosterKey=r.value||null,this._selectedPath=null,this._expanded.clear(),this._markDirty("state"),this._markDirty("wiring")}),s.append(r),this._stateSelect=r;const a=this._headerButton(s,"⌖ pick","pick a page element");a.addEventListener("click",()=>{this._pickMode?this._exitPickMode():this._enterPickMode(),a.setAttribute("aria-pressed",String(this._pickMode))}),a.dataset.role="pick";const d=this._headerButton(s,"⏸","pause timeline");d.addEventListener("click",()=>{const e=this._core;null!==e&&(e.paused=!e.paused,d.setAttribute("aria-pressed",String(e.paused)))}),d.dataset.role="pause";const c=this._headerButton(s,"🗑","clear timeline");c.addEventListener("click",()=>{this._core?.clearTimeline()}),c.dataset.role="clear";const l=document.createElement("span");l.className="spacer",s.append(l);const h=this._headerButton(s,"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(s,"×","close");u.addEventListener("click",()=>this.toggle(!1)),u.dataset.role="close",i.append(s);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 s=document.createElement("div");s.className="pane-body",n.append(i,s),p.append(n),this._paneElements[e]=s}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"),s=t.includes("shift"),o=t.includes("ctrl"),r=t.includes("meta");this._hotkeyHandler=e=>{e.key.toLowerCase()===n&&e.altKey===i&&e.shiftKey===s&&e.ctrlKey===o&&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._renderStatePane(),e.has("wiring")&&this._renderWiringPane(),e.has("timeline")&&this._renderTimelinePane()}_rosterKey(e){return`${e.sourceId}:${e.name}`}_selectedRoster(){const e=this._core.getRoster();if(0===e.length)return null;return e.find(e=>this._rosterKey(e)===this._selectedRosterKey)??e[0]}_renderStatePane(){const e=this._core,t=this._paneElements.state,n=this._stateSelect,i=e.getRoster(),s=this._selectedRoster();if(n.replaceChildren(...i.map(e=>{const t=document.createElement("option");return t.value=this._rosterKey(e),t.textContent=`${e.name} (${e.sourceId.slice(0,12)})`,t.selected=null!==s&&this._rosterKey(e)===this._rosterKey(s),t})),t.replaceChildren(),null===s)return void t.append(this._emptyRow("no <wcs-state> elements observed"));this._selectedRosterKey=this._rosterKey(s);const o=e.keysOf(s);if(0!==o.length)for(const e of o)this._renderTreeNode(t,s,{path:e,indexes:[]},e,0);else t.append(this._emptyRow("no readable keys (runtime without keys() API?)"))}_renderTreeNode(e,t,n,i,o){const r=this._core;let a,d=!0;try{a=r.readValue(t,n.path,n.indexes)}catch{d=!1}const c=document.createElement("div");c.className="tree-row",c.style.paddingLeft=14*o+"px";const l=d&&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=l&&this._expanded.has(h),p=document.createElement("span");p.className="toggle",p.textContent=l?u?"▾":"▸":"",l&&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",d){g.textContent=s(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,s){const o=document.createElement("input");o.value="string"==typeof s?s:String(s);const r=()=>{this._core?.writeValue(n,i.path,function(e){const t=e.trim();try{return JSON.parse(t)}catch{return e}}(o.value),i.indexes),this._markDirty("state")};o.addEventListener("keydown",e=>{"Enter"===e.key?r():"Escape"===e.key&&this._markDirty("state")}),e.replaceChild(o,t),o.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,s;if(null!==this._pickedNode){i=e.getWiringForNode(this._pickedNode);const t=this._pickedNode;s=t instanceof Element?`<${t.tagName.toLowerCase()}>`:t.nodeName}else if(null!==this._selectedPath){const t=this._selectedRoster();i=null!==t?e.getWiringForPath(t.name,this._selectedPath):[],s=this._selectedPath}else i=e.getAllWiring(),s="all";const o=document.createElement("div");if(o.textContent=`context: ${s} — ${i.length} live binding${1===i.length?"":"s"}`,t.append(o),i.length>0){for(const e of i)t.append(this._wiringRow(e));return}const r=e.getCanonicalDeclared(),a=this._selectedRoster(),d=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=m(i,t,"attribute");null!==e&&n.push(e)}}const i=(e.ownerDocument??e).createTreeWalker(e,NodeFilter.SHOW_COMMENT);let s=i.nextNode();for(;null!==s;){const e=s.textContent.trim(),t=p.find(t=>e===t||e.startsWith(t+":"));if(void 0!==t){const i=s.parentNode instanceof Element?s.parentNode:null;if(null!==i){const s=e===t?"":e.slice(t.length+1).trim();if(s.length>0){const e="wcs-text"===t?"textContent":t.slice(4);n.push(m(i,`${e}: ${s}`,"comment"))}}}s=i.nextNode()}return n}(this._scanRootOf(a)):[];if(0===(r?.length??0)&&0===d.length)return void t.append(this._emptyRow("no bindings observed"));const c=document.createElement("div");c.className="notice";const l=document.createElement("span");l.className="badge-tag declared",l.textContent=null!==r?"declared (canonical)":"declared",c.append(l,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 d)t.append(this._declaredRow(e))}_renderCoverageView(e){const t=this._core,n=t.observingSince,i=document.createElement("div"),s=null===n?null:new Date(Date.now()-(performance.now()-n)).toLocaleTimeString();i.textContent=null===s?"not observing":`observing since ${s} (declared vs measured after this point)`,e.append(i);const o=t.getCoverageReport();if(0!==o.length)for(const t of o){const n=document.createElement("div");n.className="wiring-row";const i=document.createElement("span");i.className="badge-tag",i.textContent=t.kind;const s=document.createElement("span");s.className="badge-tag",s.textContent=t.count>1?`${t.status} ×${t.count}`:t.status,"never"===t.status||"never-attached"===t.status||"emitted-unheard"===t.status?s.classList.add("warn"):"prerequisite-missing"===t.status&&s.classList.add("declared");const o=document.createElement("span");if(o.className="path",o.textContent=` ${t.name}@${t.stateName} `,n.append(i,document.createTextNode(" "),o,s),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 s=document.createElement("span");s.className="path";const o=e.outFilters.map(e=>` | ${e.filterName}(${e.args.join(",")})`).join("");if(s.textContent=`${e.statePathName}@${e.stateName}${o}`,t.append(n,document.createTextNode(" "),i,document.createTextNode(" ← "),s),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(" ← "),s=document.createElement("span");s.className="path",s.textContent=`${e.path}@${e.stateName}`;const o=document.createElement("span");return o.className="badge-tag",o.textContent=e.bindingType,t.append(o,document.createTextNode(" "),n,i,s),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 s=document.createElement("span");return s.className="path",s.textContent=`${e.path}@${e.stateName}`,t.append(n,document.createTextNode(" "),i,document.createTextNode(" ← "),s),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),s=[];i>0&&s.push(this._emptyRow(`…(${i} earlier entries)`));for(let e=i;e<n.length;e++)s.push(this._timelineRow(n[e]));0===s.length&&s.push(this._emptyRow("no activity yet")),t.replaceChildren(...s),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 threw; the runtime isolated it (console.error only)":"a $watch write chain hit the depth limit and was cut off"),"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 s=document.createElement("span");s.className="label";const o=null!==e.stateName?`@${e.stateName}`:"";s.textContent=` ${e.label}${o} `;const r=document.createElement("span");return r.className="detail",r.textContent=e.detail,t.append(n,i,s,r),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 s of n.getWiringForPath(e.name,t)){const e=s.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 s=e.getBoundingClientRect(),o=document.createElement("div");o.className="hl-box",o.style.left=`${s.left}px`,o.style.top=`${s.top}px`,o.style.width=`${s.width}px`,o.style.height=`${s.height}px`,t.append(o)}setTimeout(()=>{t.replaceChildren()},2e3)}}const f="wcs-devtools";function _(){null===document.querySelector(f)&&document.body.appendChild(document.createElement(f))}document.documentElement.hasAttribute("data-wcs-server")||(customElements.get(f)||customElements.define(f,g),null!==document.body?_():document.addEventListener("DOMContentLoaded",_,{once:!0}));
|
|
1
|
+
const e="__WCSTACK_DEVTOOLS_HOOK__";function t(){const t=globalThis,n=t[e];if(void 0!==n)return 2!==n.version&&console.warn(`[wcstack/devtools] hook registry version mismatch: found ${n.version}, expected 2. Keeping the existing registry (first-wins).`),n;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 t[e]=i,i}const n=80;function i(e){const t=e.constructor,n=t?.name;return"string"==typeof n&&n.length>0?n:"Object"}function s(e,t=2){switch(typeof e){case"string":return`"${e.length>n?e.slice(0,n)+"…":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 o=e;if(Array.isArray(o)){if(t<=0)return`[[Array(${o.length})]]`;const e=o.slice(0,3).map(e=>s(e,t-1)),n=o.length>3?`, …(${o.length})`:"";return`[${e.join(", ")}${n}]`}if(function(e){const t=Object.getPrototypeOf(e);return t===Object.prototype||null===t}(o)){if(t<=0)return"[[Object]]";const e=Object.keys(o),n=e.slice(0,3).map(e=>`${e}: ${s(o[e],t-1)}`),i=e.length>3?`, …(${e.length})`:"";return`{${n.join(", ")}${i}}`}return`[[${i(o)}]]`}function o(e){if(null!==e&&"object"==typeof e){const{name:t,message:s}=e;if("string"==typeof s){const o="string"==typeof t&&t.length>0?t:i(e),r=s.length>n?s.slice(0,n)+"…":s;return r.length>0?`${o}: ${r}`:o}}return s(e,1)}function r(e){if(0===e.length)return"";const t=e.slice(0,3).map(e=>{const t=s(e,1);return t.length>n?t.slice(0,n)+"…":t}),i=e.length>3?`, …(${e.length})`:"";return`${t.join(", ")}${i}`}const a=String.fromCharCode(0);function c(e){return e}function d(e,t){return e+a+t}function l(e,t){return e+a+t}function h(e){return"undefined"!=typeof ShadowRoot&&e instanceof ShadowRoot?`<${e.host.tagName.toLowerCase()}>`:9===e.nodeType?"document":e.nodeName.toLowerCase()}function u(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 p{_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;_watchFiredCounts=new Map;_tokenEmitCounts=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=t();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._watchFiredCounts.clear(),this._tokenEmitCounts.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,s]of this._sources){if("function"!=typeof s.getDeclaredBindings)continue;e=!0;const o=new Set;for(const e of this._roster.get(i)??[])o.add(e.rootNode);for(const e of o)for(const i of s.getDeclaredBindings(e)){const e=[i.statePathName,i.propName,i.bindingType,i.origin,i.raw].join(a);n.has(e)||(n.add(e),t.push(i))}}return e?t:null}getCoverageReport(){const e=[];for(const t of this.getRoster()){const n=t.summary;for(const t of n.watchPaths??[]){const i=this._watchFiredCounts.get(c(t))??0;if(i>0){e.push({kind:"watch",name:t,status:"fired",count:i,note:null});continue}const s=void 0!==n.keyedListPaths;let o=null;for(let e=t.indexOf(".*");-1!==e;e=t.indexOf(".*",e+2)){const i=t.slice(0,e);if(!(n.paths.list.has(i)||(n.keyedListPaths?.has(i)??!1))){o=i;break}}null===o?e.push({kind:"watch",name:t,status:"never",count:0,note:null}):e.push({kind:"watch",name:t,status:"prerequisite-missing",count:0,note:s?`list "${o}" 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 "${o}" (a $listKeys declaration would still let list writes fire it)`})}for(const t of n.commandTokenNames)e.push(u("command",t,this._tokenEmitCounts.get(d("command",t))));for(const t of n.eventTokenNames)e.push(u("eventToken",t,this._tokenEmitCounts.get(d("event",t))))}const t=this.getCanonicalDeclared();if(null!==t){const n=new Set;for(const i of t){if("for"===i.bindingType||"if"===i.bindingType||"elseif"===i.bindingType||"else"===i.bindingType)continue;if(i.propName.startsWith("eventToken."))continue;const t=l(i.statePathName,i.propName);if(n.has(t))continue;n.add(t);const s=this._everAttachedKeys.has(t);e.push({kind:"binding",name:`${i.propName} ← ${i.statePathName}`,status:s?"attached":"never-attached",count:s?1:0,note:"fragment"===i.origin?"template interior (attaches when rows materialize)":null})}}return e}keysOf(e){const t=this._sources.get(e.sourceId);return void 0===t||"function"!=typeof t.keys?[]:t.keys(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 s=this._sources.get(e.sourceId);void 0!==s&&s.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 s=h(i.rootNode),o=(n.get(s)??0)+1;n.set(s,o),t.push({sourceId:e.id,label:1===o?s:`${s}#${o}`,rootNode:i.rootNode,summary:i})}this._roster.set(e.id,t)}_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:h(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:h(t.rootNode),detail:"",subscriberCount:null})}case"state:write":{const n=t.hasOldValue?`${s(t.value)} (was ${s(t.oldValue)})`:s(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;const s=i>n.length?`, …(${i})`:"";return void this._appendTimeline({sourceId:e,kind:"batch",label:`${i} address${1===i?"":"es"}`,detail:`${n.join(", ")}${s}`,subscriberCount:null})}case"state:binding-added":{const n=t.absoluteAddress.absolutePathInfo.pathInfo.path,i=n;let s=this._wiringByPathKey.get(i);void 0===s&&(s=new Set,this._wiringByPathKey.set(i,s));const o=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 o&&null!==o?new WeakRef(o):null};return s.add(r),this._wiringEntryByBinding.set(t.binding,r),this._everAttachedKeys.add(l(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=d(t.kind,t.tokenName),i=this._tokenEmitCounts.get(n);return void 0===i?this._tokenEmitCounts.set(n,{count:1,zeroSubscriberCount:0===t.subscriberCount?1:0}):(i.count+=1,0===t.subscriberCount&&(i.zeroSubscriberCount+=1)),this._notify("coverage"),void this._appendTimeline({sourceId:e,kind:t.kind,label:t.tokenName,detail:r(t.args),subscriberCount:t.subscriberCount})}case"state:watch-fired":{const e=t.path;return this._watchFiredCounts.set(e,(this._watchFiredCounts.get(e)??0)+1),void this._notify("coverage")}case"state:watch-error":return void this._appendTimeline({sourceId:e,kind:"watch-error",label:t.path,detail:`${t.phase}: ${o(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: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}: ${o(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 m=["wcs-text","wcs-for","wcs-if","wcs-elseif","wcs-else"];function g(e,t,n){const i=t.trim();if(0===i.length)return null;const s=i.indexOf(":");if(s<0)return null;const o=i.slice(0,s).trim(),r=i.slice(s+1).trim();if(0===o.length||0===r.length)return null;const[a,...c]=r.split("|").map(e=>e.trim());return{element:e,propName:o,path:a,filters:c.filter(e=>e.length>0),origin:n,raw:i}}class f 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;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 p({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"):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}\nheader .title { font-weight: 700; color: #9fd0ff; margin-right: 4px; }\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; }\nheader .spacer { flex: 1; }\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.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 s=document.createElement("header"),o=document.createElement("span");o.className="title",o.textContent="wcstack devtools",s.append(o);const r=document.createElement("select");r.title="state element",r.addEventListener("change",()=>{this._selectedRosterKey=r.value||null,this._selectedPath=null,this._expanded.clear(),this._markDirty("state"),this._markDirty("wiring")}),s.append(r),this._stateSelect=r;const a=this._headerButton(s,"⌖ pick","pick a page element");a.addEventListener("click",()=>{this._pickMode?this._exitPickMode():this._enterPickMode(),a.setAttribute("aria-pressed",String(this._pickMode))}),a.dataset.role="pick";const c=this._headerButton(s,"⏸","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(s,"🗑","clear timeline");d.addEventListener("click",()=>{this._core?.clearTimeline()}),d.dataset.role="clear";const l=document.createElement("span");l.className="spacer",s.append(l);const h=this._headerButton(s,"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(s,"×","close");u.addEventListener("click",()=>this.toggle(!1)),u.dataset.role="close",i.append(s);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 s=document.createElement("div");s.className="pane-body",n.append(i,s),p.append(n),this._paneElements[e]=s}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"),s=t.includes("shift"),o=t.includes("ctrl"),r=t.includes("meta");this._hotkeyHandler=e=>{e.key.toLowerCase()===n&&e.altKey===i&&e.shiftKey===s&&e.ctrlKey===o&&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._renderStatePane(),e.has("wiring")&&this._renderWiringPane(),e.has("timeline")&&this._renderTimelinePane()}_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(){const e=this._core,t=this._paneElements.state,n=this._stateSelect,i=e.getRoster(),s=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!==s&&this._rosterKey(e)===this._rosterKey(s),t})),t.replaceChildren(),null===s)return void t.append(this._emptyRow("no <wcs-state> elements observed"));this._selectedRosterKey=this._rosterKey(s);const o=e.keysOf(s);if(0!==o.length)for(const e of o)this._renderTreeNode(t,s,{path:e,indexes:[]},e,0);else t.append(this._emptyRow("no readable keys (runtime without keys() API?)"))}_renderTreeNode(e,t,n,i,o){const r=this._core;let a,c=!0;try{a=r.readValue(t,n.path,n.indexes)}catch{c=!1}const d=document.createElement("div");d.className="tree-row",d.style.paddingLeft=14*o+"px";const l=c&&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=l&&this._expanded.has(h),p=document.createElement("span");p.className="toggle",p.textContent=l?u?"▾":"▸":"",l&&p.addEventListener("click",()=>{this._expanded.has(h)?this._expanded.delete(h):this._expanded.add(h),this._markDirty("state")}),d.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)}),d.append(m);const g=document.createElement("span");if(g.className="value",c){g.textContent=s(a,1);(null===a||"object"!=typeof a)&&"function"!=typeof a&&(g.classList.add("editable"),g.title="click to edit",g.addEventListener("click",()=>{this._beginEdit(d,g,t,n,a)}))}else g.textContent="(unreadable getter)";if(d.append(g),e.append(d),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,s){const o=document.createElement("input");o.value="string"==typeof s?s:String(s);const r=()=>{this._core?.writeValue(n,i.path,function(e){const t=e.trim();try{return JSON.parse(t)}catch{return e}}(o.value),i.indexes),this._markDirty("state")};o.addEventListener("keydown",e=>{"Enter"===e.key?r():"Escape"===e.key&&this._markDirty("state")}),e.replaceChild(o,t),o.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,s;if(null!==this._pickedNode){i=e.getWiringForNode(this._pickedNode);const t=this._pickedNode;s=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):[],s=this._selectedPath}else i=e.getAllWiring(),s="all";const o=document.createElement("div");if(o.textContent=`context: ${s} — ${i.length} live binding${1===i.length?"":"s"}`,t.append(o),i.length>0){for(const e of i)t.append(this._wiringRow(e));return}const r=e.getCanonicalDeclared(),a=this._selectedRoster(),c=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=g(i,t,"attribute");null!==e&&n.push(e)}}const i=(e.ownerDocument??e).createTreeWalker(e,NodeFilter.SHOW_COMMENT);let s=i.nextNode();for(;null!==s;){const e=s.textContent.trim(),t=m.find(t=>e===t||e.startsWith(t+":"));if(void 0!==t){const i=s.parentNode instanceof Element?s.parentNode:null;if(null!==i){const s=e===t?"":e.slice(t.length+1).trim();if(s.length>0){const e="wcs-text"===t?"textContent":t.slice(4);n.push(g(i,`${e}: ${s}`,"comment"))}}}s=i.nextNode()}return n}(this._scanRootOf(a)):[];if(0===(r?.length??0)&&0===c.length)return void t.append(this._emptyRow("no bindings observed"));const d=document.createElement("div");d.className="notice";const l=document.createElement("span");l.className="badge-tag declared",l.textContent=null!==r?"declared (canonical)":"declared",d.append(l,document.createTextNode(" attached late — reload to capture live bindings "));const h=document.createElement("button");if(h.textContent="reload",h.addEventListener("click",()=>{location.reload()}),d.append(h),t.append(d),null!==r)for(const e of r)t.append(this._canonicalDeclaredRow(e));else for(const e of c)t.append(this._declaredRow(e))}_renderCoverageView(e){const t=this._core,n=t.observingSince,i=document.createElement("div"),s=null===n?null:new Date(Date.now()-(performance.now()-n)).toLocaleTimeString();i.textContent=null===s?"not observing":`observing since ${s} (declared vs measured after this point)`,e.append(i);const o=t.getCoverageReport();if(0!==o.length)for(const t of o){const n=document.createElement("div");n.className="wiring-row";const i=document.createElement("span");i.className="badge-tag",i.textContent=t.kind;const s=document.createElement("span");s.className="badge-tag",s.textContent=t.count>1?`${t.status} ×${t.count}`:t.status,"never"===t.status||"never-attached"===t.status||"emitted-unheard"===t.status?s.classList.add("warn"):"prerequisite-missing"===t.status&&s.classList.add("declared");const o=document.createElement("span");if(o.className="path",o.textContent=` ${t.name} `,n.append(i,document.createTextNode(" "),o,s),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 s=document.createElement("span");s.className="path";const o=e.outFilters.map(e=>` | ${e.filterName}(${e.args.join(",")})`).join("");if(s.textContent=`${e.statePathName}${o}`,t.append(n,document.createTextNode(" "),i,document.createTextNode(" ← "),s),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(" ← "),s=document.createElement("span");s.className="path",s.textContent=e.path;const o=document.createElement("span");return o.className="badge-tag",o.textContent=e.bindingType,t.append(o,document.createTextNode(" "),n,i,s),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 s=document.createElement("span");return s.className="path",s.textContent=e.path,t.append(n,document.createTextNode(" "),i,document.createTextNode(" ← "),s),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),s=[];i>0&&s.push(this._emptyRow(`…(${i} earlier entries)`));for(let e=i;e<n.length;e++)s.push(this._timelineRow(n[e]));0===s.length&&s.push(this._emptyRow("no activity yet")),t.replaceChildren(...s),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 threw; the runtime isolated it (console.error only)":"a $watch write chain hit the depth limit and was cut off"),"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 s=document.createElement("span");s.className="label",s.textContent=` ${e.label} `;const o=document.createElement("span");return o.className="detail",o.textContent=e.detail,t.append(n,i,s,o),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 s of n.getWiringForPath(t,e.summary.element)){const e=s.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 s=e.getBoundingClientRect(),o=document.createElement("div");o.className="hl-box",o.style.left=`${s.left}px`,o.style.top=`${s.top}px`,o.style.width=`${s.width}px`,o.style.height=`${s.height}px`,t.append(o)}setTimeout(()=>{t.replaceChildren()},2e3)}}const _="wcs-devtools";function b(){null===document.querySelector(_)&&document.body.appendChild(document.createElement(_))}document.documentElement.hasAttribute("data-wcs-server")||(customElements.get(_)||customElements.define(_,f),null!==document.body?b():document.addEventListener("DOMContentLoaded",b,{once:!0}));
|
|
2
2
|
//# sourceMappingURL=auto.min.js.map
|