@weasel-js/devtools 1.15.0 → 1.15.1

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/index.js CHANGED
@@ -18,7 +18,7 @@ import { Input } from "@weasel-js/ui/components/Input";
18
18
  import { Tree, filterTree, treeBranchIds } from "@weasel-js/ui/components/Tree";
19
19
  import { GestureRoute } from "@weasel-js/ui/components/GestureRoute";
20
20
  import { DEBUG_FEATURES } from "@weasel-js/core";
21
- //#region src/client.ts
21
+ // src/client.ts
22
22
  /**
23
23
  * The panel's side of the devtools protocol, free of any framework: the
24
24
  * handshake, request ids and their replies, the roots the page reports, and
@@ -146,8 +146,7 @@ function connectDevtools(transport) {
146
146
  client.open();
147
147
  return client;
148
148
  }
149
- //#endregion
150
- //#region src/trace.ts
149
+ // src/trace.ts
151
150
  /** Follow `rootId`'s dispatch trace through `client`, from the oldest record the canvas still holds. */
152
151
  function followTrace(client, rootId) {
153
152
  let cursor = 0;
@@ -182,8 +181,7 @@ function followTrace(client, rootId) {
182
181
  }
183
182
  };
184
183
  }
185
- //#endregion
186
- //#region src/history.ts
184
+ // src/history.ts
187
185
  /** Follow `rootId`'s history steps through `client`, from the oldest step the canvas still holds. */
188
186
  function followHistory(client, rootId) {
189
187
  let cursor = 0;
@@ -209,8 +207,7 @@ function followHistory(client, rootId) {
209
207
  }
210
208
  };
211
209
  }
212
- //#endregion
213
- //#region src/hooks.ts
210
+ // src/hooks.ts
214
211
  /** The React side of a connection: the client a panel holds, the data it reads per root, and its polls. */
215
212
  /** A connection over `transport` for as long as the component is mounted: `yo` on mount, `bye` on unmount. */
216
213
  function useDevtoolsClient(transport) {
@@ -296,8 +293,7 @@ var DevtoolsPanel_module_default = {
296
293
  tabPanel: "_tabPanel_485101",
297
294
  empty: "_empty_485101"
298
295
  };
299
- //#endregion
300
- //#region src/RootPicker.tsx
296
+ // src/RootPicker.tsx
301
297
  /** Which canvas the panel reads, each named by its label and dimension. */
302
298
  function RootPicker({ roots, value, onChange }) {
303
299
  return /* @__PURE__ */ jsx(Select, {
@@ -322,8 +318,7 @@ function RootPicker({ roots, value, onChange }) {
322
318
  }))
323
319
  });
324
320
  }
325
- //#endregion
326
- //#region src/views/formatAge.ts
321
+ // src/views/formatAge.ts
327
322
  /** How long ago something happened, in the shortest unit that reads well: `840ms`, `12.3s`, `4m07s`. */
328
323
  function formatAge(ms) {
329
324
  if (ms < 1e3) return `${Math.round(ms)}ms`;
@@ -342,8 +337,7 @@ var TraceTable_module_default = {
342
337
  detail: "_detail_e7e309",
343
338
  heading: "_heading_e7e309"
344
339
  };
345
- //#endregion
346
- //#region src/views/CoordTable.tsx
340
+ // src/views/CoordTable.tsx
347
341
  /** Wide enough for a coordinate in the tens of thousands, sign included, at one decimal. */
348
342
  var fixed = (n, digits = 1) => n.toFixed(digits).padStart(8, " ");
349
343
  var pair = (x, y) => `${fixed(x)} ${fixed(y)}`;
@@ -395,8 +389,7 @@ function CoordTable({ entries, now }) {
395
389
  })]
396
390
  });
397
391
  }
398
- //#endregion
399
- //#region src/views/DecisionPath.tsx
392
+ // src/views/DecisionPath.tsx
400
393
  function inputText(record) {
401
394
  const { eventKind, key } = record.input;
402
395
  return key === void 0 ? eventKind : `${eventKind} ${key === " " ? "Space" : key}`;
@@ -436,8 +429,7 @@ function DecisionPath({ record }) {
436
429
  "aria-label": "Decision path"
437
430
  });
438
431
  }
439
- //#endregion
440
- //#region src/views/TraceTable.tsx
432
+ // src/views/TraceTable.tsx
441
433
  /** The trace as rows, newest first under the live prediction; a dispatch row opens to the path it took and every stage behind it. */
442
434
  var LIVE_ID = "live";
443
435
  /** Ids from each entry's timestamp, numbering entries that share one. */
@@ -533,8 +525,7 @@ var DispatchView_module_default = {
533
525
  count: "_count_fdab1f _numeric_25fd0b",
534
526
  body: "_body_fdab1f"
535
527
  };
536
- //#endregion
537
- //#region src/views/DispatchView.tsx
528
+ // src/views/DispatchView.tsx
538
529
  /**
539
530
  * The Dispatch tab: the root's trace of resolved inputs and mode switches,
540
531
  * what a press at the pointer would do now, and, behind a toggle, the
@@ -639,8 +630,7 @@ var ValueView_module_default = {
639
630
  fn: "_fn_3839e5",
640
631
  tag: "_tag_3839e5"
641
632
  };
642
- //#endregion
643
- //#region src/views/ValueView.tsx
633
+ // src/views/ValueView.tsx
644
634
  /** A serialized value as a reader expects to see it: tagged maps, sets and typed arrays named, functions and cycles marked. */
645
635
  var isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
646
636
  /** The children a container lists, or null for a value shown on one line. */
@@ -765,8 +755,7 @@ var FrameView_module_default = {
765
755
  layers: "_layers_ae00c9",
766
756
  note: "_note_ae00c9"
767
757
  };
768
- //#endregion
769
- //#region src/views/FrameView.tsx
758
+ // src/views/FrameView.tsx
770
759
  /**
771
760
  * The Frame tab: what the last paint cost, overall and per render layer. The
772
761
  * canvas measures only while its `fps` overlay is on and announces nothing, so
@@ -864,8 +853,7 @@ var HistoryView_module_default = {
864
853
  targets: "_targets_739ab5",
865
854
  note: "_note_739ab5"
866
855
  };
867
- //#endregion
868
- //#region src/views/HistoryTable.tsx
856
+ // src/views/HistoryTable.tsx
869
857
  /** History steps as rows, newest first; a row opens to the entries it touched and each entry's ops. */
870
858
  var opCount = (step) => step.entries.reduce((n, e) => n + e.opCount, 0);
871
859
  function StepDetail({ step }) {
@@ -963,8 +951,7 @@ function HistoryTable({ steps, now }) {
963
951
  renderDetail: ({ step }) => /* @__PURE__ */ jsx(StepDetail, { step })
964
952
  });
965
953
  }
966
- //#endregion
967
- //#region src/views/HistoryView.tsx
954
+ // src/views/HistoryView.tsx
968
955
  /**
969
956
  * The History tab: each step the scene's history took, newest first, read
970
957
  * through its cursor whenever a notice reports one; where the history stands;
@@ -1081,8 +1068,7 @@ var RegistryBrowser_module_default = {
1081
1068
  listPane: "_listPane_085110",
1082
1069
  detailPane: "_detailPane_085110"
1083
1070
  };
1084
- //#endregion
1085
- //#region src/views/RegistryBrowser.tsx
1071
+ // src/views/RegistryBrowser.tsx
1086
1072
  /**
1087
1073
  * A registry as a filterable tree of categories beside the entry picked. The
1088
1074
  * host supplies the categories and renders the detail, so the same screen
@@ -1225,8 +1211,7 @@ var RegistryView_module_default = {
1225
1211
  kinds: "_kinds_9c8486",
1226
1212
  note: "_note_9c8486"
1227
1213
  };
1228
- //#endregion
1229
- //#region src/views/Bindings.tsx
1214
+ // src/views/Bindings.tsx
1230
1215
  var hasOpts = (b) => typeof b.opts === "object" && b.opts !== null && Object.keys(b.opts).length > 0;
1231
1216
  function Bindings({ bindings }) {
1232
1217
  return /* @__PURE__ */ jsxs("section", {
@@ -1274,8 +1259,7 @@ function Bindings({ bindings }) {
1274
1259
  })]
1275
1260
  });
1276
1261
  }
1277
- //#endregion
1278
- //#region src/views/RegistryEntryDetail.tsx
1262
+ // src/views/RegistryEntryDetail.tsx
1279
1263
  var yesNo$1 = (v) => v ? "yes" : "no";
1280
1264
  var codes = (ids) => ids.length ? /* @__PURE__ */ jsx("span", {
1281
1265
  className: RegistryView_module_default.codes,
@@ -1487,8 +1471,7 @@ function RegistryEntryDetail({ registry, pick }) {
1487
1471
  children: [pick.id, " is no longer registered."]
1488
1472
  });
1489
1473
  }
1490
- //#endregion
1491
- //#region src/views/RegistryView.tsx
1474
+ // src/views/RegistryView.tsx
1492
1475
  /**
1493
1476
  * The Registry tab: what the canvas has registered, filtered by name, beside
1494
1477
  * the entry picked. Re-read when the registry changes, and on selection and
@@ -1587,8 +1570,7 @@ var SceneView_module_default = {
1587
1570
  heading: "_heading_9a17db",
1588
1571
  note: "_note_9a17db"
1589
1572
  };
1590
- //#endregion
1591
- //#region src/views/NodeDetail.tsx
1573
+ // src/views/NodeDetail.tsx
1592
1574
  var yesNo = (v) => v ? "yes" : "no";
1593
1575
  function NodeDetail({ client, rootId, nodeId, onPick }) {
1594
1576
  const node = useRootQuery(client, rootId, ["scene"], () => client.request(rootId, {
@@ -1681,8 +1663,7 @@ function NodeDetail({ client, rootId, nodeId, onPick }) {
1681
1663
  ]
1682
1664
  });
1683
1665
  }
1684
- //#endregion
1685
- //#region src/views/useSceneTree.ts
1666
+ // src/views/useSceneTree.ts
1686
1667
  /** A root's scene tree, loaded a level at a time as branches open, and reloaded where it is open when the scene changes. */
1687
1668
  /** The key the top level is held under. */
1688
1669
  var TOP = "";
@@ -1740,8 +1721,7 @@ function useSceneTree(client, rootId) {
1740
1721
  error
1741
1722
  };
1742
1723
  }
1743
- //#endregion
1744
- //#region src/views/SceneView.tsx
1724
+ // src/views/SceneView.tsx
1745
1725
  /** The Scene tab: a root's node tree beside the node picked in it. */
1746
1726
  function flags$1(row) {
1747
1727
  return [
@@ -1847,8 +1827,7 @@ var StateView_module_default = {
1847
1827
  probe: "_probe_5edec5",
1848
1828
  note: "_note_5edec5"
1849
1829
  };
1850
- //#endregion
1851
- //#region src/views/StateView.tsx
1830
+ // src/views/StateView.tsx
1852
1831
  /** The tool picker's value for "no tool": a select key cannot be null. */
1853
1832
  var NO_TOOL = "\0none";
1854
1833
  function StateView({ client, rootId }) {
@@ -1970,8 +1949,7 @@ function StateView({ client, rootId }) {
1970
1949
  ]
1971
1950
  });
1972
1951
  }
1973
- //#endregion
1974
- //#region src/tabs.ts
1952
+ // src/tabs.ts
1975
1953
  var DEVTOOLS_TABS = [
1976
1954
  {
1977
1955
  id: "scene",
@@ -2004,8 +1982,7 @@ var DEVTOOLS_TABS = [
2004
1982
  View: FrameView
2005
1983
  }
2006
1984
  ];
2007
- //#endregion
2008
- //#region src/DevtoolsPanel.tsx
1985
+ // src/DevtoolsPanel.tsx
2009
1986
  /**
2010
1987
  * Reads and steers the canvases of the page `transport` reaches: pick a canvas,
2011
1988
  * then walk its scene, read its state, follow its dispatch trace, or watch its
@@ -2067,8 +2044,7 @@ function statusText(status, kitVersion, error) {
2067
2044
  if (status === "connected") return `weasel ${kitVersion ?? ""}`;
2068
2045
  return status;
2069
2046
  }
2070
- //#endregion
2071
- //#region src/inPageTransport.ts
2047
+ // src/inPageTransport.ts
2072
2048
  /**
2073
2049
  * A panel's end of a connection to this page's own hook. Each `yo` opens a
2074
2050
  * fresh session and each `bye` ends it, the way a `yo` posted to the window
@@ -2093,7 +2069,6 @@ function createInPagePanelTransport(hook = installDevtoolsHook()) {
2093
2069
  onMessage: (listener) => panel.onMessage(listener)
2094
2070
  };
2095
2071
  }
2096
- //#endregion
2097
2072
  export { DevtoolsPanel, RegistryBrowser, connectDevtools, createDevtoolsClient, createInPagePanelTransport, followHistory, followTrace };
2098
2073
 
2099
2074
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["s","_Fragment","table","age","count","detail","heading","s","_Fragment","s","toolbar","count","body","POLL_MS","s","s","figure","note","s","_Fragment","heading","note","s","s","split","detailPane","s","count","facts","detail","section","heading","codes","note","s","yesNo","s","s","_Fragment","count","heading","note","s","flags","s","s","s"],"sources":["../src/client.ts","../src/trace.ts","../src/history.ts","../src/hooks.ts","../src/DevtoolsPanel.module.css","../src/RootPicker.tsx","../src/views/formatAge.ts","../src/views/TraceTable.module.css","../src/views/CoordTable.tsx","../src/views/DecisionPath.tsx","../src/views/TraceTable.tsx","../src/views/DispatchView.module.css","../src/views/DispatchView.tsx","../src/views/ValueView.module.css","../src/views/ValueView.tsx","../src/views/FrameView.module.css","../src/views/FrameView.tsx","../src/views/HistoryView.module.css","../src/views/HistoryTable.tsx","../src/views/HistoryView.tsx","../src/views/RegistryBrowser.module.css","../src/views/RegistryBrowser.tsx","../src/views/RegistryView.module.css","../src/views/Bindings.tsx","../src/views/RegistryEntryDetail.tsx","../src/views/RegistryView.tsx","../src/views/SceneView.module.css","../src/views/NodeDetail.tsx","../src/views/useSceneTree.ts","../src/views/SceneView.tsx","../src/views/StateView.module.css","../src/views/StateView.tsx","../src/tabs.ts","../src/DevtoolsPanel.tsx","../src/inPageTransport.ts"],"sourcesContent":["/**\n * The panel's side of the devtools protocol, free of any framework: the\n * handshake, request ids and their replies, the roots the page reports, and\n * its change notices. The views, the extension and tests all drive this.\n */\nimport {\n DEVTOOLS_PROTOCOL, type DevtoolsArea, type DevtoolsHistorySlice, type DevtoolsNodeDetail, type DevtoolsNodeSummary,\n type DevtoolsRegistry, type DevtoolsRequest, type DevtoolsRootInfo, type DevtoolsRootState, type DevtoolsTraceSlice,\n type PageMessage, type PanelTransport, type SerializedValue,\n} from '@weasel-js/core/devtools-protocol';\n\ntype DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;\n\n/** A request as a caller writes it: the client adds the protocol, the request id and the root. */\nexport type DevtoolsRequestBody = DistributiveOmit<DevtoolsRequest, 'protocol' | 'requestId' | 'rootId'>;\n\n/** What each request resolves to. */\nexport interface DevtoolsResultMap {\n 'get-children': DevtoolsNodeSummary[];\n 'get-node': DevtoolsNodeDetail;\n 'get-state': DevtoolsRootState;\n 'get-trace': DevtoolsTraceSlice;\n 'get-frame': SerializedValue;\n 'get-registry': DevtoolsRegistry;\n 'get-history': DevtoolsHistorySlice;\n select: null;\n highlight: null;\n 'set-tool': null;\n 'set-overlays': null;\n}\n\n/** Where a connection stands. `error` holds a message the page sent about no request, such as a protocol mismatch. */\nexport interface DevtoolsClientState {\n status: 'connecting' | 'connected' | 'error' | 'closed';\n kitVersion: string | null;\n roots: readonly DevtoolsRootInfo[];\n error: string | null;\n}\n\n/** One open connection to a page's devtools hook, from the panel's side. */\nexport interface DevtoolsClient {\n state(): DevtoolsClientState;\n /** Hear every change to {@link DevtoolsClient.state}. Returns the unsubscribe. */\n subscribe(listener: () => void): () => void;\n /** Hear a root's `changed` notices, with the areas each names. Returns the unsubscribe. */\n onChanged(listener: (rootId: string, areas: DevtoolsArea[]) => void): () => void;\n /** Send `body` about `rootId`. Rejects with the page's message when it refuses. */\n request<B extends DevtoolsRequestBody>(rootId: string, body: B): Promise<DevtoolsResultMap[B['type']]>;\n /** Say `yo` and start listening. Called again after {@link DevtoolsClient.close}, it reconnects. */\n open(): void;\n /** Say `bye` and stop listening. Pending requests reject. */\n close(): void;\n}\n\ninterface Pending {\n resolve(result: unknown): void;\n reject(err: Error): void;\n}\n\n/** A connection over `transport`, sending nothing until it is opened. It is connected once the page says `sup`. */\nexport function createDevtoolsClient(transport: PanelTransport): DevtoolsClient {\n let state: DevtoolsClientState = { status: 'closed', kitVersion: null, roots: [], error: null };\n const listeners = new Set<() => void>();\n const changeListeners = new Set<(rootId: string, areas: DevtoolsArea[]) => void>();\n const pending = new Map<number, Pending>();\n let nextId = 1;\n\n const set = (patch: Partial<DevtoolsClientState>): void => {\n state = { ...state, ...patch };\n for (const l of [...listeners]) l();\n };\n\n const receive = (m: PageMessage): void => {\n if (state.status === 'closed') return;\n switch (m.type) {\n case 'sup':\n set({ status: 'connected', kitVersion: m.kitVersion, roots: m.roots, error: null });\n return;\n case 'root-added':\n set({ roots: [...state.roots.filter((r) => r.id !== m.root.id), m.root] });\n return;\n case 'root-removed':\n set({ roots: state.roots.filter((r) => r.id !== m.rootId) });\n return;\n case 'changed': {\n const areas = Object.keys(m.areas) as DevtoolsArea[];\n for (const l of [...changeListeners]) l(m.rootId, areas);\n return;\n }\n case 'result':\n pending.get(m.requestId)?.resolve(m.result);\n pending.delete(m.requestId);\n return;\n case 'error':\n if (m.requestId === null) {\n set({ status: 'error', error: m.message });\n return;\n }\n pending.get(m.requestId)?.reject(new Error(m.message));\n pending.delete(m.requestId);\n return;\n }\n };\n\n let off: (() => void) | null = null;\n\n return {\n state: () => state,\n subscribe(listener) {\n listeners.add(listener);\n return () => { listeners.delete(listener); };\n },\n onChanged(listener) {\n changeListeners.add(listener);\n return () => { changeListeners.delete(listener); };\n },\n request(rootId, body) {\n if (state.status === 'closed') return Promise.reject(new Error('the devtools connection is closed'));\n const requestId = nextId++;\n return new Promise((resolve, reject) => {\n pending.set(requestId, { resolve: resolve as (r: unknown) => void, reject });\n transport.send({ ...body, protocol: DEVTOOLS_PROTOCOL, requestId, rootId } as DevtoolsRequest);\n });\n },\n open() {\n if (off) return;\n off = transport.onMessage(receive);\n set({ status: 'connecting', error: null });\n transport.send({ type: 'yo', protocol: DEVTOOLS_PROTOCOL });\n },\n close() {\n if (!off) return;\n transport.send({ type: 'bye', protocol: DEVTOOLS_PROTOCOL });\n off();\n off = null;\n set({ status: 'closed' });\n const err = new Error('the devtools connection is closed');\n for (const p of pending.values()) p.reject(err);\n pending.clear();\n },\n };\n}\n\n/** {@link createDevtoolsClient}, opened: it says `yo` at once. */\nexport function connectDevtools(transport: PanelTransport): DevtoolsClient {\n const client = createDevtoolsClient(transport);\n client.open();\n return client;\n}\n","/** A root's dispatch trace read a slice at a time, each read picking up where the last left off. */\nimport type { SerializedValue } from '@weasel-js/core/devtools-protocol';\nimport type { DevtoolsClient } from './client';\n\n/** What one read hands back. `coords` is present only while coord records are asked for. */\nexport interface TraceRead {\n entries: SerializedValue[];\n live: SerializedValue;\n coords?: SerializedValue[];\n}\n\n/** A cursor over one root's dispatch trace, and over its coord records once asked. */\nexport interface TraceFollower {\n /** The trace and, when on, the coord records recorded since the last read. Reads run one after another. */\n read(): Promise<TraceRead>;\n /** Ask for coord records from the next read on. Turned on, it starts from the oldest the canvas still holds. */\n setCoords(on: boolean): void;\n}\n\n/** Follow `rootId`'s dispatch trace through `client`, from the oldest record the canvas still holds. */\nexport function followTrace(client: DevtoolsClient, rootId: string): TraceFollower {\n let cursor = 0;\n let coordCursor: number | null = null;\n let last: Promise<unknown> = Promise.resolve();\n\n const readOnce = async (): Promise<TraceRead> => {\n const slice = await client.request(rootId, {\n type: 'get-trace', cursor, ...(coordCursor !== null ? { coordCursor } : {}),\n });\n cursor = slice.cursor;\n const out: TraceRead = { entries: slice.entries, live: slice.live };\n if (slice.coords && coordCursor !== null) {\n coordCursor = slice.coords.cursor;\n out.coords = slice.coords.entries;\n }\n return out;\n };\n\n return {\n read() {\n const next = last.then(readOnce, readOnce);\n last = next.catch(() => undefined);\n return next;\n },\n setCoords(on) {\n if (on && coordCursor === null) coordCursor = 0;\n else if (!on) coordCursor = null;\n },\n };\n}\n","/** A root's history steps read a slice at a time through their cursor, the stack's entries along with them on request. */\nimport type { DevtoolsHistorySlice } from '@weasel-js/core/devtools-protocol';\nimport type { DevtoolsClient } from './client';\n\n/** A cursor over one root's history steps. */\nexport interface HistoryFollower {\n /** The steps recorded since the last read, and where the history stands now. Reads run one after another. */\n read(): Promise<DevtoolsHistorySlice>;\n /** Ask for the stack's entries with every read from the next on. */\n setCheckpoints(on: boolean): void;\n}\n\n/** Follow `rootId`'s history steps through `client`, from the oldest step the canvas still holds. */\nexport function followHistory(client: DevtoolsClient, rootId: string): HistoryFollower {\n let cursor = 0;\n let checkpoints = false;\n let last: Promise<unknown> = Promise.resolve();\n\n const readOnce = async (): Promise<DevtoolsHistorySlice> => {\n const slice = await client.request(rootId, { type: 'get-history', cursor, ...(checkpoints ? { checkpoints } : {}) });\n cursor = slice.cursor;\n return slice;\n };\n\n return {\n read() {\n const next = last.then(readOnce, readOnce);\n last = next.catch(() => undefined);\n return next;\n },\n setCheckpoints(on) {\n checkpoints = on;\n },\n };\n}\n","/** The React side of a connection: the client a panel holds, the data it reads per root, and its polls. */\nimport { useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';\nimport type { DevtoolsArea, PanelTransport } from '@weasel-js/core/devtools-protocol';\nimport { useLatest, useVisibleRaf } from '@weasel-js/react';\nimport { createDevtoolsClient, type DevtoolsClient, type DevtoolsClientState } from './client';\n\n/** A connection over `transport` for as long as the component is mounted: `yo` on mount, `bye` on unmount. */\nexport function useDevtoolsClient(transport: PanelTransport): { client: DevtoolsClient; state: DevtoolsClientState } {\n const client = useMemo(() => createDevtoolsClient(transport), [transport]);\n useEffect(() => {\n client.open();\n return () => client.close();\n }, [client]);\n const state = useSyncExternalStore(client.subscribe, client.state);\n return { client, state };\n}\n\n/** What a view reads about one root: the last answer, or the page's refusal. */\nexport interface RootQuery<T> {\n data: T | undefined;\n error: string | null;\n /** Ask again now, as after a steering request whose effect no notice reports. */\n refresh(): void;\n}\n\n/**\n * `read`'s answer about `rootId`, asked again whenever a `changed` notice for\n * that root names one of `areas`, or a dependency in `deps` changes.\n */\nexport function useRootQuery<T>(\n client: DevtoolsClient,\n rootId: string,\n areas: readonly DevtoolsArea[],\n read: () => Promise<T>,\n deps: readonly unknown[] = [],\n): RootQuery<T> {\n const [data, setData] = useState<T | undefined>(undefined);\n const [error, setError] = useState<string | null>(null);\n const [version, setVersion] = useState(0);\n const readRef = useLatest(read);\n const areaKey = areas.join(',');\n\n useEffect(() => client.onChanged((id, changed) => {\n if (id === rootId && changed.some((a) => areaKey.split(',').includes(a))) setVersion((v) => v + 1);\n }), [client, rootId, areaKey]);\n\n useEffect(() => {\n let live = true;\n readRef.current().then(\n (result) => { if (live) { setData(result); setError(null); } },\n (err: Error) => { if (live) setError(err.message); },\n );\n return () => { live = false; };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- `deps` is the caller's\n }, [client, rootId, version, readRef, ...deps]);\n\n const refresh = useRef(() => setVersion((v) => v + 1)).current;\n return { data, error, refresh };\n}\n\n/** Call `tick` every `ms` while `enabled` and the page is visible, and once at the start. */\nexport function usePoll(tick: () => void, ms: number, enabled: boolean): void {\n const tickRef = useLatest(tick);\n const last = useRef(-Infinity);\n const loop = useVisibleRaf((time, l) => {\n if (time - last.current >= ms) {\n last.current = time;\n tickRef.current();\n }\n l.request();\n });\n useEffect(() => {\n if (!enabled) return;\n last.current = -Infinity;\n loop.request();\n return () => loop.cancel();\n }, [enabled, loop]);\n}\n","/* Fills whatever box it is given; each view scrolls inside its own panes. */\n.panel {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 0;\n min-width: 0;\n overflow: hidden;\n color: var(--wzl-fg);\n background: var(--wzl-panel-surface);\n font-family: var(--wzl-font-ui);\n font-size: var(--wzl-font-size-sm);\n /* The views lay themselves out by the panel's own width: a sidebar gives it far less than a page. */\n container-type: inline-size;\n}\n\n.bar {\n display: flex;\n flex-direction: row;\n justify-content: flex-start;\n align-items: center;\n gap: var(--wzl-space-4);\n padding: var(--wzl-space-2) var(--wzl-space-4);\n border-bottom: 1px solid var(--wzl-line-subtle);\n flex-shrink: 0;\n}\n\n.picker {\n flex: 0 1 auto;\n min-width: 0;\n margin: 0;\n}\n\n.dimension {\n color: var(--wzl-fg-muted);\n font-size: var(--wzl-font-size-xs);\n}\n\n.status {\n flex: 0 1 auto;\n min-width: 0;\n margin-inline-start: auto;\n color: var(--wzl-fg-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.tabs {\n flex: 1 1 auto;\n min-height: 0;\n}\n\n.tabList {\n flex-shrink: 0;\n /* In a narrow panel the tabs wrap onto a second row rather than run past its edge. */\n flex-wrap: wrap;\n padding-inline: var(--wzl-space-2);\n}\n\n.tabPanel {\n flex: 1 1 auto;\n min-height: 0;\n display: flex;\n flex-direction: column;\n padding: 0;\n overflow: hidden;\n}\n\n.empty {\n margin: 0;\n padding: var(--wzl-space-6);\n color: var(--wzl-fg-muted);\n}\n","import type { ReactElement } from 'react';\nimport type { DevtoolsRootInfo } from '@weasel-js/core/devtools-protocol';\nimport { Select } from '@weasel-js/ui/components/Select';\nimport s from './DevtoolsPanel.module.css';\n\nexport interface RootPickerProps {\n roots: readonly DevtoolsRootInfo[];\n value: string | null;\n onChange(rootId: string): void;\n}\n\n/** Which canvas the panel reads, each named by its label and dimension. */\nexport function RootPicker({ roots, value, onChange }: RootPickerProps): ReactElement {\n return (\n <Select\n className={s.picker}\n aria-label=\"Canvas\"\n width=\"fit\"\n placeholder=\"No canvas\"\n isDisabled={roots.length === 0}\n selectedKey={value}\n onSelectionChange={onChange}\n options={roots.map((r) => ({\n value: r.id,\n textValue: `${r.label} ${r.dimension}`,\n label: <>{r.label} <span className={s.dimension}>{r.dimension}</span></>,\n }))}\n />\n );\n}\n","/** How long ago something happened, in the shortest unit that reads well: `840ms`, `12.3s`, `4m07s`. */\nexport function formatAge(ms: number): string {\n if (ms < 1000) return `${Math.round(ms)}ms`;\n const sec = ms / 1000;\n if (sec < 60) return `${sec.toFixed(1)}s`;\n const m = Math.floor(sec / 60);\n return `${m}m${String(Math.floor(sec % 60)).padStart(2, '0')}s`;\n}\n",".table {\n font-family: var(--wzl-font-mono);\n}\n\n/* Age is live, variable-length text in the leading column: a fixed width keeps\n ticking values from shifting the columns after it. */\n.age {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n width: 7ch;\n min-width: 7ch;\n text-align: end;\n white-space: nowrap;\n}\n\n.count {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n text-align: end;\n}\n\n.unhandled > td { background: color-mix(in srgb, var(--wzl-danger) 14%, transparent); }\ntr.unhandled:hover > td { background: color-mix(in srgb, var(--wzl-danger) 24%, transparent); }\n\n/* Mode switches read as ambient state rather than dispatched input. */\ntr.mode { color: var(--wzl-fg-muted); cursor: default; }\n.mode > td { background: color-mix(in srgb, var(--wzl-accent) 8%, transparent); }\n.modeDetail { font-style: italic; }\n\n/* The live prediction is pinned above the log; it is not a past event. */\ntr.live > td { font-style: italic; border-block-end: 1px solid var(--wzl-border); }\n\n.detail {\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-4);\n}\n\n.heading {\n margin: var(--wzl-space-6) 0 var(--wzl-space-3);\n font-size: var(--wzl-font-size-sm);\n font-weight: var(--wzl-font-weight-bold);\n}\n","/** `clientToWorld` conversions, newest first: where the pointer was, the camera it was read under, and the world point it became. */\nimport type { ReactElement } from 'react';\nimport { DataGrid, type DataGridColumn } from '@weasel-js/ui/components/DataGrid';\nimport { formatAge } from './formatAge';\nimport s from './TraceTable.module.css';\n\n/** One coord record, as the canvas writes it. */\nexport interface CoordEntry {\n ts: number;\n clientX: number;\n clientY: number;\n view: { x: number; y: number; scaleX: number; scaleY: number } | null;\n world: { x: number; y: number };\n fallback: boolean;\n}\n\nconst DISPLAY_LIMIT = 100;\n/** Wide enough for a coordinate in the tens of thousands, sign included, at one decimal. */\nconst fixed = (n: number, digits = 1): string => n.toFixed(digits).padStart(8, ' ');\nconst pair = (x: number, y: number): string => `${fixed(x)} ${fixed(y)}`;\n\nexport function CoordTable({ entries, now }: { entries: readonly CoordEntry[]; now: number }): ReactElement {\n const rows = entries.slice(-DISPLAY_LIMIT).map((entry, i) => ({ id: `${entry.ts}-${i}`, entry })).reverse();\n const columns: readonly DataGridColumn<(typeof rows)[number]>[] = [\n { id: 'age', header: 'Age', sortable: false, className: s.age, render: ({ entry }) => formatAge(Math.max(0, now - entry.ts)) },\n { id: 'client', header: 'Client', sortable: false, className: s.count, render: ({ entry }) => pair(entry.clientX, entry.clientY) },\n { id: 'world', header: 'World', sortable: false, className: s.count, render: ({ entry }) => pair(entry.world.x, entry.world.y) },\n {\n id: 'scale',\n header: 'Scale',\n sortable: false,\n className: s.count,\n render: ({ entry }) => (entry.view ? fixed(entry.view.scaleX, 3) : 'fallback'),\n },\n ];\n return (\n <section aria-label=\"Coord records\">\n <h3 className={s.heading}>Coords</h3>\n <DataGrid className={s.table} rows={rows} columns={columns} empty=\"No conversions recorded yet.\" />\n </section>\n );\n}\n","/** The path one input took, as a powerline: the input, the binding's owner, the action that fired, and whether it was handled. */\nimport type { ReactElement } from 'react';\nimport type { DispatchRecord } from '@weasel-js/core/routing';\nimport { Powerline, type PowerlineSegment } from '@weasel-js/ui/components/Powerline';\n\nfunction inputText(record: DispatchRecord): string {\n const { eventKind, key } = record.input;\n return key === undefined ? eventKind : `${eventKind} ${key === ' ' ? 'Space' : key}`;\n}\n\nexport function DecisionPath({ record }: { record: DispatchRecord }): ReactElement {\n const winner = record.ranked.find((r) => r.walk.kind === 'fired' || r.walk.kind === 'would-fire');\n const segments: PowerlineSegment[] = [{ text: inputText(record), grade: 'info', endCap: 'chevron' }];\n if (winner) {\n segments.push(\n { text: winner.candidate.ownerId ?? 'action', emphasis: 'low', endCap: 'chevron' },\n { text: winner.candidate.actionId, emphasis: 'high', endCap: 'chevron' },\n );\n } else {\n segments.push({ text: `${record.ranked.length} ranked, none fired`, emphasis: 'low', endCap: 'chevron' });\n }\n segments.push(record.outcome === 'handled'\n ? { text: record.predicted ? 'would handle' : 'handled', grade: 'success' }\n : { text: 'unhandled', grade: 'danger' });\n return <Powerline segments={segments} size=\"sm\" variant=\"subtle\" aria-label=\"Decision path\" />;\n}\n","/** The trace as rows, newest first under the live prediction; a dispatch row opens to the path it took and every stage behind it. */\nimport { useState, type ReactElement, type ReactNode } from 'react';\nimport type { DispatchRecord, TraceLogEntry } from '@weasel-js/core/routing';\nimport { DataGrid, type DataGridColumn } from '@weasel-js/ui/components/DataGrid';\nimport { FallthroughDiagram } from '@weasel-js/ui/components/FallthroughDiagram';\nimport { DecisionPath } from './DecisionPath';\nimport { formatAge } from './formatAge';\nimport s from './TraceTable.module.css';\n\nconst DISPLAY_LIMIT = 100;\nconst LIVE_ID = 'live';\n\nexport interface TraceTableProps {\n entries: readonly TraceLogEntry[];\n /** A press at the pointer, predicted, pinned above the log. */\n live: DispatchRecord | null;\n /** The clock each row's age is measured against. */\n now: number;\n /** Inputs an action handled, with mode switches. */\n showHandled: boolean;\n showUnhandled: boolean;\n /** Shown in place of rows when the filters leave none. */\n empty: ReactNode;\n}\n\ninterface TraceRow { id: string; entry: TraceLogEntry }\n\n/** Ids from each entry's timestamp, numbering entries that share one. */\nfunction withTsIds(entries: readonly TraceLogEntry[]): TraceRow[] {\n const seen = new Map<number, number>();\n return entries.map((entry) => {\n const n = seen.get(entry.ts) ?? 0;\n seen.set(entry.ts, n + 1);\n return { id: n === 0 ? String(entry.ts) : `${entry.ts}#${n}`, entry };\n });\n}\n\nfunction renderEvent(entry: TraceLogEntry): ReactNode {\n if (entry.kind === 'mode') {\n return <><code>{entry.mode}</code>{entry.detail ? <span className={s.modeDetail}> ({entry.detail})</span> : null}</>;\n }\n const { key } = entry.input;\n return <>{entry.input.eventKind}{key !== undefined ? <> <code>{key === ' ' ? 'Space' : key}</code></> : null}</>;\n}\n\nfunction renderOutcome(entry: TraceLogEntry): ReactNode {\n if (entry.kind === 'mode') return <><code>{entry.from ?? '∅'}</code> → <code>{entry.to ?? '∅'}</code></>;\n if (entry.outcome === 'unhandled') return 'unhandled';\n return entry.fired ? <code>{entry.fired}</code> : 'handled';\n}\n\nexport function TraceTable({ entries, live, now, showHandled, showUnhandled, empty }: TraceTableProps): ReactElement {\n const [expanded, setExpanded] = useState<ReadonlySet<string>>(new Set());\n\n const rows = withTsIds(entries)\n .filter(({ entry: e }) => (e.kind === 'mode' || e.outcome === 'handled' ? showHandled : showUnhandled))\n .slice(-DISPLAY_LIMIT)\n .reverse();\n if (live) rows.unshift({ id: LIVE_ID, entry: live });\n\n const columns: readonly DataGridColumn<TraceRow>[] = [\n {\n id: 'age',\n header: 'Age',\n sortable: false,\n className: s.age,\n render: ({ id, entry }) => (id === LIVE_ID ? 'live' : formatAge(Math.max(0, now - entry.ts))),\n },\n { id: 'event', header: 'Event', sortable: false, render: ({ entry }) => renderEvent(entry) },\n { id: 'outcome', header: 'Outcome', sortable: false, render: ({ entry }) => renderOutcome(entry) },\n {\n id: 'matched',\n header: 'Matched',\n sortable: false,\n className: s.count,\n render: ({ entry }) => (entry.kind === 'mode' ? '—' : entry.matched.length),\n },\n ];\n\n return (\n <DataGrid\n className={s.table}\n rows={rows}\n columns={columns}\n empty={empty}\n rowClassName={({ id, entry }) => (id === LIVE_ID\n ? s.live\n : entry.kind === 'mode' ? s.mode : entry.outcome === 'unhandled' ? s.unhandled : undefined)}\n rowExpandable={({ entry }) => entry.kind === 'dispatch'}\n expandedIds={expanded}\n onExpandedChange={setExpanded}\n onRowClick={({ id, entry }) => {\n if (entry.kind !== 'dispatch') return;\n setExpanded((cur) => (cur.has(id) ? new Set() : new Set([id])));\n }}\n renderDetail={({ entry }) => (entry.kind === 'dispatch'\n ? <div className={s.detail}><DecisionPath record={entry} /><FallthroughDiagram record={entry} /></div>\n : null)}\n />\n );\n}\n",".dispatch {\n display: flex;\n flex-direction: column;\n flex: 1 1 auto;\n min-height: 0;\n}\n\n.toolbar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wzl-space-4);\n padding: var(--wzl-space-2) var(--wzl-space-4);\n border-bottom: 1px solid var(--wzl-line-subtle);\n flex-shrink: 0;\n}\n\n/* Last in the row and pushed to its end, so its changing width displaces nothing. */\n.count {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n margin-inline-start: auto;\n color: var(--wzl-fg-muted);\n white-space: nowrap;\n}\n\n.body {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n padding: var(--wzl-space-4);\n}\n","/**\n * The Dispatch tab: the root's trace of resolved inputs and mode switches,\n * what a press at the pointer would do now, and, behind a toggle, the\n * `clientToWorld` conversions. Read through cursors, so each read carries only\n * what is new; polled while open, because the live prediction moves with the\n * pointer and no notice reports that.\n */\nimport { useEffect, useMemo, useState, type ReactElement } from 'react';\nimport type { DispatchRecord, TraceLogEntry } from '@weasel-js/core/routing';\nimport { Button } from '@weasel-js/ui/components/Button';\nimport { Switch } from '@weasel-js/ui/components/Switch';\nimport { ToggleBar } from '@weasel-js/ui/components/ToggleBar';\nimport { usePoll } from '../hooks';\nimport type { DevtoolsViewProps } from '../tabs';\nimport { followTrace } from '../trace';\nimport { CoordTable, type CoordEntry } from './CoordTable';\nimport { TraceTable } from './TraceTable';\nimport s from './DispatchView.module.css';\n\ntype Outcome = 'handled' | 'unhandled';\n\nconst POLL_MS = 250;\n/** How many records the panel keeps, as many as a canvas's own buffer holds. */\nconst KEEP = 200;\n\nexport function DispatchView({ client, rootId }: DevtoolsViewProps): ReactElement {\n const follower = useMemo(() => followTrace(client, rootId), [client, rootId]);\n const [entries, setEntries] = useState<TraceLogEntry[]>([]);\n const [coords, setCoords] = useState<CoordEntry[]>([]);\n const [live, setLive] = useState<DispatchRecord | null>(null);\n const [now, setNow] = useState(() => Date.now());\n // Unhandled inputs are every idle pointer move and every wheel over chrome, so they start hidden.\n const [shown, setShown] = useState<readonly Outcome[]>(['handled']);\n const [showCoords, setShowCoords] = useState(false);\n\n const read = (): void => {\n follower.read().then((slice) => {\n if (slice.entries.length) setEntries((prev) => [...prev, ...(slice.entries as unknown as TraceLogEntry[])].slice(-KEEP));\n if (slice.coords?.length) setCoords((prev) => [...prev, ...(slice.coords as unknown as CoordEntry[])].slice(-KEEP));\n setLive(slice.live as unknown as DispatchRecord | null);\n setNow(Date.now());\n }, () => {});\n };\n\n useEffect(() => client.onChanged((id, areas) => {\n if (id === rootId && areas.includes('trace')) read();\n }));\n usePoll(read, POLL_MS, true);\n\n const toggleCoords = (on: boolean): void => {\n follower.setCoords(on);\n setShowCoords(on);\n if (!on) setCoords([]);\n };\n\n return (\n <div className={s.dispatch}>\n <div className={s.toolbar}>\n <ToggleBar<Outcome>\n mode=\"multiple\"\n variant=\"minimal\"\n size=\"sm\"\n ariaLabel=\"Outcome filters\"\n items={[\n { value: 'handled', label: 'handled', tooltip: 'Show handled inputs and mode switches' },\n { value: 'unhandled', label: 'unhandled', tooltip: 'Show inputs nothing handled' },\n ]}\n value={shown}\n onChange={(next) => setShown(next)}\n />\n <Switch isSelected={showCoords} onChange={toggleCoords}>coords</Switch>\n <Button size=\"sm\" variant=\"ghost\" disabled={entries.length === 0} onClick={() => setEntries([])}>\n Clear\n </Button>\n <span className={s.count}>{entries.length} {entries.length === 1 ? 'record' : 'records'}</span>\n </div>\n <div className={s.body}>\n <TraceTable\n entries={entries}\n live={live}\n now={now}\n showHandled={shown.includes('handled')}\n showUnhandled={shown.includes('unhandled')}\n empty={entries.length > 0\n ? 'Every record is hidden by the filters above.'\n : 'No input yet. Use the canvas to fill the trace.'}\n />\n {showCoords && <CoordTable entries={coords} now={now} />}\n </div>\n </div>\n );\n}\n",".value {\n font-family: var(--wzl-font-mono);\n font-size: var(--wzl-font-size-sm);\n line-height: 1.5;\n min-width: 0;\n}\n\n.row {\n display: flex;\n align-items: center;\n gap: var(--wzl-space-2);\n min-height: 1.5em;\n white-space: nowrap;\n}\n\n.children {\n padding-inline-start: var(--wzl-space-8);\n}\n\n.key {\n color: var(--wzl-fg-muted);\n}\n\n.key::after {\n content: ':';\n}\n\n.muted {\n color: var(--wzl-fg-muted);\n font-style: italic;\n}\n\n.keyword {\n color: var(--wzl-accent-fg);\n}\n\n.number {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n color: var(--wzl-accent-fg);\n}\n\n.string {\n color: var(--wzl-success);\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.fn {\n color: var(--wzl-warning);\n}\n\n.tag {\n color: var(--wzl-fg);\n}\n","/** A serialized value as a reader expects to see it: tagged maps, sets and typed arrays named, functions and cycles marked. */\nimport { useState, type ReactElement, type ReactNode } from 'react';\nimport type { SerializedValue } from '@weasel-js/core/devtools-protocol';\nimport { Disclosure } from '@weasel-js/ui/components/Disclosure';\nimport s from './ValueView.module.css';\n\ntype Obj = { [key: string]: SerializedValue };\n\nconst isObj = (v: SerializedValue): v is Obj => typeof v === 'object' && v !== null && !Array.isArray(v);\n\n/** The children a container lists, or null for a value shown on one line. */\nfunction entriesOf(v: SerializedValue): [string, SerializedValue][] | null {\n if (Array.isArray(v)) return v.map((x, i) => [String(i), x]);\n if (!isObj(v)) return null;\n if (v.$type === 'Map' || v.$type === 'Set') {\n const items = Array.isArray(v.entries) ? v.entries : [];\n return items.map((x, i) => [String(i), x]);\n }\n if (typeof v.$type === 'string') return null;\n return Object.entries(v).filter(([k]) => k !== '$class');\n}\n\n/** What a container is called on its own row: `Array(3)`, `Map(2)`, `Path {…}`. */\nfunction summaryOf(v: SerializedValue): string {\n if (Array.isArray(v)) return `Array(${v.length})`;\n if (!isObj(v)) return '';\n if (v.$type === 'Map' || v.$type === 'Set') return `${v.$type}(${String(v.size)})`;\n const name = typeof v.$class === 'string' ? v.$class : '';\n return Object.keys(v).length === 0 ? `${name}{}` : `${name ? `${name} ` : ''}{…}`;\n}\n\nfunction Scalar({ value }: { value: SerializedValue }): ReactElement {\n if (value === undefined) return <span className={s.muted}>undefined</span>;\n if (value === null) return <span className={s.keyword}>null</span>;\n if (typeof value === 'number') return <span className={s.number}>{value}</span>;\n if (typeof value === 'boolean') return <span className={s.keyword}>{String(value)}</span>;\n if (typeof value === 'string') {\n if (value.startsWith('ƒ ')) return <span className={s.fn}>{value}</span>;\n if (value === '[cycle]' || value === '…' || value.startsWith('… ')) return <span className={s.muted}>{value}</span>;\n return <span className={s.string}>{JSON.stringify(value)}</span>;\n }\n if (isObj(value) && value.$type === 'Date') return <span className={s.tag}>Date {String(value.value)}</span>;\n if (isObj(value) && typeof value.$type === 'string') {\n return <span className={s.tag}>{value.$type}({String(value.length)})</span>;\n }\n return <span className={s.muted}>{summaryOf(value)}</span>;\n}\n\nfunction Entry({ name, value, depth }: { name: ReactNode; value: SerializedValue; depth: number }): ReactElement {\n const entries = entriesOf(value);\n const [open, setOpen] = useState(depth < 2);\n if (!entries || entries.length === 0) {\n return (\n <div className={s.row}>\n <span className={s.key}>{name}</span>\n <Scalar value={value} />\n </div>\n );\n }\n return (\n <div>\n <div className={s.row}>\n <Disclosure open={open} onToggle={() => setOpen((o) => !o)} label={`${String(name)} ${summaryOf(value)}`} size={11} />\n <span className={s.key}>{name}</span>\n <span className={s.muted}>{summaryOf(value)}</span>\n </div>\n {open && (\n <div className={s.children}>\n {entries.map(([k, v]) => <Entry key={k} name={k} value={v} depth={depth + 1} />)}\n </div>\n )}\n </div>\n );\n}\n\nexport interface ValueViewProps {\n value: SerializedValue;\n /** Names the value for a screen reader. */\n label: string;\n}\n\n/** `value` as nested rows, its containers folding; the top level lists its entries directly. */\nexport function ValueView({ value, label }: ValueViewProps): ReactElement {\n const entries = entriesOf(value);\n return (\n <div className={s.value} role=\"group\" aria-label={label}>\n {entries && entries.length > 0\n ? entries.map(([k, v]) => <Entry key={k} name={k} value={v} depth={1} />)\n : <Scalar value={value} />}\n </div>\n );\n}\n",".frame {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n padding: var(--wzl-space-4);\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-6);\n}\n\n.figure {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n text-align: end;\n white-space: pre;\n}\n\n.layers {\n font-family: var(--wzl-font-mono);\n}\n\n.note {\n margin: 0;\n color: var(--wzl-fg-muted);\n}\n","/**\n * The Frame tab: what the last paint cost, overall and per render layer. The\n * canvas measures only while its `fps` overlay is on and announces nothing, so\n * this polls, and only while the tab is open and the overlay on.\n */\nimport { useState, type ReactElement } from 'react';\nimport type { FrameStats } from '@weasel-js/core';\nimport type { SerializedValue } from '@weasel-js/core/devtools-protocol';\nimport { DataGrid, type DataGridColumn } from '@weasel-js/ui/components/DataGrid';\nimport { DetailList, DetailRow } from '@weasel-js/ui/components/DetailList';\nimport { Switch } from '@weasel-js/ui/components/Switch';\nimport { usePoll, useRootQuery } from '../hooks';\nimport type { DevtoolsViewProps } from '../tabs';\nimport { ValueView } from './ValueView';\nimport s from './FrameView.module.css';\n\nconst POLL_MS = 500;\n\nconst isFrameStats = (v: SerializedValue): v is SerializedValue & FrameStats =>\n typeof v === 'object' && v !== null && !Array.isArray(v) && typeof v.paintMs === 'number' && Array.isArray(v.layers);\n\nconst ms = (n: number): string => n.toFixed(2).padStart(7, ' ');\n\ntype LayerRow = FrameStats['layers'][number];\n\nconst COLUMNS: readonly DataGridColumn<LayerRow>[] = [\n { id: 'id', header: 'Layer', sortable: false, render: (r) => r.id },\n { id: 'calls', header: 'Draw calls', sortable: false, className: s.figure, render: (r) => r.drawCalls },\n { id: 'ms', header: 'CPU ms', sortable: false, className: s.figure, render: (r) => ms(r.ms) },\n];\n\nexport function FrameView({ client, rootId }: DevtoolsViewProps): ReactElement {\n const state = useRootQuery(client, rootId, [], () => client.request(rootId, { type: 'get-state' }));\n const fps = state.data?.overlays.fps === true;\n const [frame, setFrame] = useState<SerializedValue>(null);\n usePoll(() => {\n client.request(rootId, { type: 'get-frame' }).then(setFrame, () => {});\n }, POLL_MS, fps);\n\n const setFps = (on: boolean): void => {\n client.request(rootId, { type: 'set-overlays', overlays: { fps: on } }).then(state.refresh, state.refresh);\n };\n\n return (\n <div className={s.frame}>\n <Switch isSelected={fps} onChange={setFps} isDisabled={!state.data}>fps overlay</Switch>\n {!fps ? (\n <p className={s.note}>The canvas measures its paints only while the fps overlay is on.</p>\n ) : isFrameStats(frame) ? (\n <>\n <DetailList layout=\"inline\" values=\"figures\">\n <DetailRow label=\"CPU ms\">{ms(frame.paintMs)}</DetailRow>\n <DetailRow label=\"Draw calls\">{frame.drawCalls}</DetailRow>\n </DetailList>\n <DataGrid className={s.layers} rows={frame.layers.map((l) => ({ ...l }))} columns={COLUMNS} empty=\"No layers painted.\" />\n </>\n ) : frame === null ? (\n <p className={s.note}>No paint measured yet.</p>\n ) : (\n <ValueView value={frame} label=\"Frame\" />\n )}\n </div>\n );\n}\n",".history {\n display: flex;\n flex-direction: column;\n flex: 1 1 auto;\n min-height: 0;\n}\n\n.toolbar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wzl-space-4);\n padding: var(--wzl-space-2) var(--wzl-space-4);\n border-bottom: 1px solid var(--wzl-line-subtle);\n flex-shrink: 0;\n}\n\n/* Last in the row and pushed to its end, so its changing width displaces nothing. */\n.position {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n margin-inline-start: auto;\n color: var(--wzl-fg-muted);\n white-space: nowrap;\n}\n\n.body {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n padding: var(--wzl-space-4);\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-6);\n}\n\n.heading {\n margin: 0 0 var(--wzl-space-3);\n font-size: var(--wzl-font-size-sm);\n font-weight: var(--wzl-font-weight-bold);\n}\n\n.stack {\n margin: 0;\n padding-inline-start: var(--wzl-space-8);\n font-family: var(--wzl-font-mono);\n}\n\n.applied {\n color: var(--wzl-fg);\n}\n\n.redoable {\n color: var(--wzl-fg-muted);\n font-style: italic;\n}\n\n.table {\n font-family: var(--wzl-font-mono);\n}\n\n/* Age is live, variable-length text in the leading column: a fixed width keeps\n ticking values from shifting the columns after it. */\n.age {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n width: 7ch;\n min-width: 7ch;\n text-align: end;\n white-space: nowrap;\n}\n\n.figure {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n text-align: end;\n white-space: nowrap;\n}\n\n.entries {\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-4);\n}\n\n.entry {\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-2);\n}\n\n.entryTitle {\n margin: 0;\n display: flex;\n gap: var(--wzl-space-4);\n font-size: var(--wzl-font-size-sm);\n}\n\n.ops {\n margin: 0;\n padding: 0;\n list-style: none;\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-2);\n}\n\n.op {\n display: grid;\n grid-template-columns: auto auto minmax(0, 1fr);\n gap: var(--wzl-space-4);\n align-items: start;\n}\n\n.targets {\n color: var(--wzl-fg-muted);\n}\n\n.note {\n margin: 0;\n color: var(--wzl-fg-muted);\n}\n","/** History steps as rows, newest first; a row opens to the entries it touched and each entry's ops. */\nimport { useState, type ReactElement } from 'react';\nimport type { DevtoolsHistoryRecord } from '@weasel-js/core/devtools-protocol';\nimport { Code } from '@weasel-js/ui/components/Code';\nimport { DataGrid, type DataGridColumn } from '@weasel-js/ui/components/DataGrid';\nimport { formatAge } from './formatAge';\nimport { ValueView } from './ValueView';\nimport s from './HistoryView.module.css';\n\nconst DISPLAY_LIMIT = 100;\n\ninterface StepRow { id: string; step: DevtoolsHistoryRecord }\n\nconst opCount = (step: DevtoolsHistoryRecord): number => step.entries.reduce((n, e) => n + e.opCount, 0);\n\nfunction StepDetail({ step }: { step: DevtoolsHistoryRecord }): ReactElement {\n return (\n <div className={s.entries}>\n {step.entries.map((entry) => (\n <section key={entry.id} className={s.entry} aria-label={`Entry ${entry.label || entry.id}`}>\n <h4 className={s.entryTitle}>\n {entry.label || <span className={s.note}>unlabeled</span>}\n <span className={s.figure}>{entry.opCount} {entry.opCount === 1 ? 'op' : 'ops'}</span>\n </h4>\n <ul className={s.ops}>\n {entry.ops.map((op, i) => (\n <li key={i} className={s.op}>\n <Code size=\"sm\">{op.kind}</Code>\n {op.targets.length > 0 && <span className={s.targets}>{op.targets.join(', ')}</span>}\n <ValueView value={op.summary} label={`${op.kind} arguments`} />\n </li>\n ))}\n </ul>\n </section>\n ))}\n </div>\n );\n}\n\nexport function HistoryTable({ steps, now }: { steps: readonly DevtoolsHistoryRecord[]; now: number }): ReactElement {\n const [expanded, setExpanded] = useState<ReadonlySet<string>>(new Set());\n const rows: StepRow[] = steps.map((step, i) => ({ id: `${step.ts}-${i}`, step })).slice(-DISPLAY_LIMIT).reverse();\n const columns: readonly DataGridColumn<StepRow>[] = [\n { id: 'age', header: 'Age', sortable: false, className: s.age, render: ({ step }) => formatAge(Math.max(0, now - step.ts)) },\n { id: 'step', header: 'Step', sortable: false, render: ({ step }) => step.step },\n {\n id: 'entries',\n header: 'Entries',\n sortable: false,\n render: ({ step }) => step.entries.map((e) => e.label || `#${e.id}`).join(', ') || '—',\n },\n { id: 'ops', header: 'Ops', sortable: false, className: s.figure, render: ({ step }) => opCount(step) },\n {\n id: 'position',\n header: 'Position',\n sortable: false,\n className: s.figure,\n render: ({ step }) => `${step.position.index} / ${step.position.total}`,\n },\n ];\n return (\n <DataGrid\n className={s.table}\n rows={rows}\n columns={columns}\n empty=\"No history steps yet. Edit the scene to fill the log.\"\n rowExpandable={({ step }) => step.entries.length > 0}\n expandedIds={expanded}\n onExpandedChange={setExpanded}\n onRowClick={({ id }) => setExpanded((cur) => (cur.has(id) ? new Set() : new Set([id])))}\n renderDetail={({ step }) => <StepDetail step={step} />}\n />\n );\n}\n","/**\n * The History tab: each step the scene's history took, newest first, read\n * through its cursor whenever a notice reports one; where the history stands;\n * and, on request, every entry on its stacks.\n */\nimport { useEffect, useMemo, useState, type ReactElement } from 'react';\nimport type { DevtoolsHistoryRecord, DevtoolsHistorySlice } from '@weasel-js/core/devtools-protocol';\nimport { Badge } from '@weasel-js/ui/components/Badge';\nimport { Button } from '@weasel-js/ui/components/Button';\nimport { Switch } from '@weasel-js/ui/components/Switch';\nimport type { DevtoolsViewProps } from '../tabs';\nimport { followHistory } from '../history';\nimport { HistoryTable } from './HistoryTable';\nimport s from './HistoryView.module.css';\n\n/** As many steps as a canvas's own buffer holds. */\nconst KEEP = 200;\n\nexport function HistoryView({ client, rootId }: DevtoolsViewProps): ReactElement {\n const follower = useMemo(() => followHistory(client, rootId), [client, rootId]);\n const [steps, setSteps] = useState<DevtoolsHistoryRecord[]>([]);\n const [position, setPosition] = useState<DevtoolsHistorySlice['position'] | null>(null);\n const [checkpoints, setCheckpoints] = useState<DevtoolsHistorySlice['checkpoints'] | null>(null);\n const [showStack, setShowStack] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [now, setNow] = useState(() => Date.now());\n\n useEffect(() => {\n let live = true;\n const read = (): void => {\n follower.read().then((slice) => {\n if (!live) return;\n if (slice.entries.length) setSteps((prev) => [...prev, ...slice.entries].slice(-KEEP));\n setPosition(slice.position);\n setCheckpoints(slice.checkpoints ?? null);\n setNow(Date.now());\n setError(null);\n }, (err: Error) => { if (live) setError(err.message); });\n };\n read();\n const off = client.onChanged((id, areas) => { if (id === rootId && areas.includes('history')) read(); });\n return () => { live = false; off(); };\n }, [client, rootId, follower, showStack]);\n\n const toggleStack = (on: boolean): void => {\n follower.setCheckpoints(on);\n setShowStack(on);\n };\n\n if (error) return <p className={s.note}>{error}</p>;\n\n return (\n <div className={s.history}>\n <div className={s.toolbar}>\n <Badge size=\"sm\" variant=\"subtle\" emphasis={position?.canUndo ? 'high' : 'low'}>\n {position?.canUndo ? 'can undo' : 'nothing to undo'}\n </Badge>\n <Badge size=\"sm\" variant=\"subtle\" emphasis={position?.canRedo ? 'high' : 'low'}>\n {position?.canRedo ? 'can redo' : 'nothing to redo'}\n </Badge>\n <Switch isSelected={showStack} onChange={toggleStack}>checkpoints</Switch>\n <Button size=\"sm\" variant=\"ghost\" disabled={steps.length === 0} onClick={() => setSteps([])}>Clear</Button>\n <span className={s.position} role=\"status\" aria-label=\"Position\" title=\"entries applied / entries in all\">\n {position ? `${position.index} / ${position.total}` : ''}\n </span>\n </div>\n <div className={s.body}>\n {showStack && checkpoints && (\n <section aria-label=\"Checkpoint stack\">\n <h3 className={s.heading}>Checkpoints</h3>\n {checkpoints.length === 0 ? <p className={s.note}>The stacks are empty.</p> : (\n <ol className={s.stack} aria-label=\"Checkpoints\">\n {checkpoints.map((c, i) => (\n <li key={c.id} className={position && i < position.index ? s.applied : s.redoable}>\n {c.label || c.id}\n </li>\n ))}\n </ol>\n )}\n </section>\n )}\n <HistoryTable steps={steps} now={now} />\n </div>\n </div>\n );\n}\n",".split {\n display: grid;\n grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);\n flex: 1 1 auto;\n min-height: 0;\n}\n\n.listPane,\n.detailPane {\n min-height: 0;\n min-width: 0;\n overflow: auto;\n padding: var(--wzl-space-4);\n}\n\n.listPane {\n --wzl-tree-selected: color-mix(in srgb, var(--wzl-accent) 28%, transparent);\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-4);\n border-inline-end: 1px solid var(--wzl-line-subtle);\n}\n\n/* Narrow: the list above the detail, each scrolling on its own. */\n@container (width < 480px) {\n .split {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);\n }\n\n .listPane {\n border-inline-end: none;\n border-block-end: 1px solid var(--wzl-line-subtle);\n }\n}\n","/**\n * A registry as a filterable tree of categories beside the entry picked. The\n * host supplies the categories and renders the detail, so the same screen\n * shows a live canvas's tools, actions and deps or an app's static catalog.\n */\nimport { useEffect, useMemo, useRef, useState, type ReactElement, type ReactNode } from 'react';\nimport { Badge } from '@weasel-js/ui/components/Badge';\nimport { Input } from '@weasel-js/ui/components/Input';\nimport { Tree, filterTree, treeBranchIds, type TreeNode } from '@weasel-js/ui/components/Tree';\nimport s from './RegistryBrowser.module.css';\n\n/** One entry of a {@link RegistryCategory}. */\nexport interface RegistryBrowserEntry {\n /** Unique within its category. */\n id: string;\n label: string;\n /** Further text the filter matches, besides `label`. */\n match?: readonly string[];\n /** Shown at the end of the entry's row: a count, a scope, a state. */\n trailing?: ReactNode;\n}\n\n/** A branch of the {@link RegistryBrowser} tree. Categories sharing a `group.id` nest under one parent branch. */\nexport interface RegistryCategory {\n id: string;\n label: string;\n group?: { id: string; label: string };\n entries: readonly RegistryBrowserEntry[];\n}\n\n/** An entry, by its category and its id there. */\nexport interface RegistryBrowserPick {\n category: string;\n id: string;\n}\n\n/** Props for {@link RegistryBrowser}. */\nexport interface RegistryBrowserProps {\n /** In display order: the browser sorts nothing. */\n categories: readonly RegistryCategory[];\n selected: RegistryBrowserPick | null;\n onSelect(pick: RegistryBrowserPick): void;\n /** The picked entry's detail, or what to show with nothing picked. */\n detail: ReactNode;\n /** Category ids open at mount. Default none. */\n defaultOpen?: Iterable<string>;\n /** Controlled filter text. Omit both to let the browser hold it. */\n filter?: string;\n onFilterChange?(next: string): void;\n /** A leading glyph for the filter field. */\n filterIcon?: ReactNode;\n className?: string;\n}\n\nconst categoryKey = (id: string) => `cat:${id}`;\nconst groupKey = (id: string) => `group:${id}`;\nconst leafKey = (category: string, id: string) => `${category}/${id}`;\n\nconst countBadge = (count: number, className?: string) => (\n <Badge className={className} shape=\"pill\" size=\"sm\" variant=\"solid\">{count}</Badge>\n);\n\nfunction treeOf(categories: readonly RegistryCategory[]) {\n const picks = new Map<string, RegistryBrowserPick>();\n const texts = new Map<string, string[]>();\n const out: TreeNode[] = [];\n const groups = new Map<string, TreeNode & { children: TreeNode[] }>();\n for (const c of categories) {\n const branch: TreeNode = {\n id: categoryKey(c.id),\n label: c.label,\n trailing: countBadge(c.entries.length),\n children: c.entries.map((e) => {\n const key = leafKey(c.id, e.id);\n picks.set(key, { category: c.id, id: e.id });\n texts.set(key, [e.label, ...(e.match ?? [])].map((t) => t.toLowerCase()));\n return { id: key, label: e.label, textValue: e.label, trailing: e.trailing };\n }),\n };\n if (!c.group) {\n out.push(branch);\n continue;\n }\n let group = groups.get(c.group.id);\n if (!group) {\n group = { id: groupKey(c.group.id), label: c.group.label, children: [] };\n groups.set(c.group.id, group);\n out.push(group);\n }\n group.children.push(branch);\n }\n for (const group of groups.values()) group.trailing = countBadge(group.children.length);\n return { nodes: out, picks, texts };\n}\n\n/**\n * A filter field over a tree of registry categories, beside a detail pane.\n * Filtering opens every branch with a match; clearing it restores what was\n * open. Picking an entry from outside the tree opens its category.\n */\nexport function RegistryBrowser(props: RegistryBrowserProps): ReactElement {\n const { categories, selected, onSelect, detail, filterIcon, className } = props;\n const [ownFilter, setOwnFilter] = useState('');\n const filter = props.filter ?? ownFilter;\n const setFilter = props.onFilterChange ?? setOwnFilter;\n const [openIds, setOpenIds] = useState<ReadonlySet<string>>(\n () => new Set([...(props.defaultOpen ?? [])].map(categoryKey)),\n );\n\n // Open the selection's category when the selection moves into it, and only then, so it can still be closed.\n const selectedCategory = selected ? categories.find((c) => c.id === selected.category) ?? null : null;\n const [openedFor, setOpenedFor] = useState<string | null>(null);\n if ((selectedCategory?.id ?? null) !== openedFor) {\n setOpenedFor(selectedCategory?.id ?? null);\n if (selectedCategory) {\n const ids = [categoryKey(selectedCategory.id), ...(selectedCategory.group ? [groupKey(selectedCategory.group.id)] : [])];\n setOpenIds((cur) => (ids.every((id) => cur.has(id)) ? cur : new Set([...cur, ...ids])));\n }\n }\n\n const { nodes, picks, texts } = useMemo(() => treeOf(categories), [categories]);\n const q = filter.trim().toLowerCase();\n const shown = useMemo(\n () => (q ? filterTree(nodes, (n) => texts.get(n.id)?.some((t) => t.includes(q)) ?? false) : nodes),\n [nodes, texts, q],\n );\n const selectedIds = selected ? [leafKey(selected.category, selected.id)] : [];\n\n const treeRef = useRef<HTMLUListElement | null>(null);\n useEffect(() => {\n treeRef.current?.querySelector('[aria-selected=\"true\"]')?.scrollIntoView?.({ block: 'nearest' });\n }, [selected?.category, selected?.id]);\n\n return (\n <div className={[s.split, className].filter(Boolean).join(' ')}>\n <div className={s.listPane} data-pane=\"list\">\n <Input\n aria-label=\"Filter registry\"\n placeholder=\"Filter…\"\n leadingAdornment={filterIcon}\n value={filter}\n onChange={setFilter}\n />\n <Tree\n ref={treeRef}\n aria-label=\"Registry\"\n nodes={shown}\n empty=\"No matches\"\n expandedIds={q ? treeBranchIds(shown) : openIds}\n onExpandedChange={q ? undefined : setOpenIds}\n selectionMode=\"single\"\n selectedIds={selectedIds}\n onAction={(id) => {\n const pick = picks.get(id);\n if (pick) onSelect(pick);\n }}\n />\n </div>\n <div className={s.detailPane} data-pane=\"detail\">{detail}</div>\n </div>\n );\n}\n",".count {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n color: var(--wzl-fg-muted);\n font-weight: normal;\n}\n\n.facts {\n color: var(--wzl-fg-muted);\n font-size: var(--wzl-font-size-xs);\n}\n\n.detail,\n.section {\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-4);\n}\n\n.title,\n.heading {\n margin: 0;\n display: flex;\n align-items: baseline;\n gap: var(--wzl-space-3);\n font-size: var(--wzl-font-size-sm);\n font-weight: var(--wzl-font-weight-bold);\n}\n\n.heading {\n margin-block-start: var(--wzl-space-4);\n}\n\n.codes {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wzl-space-2);\n}\n\n.bindings {\n margin: 0;\n padding: 0;\n list-style: none;\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-3);\n}\n\n.binding {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wzl-space-3);\n}\n\n.routes {\n display: inline-flex;\n flex-wrap: wrap;\n gap: var(--wzl-space-2);\n}\n\n.arrow {\n color: var(--wzl-fg-muted);\n}\n\n.kinds {\n margin: var(--wzl-space-6) 0 0;\n color: var(--wzl-fg-muted);\n font-size: var(--wzl-font-size-xs);\n}\n\n.note {\n margin: 0;\n color: var(--wzl-fg-muted);\n}\n","/** An entry's gesture bindings: each route drawn in the route grammar, beside the action it reaches. */\nimport type { ReactElement } from 'react';\nimport type { DevtoolsBinding } from '@weasel-js/core/devtools-protocol';\nimport { Code } from '@weasel-js/ui/components/Code';\nimport { GestureRoute } from '@weasel-js/ui/components/GestureRoute';\nimport { ValueView } from './ValueView';\nimport s from './RegistryView.module.css';\n\nconst hasOpts = (b: DevtoolsBinding): boolean =>\n typeof b.opts === 'object' && b.opts !== null && Object.keys(b.opts).length > 0;\n\nexport function Bindings({ bindings }: { bindings: readonly DevtoolsBinding[] }): ReactElement {\n return (\n <section className={s.section} aria-label=\"Bindings\">\n <h3 className={s.heading}>Bindings <span className={s.count}>{bindings.length}</span></h3>\n {bindings.length === 0 ? <p className={s.note}>None.</p> : (\n <ul className={s.bindings}>\n {bindings.map((b, i) => (\n <li key={i} className={s.binding}>\n <span className={s.routes}>\n {b.routes.length > 0\n ? b.routes.map((r) => <GestureRoute key={r} route={r} size=\"sm\" />)\n : <ValueView value={b.spec} label=\"Spec\" />}\n </span>\n <span className={s.arrow} aria-hidden>→</span>\n <Code size=\"sm\">{b.actionId}</Code>\n {hasOpts(b) && <ValueView value={b.opts} label={`Options for ${b.actionId}`} />}\n </li>\n ))}\n </ul>\n )}\n </section>\n );\n}\n","/** One registry entry in full: a tool, an action, or a dep. */\nimport type { ReactElement, ReactNode } from 'react';\nimport type { DevtoolsActionEntry, DevtoolsDepEntry, DevtoolsRegistry, DevtoolsToolEntry } from '@weasel-js/core/devtools-protocol';\nimport { Code } from '@weasel-js/ui/components/Code';\nimport { DetailList, DetailRow } from '@weasel-js/ui/components/DetailList';\nimport { Bindings } from './Bindings';\nimport { ValueView } from './ValueView';\nimport s from './RegistryView.module.css';\n\nexport interface RegistryPick {\n category: 'tools' | 'actions' | 'deps';\n id: string;\n}\n\nconst yesNo = (v: boolean): string => (v ? 'yes' : 'no');\nconst codes = (ids: readonly string[]): ReactNode =>\n ids.length ? <span className={s.codes}>{ids.map((id) => <Code key={id} size=\"sm\">{id}</Code>)}</span> : null;\n\nfunction ToolDetail({ tool }: { tool: DevtoolsToolEntry }): ReactElement {\n return (\n <section className={s.detail} aria-label={`Tool ${tool.id}`}>\n <h3 className={s.title}><Code size=\"sm\">{tool.id}</Code></h3>\n <DetailList layout=\"inline\">\n <DetailRow label=\"Slot\">{tool.slot}</DetailRow>\n <DetailRow label=\"Label\">{tool.label}</DetailRow>\n <DetailRow label=\"Group\">{tool.group}</DetailRow>\n <DetailRow label=\"Icon\">{tool.icon}</DetailRow>\n <DetailRow label=\"Shortcut\">{tool.shortcut}</DetailRow>\n <DetailRow label=\"Hotkey\">{tool.hotkey}</DetailRow>\n <DetailRow label=\"Hidden\">{yesNo(tool.hidden)}</DetailRow>\n <DetailRow label=\"Overlay\">{yesNo(tool.hasOverlay)}</DetailRow>\n <DetailRow label=\"Actions\">{codes(tool.actions)}</DetailRow>\n <DetailRow label=\"Deps\">{codes(tool.deps)}</DetailRow>\n </DetailList>\n <Bindings bindings={tool.bindings} />\n <h3 className={s.heading}>Cursor</h3>\n <ValueView value={tool.cursor} label=\"Cursor\" />\n <h3 className={s.heading}>Eligibility</h3>\n <ValueView value={tool.eligibility} label=\"Eligibility\" />\n </section>\n );\n}\n\nfunction ActionDetail({ action }: { action: DevtoolsActionEntry }): ReactElement {\n return (\n <section className={s.detail} aria-label={`Action ${action.id}`}>\n <h3 className={s.title}><Code size=\"sm\">{action.id}</Code></h3>\n <DetailList layout=\"inline\">\n <DetailRow label=\"Label\">{action.label}</DetailRow>\n <DetailRow label=\"Enabled\" grade={action.enabled === true ? 'success' : 'warn'}>\n {action.enabled === true ? 'yes' : action.enabled}\n </DetailRow>\n <DetailRow label=\"Active\">{action.active === null ? 'no pressed state' : yesNo(action.active)}</DetailRow>\n <DetailRow label=\"Scope\">{action.scope}</DetailRow>\n <DetailRow label=\"Invoker\">{action.invoker}</DetailRow>\n <DetailRow label=\"Group\">{action.group}</DetailRow>\n <DetailRow label=\"Tags\">{codes(action.tags)}</DetailRow>\n <DetailRow label=\"Shortcut\">{action.shortcut}</DetailRow>\n <DetailRow label=\"Requires\">{codes(action.requires)}</DetailRow>\n <DetailRow label=\"Preview\">{yesNo(action.hasPreview)}</DetailRow>\n <DetailRow label=\"Variants\">{codes(action.variants.map((v) => v.key))}</DetailRow>\n </DetailList>\n <Bindings bindings={action.bindings} />\n <h3 className={s.heading}>Eligible</h3>\n {action.eligible === null ? <p className={s.note}>Always.</p> : <ValueView value={action.eligible} label=\"Eligible\" />}\n </section>\n );\n}\n\nfunction DepDetail({ dep, users }: { dep: DevtoolsDepEntry; users: string[] }): ReactElement {\n return (\n <section className={s.detail} aria-label={`Dep ${dep.name}`}>\n <h3 className={s.title}><Code size=\"sm\">{dep.name}</Code></h3>\n <DetailList layout=\"inline\">\n <DetailRow label=\"Scope\">{dep.depth === 0 ? 'this canvas' : `${dep.depth} above`}</DetailRow>\n <DetailRow label=\"Stacked\">{dep.stacked}</DetailRow>\n <DetailRow label=\"Required by\">{codes(users)}</DetailRow>\n </DetailList>\n </section>\n );\n}\n\nexport function RegistryEntryDetail({ registry, pick }: { registry: DevtoolsRegistry; pick: RegistryPick }): ReactElement {\n if (pick.category === 'tools') {\n const tool = registry.tools.find((t) => t.id === pick.id);\n if (tool) return <ToolDetail tool={tool} />;\n } else if (pick.category === 'actions') {\n const action = registry.actions.find((a) => a.id === pick.id);\n if (action) return <ActionDetail action={action} />;\n } else {\n const dep = registry.deps.find((d) => d.name === pick.id);\n const users = registry.actions.filter((a) => a.requires.includes(pick.id)).map((a) => a.id);\n if (dep) return <DepDetail dep={dep} users={users} />;\n }\n return <p className={s.note}>{pick.id} is no longer registered.</p>;\n}\n","/**\n * The Registry tab: what the canvas has registered, filtered by name, beside\n * the entry picked. Re-read when the registry changes, and on selection and\n * scene changes too, since an action's `enabled` and `active` move with them\n * and no notice reports that.\n */\nimport { useMemo, useState, type ReactElement } from 'react';\nimport type { DevtoolsRegistry } from '@weasel-js/core/devtools-protocol';\nimport { useRootQuery } from '../hooks';\nimport type { DevtoolsViewProps } from '../tabs';\nimport { RegistryBrowser, type RegistryBrowserPick, type RegistryCategory } from './RegistryBrowser';\nimport { RegistryEntryDetail, type RegistryPick } from './RegistryEntryDetail';\nimport s from './RegistryView.module.css';\n\nconst CATEGORIES = ['tools', 'actions', 'deps'] as const;\nconst TITLES = { tools: 'Tools', actions: 'Actions', deps: 'Deps' } as const;\n\ninterface Row { id: string; facts: string }\n\nfunction rowsOf(reg: DevtoolsRegistry, category: (typeof CATEGORIES)[number]): Row[] {\n switch (category) {\n case 'tools': return reg.tools.map((t) => ({ id: t.id, facts: t.slot }));\n case 'actions': return reg.actions.map((a) => ({\n id: a.id, facts: [a.scope, a.enabled === true ? '' : 'disabled', a.active ? 'active' : ''].filter(Boolean).join(' '),\n }));\n case 'deps': return reg.deps.map((d) => ({ id: d.name, facts: d.depth === 0 ? '' : `+${d.depth}` }));\n }\n}\n\nfunction categoriesOf(reg: DevtoolsRegistry): RegistryCategory[] {\n return CATEGORIES.map((category) => ({\n id: category,\n label: TITLES[category],\n entries: rowsOf(reg, category).map((r) => ({\n id: r.id,\n label: r.id,\n ...(r.facts ? { trailing: <span className={s.facts}>{r.facts}</span> } : {}),\n })),\n }));\n}\n\nexport function RegistryView({ client, rootId }: DevtoolsViewProps): ReactElement {\n const registry = useRootQuery(\n client, rootId, ['registry', 'selection', 'scene'], () => client.request(rootId, { type: 'get-registry' }),\n );\n const [picked, setPicked] = useState<RegistryBrowserPick | null>(null);\n const reg = registry.data;\n const categories = useMemo(() => (reg ? categoriesOf(reg) : []), [reg]);\n\n if (registry.error) return <p className={s.note}>{registry.error}</p>;\n if (!reg) return <p className={s.note}>Loading…</p>;\n\n return (\n <RegistryBrowser\n categories={categories}\n defaultOpen={CATEGORIES}\n selected={picked}\n onSelect={setPicked}\n detail={\n <>\n {picked\n ? <RegistryEntryDetail registry={reg} pick={picked as RegistryPick} />\n : <p className={s.note}>Pick an entry to see its bindings.</p>}\n {reg.routingKinds.length > 0 && (\n <p className={s.kinds}>Routing kinds: {reg.routingKinds.join(', ')}</p>\n )}\n </>\n }\n />\n );\n}\n",".split {\n display: grid;\n grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);\n flex: 1 1 auto;\n min-height: 0;\n}\n\n.treePane,\n.detailPane {\n min-height: 0;\n min-width: 0;\n overflow: auto;\n padding: var(--wzl-space-4);\n}\n\n.treePane {\n border-inline-end: 1px solid var(--wzl-line-subtle);\n --wzl-tree-selected: color-mix(in srgb, var(--wzl-accent) 28%, transparent);\n}\n\n.facts {\n display: inline-flex;\n gap: var(--wzl-space-3);\n color: var(--wzl-fg-muted);\n font-size: var(--wzl-font-size-xs);\n}\n\n.kind,\n.layer {\n white-space: nowrap;\n}\n\n.count {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n min-width: 3ch;\n text-align: end;\n}\n\n.flag {\n color: var(--wzl-warning);\n}\n\n.detail {\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-4);\n}\n\n.detailHead {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--wzl-space-4);\n}\n\n.heading {\n margin: var(--wzl-space-4) 0 0;\n font-size: var(--wzl-font-size-sm);\n font-weight: var(--wzl-font-weight-bold);\n}\n\n.note {\n margin: 0;\n color: var(--wzl-fg-muted);\n}\n\n/* Narrow: the list above the detail, each scrolling on its own. */\n@container (width < 480px) {\n .split {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);\n }\n\n .treePane {\n border-inline-end: none;\n border-block-end: 1px solid var(--wzl-line-subtle);\n }\n}\n","/** One node as `get-node` describes it, re-read whenever the scene changes. */\nimport type { ReactElement } from 'react';\nimport { Button } from '@weasel-js/ui/components/Button';\nimport { Code } from '@weasel-js/ui/components/Code';\nimport { DetailList, DetailRow } from '@weasel-js/ui/components/DetailList';\nimport type { DevtoolsClient } from '../client';\nimport { useRootQuery } from '../hooks';\nimport { ValueView } from './ValueView';\nimport s from './SceneView.module.css';\n\nexport interface NodeDetailProps {\n client: DevtoolsClient;\n rootId: string;\n nodeId: string;\n /** Show another node: the parent, when its id is pressed. */\n onPick(nodeId: string): void;\n}\n\nconst yesNo = (v: boolean): string => (v ? 'yes' : 'no');\n\nexport function NodeDetail({ client, rootId, nodeId, onPick }: NodeDetailProps): ReactElement {\n const node = useRootQuery(client, rootId, ['scene'], () => client.request(rootId, { type: 'get-node', nodeId }));\n if (node.error) return <p className={s.note}>{node.error}</p>;\n const d = node.data;\n if (!d) return <p className={s.note}>Loading…</p>;\n return (\n <div className={s.detail}>\n <div className={s.detailHead}>\n <Code size=\"sm\">{d.id}</Code>\n <Button\n size=\"sm\"\n onClick={() => { client.request(rootId, { type: 'select', ids: [d.id] }).catch(() => {}); }}\n >\n Select on canvas\n </Button>\n </div>\n <DetailList layout=\"inline\">\n <DetailRow label=\"Kind\">{d.kind}</DetailRow>\n <DetailRow label=\"Layer\">{d.layer}</DetailRow>\n <DetailRow label=\"Parent\">\n {d.parent && (\n <Button size=\"sm\" variant=\"link\" onClick={() => onPick(d.parent!)} ariaLabel={`Show parent ${d.parent}`}>\n {d.parent}\n </Button>\n )}\n </DetailRow>\n <DetailRow label=\"Children\">{d.childCount}</DetailRow>\n <DetailRow label=\"Hidden\">{yesNo(d.hidden)}</DetailRow>\n <DetailRow label=\"Locked\">{yesNo(d.locked)}</DetailRow>\n <DetailRow label=\"Pickable\">{yesNo(d.pickable)}</DetailRow>\n </DetailList>\n <h3 className={s.heading}>Pose</h3>\n <ValueView value={d.pose} label=\"Pose\" />\n <h3 className={s.heading}>Data</h3>\n <ValueView value={d.data} label=\"Data\" />\n </div>\n );\n}\n","/** A root's scene tree, loaded a level at a time as branches open, and reloaded where it is open when the scene changes. */\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { DevtoolsNodeSummary } from '@weasel-js/core/devtools-protocol';\nimport { useLatest } from '@weasel-js/react';\nimport type { DevtoolsClient } from '../client';\n\n/** The key the top level is held under. */\nconst TOP = '';\n\nexport interface SceneTree {\n /** Each loaded level, by parent id; the top level under `''`. */\n levels: ReadonlyMap<string, readonly DevtoolsNodeSummary[]>;\n expanded: ReadonlySet<string>;\n setExpanded(ids: Set<string>): void;\n /** Why the top level could not be read, such as a scene not mounted yet. */\n error: string | null;\n}\n\nexport function useSceneTree(client: DevtoolsClient, rootId: string): SceneTree {\n const [levels, setLevels] = useState<ReadonlyMap<string, readonly DevtoolsNodeSummary[]>>(new Map());\n const [expanded, setExpandedState] = useState<ReadonlySet<string>>(new Set());\n const [error, setError] = useState<string | null>(null);\n const expandedRef = useLatest(expanded);\n const alive = useRef(true);\n useEffect(() => {\n alive.current = true;\n return () => { alive.current = false; };\n }, []);\n\n const load = useCallback((parent: string): void => {\n const body = parent === TOP ? { type: 'get-children' as const } : { type: 'get-children' as const, nodeId: parent };\n client.request(rootId, body).then(\n (rows) => {\n if (!alive.current) return;\n setLevels((prev) => new Map(prev).set(parent, rows));\n if (parent === TOP) setError(null);\n },\n (err: Error) => {\n if (!alive.current) return;\n if (parent === TOP) setError(err.message);\n setLevels((prev) => {\n const next = new Map(prev);\n next.delete(parent);\n return next;\n });\n },\n );\n }, [client, rootId]);\n\n useEffect(() => {\n load(TOP);\n return client.onChanged((id, areas) => {\n if (id !== rootId || !areas.includes('scene')) return;\n load(TOP);\n for (const open of expandedRef.current) load(open);\n });\n }, [client, rootId, load, expandedRef]);\n\n const setExpanded = useCallback((ids: Set<string>): void => {\n for (const id of ids) if (!expandedRef.current.has(id)) load(id);\n setExpandedState(ids);\n }, [load, expandedRef]);\n\n return { levels, expanded, setExpanded, error };\n}\n","/** The Scene tab: a root's node tree beside the node picked in it. */\nimport { useRef, useState, type PointerEvent, type ReactElement } from 'react';\nimport type { DevtoolsNodeSummary } from '@weasel-js/core/devtools-protocol';\nimport { Tree, type TreeNode } from '@weasel-js/ui/components/Tree';\nimport type { DevtoolsViewProps } from '../tabs';\nimport { NodeDetail } from './NodeDetail';\nimport { useSceneTree } from './useSceneTree';\nimport s from './SceneView.module.css';\n\nfunction flags(row: DevtoolsNodeSummary): string[] {\n return [row.hidden && 'hidden', row.locked && 'locked', !row.pickable && 'unpickable'].filter(\n (f): f is string => typeof f === 'string',\n );\n}\n\nfunction RowFacts({ row }: { row: DevtoolsNodeSummary }): ReactElement {\n return (\n <span className={s.facts}>\n <span className={s.kind}>{row.kind}</span>\n <span className={s.layer}>{row.layer}</span>\n {row.kind === 'group' && <span className={s.count}>{row.childCount}</span>}\n {flags(row).map((f) => <span key={f} className={s.flag}>{f}</span>)}\n </span>\n );\n}\n\nfunction toNodes(levels: ReadonlyMap<string, readonly DevtoolsNodeSummary[]>, parent: string): TreeNode[] {\n return (levels.get(parent) ?? []).map((row) => ({\n id: row.id,\n textValue: row.id,\n label: <span data-node-id={row.id}>{row.id}</span>,\n trailing: <RowFacts row={row} />,\n muted: row.hidden,\n ...(row.kind === 'group' && row.childCount > 0 ? { children: toNodes(levels, row.id) } : {}),\n }));\n}\n\nexport function SceneView({ client, rootId }: DevtoolsViewProps): ReactElement {\n const tree = useSceneTree(client, rootId);\n const [selected, setSelected] = useState<string | null>(null);\n const hovered = useRef<string | null>(null);\n\n const highlight = (id: string | null): void => {\n if (hovered.current === id) return;\n hovered.current = id;\n client.request(rootId, { type: 'highlight', ids: id ? [id] : [] }).catch(() => {});\n };\n const onPointerOver = (e: PointerEvent<HTMLDivElement>): void => {\n const row = (e.target as Element).closest('[role=\"treeitem\"]');\n highlight(row?.querySelector('[data-node-id]')?.getAttribute('data-node-id') ?? null);\n };\n\n return (\n <div className={s.split}>\n <div className={s.treePane} data-pane=\"tree\" onPointerOver={onPointerOver} onPointerLeave={() => highlight(null)}>\n <Tree\n aria-label=\"Scene nodes\"\n nodes={toNodes(tree.levels, '')}\n empty={<p className={s.note}>{tree.error ?? 'The scene is empty.'}</p>}\n expandedIds={tree.expanded}\n onExpandedChange={tree.setExpanded}\n selectionMode=\"single\"\n selectedIds={selected ? [selected] : []}\n onSelectionChange={(ids) => setSelected(ids.values().next().value ?? null)}\n />\n </div>\n <div className={s.detailPane} data-pane=\"detail\">\n {selected\n ? <NodeDetail key={selected} client={client} rootId={rootId} nodeId={selected} onPick={setSelected} />\n : <p className={s.note}>Pick a node to see its pose and data.</p>}\n </div>\n </div>\n );\n}\n",".state {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n padding: var(--wzl-space-4);\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-6);\n}\n\n.section {\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-3);\n}\n\n.heading {\n margin: 0;\n display: flex;\n align-items: baseline;\n gap: var(--wzl-space-3);\n font-size: var(--wzl-font-size-sm);\n font-weight: var(--wzl-font-weight-bold);\n}\n\n.count {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n color: var(--wzl-fg-muted);\n font-weight: normal;\n}\n\n.ids {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wzl-space-2);\n}\n\n.flags {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(12ch, 1fr));\n gap: var(--wzl-space-3) var(--wzl-space-6);\n}\n\n.probe {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr);\n gap: var(--wzl-space-4);\n align-items: start;\n}\n\n.note {\n margin: 0;\n color: var(--wzl-fg-muted);\n}\n","/** The State tab: selection, view, the active tool and the overlay flags, with the two the panel may steer. */\nimport type { ReactElement } from 'react';\nimport { DEBUG_FEATURES } from '@weasel-js/core';\nimport { Code } from '@weasel-js/ui/components/Code';\nimport { Select } from '@weasel-js/ui/components/Select';\nimport { Switch } from '@weasel-js/ui/components/Switch';\nimport { useRootQuery } from '../hooks';\nimport type { DevtoolsViewProps } from '../tabs';\nimport { ValueView } from './ValueView';\nimport s from './StateView.module.css';\n\n/** The tool picker's value for \"no tool\": a select key cannot be null. */\nconst NO_TOOL = '\\u0000none';\n\nexport function StateView({ client, rootId }: DevtoolsViewProps): ReactElement {\n const state = useRootQuery(client, rootId, ['selection', 'view', 'tool'], () => client.request(rootId, { type: 'get-state' }));\n if (state.error) return <p className={s.note}>{state.error}</p>;\n const st = state.data;\n if (!st) return <p className={s.note}>Loading…</p>;\n\n const steer = (p: Promise<unknown>): void => { p.then(state.refresh, state.refresh); };\n const probes = Object.entries(st.probes);\n\n return (\n <div className={s.state}>\n <section className={s.section} aria-label=\"Selection\">\n <h3 className={s.heading}>Selection <span className={s.count}>{st.selection.length}</span></h3>\n {st.selection.length === 0\n ? <p className={s.note}>Nothing selected.</p>\n : <div className={s.ids}>{st.selection.map((id) => <Code key={id} size=\"sm\">{id}</Code>)}</div>}\n </section>\n\n <section className={s.section} aria-label=\"Tool\">\n <h3 className={s.heading}>Tool</h3>\n <Select\n aria-label=\"Active tool\"\n width=\"fit\"\n selectedKey={st.activeTool ?? NO_TOOL}\n onSelectionChange={(key) => {\n steer(client.request(rootId, { type: 'set-tool', toolId: key === NO_TOOL ? null : key }));\n }}\n options={[{ value: NO_TOOL, label: 'none' }, ...st.tools.map((t) => ({ value: t, label: t }))]}\n />\n </section>\n\n <section className={s.section} aria-label=\"Overlays\">\n <h3 className={s.heading}>Overlays</h3>\n <div className={s.flags}>\n {DEBUG_FEATURES.map((flag) => (\n <Switch\n key={flag}\n isSelected={st.overlays[flag] === true}\n onChange={(on) => steer(client.request(rootId, { type: 'set-overlays', overlays: { [flag]: on } }))}\n >\n {flag}\n </Switch>\n ))}\n </div>\n </section>\n\n <section className={s.section} aria-label=\"View\">\n <h3 className={s.heading}>View</h3>\n <ValueView value={st.view} label=\"View\" />\n </section>\n\n <section className={s.section} aria-label=\"Probes\">\n <h3 className={s.heading}>Probes</h3>\n {probes.length === 0\n ? <p className={s.note}>No probes registered.</p>\n : probes.map(([name, value]) => (\n <div key={name} className={s.probe}>\n <Code size=\"sm\">{name}</Code>\n <ValueView value={value} label={name} />\n </div>\n ))}\n </section>\n </div>\n );\n}\n","/** The panel's tabs, in order. A new area of the protocol is a new entry here and a view of its own. */\nimport type { ComponentType } from 'react';\nimport type { DevtoolsClient } from './client';\nimport { DispatchView } from './views/DispatchView';\nimport { FrameView } from './views/FrameView';\nimport { HistoryView } from './views/HistoryView';\nimport { RegistryView } from './views/RegistryView';\nimport { SceneView } from './views/SceneView';\nimport { StateView } from './views/StateView';\n\n/** What every tab's view is handed: the connection, and the root the picker has chosen. */\nexport interface DevtoolsViewProps {\n client: DevtoolsClient;\n rootId: string;\n}\n\n/** A tab of the panel, as `DevtoolsPanel`'s `tabs` and `defaultTab` name it. */\nexport type DevtoolsTabId = 'scene' | 'state' | 'registry' | 'dispatch' | 'history' | 'frame';\n\nexport interface DevtoolsTab {\n id: DevtoolsTabId;\n label: string;\n View: ComponentType<DevtoolsViewProps>;\n}\n\nexport const DEVTOOLS_TABS: readonly DevtoolsTab[] = [\n { id: 'scene', label: 'Scene', View: SceneView },\n { id: 'state', label: 'State', View: StateView },\n { id: 'registry', label: 'Registry', View: RegistryView },\n { id: 'dispatch', label: 'Dispatch', View: DispatchView },\n { id: 'history', label: 'History', View: HistoryView },\n { id: 'frame', label: 'Frame', View: FrameView },\n];\n","import { useState, type ReactElement } from 'react';\nimport type { PanelTransport } from '@weasel-js/core/devtools-protocol';\nimport { Tab, TabList, TabPanel, Tabs } from '@weasel-js/ui/components/Tabs';\nimport { useDevtoolsClient } from './hooks';\nimport { RootPicker } from './RootPicker';\nimport type { DevtoolsClient } from './client';\nimport { DEVTOOLS_TABS, type DevtoolsTab, type DevtoolsTabId } from './tabs';\nimport s from './DevtoolsPanel.module.css';\n\n/** Props for {@link DevtoolsPanel}. */\nexport interface DevtoolsPanelProps {\n /** The panel's end of a connection to a page's devtools hook. */\n transport: PanelTransport;\n /** The tabs to show, in the panel's own order. Default: every tab. With one, the tab bar is left out. */\n tabs?: readonly DevtoolsTabId[];\n /** The tab open first. Default: the first shown. */\n defaultTab?: DevtoolsTabId;\n className?: string;\n}\n\n/**\n * Reads and steers the canvases of the page `transport` reaches: pick a canvas,\n * then walk its scene, read its state, follow its dispatch trace, or watch its\n * frame stats. It fills its container; give that a size.\n */\nexport function DevtoolsPanel({ transport, tabs, defaultTab, className }: DevtoolsPanelProps): ReactElement {\n const { client, state } = useDevtoolsClient(transport);\n const shown = tabs ? DEVTOOLS_TABS.filter((t) => tabs.includes(t.id)) : DEVTOOLS_TABS;\n const [tab, setTab] = useState<DevtoolsTabId>(defaultTab ?? shown[0]?.id ?? 'scene');\n const [picked, setPicked] = useState<string | null>(null);\n const rootId = state.roots.some((r) => r.id === picked) ? picked : state.roots[0]?.id ?? null;\n\n return (\n <section className={[s.panel, className].filter(Boolean).join(' ')} aria-label=\"Devtools\">\n <div className={s.bar}>\n <RootPicker roots={state.roots} value={rootId} onChange={setPicked} />\n <span className={s.status}>{statusText(state.status, state.kitVersion, state.error)}</span>\n </div>\n {rootId && shown.length === 1 ? (\n <div className={s.tabPanel}>{renderView(shown[0]!.View, client, rootId)}</div>\n ) : rootId ? (\n <Tabs className={s.tabs} selectedKey={tab} onSelectionChange={(k) => setTab(k as DevtoolsTabId)}>\n <TabList aria-label=\"Devtools areas\" className={s.tabList}>\n {shown.map((t) => <Tab key={t.id} id={t.id}>{t.label}</Tab>)}\n </TabList>\n {shown.map(({ id, View }) => (\n <TabPanel key={id} id={id} className={s.tabPanel}>\n {renderView(View, client, rootId)}\n </TabPanel>\n ))}\n </Tabs>\n ) : (\n <p className={s.empty}>{state.status === 'connected' ? 'No canvas on this page.' : 'Connecting…'}</p>\n )}\n </section>\n );\n}\n\n/** A view keyed by its root, so picking another canvas starts it fresh. */\nfunction renderView(View: DevtoolsTab['View'], client: DevtoolsClient, rootId: string): ReactElement {\n return <View key={rootId} client={client} rootId={rootId} />;\n}\n\nfunction statusText(status: string, kitVersion: string | null, error: string | null): string {\n if (status === 'error') return error ?? 'error';\n if (status === 'connected') return `weasel ${kitVersion ?? ''}`;\n return status;\n}\n","import {\n createInPageTransports, installDevtoolsHook, type PanelTransport, type WeaselDevtoolsHook,\n} from '@weasel-js/core/devtools-protocol';\n\n/**\n * A panel's end of a connection to this page's own hook. Each `yo` opens a\n * fresh session and each `bye` ends it, the way a `yo` posted to the window\n * does, so a panel that unmounts and mounts again reconnects. Installs the\n * hook when the page has none.\n */\nexport function createInPagePanelTransport(hook: WeaselDevtoolsHook | null = installDevtoolsHook()): PanelTransport {\n const { page, panel } = createInPageTransports();\n let close: (() => void) | null = null;\n return {\n send(message) {\n if (message.type === 'yo' && hook) {\n close?.();\n close = hook.connect(page);\n }\n panel.send(message);\n if (message.type === 'bye') {\n close?.();\n close = null;\n }\n },\n onMessage: (listener) => panel.onMessage(listener),\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["s","_Fragment","table","age","count","detail","heading","s","_Fragment","s","toolbar","count","body","POLL_MS","s","s","figure","note","s","_Fragment","heading","note","s","s","split","detailPane","s","count","facts","detail","section","heading","codes","note","s","yesNo","s","s","_Fragment","count","heading","note","s","flags","s","s","s"],"sources":["../src/client.ts","../src/trace.ts","../src/history.ts","../src/hooks.ts","../src/DevtoolsPanel.module.css","../src/RootPicker.tsx","../src/views/formatAge.ts","../src/views/TraceTable.module.css","../src/views/CoordTable.tsx","../src/views/DecisionPath.tsx","../src/views/TraceTable.tsx","../src/views/DispatchView.module.css","../src/views/DispatchView.tsx","../src/views/ValueView.module.css","../src/views/ValueView.tsx","../src/views/FrameView.module.css","../src/views/FrameView.tsx","../src/views/HistoryView.module.css","../src/views/HistoryTable.tsx","../src/views/HistoryView.tsx","../src/views/RegistryBrowser.module.css","../src/views/RegistryBrowser.tsx","../src/views/RegistryView.module.css","../src/views/Bindings.tsx","../src/views/RegistryEntryDetail.tsx","../src/views/RegistryView.tsx","../src/views/SceneView.module.css","../src/views/NodeDetail.tsx","../src/views/useSceneTree.ts","../src/views/SceneView.tsx","../src/views/StateView.module.css","../src/views/StateView.tsx","../src/tabs.ts","../src/DevtoolsPanel.tsx","../src/inPageTransport.ts"],"sourcesContent":["/**\n * The panel's side of the devtools protocol, free of any framework: the\n * handshake, request ids and their replies, the roots the page reports, and\n * its change notices. The views, the extension and tests all drive this.\n */\nimport {\n DEVTOOLS_PROTOCOL, type DevtoolsArea, type DevtoolsHistorySlice, type DevtoolsNodeDetail, type DevtoolsNodeSummary,\n type DevtoolsRegistry, type DevtoolsRequest, type DevtoolsRootInfo, type DevtoolsRootState, type DevtoolsTraceSlice,\n type PageMessage, type PanelTransport, type SerializedValue,\n} from '@weasel-js/core/devtools-protocol';\n\ntype DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;\n\n/** A request as a caller writes it: the client adds the protocol, the request id and the root. */\nexport type DevtoolsRequestBody = DistributiveOmit<DevtoolsRequest, 'protocol' | 'requestId' | 'rootId'>;\n\n/** What each request resolves to. */\nexport interface DevtoolsResultMap {\n 'get-children': DevtoolsNodeSummary[];\n 'get-node': DevtoolsNodeDetail;\n 'get-state': DevtoolsRootState;\n 'get-trace': DevtoolsTraceSlice;\n 'get-frame': SerializedValue;\n 'get-registry': DevtoolsRegistry;\n 'get-history': DevtoolsHistorySlice;\n select: null;\n highlight: null;\n 'set-tool': null;\n 'set-overlays': null;\n}\n\n/** Where a connection stands. `error` holds a message the page sent about no request, such as a protocol mismatch. */\nexport interface DevtoolsClientState {\n status: 'connecting' | 'connected' | 'error' | 'closed';\n kitVersion: string | null;\n roots: readonly DevtoolsRootInfo[];\n error: string | null;\n}\n\n/** One open connection to a page's devtools hook, from the panel's side. */\nexport interface DevtoolsClient {\n state(): DevtoolsClientState;\n /** Hear every change to {@link DevtoolsClient.state}. Returns the unsubscribe. */\n subscribe(listener: () => void): () => void;\n /** Hear a root's `changed` notices, with the areas each names. Returns the unsubscribe. */\n onChanged(listener: (rootId: string, areas: DevtoolsArea[]) => void): () => void;\n /** Send `body` about `rootId`. Rejects with the page's message when it refuses. */\n request<B extends DevtoolsRequestBody>(rootId: string, body: B): Promise<DevtoolsResultMap[B['type']]>;\n /** Say `yo` and start listening. Called again after {@link DevtoolsClient.close}, it reconnects. */\n open(): void;\n /** Say `bye` and stop listening. Pending requests reject. */\n close(): void;\n}\n\ninterface Pending {\n resolve(result: unknown): void;\n reject(err: Error): void;\n}\n\n/** A connection over `transport`, sending nothing until it is opened. It is connected once the page says `sup`. */\nexport function createDevtoolsClient(transport: PanelTransport): DevtoolsClient {\n let state: DevtoolsClientState = { status: 'closed', kitVersion: null, roots: [], error: null };\n const listeners = new Set<() => void>();\n const changeListeners = new Set<(rootId: string, areas: DevtoolsArea[]) => void>();\n const pending = new Map<number, Pending>();\n let nextId = 1;\n\n const set = (patch: Partial<DevtoolsClientState>): void => {\n state = { ...state, ...patch };\n for (const l of [...listeners]) l();\n };\n\n const receive = (m: PageMessage): void => {\n if (state.status === 'closed') return;\n switch (m.type) {\n case 'sup':\n set({ status: 'connected', kitVersion: m.kitVersion, roots: m.roots, error: null });\n return;\n case 'root-added':\n set({ roots: [...state.roots.filter((r) => r.id !== m.root.id), m.root] });\n return;\n case 'root-removed':\n set({ roots: state.roots.filter((r) => r.id !== m.rootId) });\n return;\n case 'changed': {\n const areas = Object.keys(m.areas) as DevtoolsArea[];\n for (const l of [...changeListeners]) l(m.rootId, areas);\n return;\n }\n case 'result':\n pending.get(m.requestId)?.resolve(m.result);\n pending.delete(m.requestId);\n return;\n case 'error':\n if (m.requestId === null) {\n set({ status: 'error', error: m.message });\n return;\n }\n pending.get(m.requestId)?.reject(new Error(m.message));\n pending.delete(m.requestId);\n return;\n }\n };\n\n let off: (() => void) | null = null;\n\n return {\n state: () => state,\n subscribe(listener) {\n listeners.add(listener);\n return () => { listeners.delete(listener); };\n },\n onChanged(listener) {\n changeListeners.add(listener);\n return () => { changeListeners.delete(listener); };\n },\n request(rootId, body) {\n if (state.status === 'closed') return Promise.reject(new Error('the devtools connection is closed'));\n const requestId = nextId++;\n return new Promise((resolve, reject) => {\n pending.set(requestId, { resolve: resolve as (r: unknown) => void, reject });\n transport.send({ ...body, protocol: DEVTOOLS_PROTOCOL, requestId, rootId } as DevtoolsRequest);\n });\n },\n open() {\n if (off) return;\n off = transport.onMessage(receive);\n set({ status: 'connecting', error: null });\n transport.send({ type: 'yo', protocol: DEVTOOLS_PROTOCOL });\n },\n close() {\n if (!off) return;\n transport.send({ type: 'bye', protocol: DEVTOOLS_PROTOCOL });\n off();\n off = null;\n set({ status: 'closed' });\n const err = new Error('the devtools connection is closed');\n for (const p of pending.values()) p.reject(err);\n pending.clear();\n },\n };\n}\n\n/** {@link createDevtoolsClient}, opened: it says `yo` at once. */\nexport function connectDevtools(transport: PanelTransport): DevtoolsClient {\n const client = createDevtoolsClient(transport);\n client.open();\n return client;\n}\n","/** A root's dispatch trace read a slice at a time, each read picking up where the last left off. */\nimport type { SerializedValue } from '@weasel-js/core/devtools-protocol';\nimport type { DevtoolsClient } from './client';\n\n/** What one read hands back. `coords` is present only while coord records are asked for. */\nexport interface TraceRead {\n entries: SerializedValue[];\n live: SerializedValue;\n coords?: SerializedValue[];\n}\n\n/** A cursor over one root's dispatch trace, and over its coord records once asked. */\nexport interface TraceFollower {\n /** The trace and, when on, the coord records recorded since the last read. Reads run one after another. */\n read(): Promise<TraceRead>;\n /** Ask for coord records from the next read on. Turned on, it starts from the oldest the canvas still holds. */\n setCoords(on: boolean): void;\n}\n\n/** Follow `rootId`'s dispatch trace through `client`, from the oldest record the canvas still holds. */\nexport function followTrace(client: DevtoolsClient, rootId: string): TraceFollower {\n let cursor = 0;\n let coordCursor: number | null = null;\n let last: Promise<unknown> = Promise.resolve();\n\n const readOnce = async (): Promise<TraceRead> => {\n const slice = await client.request(rootId, {\n type: 'get-trace', cursor, ...(coordCursor !== null ? { coordCursor } : {}),\n });\n cursor = slice.cursor;\n const out: TraceRead = { entries: slice.entries, live: slice.live };\n if (slice.coords && coordCursor !== null) {\n coordCursor = slice.coords.cursor;\n out.coords = slice.coords.entries;\n }\n return out;\n };\n\n return {\n read() {\n const next = last.then(readOnce, readOnce);\n last = next.catch(() => undefined);\n return next;\n },\n setCoords(on) {\n if (on && coordCursor === null) coordCursor = 0;\n else if (!on) coordCursor = null;\n },\n };\n}\n","/** A root's history steps read a slice at a time through their cursor, the stack's entries along with them on request. */\nimport type { DevtoolsHistorySlice } from '@weasel-js/core/devtools-protocol';\nimport type { DevtoolsClient } from './client';\n\n/** A cursor over one root's history steps. */\nexport interface HistoryFollower {\n /** The steps recorded since the last read, and where the history stands now. Reads run one after another. */\n read(): Promise<DevtoolsHistorySlice>;\n /** Ask for the stack's entries with every read from the next on. */\n setCheckpoints(on: boolean): void;\n}\n\n/** Follow `rootId`'s history steps through `client`, from the oldest step the canvas still holds. */\nexport function followHistory(client: DevtoolsClient, rootId: string): HistoryFollower {\n let cursor = 0;\n let checkpoints = false;\n let last: Promise<unknown> = Promise.resolve();\n\n const readOnce = async (): Promise<DevtoolsHistorySlice> => {\n const slice = await client.request(rootId, { type: 'get-history', cursor, ...(checkpoints ? { checkpoints } : {}) });\n cursor = slice.cursor;\n return slice;\n };\n\n return {\n read() {\n const next = last.then(readOnce, readOnce);\n last = next.catch(() => undefined);\n return next;\n },\n setCheckpoints(on) {\n checkpoints = on;\n },\n };\n}\n","/** The React side of a connection: the client a panel holds, the data it reads per root, and its polls. */\nimport { useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';\nimport type { DevtoolsArea, PanelTransport } from '@weasel-js/core/devtools-protocol';\nimport { useLatest, useVisibleRaf } from '@weasel-js/react';\nimport { createDevtoolsClient, type DevtoolsClient, type DevtoolsClientState } from './client';\n\n/** A connection over `transport` for as long as the component is mounted: `yo` on mount, `bye` on unmount. */\nexport function useDevtoolsClient(transport: PanelTransport): { client: DevtoolsClient; state: DevtoolsClientState } {\n const client = useMemo(() => createDevtoolsClient(transport), [transport]);\n useEffect(() => {\n client.open();\n return () => client.close();\n }, [client]);\n const state = useSyncExternalStore(client.subscribe, client.state);\n return { client, state };\n}\n\n/** What a view reads about one root: the last answer, or the page's refusal. */\nexport interface RootQuery<T> {\n data: T | undefined;\n error: string | null;\n /** Ask again now, as after a steering request whose effect no notice reports. */\n refresh(): void;\n}\n\n/**\n * `read`'s answer about `rootId`, asked again whenever a `changed` notice for\n * that root names one of `areas`, or a dependency in `deps` changes.\n */\nexport function useRootQuery<T>(\n client: DevtoolsClient,\n rootId: string,\n areas: readonly DevtoolsArea[],\n read: () => Promise<T>,\n deps: readonly unknown[] = [],\n): RootQuery<T> {\n const [data, setData] = useState<T | undefined>(undefined);\n const [error, setError] = useState<string | null>(null);\n const [version, setVersion] = useState(0);\n const readRef = useLatest(read);\n const areaKey = areas.join(',');\n\n useEffect(() => client.onChanged((id, changed) => {\n if (id === rootId && changed.some((a) => areaKey.split(',').includes(a))) setVersion((v) => v + 1);\n }), [client, rootId, areaKey]);\n\n useEffect(() => {\n let live = true;\n readRef.current().then(\n (result) => { if (live) { setData(result); setError(null); } },\n (err: Error) => { if (live) setError(err.message); },\n );\n return () => { live = false; };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- `deps` is the caller's\n }, [client, rootId, version, readRef, ...deps]);\n\n const refresh = useRef(() => setVersion((v) => v + 1)).current;\n return { data, error, refresh };\n}\n\n/** Call `tick` every `ms` while `enabled` and the page is visible, and once at the start. */\nexport function usePoll(tick: () => void, ms: number, enabled: boolean): void {\n const tickRef = useLatest(tick);\n const last = useRef(-Infinity);\n const loop = useVisibleRaf((time, l) => {\n if (time - last.current >= ms) {\n last.current = time;\n tickRef.current();\n }\n l.request();\n });\n useEffect(() => {\n if (!enabled) return;\n last.current = -Infinity;\n loop.request();\n return () => loop.cancel();\n }, [enabled, loop]);\n}\n","/* Fills whatever box it is given; each view scrolls inside its own panes. */\n.panel {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 0;\n min-width: 0;\n overflow: hidden;\n color: var(--wzl-fg);\n background: var(--wzl-panel-surface);\n font-family: var(--wzl-font-ui);\n font-size: var(--wzl-font-size-sm);\n /* The views lay themselves out by the panel's own width: a sidebar gives it far less than a page. */\n container-type: inline-size;\n}\n\n.bar {\n display: flex;\n flex-direction: row;\n justify-content: flex-start;\n align-items: center;\n gap: var(--wzl-space-4);\n padding: var(--wzl-space-2) var(--wzl-space-4);\n border-bottom: 1px solid var(--wzl-line-subtle);\n flex-shrink: 0;\n}\n\n.picker {\n flex: 0 1 auto;\n min-width: 0;\n margin: 0;\n}\n\n.dimension {\n color: var(--wzl-fg-muted);\n font-size: var(--wzl-font-size-xs);\n}\n\n.status {\n flex: 0 1 auto;\n min-width: 0;\n margin-inline-start: auto;\n color: var(--wzl-fg-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.tabs {\n flex: 1 1 auto;\n min-height: 0;\n}\n\n.tabList {\n flex-shrink: 0;\n /* In a narrow panel the tabs wrap onto a second row rather than run past its edge. */\n flex-wrap: wrap;\n padding-inline: var(--wzl-space-2);\n}\n\n.tabPanel {\n flex: 1 1 auto;\n min-height: 0;\n display: flex;\n flex-direction: column;\n padding: 0;\n overflow: hidden;\n}\n\n.empty {\n margin: 0;\n padding: var(--wzl-space-6);\n color: var(--wzl-fg-muted);\n}\n","import type { ReactElement } from 'react';\nimport type { DevtoolsRootInfo } from '@weasel-js/core/devtools-protocol';\nimport { Select } from '@weasel-js/ui/components/Select';\nimport s from './DevtoolsPanel.module.css';\n\nexport interface RootPickerProps {\n roots: readonly DevtoolsRootInfo[];\n value: string | null;\n onChange(rootId: string): void;\n}\n\n/** Which canvas the panel reads, each named by its label and dimension. */\nexport function RootPicker({ roots, value, onChange }: RootPickerProps): ReactElement {\n return (\n <Select\n className={s.picker}\n aria-label=\"Canvas\"\n width=\"fit\"\n placeholder=\"No canvas\"\n isDisabled={roots.length === 0}\n selectedKey={value}\n onSelectionChange={onChange}\n options={roots.map((r) => ({\n value: r.id,\n textValue: `${r.label} ${r.dimension}`,\n label: <>{r.label} <span className={s.dimension}>{r.dimension}</span></>,\n }))}\n />\n );\n}\n","/** How long ago something happened, in the shortest unit that reads well: `840ms`, `12.3s`, `4m07s`. */\nexport function formatAge(ms: number): string {\n if (ms < 1000) return `${Math.round(ms)}ms`;\n const sec = ms / 1000;\n if (sec < 60) return `${sec.toFixed(1)}s`;\n const m = Math.floor(sec / 60);\n return `${m}m${String(Math.floor(sec % 60)).padStart(2, '0')}s`;\n}\n",".table {\n font-family: var(--wzl-font-mono);\n}\n\n/* Age is live, variable-length text in the leading column: a fixed width keeps\n ticking values from shifting the columns after it. */\n.age {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n width: 7ch;\n min-width: 7ch;\n text-align: end;\n white-space: nowrap;\n}\n\n.count {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n text-align: end;\n}\n\n.unhandled > td { background: color-mix(in srgb, var(--wzl-danger) 14%, transparent); }\ntr.unhandled:hover > td { background: color-mix(in srgb, var(--wzl-danger) 24%, transparent); }\n\n/* Mode switches read as ambient state rather than dispatched input. */\ntr.mode { color: var(--wzl-fg-muted); cursor: default; }\n.mode > td { background: color-mix(in srgb, var(--wzl-accent) 8%, transparent); }\n.modeDetail { font-style: italic; }\n\n/* The live prediction is pinned above the log; it is not a past event. */\ntr.live > td { font-style: italic; border-block-end: 1px solid var(--wzl-border); }\n\n.detail {\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-4);\n}\n\n.heading {\n margin: var(--wzl-space-6) 0 var(--wzl-space-3);\n font-size: var(--wzl-font-size-sm);\n font-weight: var(--wzl-font-weight-bold);\n}\n","/** `clientToWorld` conversions, newest first: where the pointer was, the camera it was read under, and the world point it became. */\nimport type { ReactElement } from 'react';\nimport { DataGrid, type DataGridColumn } from '@weasel-js/ui/components/DataGrid';\nimport { formatAge } from './formatAge';\nimport s from './TraceTable.module.css';\n\n/** One coord record, as the canvas writes it. */\nexport interface CoordEntry {\n ts: number;\n clientX: number;\n clientY: number;\n view: { x: number; y: number; scaleX: number; scaleY: number } | null;\n world: { x: number; y: number };\n fallback: boolean;\n}\n\nconst DISPLAY_LIMIT = 100;\n/** Wide enough for a coordinate in the tens of thousands, sign included, at one decimal. */\nconst fixed = (n: number, digits = 1): string => n.toFixed(digits).padStart(8, ' ');\nconst pair = (x: number, y: number): string => `${fixed(x)} ${fixed(y)}`;\n\nexport function CoordTable({ entries, now }: { entries: readonly CoordEntry[]; now: number }): ReactElement {\n const rows = entries.slice(-DISPLAY_LIMIT).map((entry, i) => ({ id: `${entry.ts}-${i}`, entry })).reverse();\n const columns: readonly DataGridColumn<(typeof rows)[number]>[] = [\n { id: 'age', header: 'Age', sortable: false, className: s.age, render: ({ entry }) => formatAge(Math.max(0, now - entry.ts)) },\n { id: 'client', header: 'Client', sortable: false, className: s.count, render: ({ entry }) => pair(entry.clientX, entry.clientY) },\n { id: 'world', header: 'World', sortable: false, className: s.count, render: ({ entry }) => pair(entry.world.x, entry.world.y) },\n {\n id: 'scale',\n header: 'Scale',\n sortable: false,\n className: s.count,\n render: ({ entry }) => (entry.view ? fixed(entry.view.scaleX, 3) : 'fallback'),\n },\n ];\n return (\n <section aria-label=\"Coord records\">\n <h3 className={s.heading}>Coords</h3>\n <DataGrid className={s.table} rows={rows} columns={columns} empty=\"No conversions recorded yet.\" />\n </section>\n );\n}\n","/** The path one input took, as a powerline: the input, the binding's owner, the action that fired, and whether it was handled. */\nimport type { ReactElement } from 'react';\nimport type { DispatchRecord } from '@weasel-js/core/routing';\nimport { Powerline, type PowerlineSegment } from '@weasel-js/ui/components/Powerline';\n\nfunction inputText(record: DispatchRecord): string {\n const { eventKind, key } = record.input;\n return key === undefined ? eventKind : `${eventKind} ${key === ' ' ? 'Space' : key}`;\n}\n\nexport function DecisionPath({ record }: { record: DispatchRecord }): ReactElement {\n const winner = record.ranked.find((r) => r.walk.kind === 'fired' || r.walk.kind === 'would-fire');\n const segments: PowerlineSegment[] = [{ text: inputText(record), grade: 'info', endCap: 'chevron' }];\n if (winner) {\n segments.push(\n { text: winner.candidate.ownerId ?? 'action', emphasis: 'low', endCap: 'chevron' },\n { text: winner.candidate.actionId, emphasis: 'high', endCap: 'chevron' },\n );\n } else {\n segments.push({ text: `${record.ranked.length} ranked, none fired`, emphasis: 'low', endCap: 'chevron' });\n }\n segments.push(record.outcome === 'handled'\n ? { text: record.predicted ? 'would handle' : 'handled', grade: 'success' }\n : { text: 'unhandled', grade: 'danger' });\n return <Powerline segments={segments} size=\"sm\" variant=\"subtle\" aria-label=\"Decision path\" />;\n}\n","/** The trace as rows, newest first under the live prediction; a dispatch row opens to the path it took and every stage behind it. */\nimport { useState, type ReactElement, type ReactNode } from 'react';\nimport type { DispatchRecord, TraceLogEntry } from '@weasel-js/core/routing';\nimport { DataGrid, type DataGridColumn } from '@weasel-js/ui/components/DataGrid';\nimport { FallthroughDiagram } from '@weasel-js/ui/components/FallthroughDiagram';\nimport { DecisionPath } from './DecisionPath';\nimport { formatAge } from './formatAge';\nimport s from './TraceTable.module.css';\n\nconst DISPLAY_LIMIT = 100;\nconst LIVE_ID = 'live';\n\nexport interface TraceTableProps {\n entries: readonly TraceLogEntry[];\n /** A press at the pointer, predicted, pinned above the log. */\n live: DispatchRecord | null;\n /** The clock each row's age is measured against. */\n now: number;\n /** Inputs an action handled, with mode switches. */\n showHandled: boolean;\n showUnhandled: boolean;\n /** Shown in place of rows when the filters leave none. */\n empty: ReactNode;\n}\n\ninterface TraceRow { id: string; entry: TraceLogEntry }\n\n/** Ids from each entry's timestamp, numbering entries that share one. */\nfunction withTsIds(entries: readonly TraceLogEntry[]): TraceRow[] {\n const seen = new Map<number, number>();\n return entries.map((entry) => {\n const n = seen.get(entry.ts) ?? 0;\n seen.set(entry.ts, n + 1);\n return { id: n === 0 ? String(entry.ts) : `${entry.ts}#${n}`, entry };\n });\n}\n\nfunction renderEvent(entry: TraceLogEntry): ReactNode {\n if (entry.kind === 'mode') {\n return <><code>{entry.mode}</code>{entry.detail ? <span className={s.modeDetail}> ({entry.detail})</span> : null}</>;\n }\n const { key } = entry.input;\n return <>{entry.input.eventKind}{key !== undefined ? <> <code>{key === ' ' ? 'Space' : key}</code></> : null}</>;\n}\n\nfunction renderOutcome(entry: TraceLogEntry): ReactNode {\n if (entry.kind === 'mode') return <><code>{entry.from ?? '∅'}</code> → <code>{entry.to ?? '∅'}</code></>;\n if (entry.outcome === 'unhandled') return 'unhandled';\n return entry.fired ? <code>{entry.fired}</code> : 'handled';\n}\n\nexport function TraceTable({ entries, live, now, showHandled, showUnhandled, empty }: TraceTableProps): ReactElement {\n const [expanded, setExpanded] = useState<ReadonlySet<string>>(new Set());\n\n const rows = withTsIds(entries)\n .filter(({ entry: e }) => (e.kind === 'mode' || e.outcome === 'handled' ? showHandled : showUnhandled))\n .slice(-DISPLAY_LIMIT)\n .reverse();\n if (live) rows.unshift({ id: LIVE_ID, entry: live });\n\n const columns: readonly DataGridColumn<TraceRow>[] = [\n {\n id: 'age',\n header: 'Age',\n sortable: false,\n className: s.age,\n render: ({ id, entry }) => (id === LIVE_ID ? 'live' : formatAge(Math.max(0, now - entry.ts))),\n },\n { id: 'event', header: 'Event', sortable: false, render: ({ entry }) => renderEvent(entry) },\n { id: 'outcome', header: 'Outcome', sortable: false, render: ({ entry }) => renderOutcome(entry) },\n {\n id: 'matched',\n header: 'Matched',\n sortable: false,\n className: s.count,\n render: ({ entry }) => (entry.kind === 'mode' ? '—' : entry.matched.length),\n },\n ];\n\n return (\n <DataGrid\n className={s.table}\n rows={rows}\n columns={columns}\n empty={empty}\n rowClassName={({ id, entry }) => (id === LIVE_ID\n ? s.live\n : entry.kind === 'mode' ? s.mode : entry.outcome === 'unhandled' ? s.unhandled : undefined)}\n rowExpandable={({ entry }) => entry.kind === 'dispatch'}\n expandedIds={expanded}\n onExpandedChange={setExpanded}\n onRowClick={({ id, entry }) => {\n if (entry.kind !== 'dispatch') return;\n setExpanded((cur) => (cur.has(id) ? new Set() : new Set([id])));\n }}\n renderDetail={({ entry }) => (entry.kind === 'dispatch'\n ? <div className={s.detail}><DecisionPath record={entry} /><FallthroughDiagram record={entry} /></div>\n : null)}\n />\n );\n}\n",".dispatch {\n display: flex;\n flex-direction: column;\n flex: 1 1 auto;\n min-height: 0;\n}\n\n.toolbar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wzl-space-4);\n padding: var(--wzl-space-2) var(--wzl-space-4);\n border-bottom: 1px solid var(--wzl-line-subtle);\n flex-shrink: 0;\n}\n\n/* Last in the row and pushed to its end, so its changing width displaces nothing. */\n.count {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n margin-inline-start: auto;\n color: var(--wzl-fg-muted);\n white-space: nowrap;\n}\n\n.body {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n padding: var(--wzl-space-4);\n}\n","/**\n * The Dispatch tab: the root's trace of resolved inputs and mode switches,\n * what a press at the pointer would do now, and, behind a toggle, the\n * `clientToWorld` conversions. Read through cursors, so each read carries only\n * what is new; polled while open, because the live prediction moves with the\n * pointer and no notice reports that.\n */\nimport { useEffect, useMemo, useState, type ReactElement } from 'react';\nimport type { DispatchRecord, TraceLogEntry } from '@weasel-js/core/routing';\nimport { Button } from '@weasel-js/ui/components/Button';\nimport { Switch } from '@weasel-js/ui/components/Switch';\nimport { ToggleBar } from '@weasel-js/ui/components/ToggleBar';\nimport { usePoll } from '../hooks';\nimport type { DevtoolsViewProps } from '../tabs';\nimport { followTrace } from '../trace';\nimport { CoordTable, type CoordEntry } from './CoordTable';\nimport { TraceTable } from './TraceTable';\nimport s from './DispatchView.module.css';\n\ntype Outcome = 'handled' | 'unhandled';\n\nconst POLL_MS = 250;\n/** How many records the panel keeps, as many as a canvas's own buffer holds. */\nconst KEEP = 200;\n\nexport function DispatchView({ client, rootId }: DevtoolsViewProps): ReactElement {\n const follower = useMemo(() => followTrace(client, rootId), [client, rootId]);\n const [entries, setEntries] = useState<TraceLogEntry[]>([]);\n const [coords, setCoords] = useState<CoordEntry[]>([]);\n const [live, setLive] = useState<DispatchRecord | null>(null);\n const [now, setNow] = useState(() => Date.now());\n // Unhandled inputs are every idle pointer move and every wheel over chrome, so they start hidden.\n const [shown, setShown] = useState<readonly Outcome[]>(['handled']);\n const [showCoords, setShowCoords] = useState(false);\n\n const read = (): void => {\n follower.read().then((slice) => {\n if (slice.entries.length) setEntries((prev) => [...prev, ...(slice.entries as unknown as TraceLogEntry[])].slice(-KEEP));\n if (slice.coords?.length) setCoords((prev) => [...prev, ...(slice.coords as unknown as CoordEntry[])].slice(-KEEP));\n setLive(slice.live as unknown as DispatchRecord | null);\n setNow(Date.now());\n }, () => {});\n };\n\n useEffect(() => client.onChanged((id, areas) => {\n if (id === rootId && areas.includes('trace')) read();\n }));\n usePoll(read, POLL_MS, true);\n\n const toggleCoords = (on: boolean): void => {\n follower.setCoords(on);\n setShowCoords(on);\n if (!on) setCoords([]);\n };\n\n return (\n <div className={s.dispatch}>\n <div className={s.toolbar}>\n <ToggleBar<Outcome>\n mode=\"multiple\"\n variant=\"minimal\"\n size=\"sm\"\n ariaLabel=\"Outcome filters\"\n items={[\n { value: 'handled', label: 'handled', tooltip: 'Show handled inputs and mode switches' },\n { value: 'unhandled', label: 'unhandled', tooltip: 'Show inputs nothing handled' },\n ]}\n value={shown}\n onChange={(next) => setShown(next)}\n />\n <Switch isSelected={showCoords} onChange={toggleCoords}>coords</Switch>\n <Button size=\"sm\" variant=\"ghost\" disabled={entries.length === 0} onClick={() => setEntries([])}>\n Clear\n </Button>\n <span className={s.count}>{entries.length} {entries.length === 1 ? 'record' : 'records'}</span>\n </div>\n <div className={s.body}>\n <TraceTable\n entries={entries}\n live={live}\n now={now}\n showHandled={shown.includes('handled')}\n showUnhandled={shown.includes('unhandled')}\n empty={entries.length > 0\n ? 'Every record is hidden by the filters above.'\n : 'No input yet. Use the canvas to fill the trace.'}\n />\n {showCoords && <CoordTable entries={coords} now={now} />}\n </div>\n </div>\n );\n}\n",".value {\n font-family: var(--wzl-font-mono);\n font-size: var(--wzl-font-size-sm);\n line-height: 1.5;\n min-width: 0;\n}\n\n.row {\n display: flex;\n align-items: center;\n gap: var(--wzl-space-2);\n min-height: 1.5em;\n white-space: nowrap;\n}\n\n.children {\n padding-inline-start: var(--wzl-space-8);\n}\n\n.key {\n color: var(--wzl-fg-muted);\n}\n\n.key::after {\n content: ':';\n}\n\n.muted {\n color: var(--wzl-fg-muted);\n font-style: italic;\n}\n\n.keyword {\n color: var(--wzl-accent-fg);\n}\n\n.number {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n color: var(--wzl-accent-fg);\n}\n\n.string {\n color: var(--wzl-success);\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.fn {\n color: var(--wzl-warning);\n}\n\n.tag {\n color: var(--wzl-fg);\n}\n","/** A serialized value as a reader expects to see it: tagged maps, sets and typed arrays named, functions and cycles marked. */\nimport { useState, type ReactElement, type ReactNode } from 'react';\nimport type { SerializedValue } from '@weasel-js/core/devtools-protocol';\nimport { Disclosure } from '@weasel-js/ui/components/Disclosure';\nimport s from './ValueView.module.css';\n\ntype Obj = { [key: string]: SerializedValue };\n\nconst isObj = (v: SerializedValue): v is Obj => typeof v === 'object' && v !== null && !Array.isArray(v);\n\n/** The children a container lists, or null for a value shown on one line. */\nfunction entriesOf(v: SerializedValue): [string, SerializedValue][] | null {\n if (Array.isArray(v)) return v.map((x, i) => [String(i), x]);\n if (!isObj(v)) return null;\n if (v.$type === 'Map' || v.$type === 'Set') {\n const items = Array.isArray(v.entries) ? v.entries : [];\n return items.map((x, i) => [String(i), x]);\n }\n if (typeof v.$type === 'string') return null;\n return Object.entries(v).filter(([k]) => k !== '$class');\n}\n\n/** What a container is called on its own row: `Array(3)`, `Map(2)`, `Path {…}`. */\nfunction summaryOf(v: SerializedValue): string {\n if (Array.isArray(v)) return `Array(${v.length})`;\n if (!isObj(v)) return '';\n if (v.$type === 'Map' || v.$type === 'Set') return `${v.$type}(${String(v.size)})`;\n const name = typeof v.$class === 'string' ? v.$class : '';\n return Object.keys(v).length === 0 ? `${name}{}` : `${name ? `${name} ` : ''}{…}`;\n}\n\nfunction Scalar({ value }: { value: SerializedValue }): ReactElement {\n if (value === undefined) return <span className={s.muted}>undefined</span>;\n if (value === null) return <span className={s.keyword}>null</span>;\n if (typeof value === 'number') return <span className={s.number}>{value}</span>;\n if (typeof value === 'boolean') return <span className={s.keyword}>{String(value)}</span>;\n if (typeof value === 'string') {\n if (value.startsWith('ƒ ')) return <span className={s.fn}>{value}</span>;\n if (value === '[cycle]' || value === '…' || value.startsWith('… ')) return <span className={s.muted}>{value}</span>;\n return <span className={s.string}>{JSON.stringify(value)}</span>;\n }\n if (isObj(value) && value.$type === 'Date') return <span className={s.tag}>Date {String(value.value)}</span>;\n if (isObj(value) && typeof value.$type === 'string') {\n return <span className={s.tag}>{value.$type}({String(value.length)})</span>;\n }\n return <span className={s.muted}>{summaryOf(value)}</span>;\n}\n\nfunction Entry({ name, value, depth }: { name: ReactNode; value: SerializedValue; depth: number }): ReactElement {\n const entries = entriesOf(value);\n const [open, setOpen] = useState(depth < 2);\n if (!entries || entries.length === 0) {\n return (\n <div className={s.row}>\n <span className={s.key}>{name}</span>\n <Scalar value={value} />\n </div>\n );\n }\n return (\n <div>\n <div className={s.row}>\n <Disclosure open={open} onToggle={() => setOpen((o) => !o)} label={`${String(name)} ${summaryOf(value)}`} size={11} />\n <span className={s.key}>{name}</span>\n <span className={s.muted}>{summaryOf(value)}</span>\n </div>\n {open && (\n <div className={s.children}>\n {entries.map(([k, v]) => <Entry key={k} name={k} value={v} depth={depth + 1} />)}\n </div>\n )}\n </div>\n );\n}\n\nexport interface ValueViewProps {\n value: SerializedValue;\n /** Names the value for a screen reader. */\n label: string;\n}\n\n/** `value` as nested rows, its containers folding; the top level lists its entries directly. */\nexport function ValueView({ value, label }: ValueViewProps): ReactElement {\n const entries = entriesOf(value);\n return (\n <div className={s.value} role=\"group\" aria-label={label}>\n {entries && entries.length > 0\n ? entries.map(([k, v]) => <Entry key={k} name={k} value={v} depth={1} />)\n : <Scalar value={value} />}\n </div>\n );\n}\n",".frame {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n padding: var(--wzl-space-4);\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-6);\n}\n\n.figure {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n text-align: end;\n white-space: pre;\n}\n\n.layers {\n font-family: var(--wzl-font-mono);\n}\n\n.note {\n margin: 0;\n color: var(--wzl-fg-muted);\n}\n","/**\n * The Frame tab: what the last paint cost, overall and per render layer. The\n * canvas measures only while its `fps` overlay is on and announces nothing, so\n * this polls, and only while the tab is open and the overlay on.\n */\nimport { useState, type ReactElement } from 'react';\nimport type { FrameStats } from '@weasel-js/core';\nimport type { SerializedValue } from '@weasel-js/core/devtools-protocol';\nimport { DataGrid, type DataGridColumn } from '@weasel-js/ui/components/DataGrid';\nimport { DetailList, DetailRow } from '@weasel-js/ui/components/DetailList';\nimport { Switch } from '@weasel-js/ui/components/Switch';\nimport { usePoll, useRootQuery } from '../hooks';\nimport type { DevtoolsViewProps } from '../tabs';\nimport { ValueView } from './ValueView';\nimport s from './FrameView.module.css';\n\nconst POLL_MS = 500;\n\nconst isFrameStats = (v: SerializedValue): v is SerializedValue & FrameStats =>\n typeof v === 'object' && v !== null && !Array.isArray(v) && typeof v.paintMs === 'number' && Array.isArray(v.layers);\n\nconst ms = (n: number): string => n.toFixed(2).padStart(7, ' ');\n\ntype LayerRow = FrameStats['layers'][number];\n\nconst COLUMNS: readonly DataGridColumn<LayerRow>[] = [\n { id: 'id', header: 'Layer', sortable: false, render: (r) => r.id },\n { id: 'calls', header: 'Draw calls', sortable: false, className: s.figure, render: (r) => r.drawCalls },\n { id: 'ms', header: 'CPU ms', sortable: false, className: s.figure, render: (r) => ms(r.ms) },\n];\n\nexport function FrameView({ client, rootId }: DevtoolsViewProps): ReactElement {\n const state = useRootQuery(client, rootId, [], () => client.request(rootId, { type: 'get-state' }));\n const fps = state.data?.overlays.fps === true;\n const [frame, setFrame] = useState<SerializedValue>(null);\n usePoll(() => {\n client.request(rootId, { type: 'get-frame' }).then(setFrame, () => {});\n }, POLL_MS, fps);\n\n const setFps = (on: boolean): void => {\n client.request(rootId, { type: 'set-overlays', overlays: { fps: on } }).then(state.refresh, state.refresh);\n };\n\n return (\n <div className={s.frame}>\n <Switch isSelected={fps} onChange={setFps} isDisabled={!state.data}>fps overlay</Switch>\n {!fps ? (\n <p className={s.note}>The canvas measures its paints only while the fps overlay is on.</p>\n ) : isFrameStats(frame) ? (\n <>\n <DetailList layout=\"inline\" values=\"figures\">\n <DetailRow label=\"CPU ms\">{ms(frame.paintMs)}</DetailRow>\n <DetailRow label=\"Draw calls\">{frame.drawCalls}</DetailRow>\n </DetailList>\n <DataGrid className={s.layers} rows={frame.layers.map((l) => ({ ...l }))} columns={COLUMNS} empty=\"No layers painted.\" />\n </>\n ) : frame === null ? (\n <p className={s.note}>No paint measured yet.</p>\n ) : (\n <ValueView value={frame} label=\"Frame\" />\n )}\n </div>\n );\n}\n",".history {\n display: flex;\n flex-direction: column;\n flex: 1 1 auto;\n min-height: 0;\n}\n\n.toolbar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wzl-space-4);\n padding: var(--wzl-space-2) var(--wzl-space-4);\n border-bottom: 1px solid var(--wzl-line-subtle);\n flex-shrink: 0;\n}\n\n/* Last in the row and pushed to its end, so its changing width displaces nothing. */\n.position {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n margin-inline-start: auto;\n color: var(--wzl-fg-muted);\n white-space: nowrap;\n}\n\n.body {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n padding: var(--wzl-space-4);\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-6);\n}\n\n.heading {\n margin: 0 0 var(--wzl-space-3);\n font-size: var(--wzl-font-size-sm);\n font-weight: var(--wzl-font-weight-bold);\n}\n\n.stack {\n margin: 0;\n padding-inline-start: var(--wzl-space-8);\n font-family: var(--wzl-font-mono);\n}\n\n.applied {\n color: var(--wzl-fg);\n}\n\n.redoable {\n color: var(--wzl-fg-muted);\n font-style: italic;\n}\n\n.table {\n font-family: var(--wzl-font-mono);\n}\n\n/* Age is live, variable-length text in the leading column: a fixed width keeps\n ticking values from shifting the columns after it. */\n.age {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n width: 7ch;\n min-width: 7ch;\n text-align: end;\n white-space: nowrap;\n}\n\n.figure {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n text-align: end;\n white-space: nowrap;\n}\n\n.entries {\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-4);\n}\n\n.entry {\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-2);\n}\n\n.entryTitle {\n margin: 0;\n display: flex;\n gap: var(--wzl-space-4);\n font-size: var(--wzl-font-size-sm);\n}\n\n.ops {\n margin: 0;\n padding: 0;\n list-style: none;\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-2);\n}\n\n.op {\n display: grid;\n grid-template-columns: auto auto minmax(0, 1fr);\n gap: var(--wzl-space-4);\n align-items: start;\n}\n\n.targets {\n color: var(--wzl-fg-muted);\n}\n\n.note {\n margin: 0;\n color: var(--wzl-fg-muted);\n}\n","/** History steps as rows, newest first; a row opens to the entries it touched and each entry's ops. */\nimport { useState, type ReactElement } from 'react';\nimport type { DevtoolsHistoryRecord } from '@weasel-js/core/devtools-protocol';\nimport { Code } from '@weasel-js/ui/components/Code';\nimport { DataGrid, type DataGridColumn } from '@weasel-js/ui/components/DataGrid';\nimport { formatAge } from './formatAge';\nimport { ValueView } from './ValueView';\nimport s from './HistoryView.module.css';\n\nconst DISPLAY_LIMIT = 100;\n\ninterface StepRow { id: string; step: DevtoolsHistoryRecord }\n\nconst opCount = (step: DevtoolsHistoryRecord): number => step.entries.reduce((n, e) => n + e.opCount, 0);\n\nfunction StepDetail({ step }: { step: DevtoolsHistoryRecord }): ReactElement {\n return (\n <div className={s.entries}>\n {step.entries.map((entry) => (\n <section key={entry.id} className={s.entry} aria-label={`Entry ${entry.label || entry.id}`}>\n <h4 className={s.entryTitle}>\n {entry.label || <span className={s.note}>unlabeled</span>}\n <span className={s.figure}>{entry.opCount} {entry.opCount === 1 ? 'op' : 'ops'}</span>\n </h4>\n <ul className={s.ops}>\n {entry.ops.map((op, i) => (\n <li key={i} className={s.op}>\n <Code size=\"sm\">{op.kind}</Code>\n {op.targets.length > 0 && <span className={s.targets}>{op.targets.join(', ')}</span>}\n <ValueView value={op.summary} label={`${op.kind} arguments`} />\n </li>\n ))}\n </ul>\n </section>\n ))}\n </div>\n );\n}\n\nexport function HistoryTable({ steps, now }: { steps: readonly DevtoolsHistoryRecord[]; now: number }): ReactElement {\n const [expanded, setExpanded] = useState<ReadonlySet<string>>(new Set());\n const rows: StepRow[] = steps.map((step, i) => ({ id: `${step.ts}-${i}`, step })).slice(-DISPLAY_LIMIT).reverse();\n const columns: readonly DataGridColumn<StepRow>[] = [\n { id: 'age', header: 'Age', sortable: false, className: s.age, render: ({ step }) => formatAge(Math.max(0, now - step.ts)) },\n { id: 'step', header: 'Step', sortable: false, render: ({ step }) => step.step },\n {\n id: 'entries',\n header: 'Entries',\n sortable: false,\n render: ({ step }) => step.entries.map((e) => e.label || `#${e.id}`).join(', ') || '—',\n },\n { id: 'ops', header: 'Ops', sortable: false, className: s.figure, render: ({ step }) => opCount(step) },\n {\n id: 'position',\n header: 'Position',\n sortable: false,\n className: s.figure,\n render: ({ step }) => `${step.position.index} / ${step.position.total}`,\n },\n ];\n return (\n <DataGrid\n className={s.table}\n rows={rows}\n columns={columns}\n empty=\"No history steps yet. Edit the scene to fill the log.\"\n rowExpandable={({ step }) => step.entries.length > 0}\n expandedIds={expanded}\n onExpandedChange={setExpanded}\n onRowClick={({ id }) => setExpanded((cur) => (cur.has(id) ? new Set() : new Set([id])))}\n renderDetail={({ step }) => <StepDetail step={step} />}\n />\n );\n}\n","/**\n * The History tab: each step the scene's history took, newest first, read\n * through its cursor whenever a notice reports one; where the history stands;\n * and, on request, every entry on its stacks.\n */\nimport { useEffect, useMemo, useState, type ReactElement } from 'react';\nimport type { DevtoolsHistoryRecord, DevtoolsHistorySlice } from '@weasel-js/core/devtools-protocol';\nimport { Badge } from '@weasel-js/ui/components/Badge';\nimport { Button } from '@weasel-js/ui/components/Button';\nimport { Switch } from '@weasel-js/ui/components/Switch';\nimport type { DevtoolsViewProps } from '../tabs';\nimport { followHistory } from '../history';\nimport { HistoryTable } from './HistoryTable';\nimport s from './HistoryView.module.css';\n\n/** As many steps as a canvas's own buffer holds. */\nconst KEEP = 200;\n\nexport function HistoryView({ client, rootId }: DevtoolsViewProps): ReactElement {\n const follower = useMemo(() => followHistory(client, rootId), [client, rootId]);\n const [steps, setSteps] = useState<DevtoolsHistoryRecord[]>([]);\n const [position, setPosition] = useState<DevtoolsHistorySlice['position'] | null>(null);\n const [checkpoints, setCheckpoints] = useState<DevtoolsHistorySlice['checkpoints'] | null>(null);\n const [showStack, setShowStack] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [now, setNow] = useState(() => Date.now());\n\n useEffect(() => {\n let live = true;\n const read = (): void => {\n follower.read().then((slice) => {\n if (!live) return;\n if (slice.entries.length) setSteps((prev) => [...prev, ...slice.entries].slice(-KEEP));\n setPosition(slice.position);\n setCheckpoints(slice.checkpoints ?? null);\n setNow(Date.now());\n setError(null);\n }, (err: Error) => { if (live) setError(err.message); });\n };\n read();\n const off = client.onChanged((id, areas) => { if (id === rootId && areas.includes('history')) read(); });\n return () => { live = false; off(); };\n }, [client, rootId, follower, showStack]);\n\n const toggleStack = (on: boolean): void => {\n follower.setCheckpoints(on);\n setShowStack(on);\n };\n\n if (error) return <p className={s.note}>{error}</p>;\n\n return (\n <div className={s.history}>\n <div className={s.toolbar}>\n <Badge size=\"sm\" variant=\"subtle\" emphasis={position?.canUndo ? 'high' : 'low'}>\n {position?.canUndo ? 'can undo' : 'nothing to undo'}\n </Badge>\n <Badge size=\"sm\" variant=\"subtle\" emphasis={position?.canRedo ? 'high' : 'low'}>\n {position?.canRedo ? 'can redo' : 'nothing to redo'}\n </Badge>\n <Switch isSelected={showStack} onChange={toggleStack}>checkpoints</Switch>\n <Button size=\"sm\" variant=\"ghost\" disabled={steps.length === 0} onClick={() => setSteps([])}>Clear</Button>\n <span className={s.position} role=\"status\" aria-label=\"Position\" title=\"entries applied / entries in all\">\n {position ? `${position.index} / ${position.total}` : ''}\n </span>\n </div>\n <div className={s.body}>\n {showStack && checkpoints && (\n <section aria-label=\"Checkpoint stack\">\n <h3 className={s.heading}>Checkpoints</h3>\n {checkpoints.length === 0 ? <p className={s.note}>The stacks are empty.</p> : (\n <ol className={s.stack} aria-label=\"Checkpoints\">\n {checkpoints.map((c, i) => (\n <li key={c.id} className={position && i < position.index ? s.applied : s.redoable}>\n {c.label || c.id}\n </li>\n ))}\n </ol>\n )}\n </section>\n )}\n <HistoryTable steps={steps} now={now} />\n </div>\n </div>\n );\n}\n",".split {\n display: grid;\n grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);\n flex: 1 1 auto;\n min-height: 0;\n}\n\n.listPane,\n.detailPane {\n min-height: 0;\n min-width: 0;\n overflow: auto;\n padding: var(--wzl-space-4);\n}\n\n.listPane {\n --wzl-tree-selected: color-mix(in srgb, var(--wzl-accent) 28%, transparent);\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-4);\n border-inline-end: 1px solid var(--wzl-line-subtle);\n}\n\n/* Narrow: the list above the detail, each scrolling on its own. */\n@container (width < 480px) {\n .split {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);\n }\n\n .listPane {\n border-inline-end: none;\n border-block-end: 1px solid var(--wzl-line-subtle);\n }\n}\n","/**\n * A registry as a filterable tree of categories beside the entry picked. The\n * host supplies the categories and renders the detail, so the same screen\n * shows a live canvas's tools, actions and deps or an app's static catalog.\n */\nimport { useEffect, useMemo, useRef, useState, type ReactElement, type ReactNode } from 'react';\nimport { Badge } from '@weasel-js/ui/components/Badge';\nimport { Input } from '@weasel-js/ui/components/Input';\nimport { Tree, filterTree, treeBranchIds, type TreeNode } from '@weasel-js/ui/components/Tree';\nimport s from './RegistryBrowser.module.css';\n\n/** One entry of a {@link RegistryCategory}. */\nexport interface RegistryBrowserEntry {\n /** Unique within its category. */\n id: string;\n label: string;\n /** Further text the filter matches, besides `label`. */\n match?: readonly string[];\n /** Shown at the end of the entry's row: a count, a scope, a state. */\n trailing?: ReactNode;\n}\n\n/** A branch of the {@link RegistryBrowser} tree. Categories sharing a `group.id` nest under one parent branch. */\nexport interface RegistryCategory {\n id: string;\n label: string;\n group?: { id: string; label: string };\n entries: readonly RegistryBrowserEntry[];\n}\n\n/** An entry, by its category and its id there. */\nexport interface RegistryBrowserPick {\n category: string;\n id: string;\n}\n\n/** Props for {@link RegistryBrowser}. */\nexport interface RegistryBrowserProps {\n /** In display order: the browser sorts nothing. */\n categories: readonly RegistryCategory[];\n selected: RegistryBrowserPick | null;\n onSelect(pick: RegistryBrowserPick): void;\n /** The picked entry's detail, or what to show with nothing picked. */\n detail: ReactNode;\n /** Category ids open at mount. Default none. */\n defaultOpen?: Iterable<string>;\n /** Controlled filter text. Omit both to let the browser hold it. */\n filter?: string;\n onFilterChange?(next: string): void;\n /** A leading glyph for the filter field. */\n filterIcon?: ReactNode;\n className?: string;\n}\n\nconst categoryKey = (id: string) => `cat:${id}`;\nconst groupKey = (id: string) => `group:${id}`;\nconst leafKey = (category: string, id: string) => `${category}/${id}`;\n\nconst countBadge = (count: number, className?: string) => (\n <Badge className={className} shape=\"pill\" size=\"sm\" variant=\"solid\">{count}</Badge>\n);\n\nfunction treeOf(categories: readonly RegistryCategory[]) {\n const picks = new Map<string, RegistryBrowserPick>();\n const texts = new Map<string, string[]>();\n const out: TreeNode[] = [];\n const groups = new Map<string, TreeNode & { children: TreeNode[] }>();\n for (const c of categories) {\n const branch: TreeNode = {\n id: categoryKey(c.id),\n label: c.label,\n trailing: countBadge(c.entries.length),\n children: c.entries.map((e) => {\n const key = leafKey(c.id, e.id);\n picks.set(key, { category: c.id, id: e.id });\n texts.set(key, [e.label, ...(e.match ?? [])].map((t) => t.toLowerCase()));\n return { id: key, label: e.label, textValue: e.label, trailing: e.trailing };\n }),\n };\n if (!c.group) {\n out.push(branch);\n continue;\n }\n let group = groups.get(c.group.id);\n if (!group) {\n group = { id: groupKey(c.group.id), label: c.group.label, children: [] };\n groups.set(c.group.id, group);\n out.push(group);\n }\n group.children.push(branch);\n }\n for (const group of groups.values()) group.trailing = countBadge(group.children.length);\n return { nodes: out, picks, texts };\n}\n\n/**\n * A filter field over a tree of registry categories, beside a detail pane.\n * Filtering opens every branch with a match; clearing it restores what was\n * open. Picking an entry from outside the tree opens its category.\n */\nexport function RegistryBrowser(props: RegistryBrowserProps): ReactElement {\n const { categories, selected, onSelect, detail, filterIcon, className } = props;\n const [ownFilter, setOwnFilter] = useState('');\n const filter = props.filter ?? ownFilter;\n const setFilter = props.onFilterChange ?? setOwnFilter;\n const [openIds, setOpenIds] = useState<ReadonlySet<string>>(\n () => new Set([...(props.defaultOpen ?? [])].map(categoryKey)),\n );\n\n // Open the selection's category when the selection moves into it, and only then, so it can still be closed.\n const selectedCategory = selected ? categories.find((c) => c.id === selected.category) ?? null : null;\n const [openedFor, setOpenedFor] = useState<string | null>(null);\n if ((selectedCategory?.id ?? null) !== openedFor) {\n setOpenedFor(selectedCategory?.id ?? null);\n if (selectedCategory) {\n const ids = [categoryKey(selectedCategory.id), ...(selectedCategory.group ? [groupKey(selectedCategory.group.id)] : [])];\n setOpenIds((cur) => (ids.every((id) => cur.has(id)) ? cur : new Set([...cur, ...ids])));\n }\n }\n\n const { nodes, picks, texts } = useMemo(() => treeOf(categories), [categories]);\n const q = filter.trim().toLowerCase();\n const shown = useMemo(\n () => (q ? filterTree(nodes, (n) => texts.get(n.id)?.some((t) => t.includes(q)) ?? false) : nodes),\n [nodes, texts, q],\n );\n const selectedIds = selected ? [leafKey(selected.category, selected.id)] : [];\n\n const treeRef = useRef<HTMLUListElement | null>(null);\n useEffect(() => {\n treeRef.current?.querySelector('[aria-selected=\"true\"]')?.scrollIntoView?.({ block: 'nearest' });\n }, [selected?.category, selected?.id]);\n\n return (\n <div className={[s.split, className].filter(Boolean).join(' ')}>\n <div className={s.listPane} data-pane=\"list\">\n <Input\n aria-label=\"Filter registry\"\n placeholder=\"Filter…\"\n leadingAdornment={filterIcon}\n value={filter}\n onChange={setFilter}\n />\n <Tree\n ref={treeRef}\n aria-label=\"Registry\"\n nodes={shown}\n empty=\"No matches\"\n expandedIds={q ? treeBranchIds(shown) : openIds}\n onExpandedChange={q ? undefined : setOpenIds}\n selectionMode=\"single\"\n selectedIds={selectedIds}\n onAction={(id) => {\n const pick = picks.get(id);\n if (pick) onSelect(pick);\n }}\n />\n </div>\n <div className={s.detailPane} data-pane=\"detail\">{detail}</div>\n </div>\n );\n}\n",".count {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n color: var(--wzl-fg-muted);\n font-weight: normal;\n}\n\n.facts {\n color: var(--wzl-fg-muted);\n font-size: var(--wzl-font-size-xs);\n}\n\n.detail,\n.section {\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-4);\n}\n\n.title,\n.heading {\n margin: 0;\n display: flex;\n align-items: baseline;\n gap: var(--wzl-space-3);\n font-size: var(--wzl-font-size-sm);\n font-weight: var(--wzl-font-weight-bold);\n}\n\n.heading {\n margin-block-start: var(--wzl-space-4);\n}\n\n.codes {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wzl-space-2);\n}\n\n.bindings {\n margin: 0;\n padding: 0;\n list-style: none;\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-3);\n}\n\n.binding {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wzl-space-3);\n}\n\n.routes {\n display: inline-flex;\n flex-wrap: wrap;\n gap: var(--wzl-space-2);\n}\n\n.arrow {\n color: var(--wzl-fg-muted);\n}\n\n.kinds {\n margin: var(--wzl-space-6) 0 0;\n color: var(--wzl-fg-muted);\n font-size: var(--wzl-font-size-xs);\n}\n\n.note {\n margin: 0;\n color: var(--wzl-fg-muted);\n}\n","/** An entry's gesture bindings: each route drawn in the route grammar, beside the action it reaches. */\nimport type { ReactElement } from 'react';\nimport type { DevtoolsBinding } from '@weasel-js/core/devtools-protocol';\nimport { Code } from '@weasel-js/ui/components/Code';\nimport { GestureRoute } from '@weasel-js/ui/components/GestureRoute';\nimport { ValueView } from './ValueView';\nimport s from './RegistryView.module.css';\n\nconst hasOpts = (b: DevtoolsBinding): boolean =>\n typeof b.opts === 'object' && b.opts !== null && Object.keys(b.opts).length > 0;\n\nexport function Bindings({ bindings }: { bindings: readonly DevtoolsBinding[] }): ReactElement {\n return (\n <section className={s.section} aria-label=\"Bindings\">\n <h3 className={s.heading}>Bindings <span className={s.count}>{bindings.length}</span></h3>\n {bindings.length === 0 ? <p className={s.note}>None.</p> : (\n <ul className={s.bindings}>\n {bindings.map((b, i) => (\n <li key={i} className={s.binding}>\n <span className={s.routes}>\n {b.routes.length > 0\n ? b.routes.map((r) => <GestureRoute key={r} route={r} size=\"sm\" />)\n : <ValueView value={b.spec} label=\"Spec\" />}\n </span>\n <span className={s.arrow} aria-hidden>→</span>\n <Code size=\"sm\">{b.actionId}</Code>\n {hasOpts(b) && <ValueView value={b.opts} label={`Options for ${b.actionId}`} />}\n </li>\n ))}\n </ul>\n )}\n </section>\n );\n}\n","/** One registry entry in full: a tool, an action, or a dep. */\nimport type { ReactElement, ReactNode } from 'react';\nimport type { DevtoolsActionEntry, DevtoolsDepEntry, DevtoolsRegistry, DevtoolsToolEntry } from '@weasel-js/core/devtools-protocol';\nimport { Code } from '@weasel-js/ui/components/Code';\nimport { DetailList, DetailRow } from '@weasel-js/ui/components/DetailList';\nimport { Bindings } from './Bindings';\nimport { ValueView } from './ValueView';\nimport s from './RegistryView.module.css';\n\nexport interface RegistryPick {\n category: 'tools' | 'actions' | 'deps';\n id: string;\n}\n\nconst yesNo = (v: boolean): string => (v ? 'yes' : 'no');\nconst codes = (ids: readonly string[]): ReactNode =>\n ids.length ? <span className={s.codes}>{ids.map((id) => <Code key={id} size=\"sm\">{id}</Code>)}</span> : null;\n\nfunction ToolDetail({ tool }: { tool: DevtoolsToolEntry }): ReactElement {\n return (\n <section className={s.detail} aria-label={`Tool ${tool.id}`}>\n <h3 className={s.title}><Code size=\"sm\">{tool.id}</Code></h3>\n <DetailList layout=\"inline\">\n <DetailRow label=\"Slot\">{tool.slot}</DetailRow>\n <DetailRow label=\"Label\">{tool.label}</DetailRow>\n <DetailRow label=\"Group\">{tool.group}</DetailRow>\n <DetailRow label=\"Icon\">{tool.icon}</DetailRow>\n <DetailRow label=\"Shortcut\">{tool.shortcut}</DetailRow>\n <DetailRow label=\"Hotkey\">{tool.hotkey}</DetailRow>\n <DetailRow label=\"Hidden\">{yesNo(tool.hidden)}</DetailRow>\n <DetailRow label=\"Overlay\">{yesNo(tool.hasOverlay)}</DetailRow>\n <DetailRow label=\"Actions\">{codes(tool.actions)}</DetailRow>\n <DetailRow label=\"Deps\">{codes(tool.deps)}</DetailRow>\n </DetailList>\n <Bindings bindings={tool.bindings} />\n <h3 className={s.heading}>Cursor</h3>\n <ValueView value={tool.cursor} label=\"Cursor\" />\n <h3 className={s.heading}>Eligibility</h3>\n <ValueView value={tool.eligibility} label=\"Eligibility\" />\n </section>\n );\n}\n\nfunction ActionDetail({ action }: { action: DevtoolsActionEntry }): ReactElement {\n return (\n <section className={s.detail} aria-label={`Action ${action.id}`}>\n <h3 className={s.title}><Code size=\"sm\">{action.id}</Code></h3>\n <DetailList layout=\"inline\">\n <DetailRow label=\"Label\">{action.label}</DetailRow>\n <DetailRow label=\"Enabled\" grade={action.enabled === true ? 'success' : 'warn'}>\n {action.enabled === true ? 'yes' : action.enabled}\n </DetailRow>\n <DetailRow label=\"Active\">{action.active === null ? 'no pressed state' : yesNo(action.active)}</DetailRow>\n <DetailRow label=\"Scope\">{action.scope}</DetailRow>\n <DetailRow label=\"Invoker\">{action.invoker}</DetailRow>\n <DetailRow label=\"Group\">{action.group}</DetailRow>\n <DetailRow label=\"Tags\">{codes(action.tags)}</DetailRow>\n <DetailRow label=\"Shortcut\">{action.shortcut}</DetailRow>\n <DetailRow label=\"Requires\">{codes(action.requires)}</DetailRow>\n <DetailRow label=\"Preview\">{yesNo(action.hasPreview)}</DetailRow>\n <DetailRow label=\"Variants\">{codes(action.variants.map((v) => v.key))}</DetailRow>\n </DetailList>\n <Bindings bindings={action.bindings} />\n <h3 className={s.heading}>Eligible</h3>\n {action.eligible === null ? <p className={s.note}>Always.</p> : <ValueView value={action.eligible} label=\"Eligible\" />}\n </section>\n );\n}\n\nfunction DepDetail({ dep, users }: { dep: DevtoolsDepEntry; users: string[] }): ReactElement {\n return (\n <section className={s.detail} aria-label={`Dep ${dep.name}`}>\n <h3 className={s.title}><Code size=\"sm\">{dep.name}</Code></h3>\n <DetailList layout=\"inline\">\n <DetailRow label=\"Scope\">{dep.depth === 0 ? 'this canvas' : `${dep.depth} above`}</DetailRow>\n <DetailRow label=\"Stacked\">{dep.stacked}</DetailRow>\n <DetailRow label=\"Required by\">{codes(users)}</DetailRow>\n </DetailList>\n </section>\n );\n}\n\nexport function RegistryEntryDetail({ registry, pick }: { registry: DevtoolsRegistry; pick: RegistryPick }): ReactElement {\n if (pick.category === 'tools') {\n const tool = registry.tools.find((t) => t.id === pick.id);\n if (tool) return <ToolDetail tool={tool} />;\n } else if (pick.category === 'actions') {\n const action = registry.actions.find((a) => a.id === pick.id);\n if (action) return <ActionDetail action={action} />;\n } else {\n const dep = registry.deps.find((d) => d.name === pick.id);\n const users = registry.actions.filter((a) => a.requires.includes(pick.id)).map((a) => a.id);\n if (dep) return <DepDetail dep={dep} users={users} />;\n }\n return <p className={s.note}>{pick.id} is no longer registered.</p>;\n}\n","/**\n * The Registry tab: what the canvas has registered, filtered by name, beside\n * the entry picked. Re-read when the registry changes, and on selection and\n * scene changes too, since an action's `enabled` and `active` move with them\n * and no notice reports that.\n */\nimport { useMemo, useState, type ReactElement } from 'react';\nimport type { DevtoolsRegistry } from '@weasel-js/core/devtools-protocol';\nimport { useRootQuery } from '../hooks';\nimport type { DevtoolsViewProps } from '../tabs';\nimport { RegistryBrowser, type RegistryBrowserPick, type RegistryCategory } from './RegistryBrowser';\nimport { RegistryEntryDetail, type RegistryPick } from './RegistryEntryDetail';\nimport s from './RegistryView.module.css';\n\nconst CATEGORIES = ['tools', 'actions', 'deps'] as const;\nconst TITLES = { tools: 'Tools', actions: 'Actions', deps: 'Deps' } as const;\n\ninterface Row { id: string; facts: string }\n\nfunction rowsOf(reg: DevtoolsRegistry, category: (typeof CATEGORIES)[number]): Row[] {\n switch (category) {\n case 'tools': return reg.tools.map((t) => ({ id: t.id, facts: t.slot }));\n case 'actions': return reg.actions.map((a) => ({\n id: a.id, facts: [a.scope, a.enabled === true ? '' : 'disabled', a.active ? 'active' : ''].filter(Boolean).join(' '),\n }));\n case 'deps': return reg.deps.map((d) => ({ id: d.name, facts: d.depth === 0 ? '' : `+${d.depth}` }));\n }\n}\n\nfunction categoriesOf(reg: DevtoolsRegistry): RegistryCategory[] {\n return CATEGORIES.map((category) => ({\n id: category,\n label: TITLES[category],\n entries: rowsOf(reg, category).map((r) => ({\n id: r.id,\n label: r.id,\n ...(r.facts ? { trailing: <span className={s.facts}>{r.facts}</span> } : {}),\n })),\n }));\n}\n\nexport function RegistryView({ client, rootId }: DevtoolsViewProps): ReactElement {\n const registry = useRootQuery(\n client, rootId, ['registry', 'selection', 'scene'], () => client.request(rootId, { type: 'get-registry' }),\n );\n const [picked, setPicked] = useState<RegistryBrowserPick | null>(null);\n const reg = registry.data;\n const categories = useMemo(() => (reg ? categoriesOf(reg) : []), [reg]);\n\n if (registry.error) return <p className={s.note}>{registry.error}</p>;\n if (!reg) return <p className={s.note}>Loading…</p>;\n\n return (\n <RegistryBrowser\n categories={categories}\n defaultOpen={CATEGORIES}\n selected={picked}\n onSelect={setPicked}\n detail={\n <>\n {picked\n ? <RegistryEntryDetail registry={reg} pick={picked as RegistryPick} />\n : <p className={s.note}>Pick an entry to see its bindings.</p>}\n {reg.routingKinds.length > 0 && (\n <p className={s.kinds}>Routing kinds: {reg.routingKinds.join(', ')}</p>\n )}\n </>\n }\n />\n );\n}\n",".split {\n display: grid;\n grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);\n flex: 1 1 auto;\n min-height: 0;\n}\n\n.treePane,\n.detailPane {\n min-height: 0;\n min-width: 0;\n overflow: auto;\n padding: var(--wzl-space-4);\n}\n\n.treePane {\n border-inline-end: 1px solid var(--wzl-line-subtle);\n --wzl-tree-selected: color-mix(in srgb, var(--wzl-accent) 28%, transparent);\n}\n\n.facts {\n display: inline-flex;\n gap: var(--wzl-space-3);\n color: var(--wzl-fg-muted);\n font-size: var(--wzl-font-size-xs);\n}\n\n.kind,\n.layer {\n white-space: nowrap;\n}\n\n.count {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n min-width: 3ch;\n text-align: end;\n}\n\n.flag {\n color: var(--wzl-warning);\n}\n\n.detail {\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-4);\n}\n\n.detailHead {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--wzl-space-4);\n}\n\n.heading {\n margin: var(--wzl-space-4) 0 0;\n font-size: var(--wzl-font-size-sm);\n font-weight: var(--wzl-font-weight-bold);\n}\n\n.note {\n margin: 0;\n color: var(--wzl-fg-muted);\n}\n\n/* Narrow: the list above the detail, each scrolling on its own. */\n@container (width < 480px) {\n .split {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);\n }\n\n .treePane {\n border-inline-end: none;\n border-block-end: 1px solid var(--wzl-line-subtle);\n }\n}\n","/** One node as `get-node` describes it, re-read whenever the scene changes. */\nimport type { ReactElement } from 'react';\nimport { Button } from '@weasel-js/ui/components/Button';\nimport { Code } from '@weasel-js/ui/components/Code';\nimport { DetailList, DetailRow } from '@weasel-js/ui/components/DetailList';\nimport type { DevtoolsClient } from '../client';\nimport { useRootQuery } from '../hooks';\nimport { ValueView } from './ValueView';\nimport s from './SceneView.module.css';\n\nexport interface NodeDetailProps {\n client: DevtoolsClient;\n rootId: string;\n nodeId: string;\n /** Show another node: the parent, when its id is pressed. */\n onPick(nodeId: string): void;\n}\n\nconst yesNo = (v: boolean): string => (v ? 'yes' : 'no');\n\nexport function NodeDetail({ client, rootId, nodeId, onPick }: NodeDetailProps): ReactElement {\n const node = useRootQuery(client, rootId, ['scene'], () => client.request(rootId, { type: 'get-node', nodeId }));\n if (node.error) return <p className={s.note}>{node.error}</p>;\n const d = node.data;\n if (!d) return <p className={s.note}>Loading…</p>;\n return (\n <div className={s.detail}>\n <div className={s.detailHead}>\n <Code size=\"sm\">{d.id}</Code>\n <Button\n size=\"sm\"\n onClick={() => { client.request(rootId, { type: 'select', ids: [d.id] }).catch(() => {}); }}\n >\n Select on canvas\n </Button>\n </div>\n <DetailList layout=\"inline\">\n <DetailRow label=\"Kind\">{d.kind}</DetailRow>\n <DetailRow label=\"Layer\">{d.layer}</DetailRow>\n <DetailRow label=\"Parent\">\n {d.parent && (\n <Button size=\"sm\" variant=\"link\" onClick={() => onPick(d.parent!)} ariaLabel={`Show parent ${d.parent}`}>\n {d.parent}\n </Button>\n )}\n </DetailRow>\n <DetailRow label=\"Children\">{d.childCount}</DetailRow>\n <DetailRow label=\"Hidden\">{yesNo(d.hidden)}</DetailRow>\n <DetailRow label=\"Locked\">{yesNo(d.locked)}</DetailRow>\n <DetailRow label=\"Pickable\">{yesNo(d.pickable)}</DetailRow>\n </DetailList>\n <h3 className={s.heading}>Pose</h3>\n <ValueView value={d.pose} label=\"Pose\" />\n <h3 className={s.heading}>Data</h3>\n <ValueView value={d.data} label=\"Data\" />\n </div>\n );\n}\n","/** A root's scene tree, loaded a level at a time as branches open, and reloaded where it is open when the scene changes. */\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { DevtoolsNodeSummary } from '@weasel-js/core/devtools-protocol';\nimport { useLatest } from '@weasel-js/react';\nimport type { DevtoolsClient } from '../client';\n\n/** The key the top level is held under. */\nconst TOP = '';\n\nexport interface SceneTree {\n /** Each loaded level, by parent id; the top level under `''`. */\n levels: ReadonlyMap<string, readonly DevtoolsNodeSummary[]>;\n expanded: ReadonlySet<string>;\n setExpanded(ids: Set<string>): void;\n /** Why the top level could not be read, such as a scene not mounted yet. */\n error: string | null;\n}\n\nexport function useSceneTree(client: DevtoolsClient, rootId: string): SceneTree {\n const [levels, setLevels] = useState<ReadonlyMap<string, readonly DevtoolsNodeSummary[]>>(new Map());\n const [expanded, setExpandedState] = useState<ReadonlySet<string>>(new Set());\n const [error, setError] = useState<string | null>(null);\n const expandedRef = useLatest(expanded);\n const alive = useRef(true);\n useEffect(() => {\n alive.current = true;\n return () => { alive.current = false; };\n }, []);\n\n const load = useCallback((parent: string): void => {\n const body = parent === TOP ? { type: 'get-children' as const } : { type: 'get-children' as const, nodeId: parent };\n client.request(rootId, body).then(\n (rows) => {\n if (!alive.current) return;\n setLevels((prev) => new Map(prev).set(parent, rows));\n if (parent === TOP) setError(null);\n },\n (err: Error) => {\n if (!alive.current) return;\n if (parent === TOP) setError(err.message);\n setLevels((prev) => {\n const next = new Map(prev);\n next.delete(parent);\n return next;\n });\n },\n );\n }, [client, rootId]);\n\n useEffect(() => {\n load(TOP);\n return client.onChanged((id, areas) => {\n if (id !== rootId || !areas.includes('scene')) return;\n load(TOP);\n for (const open of expandedRef.current) load(open);\n });\n }, [client, rootId, load, expandedRef]);\n\n const setExpanded = useCallback((ids: Set<string>): void => {\n for (const id of ids) if (!expandedRef.current.has(id)) load(id);\n setExpandedState(ids);\n }, [load, expandedRef]);\n\n return { levels, expanded, setExpanded, error };\n}\n","/** The Scene tab: a root's node tree beside the node picked in it. */\nimport { useRef, useState, type PointerEvent, type ReactElement } from 'react';\nimport type { DevtoolsNodeSummary } from '@weasel-js/core/devtools-protocol';\nimport { Tree, type TreeNode } from '@weasel-js/ui/components/Tree';\nimport type { DevtoolsViewProps } from '../tabs';\nimport { NodeDetail } from './NodeDetail';\nimport { useSceneTree } from './useSceneTree';\nimport s from './SceneView.module.css';\n\nfunction flags(row: DevtoolsNodeSummary): string[] {\n return [row.hidden && 'hidden', row.locked && 'locked', !row.pickable && 'unpickable'].filter(\n (f): f is string => typeof f === 'string',\n );\n}\n\nfunction RowFacts({ row }: { row: DevtoolsNodeSummary }): ReactElement {\n return (\n <span className={s.facts}>\n <span className={s.kind}>{row.kind}</span>\n <span className={s.layer}>{row.layer}</span>\n {row.kind === 'group' && <span className={s.count}>{row.childCount}</span>}\n {flags(row).map((f) => <span key={f} className={s.flag}>{f}</span>)}\n </span>\n );\n}\n\nfunction toNodes(levels: ReadonlyMap<string, readonly DevtoolsNodeSummary[]>, parent: string): TreeNode[] {\n return (levels.get(parent) ?? []).map((row) => ({\n id: row.id,\n textValue: row.id,\n label: <span data-node-id={row.id}>{row.id}</span>,\n trailing: <RowFacts row={row} />,\n muted: row.hidden,\n ...(row.kind === 'group' && row.childCount > 0 ? { children: toNodes(levels, row.id) } : {}),\n }));\n}\n\nexport function SceneView({ client, rootId }: DevtoolsViewProps): ReactElement {\n const tree = useSceneTree(client, rootId);\n const [selected, setSelected] = useState<string | null>(null);\n const hovered = useRef<string | null>(null);\n\n const highlight = (id: string | null): void => {\n if (hovered.current === id) return;\n hovered.current = id;\n client.request(rootId, { type: 'highlight', ids: id ? [id] : [] }).catch(() => {});\n };\n const onPointerOver = (e: PointerEvent<HTMLDivElement>): void => {\n const row = (e.target as Element).closest('[role=\"treeitem\"]');\n highlight(row?.querySelector('[data-node-id]')?.getAttribute('data-node-id') ?? null);\n };\n\n return (\n <div className={s.split}>\n <div className={s.treePane} data-pane=\"tree\" onPointerOver={onPointerOver} onPointerLeave={() => highlight(null)}>\n <Tree\n aria-label=\"Scene nodes\"\n nodes={toNodes(tree.levels, '')}\n empty={<p className={s.note}>{tree.error ?? 'The scene is empty.'}</p>}\n expandedIds={tree.expanded}\n onExpandedChange={tree.setExpanded}\n selectionMode=\"single\"\n selectedIds={selected ? [selected] : []}\n onSelectionChange={(ids) => setSelected(ids.values().next().value ?? null)}\n />\n </div>\n <div className={s.detailPane} data-pane=\"detail\">\n {selected\n ? <NodeDetail key={selected} client={client} rootId={rootId} nodeId={selected} onPick={setSelected} />\n : <p className={s.note}>Pick a node to see its pose and data.</p>}\n </div>\n </div>\n );\n}\n",".state {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n padding: var(--wzl-space-4);\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-6);\n}\n\n.section {\n display: flex;\n flex-direction: column;\n gap: var(--wzl-space-3);\n}\n\n.heading {\n margin: 0;\n display: flex;\n align-items: baseline;\n gap: var(--wzl-space-3);\n font-size: var(--wzl-font-size-sm);\n font-weight: var(--wzl-font-weight-bold);\n}\n\n.count {\n composes: numeric from '@weasel-js/theme/numeric.module.css';\n color: var(--wzl-fg-muted);\n font-weight: normal;\n}\n\n.ids {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wzl-space-2);\n}\n\n.flags {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(12ch, 1fr));\n gap: var(--wzl-space-3) var(--wzl-space-6);\n}\n\n.probe {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr);\n gap: var(--wzl-space-4);\n align-items: start;\n}\n\n.note {\n margin: 0;\n color: var(--wzl-fg-muted);\n}\n","/** The State tab: selection, view, the active tool and the overlay flags, with the two the panel may steer. */\nimport type { ReactElement } from 'react';\nimport { DEBUG_FEATURES } from '@weasel-js/core';\nimport { Code } from '@weasel-js/ui/components/Code';\nimport { Select } from '@weasel-js/ui/components/Select';\nimport { Switch } from '@weasel-js/ui/components/Switch';\nimport { useRootQuery } from '../hooks';\nimport type { DevtoolsViewProps } from '../tabs';\nimport { ValueView } from './ValueView';\nimport s from './StateView.module.css';\n\n/** The tool picker's value for \"no tool\": a select key cannot be null. */\nconst NO_TOOL = '\\u0000none';\n\nexport function StateView({ client, rootId }: DevtoolsViewProps): ReactElement {\n const state = useRootQuery(client, rootId, ['selection', 'view', 'tool'], () => client.request(rootId, { type: 'get-state' }));\n if (state.error) return <p className={s.note}>{state.error}</p>;\n const st = state.data;\n if (!st) return <p className={s.note}>Loading…</p>;\n\n const steer = (p: Promise<unknown>): void => { p.then(state.refresh, state.refresh); };\n const probes = Object.entries(st.probes);\n\n return (\n <div className={s.state}>\n <section className={s.section} aria-label=\"Selection\">\n <h3 className={s.heading}>Selection <span className={s.count}>{st.selection.length}</span></h3>\n {st.selection.length === 0\n ? <p className={s.note}>Nothing selected.</p>\n : <div className={s.ids}>{st.selection.map((id) => <Code key={id} size=\"sm\">{id}</Code>)}</div>}\n </section>\n\n <section className={s.section} aria-label=\"Tool\">\n <h3 className={s.heading}>Tool</h3>\n <Select\n aria-label=\"Active tool\"\n width=\"fit\"\n selectedKey={st.activeTool ?? NO_TOOL}\n onSelectionChange={(key) => {\n steer(client.request(rootId, { type: 'set-tool', toolId: key === NO_TOOL ? null : key }));\n }}\n options={[{ value: NO_TOOL, label: 'none' }, ...st.tools.map((t) => ({ value: t, label: t }))]}\n />\n </section>\n\n <section className={s.section} aria-label=\"Overlays\">\n <h3 className={s.heading}>Overlays</h3>\n <div className={s.flags}>\n {DEBUG_FEATURES.map((flag) => (\n <Switch\n key={flag}\n isSelected={st.overlays[flag] === true}\n onChange={(on) => steer(client.request(rootId, { type: 'set-overlays', overlays: { [flag]: on } }))}\n >\n {flag}\n </Switch>\n ))}\n </div>\n </section>\n\n <section className={s.section} aria-label=\"View\">\n <h3 className={s.heading}>View</h3>\n <ValueView value={st.view} label=\"View\" />\n </section>\n\n <section className={s.section} aria-label=\"Probes\">\n <h3 className={s.heading}>Probes</h3>\n {probes.length === 0\n ? <p className={s.note}>No probes registered.</p>\n : probes.map(([name, value]) => (\n <div key={name} className={s.probe}>\n <Code size=\"sm\">{name}</Code>\n <ValueView value={value} label={name} />\n </div>\n ))}\n </section>\n </div>\n );\n}\n","/** The panel's tabs, in order. A new area of the protocol is a new entry here and a view of its own. */\nimport type { ComponentType } from 'react';\nimport type { DevtoolsClient } from './client';\nimport { DispatchView } from './views/DispatchView';\nimport { FrameView } from './views/FrameView';\nimport { HistoryView } from './views/HistoryView';\nimport { RegistryView } from './views/RegistryView';\nimport { SceneView } from './views/SceneView';\nimport { StateView } from './views/StateView';\n\n/** What every tab's view is handed: the connection, and the root the picker has chosen. */\nexport interface DevtoolsViewProps {\n client: DevtoolsClient;\n rootId: string;\n}\n\n/** A tab of the panel, as `DevtoolsPanel`'s `tabs` and `defaultTab` name it. */\nexport type DevtoolsTabId = 'scene' | 'state' | 'registry' | 'dispatch' | 'history' | 'frame';\n\nexport interface DevtoolsTab {\n id: DevtoolsTabId;\n label: string;\n View: ComponentType<DevtoolsViewProps>;\n}\n\nexport const DEVTOOLS_TABS: readonly DevtoolsTab[] = [\n { id: 'scene', label: 'Scene', View: SceneView },\n { id: 'state', label: 'State', View: StateView },\n { id: 'registry', label: 'Registry', View: RegistryView },\n { id: 'dispatch', label: 'Dispatch', View: DispatchView },\n { id: 'history', label: 'History', View: HistoryView },\n { id: 'frame', label: 'Frame', View: FrameView },\n];\n","import { useState, type ReactElement } from 'react';\nimport type { PanelTransport } from '@weasel-js/core/devtools-protocol';\nimport { Tab, TabList, TabPanel, Tabs } from '@weasel-js/ui/components/Tabs';\nimport { useDevtoolsClient } from './hooks';\nimport { RootPicker } from './RootPicker';\nimport type { DevtoolsClient } from './client';\nimport { DEVTOOLS_TABS, type DevtoolsTab, type DevtoolsTabId } from './tabs';\nimport s from './DevtoolsPanel.module.css';\n\n/** Props for {@link DevtoolsPanel}. */\nexport interface DevtoolsPanelProps {\n /** The panel's end of a connection to a page's devtools hook. */\n transport: PanelTransport;\n /** The tabs to show, in the panel's own order. Default: every tab. With one, the tab bar is left out. */\n tabs?: readonly DevtoolsTabId[];\n /** The tab open first. Default: the first shown. */\n defaultTab?: DevtoolsTabId;\n className?: string;\n}\n\n/**\n * Reads and steers the canvases of the page `transport` reaches: pick a canvas,\n * then walk its scene, read its state, follow its dispatch trace, or watch its\n * frame stats. It fills its container; give that a size.\n */\nexport function DevtoolsPanel({ transport, tabs, defaultTab, className }: DevtoolsPanelProps): ReactElement {\n const { client, state } = useDevtoolsClient(transport);\n const shown = tabs ? DEVTOOLS_TABS.filter((t) => tabs.includes(t.id)) : DEVTOOLS_TABS;\n const [tab, setTab] = useState<DevtoolsTabId>(defaultTab ?? shown[0]?.id ?? 'scene');\n const [picked, setPicked] = useState<string | null>(null);\n const rootId = state.roots.some((r) => r.id === picked) ? picked : state.roots[0]?.id ?? null;\n\n return (\n <section className={[s.panel, className].filter(Boolean).join(' ')} aria-label=\"Devtools\">\n <div className={s.bar}>\n <RootPicker roots={state.roots} value={rootId} onChange={setPicked} />\n <span className={s.status}>{statusText(state.status, state.kitVersion, state.error)}</span>\n </div>\n {rootId && shown.length === 1 ? (\n <div className={s.tabPanel}>{renderView(shown[0]!.View, client, rootId)}</div>\n ) : rootId ? (\n <Tabs className={s.tabs} selectedKey={tab} onSelectionChange={(k) => setTab(k as DevtoolsTabId)}>\n <TabList aria-label=\"Devtools areas\" className={s.tabList}>\n {shown.map((t) => <Tab key={t.id} id={t.id}>{t.label}</Tab>)}\n </TabList>\n {shown.map(({ id, View }) => (\n <TabPanel key={id} id={id} className={s.tabPanel}>\n {renderView(View, client, rootId)}\n </TabPanel>\n ))}\n </Tabs>\n ) : (\n <p className={s.empty}>{state.status === 'connected' ? 'No canvas on this page.' : 'Connecting…'}</p>\n )}\n </section>\n );\n}\n\n/** A view keyed by its root, so picking another canvas starts it fresh. */\nfunction renderView(View: DevtoolsTab['View'], client: DevtoolsClient, rootId: string): ReactElement {\n return <View key={rootId} client={client} rootId={rootId} />;\n}\n\nfunction statusText(status: string, kitVersion: string | null, error: string | null): string {\n if (status === 'error') return error ?? 'error';\n if (status === 'connected') return `weasel ${kitVersion ?? ''}`;\n return status;\n}\n","import {\n createInPageTransports, installDevtoolsHook, type PanelTransport, type WeaselDevtoolsHook,\n} from '@weasel-js/core/devtools-protocol';\n\n/**\n * A panel's end of a connection to this page's own hook. Each `yo` opens a\n * fresh session and each `bye` ends it, the way a `yo` posted to the window\n * does, so a panel that unmounts and mounts again reconnects. Installs the\n * hook when the page has none.\n */\nexport function createInPagePanelTransport(hook: WeaselDevtoolsHook | null = installDevtoolsHook()): PanelTransport {\n const { page, panel } = createInPageTransports();\n let close: (() => void) | null = null;\n return {\n send(message) {\n if (message.type === 'yo' && hook) {\n close?.();\n close = hook.connect(page);\n }\n panel.send(message);\n if (message.type === 'bye') {\n close?.();\n close = null;\n }\n },\n onMessage: (listener) => panel.onMessage(listener),\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weasel-js/devtools",
3
- "version": "1.15.0",
3
+ "version": "1.15.1",
4
4
  "description": "A devtools panel for weasel canvases: each canvas's scene tree, state, dispatch trace and frame stats, read and steered over the devtools hook's protocol.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -40,11 +40,11 @@
40
40
  "build": "vite build && tsc -p tsconfig.build.json"
41
41
  },
42
42
  "dependencies": {
43
- "@weasel-js/react": "1.15.0",
44
- "@weasel-js/ui": "1.15.0"
43
+ "@weasel-js/react": "1.15.1",
44
+ "@weasel-js/ui": "1.15.1"
45
45
  },
46
46
  "peerDependencies": {
47
- "@weasel-js/core": "1.15.0",
47
+ "@weasel-js/core": "1.15.1",
48
48
  "react": ">=18",
49
49
  "react-dom": ">=18"
50
50
  },