@oddsquad/vite-plugin-lit 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (292) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/LICENSE +1 -1
  3. package/README.md +14 -7
  4. package/bin.mjs +2 -8
  5. package/client.d.ts +0 -6
  6. package/dist/client/assets/{browser-agent-rpc-BXhoSh1z-BuCvPGjS.js → browser-agent-rpc-BXhoSh1z-ybEeG-x9.js} +2 -2
  7. package/dist/client/assets/{browser-agent-rpc-BXhoSh1z-BuCvPGjS.js.map → browser-agent-rpc-BXhoSh1z-ybEeG-x9.js.map} +1 -1
  8. package/dist/client/assets/{index-D632jo79.js → index-CgkhETVR.js} +2 -144
  9. package/dist/client/assets/index-CgkhETVR.js.map +1 -0
  10. package/dist/client/index.html +1 -1
  11. package/dist/standalone/lit-devtools.js +2 -105
  12. package/index.d.ts +0 -5
  13. package/index.d.ts.map +1 -1
  14. package/index.js +1 -5
  15. package/index.js.map +1 -1
  16. package/lib/color-scheme.d.ts +0 -5
  17. package/lib/color-scheme.d.ts.map +1 -1
  18. package/lib/color-scheme.js +0 -5
  19. package/lib/color-scheme.js.map +1 -1
  20. package/lib/confine.d.ts +0 -5
  21. package/lib/confine.d.ts.map +1 -1
  22. package/lib/confine.js +0 -5
  23. package/lib/confine.js.map +1 -1
  24. package/lib/devframe/allowed-origins.d.ts +11 -3
  25. package/lib/devframe/allowed-origins.d.ts.map +1 -1
  26. package/lib/devframe/allowed-origins.js +0 -5
  27. package/lib/devframe/allowed-origins.js.map +1 -1
  28. package/lib/devframe/definition.d.ts +7 -3
  29. package/lib/devframe/definition.d.ts.map +1 -1
  30. package/lib/devframe/definition.js +1 -6
  31. package/lib/devframe/definition.js.map +1 -1
  32. package/lib/devframe/icon.d.ts +0 -5
  33. package/lib/devframe/icon.d.ts.map +1 -1
  34. package/lib/devframe/icon.js +0 -5
  35. package/lib/devframe/icon.js.map +1 -1
  36. package/lib/devframe/launch-editor.d.ts +0 -5
  37. package/lib/devframe/launch-editor.d.ts.map +1 -1
  38. package/lib/devframe/launch-editor.js +0 -5
  39. package/lib/devframe/launch-editor.js.map +1 -1
  40. package/lib/devframe/paths.d.ts +8 -3
  41. package/lib/devframe/paths.d.ts.map +1 -1
  42. package/lib/devframe/paths.js +0 -5
  43. package/lib/devframe/paths.js.map +1 -1
  44. package/lib/devframe/protocol.d.ts +6 -3
  45. package/lib/devframe/protocol.d.ts.map +1 -1
  46. package/lib/devframe/protocol.js +0 -5
  47. package/lib/devframe/protocol.js.map +1 -1
  48. package/lib/devframe/rpc-source.d.ts +15 -3
  49. package/lib/devframe/rpc-source.d.ts.map +1 -1
  50. package/lib/devframe/rpc-source.js +0 -5
  51. package/lib/devframe/rpc-source.js.map +1 -1
  52. package/lib/devframe/source.d.ts +0 -5
  53. package/lib/devframe/source.d.ts.map +1 -1
  54. package/lib/devframe/source.js +7 -3
  55. package/lib/devframe/source.js.map +1 -1
  56. package/lib/devframe/vite.d.ts +0 -5
  57. package/lib/devframe/vite.d.ts.map +1 -1
  58. package/lib/devframe/vite.js +16 -3
  59. package/lib/devframe/vite.js.map +1 -1
  60. package/lib/http.d.ts +0 -5
  61. package/lib/http.d.ts.map +1 -1
  62. package/lib/http.js +0 -5
  63. package/lib/http.js.map +1 -1
  64. package/lib/icons.d.ts +0 -5
  65. package/lib/icons.d.ts.map +1 -1
  66. package/lib/icons.js +0 -5
  67. package/lib/icons.js.map +1 -1
  68. package/lib/options.d.ts +0 -5
  69. package/lib/options.d.ts.map +1 -1
  70. package/lib/options.js +0 -5
  71. package/lib/options.js.map +1 -1
  72. package/lib/override-baselines.d.ts +0 -5
  73. package/lib/override-baselines.d.ts.map +1 -1
  74. package/lib/override-baselines.js +0 -5
  75. package/lib/override-baselines.js.map +1 -1
  76. package/lib/plugin.d.ts +0 -5
  77. package/lib/plugin.d.ts.map +1 -1
  78. package/lib/plugin.js +0 -5
  79. package/lib/plugin.js.map +1 -1
  80. package/lib/plugins/css-literals.d.ts +0 -5
  81. package/lib/plugins/css-literals.d.ts.map +1 -1
  82. package/lib/plugins/css-literals.js +0 -5
  83. package/lib/plugins/css-literals.js.map +1 -1
  84. package/lib/plugins/css-queries.d.ts +0 -5
  85. package/lib/plugins/css-queries.d.ts.map +1 -1
  86. package/lib/plugins/css-queries.js +0 -5
  87. package/lib/plugins/css-queries.js.map +1 -1
  88. package/lib/plugins/open-in-editor.d.ts +0 -5
  89. package/lib/plugins/open-in-editor.d.ts.map +1 -1
  90. package/lib/plugins/open-in-editor.js +0 -5
  91. package/lib/plugins/open-in-editor.js.map +1 -1
  92. package/lib/plugins/private-fields.d.ts +0 -5
  93. package/lib/plugins/private-fields.d.ts.map +1 -1
  94. package/lib/plugins/private-fields.js +0 -5
  95. package/lib/plugins/private-fields.js.map +1 -1
  96. package/lib/plugins/shared.d.ts +0 -5
  97. package/lib/plugins/shared.d.ts.map +1 -1
  98. package/lib/plugins/shared.js +0 -5
  99. package/lib/plugins/shared.js.map +1 -1
  100. package/lib/plugins/timeline-virtual.d.ts +0 -5
  101. package/lib/plugins/timeline-virtual.d.ts.map +1 -1
  102. package/lib/plugins/timeline-virtual.js +0 -5
  103. package/lib/plugins/timeline-virtual.js.map +1 -1
  104. package/lib/runtime/child-state.d.ts +0 -5
  105. package/lib/runtime/child-state.d.ts.map +1 -1
  106. package/lib/runtime/child-state.js +18 -3
  107. package/lib/runtime/child-state.js.map +1 -1
  108. package/lib/runtime/css.d.ts +14 -3
  109. package/lib/runtime/css.d.ts.map +1 -1
  110. package/lib/runtime/css.js +3 -5
  111. package/lib/runtime/css.js.map +1 -1
  112. package/lib/runtime/edge-panel.d.ts +8 -3
  113. package/lib/runtime/edge-panel.d.ts.map +1 -1
  114. package/lib/runtime/edge-panel.js +0 -5
  115. package/lib/runtime/edge-panel.js.map +1 -1
  116. package/lib/runtime/fonts.d.ts +0 -5
  117. package/lib/runtime/fonts.d.ts.map +1 -1
  118. package/lib/runtime/fonts.js +0 -5
  119. package/lib/runtime/fonts.js.map +1 -1
  120. package/lib/runtime/indicator.d.ts +3 -3
  121. package/lib/runtime/indicator.js +0 -5
  122. package/lib/runtime/indicator.js.map +1 -1
  123. package/lib/runtime/inspector/collect.d.ts +3 -3
  124. package/lib/runtime/inspector/collect.d.ts.map +1 -1
  125. package/lib/runtime/inspector/collect.js +0 -5
  126. package/lib/runtime/inspector/collect.js.map +1 -1
  127. package/lib/runtime/inspector/highlight.d.ts +10 -3
  128. package/lib/runtime/inspector/highlight.d.ts.map +1 -1
  129. package/lib/runtime/inspector/highlight.js +0 -5
  130. package/lib/runtime/inspector/highlight.js.map +1 -1
  131. package/lib/runtime/inspector/install.d.ts +6 -3
  132. package/lib/runtime/inspector/install.d.ts.map +1 -1
  133. package/lib/runtime/inspector/install.js +0 -5
  134. package/lib/runtime/inspector/install.js.map +1 -1
  135. package/lib/runtime/inspector/serialize.d.ts +4 -3
  136. package/lib/runtime/inspector/serialize.d.ts.map +1 -1
  137. package/lib/runtime/inspector/serialize.js +0 -5
  138. package/lib/runtime/inspector/serialize.js.map +1 -1
  139. package/lib/runtime/intern.d.ts +11 -3
  140. package/lib/runtime/intern.d.ts.map +1 -1
  141. package/lib/runtime/intern.js +11 -3
  142. package/lib/runtime/intern.js.map +1 -1
  143. package/lib/runtime/overrides.d.ts +3 -3
  144. package/lib/runtime/overrides.d.ts.map +1 -1
  145. package/lib/runtime/overrides.js +0 -5
  146. package/lib/runtime/overrides.js.map +1 -1
  147. package/lib/runtime/page-channel.d.ts +0 -5
  148. package/lib/runtime/page-channel.d.ts.map +1 -1
  149. package/lib/runtime/page-channel.js +13 -3
  150. package/lib/runtime/page-channel.js.map +1 -1
  151. package/lib/runtime/patch.d.ts +0 -5
  152. package/lib/runtime/patch.d.ts.map +1 -1
  153. package/lib/runtime/patch.js +0 -5
  154. package/lib/runtime/patch.js.map +1 -1
  155. package/lib/runtime/rpc-transport.d.ts +13 -3
  156. package/lib/runtime/rpc-transport.d.ts.map +1 -1
  157. package/lib/runtime/rpc-transport.js +3 -5
  158. package/lib/runtime/rpc-transport.js.map +1 -1
  159. package/lib/runtime/source-meta.d.ts +0 -5
  160. package/lib/runtime/source-meta.d.ts.map +1 -1
  161. package/lib/runtime/source-meta.js +0 -5
  162. package/lib/runtime/source-meta.js.map +1 -1
  163. package/lib/runtime/source-overlay/editors.d.ts +0 -5
  164. package/lib/runtime/source-overlay/editors.d.ts.map +1 -1
  165. package/lib/runtime/source-overlay/editors.js +0 -5
  166. package/lib/runtime/source-overlay/editors.js.map +1 -1
  167. package/lib/runtime/source-overlay/mask-path.d.ts +0 -5
  168. package/lib/runtime/source-overlay/mask-path.d.ts.map +1 -1
  169. package/lib/runtime/source-overlay/mask-path.js +0 -5
  170. package/lib/runtime/source-overlay/mask-path.js.map +1 -1
  171. package/lib/runtime/source-overlay/overlay-element.d.ts +0 -5
  172. package/lib/runtime/source-overlay/overlay-element.d.ts.map +1 -1
  173. package/lib/runtime/source-overlay/overlay-element.js +0 -5
  174. package/lib/runtime/source-overlay/overlay-element.js.map +1 -1
  175. package/lib/runtime/source-overlay/source-host.d.ts +0 -5
  176. package/lib/runtime/source-overlay/source-host.d.ts.map +1 -1
  177. package/lib/runtime/source-overlay/source-host.js +0 -5
  178. package/lib/runtime/source-overlay/source-host.js.map +1 -1
  179. package/lib/runtime/source-overlay/template.d.ts +0 -5
  180. package/lib/runtime/source-overlay/template.d.ts.map +1 -1
  181. package/lib/runtime/source-overlay/template.js +0 -5
  182. package/lib/runtime/source-overlay/template.js.map +1 -1
  183. package/lib/runtime/source-overlay.d.ts +0 -5
  184. package/lib/runtime/source-overlay.d.ts.map +1 -1
  185. package/lib/runtime/source-overlay.js +0 -5
  186. package/lib/runtime/source-overlay.js.map +1 -1
  187. package/lib/runtime/standalone.d.ts +0 -5
  188. package/lib/runtime/standalone.d.ts.map +1 -1
  189. package/lib/runtime/standalone.js +0 -5
  190. package/lib/runtime/standalone.js.map +1 -1
  191. package/lib/runtime/timeline/chrome-tracks.d.ts +0 -5
  192. package/lib/runtime/timeline/chrome-tracks.d.ts.map +1 -1
  193. package/lib/runtime/timeline/chrome-tracks.js +5 -3
  194. package/lib/runtime/timeline/chrome-tracks.js.map +1 -1
  195. package/lib/runtime/timeline/clock.d.ts +7 -3
  196. package/lib/runtime/timeline/clock.d.ts.map +1 -1
  197. package/lib/runtime/timeline/clock.js +0 -5
  198. package/lib/runtime/timeline/clock.js.map +1 -1
  199. package/lib/runtime/timeline/flash.d.ts +0 -5
  200. package/lib/runtime/timeline/flash.d.ts.map +1 -1
  201. package/lib/runtime/timeline/flash.js +15 -3
  202. package/lib/runtime/timeline/flash.js.map +1 -1
  203. package/lib/runtime/timeline/identity.d.ts +0 -5
  204. package/lib/runtime/timeline/identity.d.ts.map +1 -1
  205. package/lib/runtime/timeline/identity.js +9 -3
  206. package/lib/runtime/timeline/identity.js.map +1 -1
  207. package/lib/runtime/timeline/input.d.ts +0 -5
  208. package/lib/runtime/timeline/input.d.ts.map +1 -1
  209. package/lib/runtime/timeline/input.js +2 -3
  210. package/lib/runtime/timeline/input.js.map +1 -1
  211. package/lib/runtime/timeline/install.d.ts +11 -3
  212. package/lib/runtime/timeline/install.d.ts.map +1 -1
  213. package/lib/runtime/timeline/install.js +0 -5
  214. package/lib/runtime/timeline/install.js.map +1 -1
  215. package/lib/runtime/timeline/lifecycle.d.ts +13 -3
  216. package/lib/runtime/timeline/lifecycle.d.ts.map +1 -1
  217. package/lib/runtime/timeline/lifecycle.js +0 -5
  218. package/lib/runtime/timeline/lifecycle.js.map +1 -1
  219. package/lib/runtime/timeline/public-api.d.ts +6 -3
  220. package/lib/runtime/timeline/public-api.d.ts.map +1 -1
  221. package/lib/runtime/timeline/public-api.js +0 -5
  222. package/lib/runtime/timeline/public-api.js.map +1 -1
  223. package/lib/runtime/timeline/render.d.ts +0 -5
  224. package/lib/runtime/timeline/render.d.ts.map +1 -1
  225. package/lib/runtime/timeline/render.js +21 -3
  226. package/lib/runtime/timeline/render.js.map +1 -1
  227. package/lib/runtime/timeline/transport.d.ts +0 -5
  228. package/lib/runtime/timeline/transport.d.ts.map +1 -1
  229. package/lib/runtime/timeline/transport.js +10 -3
  230. package/lib/runtime/timeline/transport.js.map +1 -1
  231. package/lib/segmented-tabs.d.ts +0 -5
  232. package/lib/segmented-tabs.d.ts.map +1 -1
  233. package/lib/segmented-tabs.js +0 -5
  234. package/lib/segmented-tabs.js.map +1 -1
  235. package/lib/snapshot.d.ts +11 -3
  236. package/lib/snapshot.d.ts.map +1 -1
  237. package/lib/snapshot.js +0 -5
  238. package/lib/snapshot.js.map +1 -1
  239. package/lib/source-meta.d.ts +0 -5
  240. package/lib/source-meta.d.ts.map +1 -1
  241. package/lib/source-meta.js +0 -5
  242. package/lib/source-meta.js.map +1 -1
  243. package/lib/timeline/derive.d.ts +0 -5
  244. package/lib/timeline/derive.d.ts.map +1 -1
  245. package/lib/timeline/derive.js +22 -3
  246. package/lib/timeline/derive.js.map +1 -1
  247. package/lib/timeline/filter.d.ts +0 -5
  248. package/lib/timeline/filter.d.ts.map +1 -1
  249. package/lib/timeline/filter.js +6 -3
  250. package/lib/timeline/filter.js.map +1 -1
  251. package/lib/timeline/tracks.d.ts +0 -5
  252. package/lib/timeline/tracks.d.ts.map +1 -1
  253. package/lib/timeline/tracks.js +12 -3
  254. package/lib/timeline/tracks.js.map +1 -1
  255. package/lib/tokens.d.ts +0 -5
  256. package/lib/tokens.d.ts.map +1 -1
  257. package/lib/tokens.js +0 -5
  258. package/lib/tokens.js.map +1 -1
  259. package/lib/transform.d.ts +0 -5
  260. package/lib/transform.d.ts.map +1 -1
  261. package/lib/transform.js +0 -5
  262. package/lib/transform.js.map +1 -1
  263. package/lib/types.d.ts +10 -5
  264. package/lib/types.d.ts.map +1 -1
  265. package/lib/types.js +0 -5
  266. package/lib/types.js.map +1 -1
  267. package/lib/wrap-table.d.ts +0 -5
  268. package/lib/wrap-table.d.ts.map +1 -1
  269. package/lib/wrap-table.js +12 -3
  270. package/lib/wrap-table.js.map +1 -1
  271. package/package.json +2 -2
  272. package/types/hmr-incompatibility.d.ts +0 -5
  273. package/types/hmr-incompatibility.d.ts.map +1 -1
  274. package/types/hmr-incompatibility.js +13 -3
  275. package/types/hmr-incompatibility.js.map +1 -1
  276. package/types/in-page.d.ts +0 -5
  277. package/types/in-page.d.ts.map +1 -1
  278. package/types/in-page.js +0 -5
  279. package/types/in-page.js.map +1 -1
  280. package/types/inspector.d.ts +0 -5
  281. package/types/inspector.d.ts.map +1 -1
  282. package/types/inspector.js +13 -3
  283. package/types/inspector.js.map +1 -1
  284. package/types/snapshot.d.ts +0 -5
  285. package/types/snapshot.d.ts.map +1 -1
  286. package/types/snapshot.js +12 -3
  287. package/types/snapshot.js.map +1 -1
  288. package/types/timeline.d.ts +0 -5
  289. package/types/timeline.d.ts.map +1 -1
  290. package/types/timeline.js +0 -5
  291. package/types/timeline.js.map +1 -1
  292. package/dist/client/assets/index-D632jo79.js.map +0 -1
@@ -1,7 +1,25 @@
1
1
  /**
2
- * @license
3
- * Copyright 2026 Google LLC
4
- * SPDX-License-Identifier: BSD-3-Clause
2
+ * lit-render timeline layers — listen to the built-in lit-debug CustomEvents
3
+ * instead of patching prototypes, so they're zero-cost when the Lit debug
4
+ * flag is off and perfectly accurate for the render layers.
5
+ *
6
+ * `globalThis.emitLitDebugLogEvents = true` gates the events, and lit-html
7
+ * dispatches a CustomEvent per render whenever it's set — a real per-render
8
+ * cost. So the caller drives the flag via {@link setRenderDebugEnabled} from
9
+ * `recording × (lit-render OR lit-render-verbose enabled)` rather than
10
+ * leaving it on for the whole session.
11
+ * The events are tagged `*Unstable` in the Lit source; we tolerate missing
12
+ * `kind` values gracefully.
13
+ *
14
+ * begin render / end render share a numeric `id` → we use it as groupId so
15
+ * the panel can show a duration bar for each render call.
16
+ *
17
+ * `template updating` / `template instantiated[ and updated]` / `set part` /
18
+ * `commit *` fire once per template-bound part on *every* render — extremely
19
+ * high volume (a ticking clock or animation floods the layer). They're
20
+ * emitted on the separate opt-in `lit-render-verbose` layer rather than
21
+ * `lit-render`, so the common case (the begin/end render duration bar) stays
22
+ * quiet by default.
5
23
  */
6
24
  import {idOf, sourceOf} from './identity.js';
7
25
  import {now} from './clock.js';
@@ -1 +1 @@
1
- {"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/lib/runtime/timeline/render.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * lit-render timeline layers — listen to the built-in lit-debug CustomEvents\n * instead of patching prototypes, so they're zero-cost when the Lit debug\n * flag is off and perfectly accurate for the render layers.\n *\n * `globalThis.emitLitDebugLogEvents = true` gates the events, and lit-html\n * dispatches a CustomEvent per render whenever it's set — a real per-render\n * cost. So the caller drives the flag via {@link setRenderDebugEnabled} from\n * `recording × (lit-render OR lit-render-verbose enabled)` rather than\n * leaving it on for the whole session.\n * The events are tagged `*Unstable` in the Lit source; we tolerate missing\n * `kind` values gracefully.\n *\n * begin render / end render share a numeric `id` → we use it as groupId so\n * the panel can show a duration bar for each render call.\n *\n * `template updating` / `template instantiated[ and updated]` / `set part` /\n * `commit *` fire once per template-bound part on *every* render — extremely\n * high volume (a ticking clock or animation floods the layer). They're\n * emitted on the separate opt-in `lit-render-verbose` layer rather than\n * `lit-render`, so the common case (the begin/end render duration bar) stays\n * quiet by default.\n */\n\nimport type {TimelineEvent} from '../../../types/timeline.js';\nimport {idOf, sourceOf} from './identity.js';\nimport {now} from './clock.js';\n\ntype EmitFn = (event: TimelineEvent) => void;\ntype RecordingFn = () => boolean;\ntype LayerEnabledFn = () => boolean;\n\n/**\n * Minimal shape of the lit-debug event detail we care about. Broader than any\n * single `kind` needs — see lit-html's `LitUnstable.DebugLog.Entry` union in\n * `packages/lit-html/src/lit-html.ts` for the exact per-kind shapes; fields\n * below are the ones this layer reads across all of them.\n */\ninterface LitDebugDetail {\n kind: string;\n id?: number;\n template?: unknown;\n instance?: unknown;\n /** Render options passed to lit-html's `render()`; `host` is the element. */\n options?: {host?: unknown};\n /** `template updating` / `template instantiated[ and updated]`. */\n values?: unknown[];\n /** `set part` / most `commit *` kinds. */\n value?: unknown;\n /**\n * `set part` only. Unlike every other kind, `set part` carries no\n * top-level `options` — the host lives on the `Part` instance itself\n * (`ChildPart` / `AttributePart` / `EventPart` / `ElementPart` all expose a\n * public `options: RenderOptions | undefined`), so the host is derived via\n * {@link partHost} instead of `options?.host` directly.\n */\n part?: {options?: {host?: unknown}};\n /** `set part`. */\n valueIndex?: number;\n /** `commit attribute` / `commit property` / `commit boolean attribute` /\n * `commit event listener`. */\n name?: string;\n /** `commit event listener`. */\n addListener?: boolean;\n removeListener?: boolean;\n}\n\n/**\n * Builds the element-identity `meta` for a render event from the render\n * `host` (the LitElement whose `render()` produced these debug events).\n * Uses the same id/source maps as the lifecycle layer so an element keeps one\n * stable id across both layers. Returns undefined for host-less renders\n * (e.g. a bare lit-html `render()` call not driven by a LitElement).\n */\nconst hostMeta = (\n host: unknown\n): NonNullable<TimelineEvent['meta']> | undefined => {\n if (host === null || typeof host !== 'object') return undefined;\n return {\n elementId: idOf(host),\n tagName: (host as Element).localName ?? 'unknown',\n source: sourceOf(host),\n };\n};\n\n/** Reads the render `host` off a `Part` for the one kind (`set part`) whose\n * detail carries the part instead of the render `options` directly. */\nconst partHost = (part: LitDebugDetail['part']): unknown => part?.options?.host;\n\ntype LitDebugEvent = CustomEvent<LitDebugDetail>;\n\nlet removeListener: (() => void) | null = null;\n\n/**\n * Reduces an arbitrary lit-html binding value to a small JSON-serializable\n * summary for the verbose layer's `data` field. Never puts the value itself\n * in `data` — it may be a DOM Node, a TemplateResult, a function, or hold a\n * reference back to the host element, none of which survive (or belong in) a\n * structured-clone over the HMR channel.\n */\nconst describeValue = (value: unknown): string => {\n if (value === null) return 'null';\n if (value === undefined) return 'undefined';\n if (typeof value === 'string') {\n return value.length > 40\n ? `string:\"${value.slice(0, 40)}…\"`\n : `string:\"${value}\"`;\n }\n if (typeof value === 'number') return `number:${value}`;\n if (typeof value === 'boolean') return `boolean:${value}`;\n if (typeof value === 'function') {\n return `function:${value.name || 'anonymous'}`;\n }\n // lit's sentinels (`nothing`, `noChange`) are symbols.\n if (typeof value === 'symbol') return `symbol:${value.description ?? ''}`;\n if (Array.isArray(value)) return `array(${value.length})`;\n if (typeof value === 'object' && '_$litType$' in value) return 'template';\n if (typeof Node !== 'undefined' && value instanceof Node) {\n const tag = (value as Partial<Element>).tagName?.toLowerCase();\n return tag ? `node:<${tag}>` : `node:#${value.nodeType}`;\n }\n const ctor = (value as {constructor?: {name?: string}})?.constructor?.name;\n return `object:${ctor ?? 'Object'}`;\n};\n\n/** Summarizes each entry of a template-instance's `values` array. */\nconst describeValues = (values: unknown[] | undefined): string[] | undefined =>\n values?.map(describeValue);\n\nconst onLitDebug = (\n e: Event,\n emit: EmitFn,\n recording: RecordingFn,\n renderEnabled: LayerEnabledFn,\n verboseEnabled: LayerEnabledFn\n): void => {\n if (!recording() || (!renderEnabled() && !verboseEnabled())) return;\n\n const detail = (e as LitDebugEvent).detail;\n if (!detail?.kind) return;\n\n const time = now();\n const {kind, id} = detail;\n\n switch (kind) {\n case 'begin render': {\n if (!renderEnabled()) break;\n const meta = hostMeta(detail.options?.host);\n emit({\n layerId: 'lit-render',\n time,\n groupId: id,\n title: 'render:start',\n subtitle: meta?.tagName,\n data: {kind, id},\n meta,\n });\n break;\n }\n\n case 'end render': {\n if (!renderEnabled()) break;\n const meta = hostMeta(detail.options?.host);\n emit({\n layerId: 'lit-render',\n time,\n groupId: id,\n title: 'render:end',\n subtitle: meta?.tagName,\n data: {kind, id},\n meta,\n });\n break;\n }\n\n // `template prep` fires once per *unique* template, the first time it's\n // compiled — low volume, useful as a \"new template\" marker.\n case 'template prep':\n if (!renderEnabled()) break;\n emit({\n layerId: 'lit-render',\n time,\n title: kind,\n data: {kind, id},\n });\n break;\n\n // The events below fire once per template-bound part on *every* render —\n // extremely high volume (a ticking clock or animation floods the layer).\n // The begin/end render pair above already captures each render as a\n // grouped duration, so these live on the separate opt-in\n // `lit-render-verbose` layer instead of adding noise to `lit-render`.\n case 'template updating':\n case 'template instantiated':\n case 'template instantiated and updated': {\n if (!verboseEnabled()) break;\n const meta = hostMeta(detail.options?.host);\n emit({\n layerId: 'lit-render-verbose',\n time,\n title: kind,\n subtitle: meta?.tagName,\n data: {kind, values: describeValues(detail.values)},\n meta,\n });\n break;\n }\n\n case 'set part': {\n if (!verboseEnabled()) break;\n const meta = hostMeta(partHost(detail.part));\n emit({\n layerId: 'lit-render-verbose',\n time,\n title: kind,\n subtitle: meta?.tagName,\n data: {\n kind,\n valueIndex: detail.valueIndex,\n value: describeValue(detail.value),\n },\n meta,\n });\n break;\n }\n\n case 'commit nothing to child': {\n if (!verboseEnabled()) break;\n const meta = hostMeta(detail.options?.host);\n emit({\n layerId: 'lit-render-verbose',\n time,\n title: kind,\n subtitle: meta?.tagName,\n data: {kind},\n meta,\n });\n break;\n }\n\n case 'commit text':\n case 'commit node':\n case 'commit to element binding': {\n if (!verboseEnabled()) break;\n const meta = hostMeta(detail.options?.host);\n emit({\n layerId: 'lit-render-verbose',\n time,\n title: kind,\n subtitle: meta?.tagName,\n data: {kind, value: describeValue(detail.value)},\n meta,\n });\n break;\n }\n\n case 'commit attribute':\n case 'commit property':\n case 'commit boolean attribute': {\n if (!verboseEnabled()) break;\n const meta = hostMeta(detail.options?.host);\n emit({\n layerId: 'lit-render-verbose',\n time,\n title: kind,\n subtitle: meta?.tagName,\n data: {kind, name: detail.name, value: describeValue(detail.value)},\n meta,\n });\n break;\n }\n\n case 'commit event listener': {\n if (!verboseEnabled()) break;\n const meta = hostMeta(detail.options?.host);\n emit({\n layerId: 'lit-render-verbose',\n time,\n title: kind,\n subtitle: meta?.tagName,\n data: {\n kind,\n name: detail.name,\n addListener: detail.addListener,\n removeListener: detail.removeListener,\n },\n meta,\n });\n break;\n }\n\n // Unknown or future `*Unstable` kind — ignore rather than guess a shape.\n default:\n break;\n }\n};\n\n/**\n * Install the lit-debug render layers (`lit-render` and the opt-in\n * `lit-render-verbose`).\n * Idempotent — calling again when already installed is a no-op.\n */\nexport const installRenderLayer = (\n emit: EmitFn,\n recording: RecordingFn,\n renderEnabled: LayerEnabledFn,\n verboseEnabled: LayerEnabledFn\n): void => {\n if (removeListener !== null) return;\n\n // The listener is cheap and always attached; the per-render cost lives in the\n // `emitLitDebugLogEvents` flag, which the caller toggles via\n // `setRenderDebugEnabled` only while actively capturing.\n const handler = (e: Event) =>\n onLitDebug(e, emit, recording, renderEnabled, verboseEnabled);\n window.addEventListener('lit-debug', handler);\n removeListener = () => window.removeEventListener('lit-debug', handler);\n};\n\n/**\n * Toggle Lit's debug event system. Enabling makes lit-html dispatch a\n * CustomEvent on every render (dev-only; no-op in prod builds), so the caller\n * keeps it off unless the render layer is actively recording.\n */\nexport const setRenderDebugEnabled = (enabled: boolean): void => {\n (globalThis as {emitLitDebugLogEvents?: boolean}).emitLitDebugLogEvents =\n enabled;\n};\n\n/** Remove the listener and clear the Lit debug flag. */\nexport const uninstallRenderLayer = (): void => {\n removeListener?.();\n removeListener = null;\n setRenderDebugEnabled(false);\n};\n"]}
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/lib/runtime/timeline/render.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * lit-render timeline layers — listen to the built-in lit-debug CustomEvents\n * instead of patching prototypes, so they're zero-cost when the Lit debug\n * flag is off and perfectly accurate for the render layers.\n *\n * `globalThis.emitLitDebugLogEvents = true` gates the events, and lit-html\n * dispatches a CustomEvent per render whenever it's set — a real per-render\n * cost. So the caller drives the flag via {@link setRenderDebugEnabled} from\n * `recording × (lit-render OR lit-render-verbose enabled)` rather than\n * leaving it on for the whole session.\n * The events are tagged `*Unstable` in the Lit source; we tolerate missing\n * `kind` values gracefully.\n *\n * begin render / end render share a numeric `id` → we use it as groupId so\n * the panel can show a duration bar for each render call.\n *\n * `template updating` / `template instantiated[ and updated]` / `set part` /\n * `commit *` fire once per template-bound part on *every* render — extremely\n * high volume (a ticking clock or animation floods the layer). They're\n * emitted on the separate opt-in `lit-render-verbose` layer rather than\n * `lit-render`, so the common case (the begin/end render duration bar) stays\n * quiet by default.\n */\n\nimport type {TimelineEvent} from '../../../types/timeline.js';\nimport {idOf, sourceOf} from './identity.js';\nimport {now} from './clock.js';\n\ntype EmitFn = (event: TimelineEvent) => void;\ntype RecordingFn = () => boolean;\ntype LayerEnabledFn = () => boolean;\n\n/**\n * Minimal shape of the lit-debug event detail we care about. Broader than any\n * single `kind` needs — see lit-html's `LitUnstable.DebugLog.Entry` union in\n * `packages/lit-html/src/lit-html.ts` for the exact per-kind shapes; fields\n * below are the ones this layer reads across all of them.\n */\ninterface LitDebugDetail {\n kind: string;\n id?: number;\n template?: unknown;\n instance?: unknown;\n /** Render options passed to lit-html's `render()`; `host` is the element. */\n options?: {host?: unknown};\n /** `template updating` / `template instantiated[ and updated]`. */\n values?: unknown[];\n /** `set part` / most `commit *` kinds. */\n value?: unknown;\n /**\n * `set part` only. Unlike every other kind, `set part` carries no\n * top-level `options` — the host lives on the `Part` instance itself\n * (`ChildPart` / `AttributePart` / `EventPart` / `ElementPart` all expose a\n * public `options: RenderOptions | undefined`), so the host is derived via\n * {@link partHost} instead of `options?.host` directly.\n */\n part?: {options?: {host?: unknown}};\n /** `set part`. */\n valueIndex?: number;\n /** `commit attribute` / `commit property` / `commit boolean attribute` /\n * `commit event listener`. */\n name?: string;\n /** `commit event listener`. */\n addListener?: boolean;\n removeListener?: boolean;\n}\n\n/**\n * Builds the element-identity `meta` for a render event from the render\n * `host` (the LitElement whose `render()` produced these debug events).\n * Uses the same id/source maps as the lifecycle layer so an element keeps one\n * stable id across both layers. Returns undefined for host-less renders\n * (e.g. a bare lit-html `render()` call not driven by a LitElement).\n */\nconst hostMeta = (\n host: unknown\n): NonNullable<TimelineEvent['meta']> | undefined => {\n if (host === null || typeof host !== 'object') return undefined;\n return {\n elementId: idOf(host),\n tagName: (host as Element).localName ?? 'unknown',\n source: sourceOf(host),\n };\n};\n\n/** Reads the render `host` off a `Part` for the one kind (`set part`) whose\n * detail carries the part instead of the render `options` directly. */\nconst partHost = (part: LitDebugDetail['part']): unknown => part?.options?.host;\n\ntype LitDebugEvent = CustomEvent<LitDebugDetail>;\n\nlet removeListener: (() => void) | null = null;\n\n/**\n * Reduces an arbitrary lit-html binding value to a small JSON-serializable\n * summary for the verbose layer's `data` field. Never puts the value itself\n * in `data` — it may be a DOM Node, a TemplateResult, a function, or hold a\n * reference back to the host element, none of which survive (or belong in) a\n * structured-clone over the HMR channel.\n */\nconst describeValue = (value: unknown): string => {\n if (value === null) return 'null';\n if (value === undefined) return 'undefined';\n if (typeof value === 'string') {\n return value.length > 40\n ? `string:\"${value.slice(0, 40)}…\"`\n : `string:\"${value}\"`;\n }\n if (typeof value === 'number') return `number:${value}`;\n if (typeof value === 'boolean') return `boolean:${value}`;\n if (typeof value === 'function') {\n return `function:${value.name || 'anonymous'}`;\n }\n // lit's sentinels (`nothing`, `noChange`) are symbols.\n if (typeof value === 'symbol') return `symbol:${value.description ?? ''}`;\n if (Array.isArray(value)) return `array(${value.length})`;\n if (typeof value === 'object' && '_$litType$' in value) return 'template';\n if (typeof Node !== 'undefined' && value instanceof Node) {\n const tag = (value as Partial<Element>).tagName?.toLowerCase();\n return tag ? `node:<${tag}>` : `node:#${value.nodeType}`;\n }\n const ctor = (value as {constructor?: {name?: string}})?.constructor?.name;\n return `object:${ctor ?? 'Object'}`;\n};\n\n/** Summarizes each entry of a template-instance's `values` array. */\nconst describeValues = (values: unknown[] | undefined): string[] | undefined =>\n values?.map(describeValue);\n\nconst onLitDebug = (\n e: Event,\n emit: EmitFn,\n recording: RecordingFn,\n renderEnabled: LayerEnabledFn,\n verboseEnabled: LayerEnabledFn\n): void => {\n if (!recording() || (!renderEnabled() && !verboseEnabled())) return;\n\n const detail = (e as LitDebugEvent).detail;\n if (!detail?.kind) return;\n\n const time = now();\n const {kind, id} = detail;\n\n switch (kind) {\n case 'begin render': {\n if (!renderEnabled()) break;\n const meta = hostMeta(detail.options?.host);\n emit({\n layerId: 'lit-render',\n time,\n groupId: id,\n title: 'render:start',\n subtitle: meta?.tagName,\n data: {kind, id},\n meta,\n });\n break;\n }\n\n case 'end render': {\n if (!renderEnabled()) break;\n const meta = hostMeta(detail.options?.host);\n emit({\n layerId: 'lit-render',\n time,\n groupId: id,\n title: 'render:end',\n subtitle: meta?.tagName,\n data: {kind, id},\n meta,\n });\n break;\n }\n\n // `template prep` fires once per *unique* template, the first time it's\n // compiled — low volume, useful as a \"new template\" marker.\n case 'template prep':\n if (!renderEnabled()) break;\n emit({\n layerId: 'lit-render',\n time,\n title: kind,\n data: {kind, id},\n });\n break;\n\n // The events below fire once per template-bound part on *every* render —\n // extremely high volume (a ticking clock or animation floods the layer).\n // The begin/end render pair above already captures each render as a\n // grouped duration, so these live on the separate opt-in\n // `lit-render-verbose` layer instead of adding noise to `lit-render`.\n case 'template updating':\n case 'template instantiated':\n case 'template instantiated and updated': {\n if (!verboseEnabled()) break;\n const meta = hostMeta(detail.options?.host);\n emit({\n layerId: 'lit-render-verbose',\n time,\n title: kind,\n subtitle: meta?.tagName,\n data: {kind, values: describeValues(detail.values)},\n meta,\n });\n break;\n }\n\n case 'set part': {\n if (!verboseEnabled()) break;\n const meta = hostMeta(partHost(detail.part));\n emit({\n layerId: 'lit-render-verbose',\n time,\n title: kind,\n subtitle: meta?.tagName,\n data: {\n kind,\n valueIndex: detail.valueIndex,\n value: describeValue(detail.value),\n },\n meta,\n });\n break;\n }\n\n case 'commit nothing to child': {\n if (!verboseEnabled()) break;\n const meta = hostMeta(detail.options?.host);\n emit({\n layerId: 'lit-render-verbose',\n time,\n title: kind,\n subtitle: meta?.tagName,\n data: {kind},\n meta,\n });\n break;\n }\n\n case 'commit text':\n case 'commit node':\n case 'commit to element binding': {\n if (!verboseEnabled()) break;\n const meta = hostMeta(detail.options?.host);\n emit({\n layerId: 'lit-render-verbose',\n time,\n title: kind,\n subtitle: meta?.tagName,\n data: {kind, value: describeValue(detail.value)},\n meta,\n });\n break;\n }\n\n case 'commit attribute':\n case 'commit property':\n case 'commit boolean attribute': {\n if (!verboseEnabled()) break;\n const meta = hostMeta(detail.options?.host);\n emit({\n layerId: 'lit-render-verbose',\n time,\n title: kind,\n subtitle: meta?.tagName,\n data: {kind, name: detail.name, value: describeValue(detail.value)},\n meta,\n });\n break;\n }\n\n case 'commit event listener': {\n if (!verboseEnabled()) break;\n const meta = hostMeta(detail.options?.host);\n emit({\n layerId: 'lit-render-verbose',\n time,\n title: kind,\n subtitle: meta?.tagName,\n data: {\n kind,\n name: detail.name,\n addListener: detail.addListener,\n removeListener: detail.removeListener,\n },\n meta,\n });\n break;\n }\n\n // Unknown or future `*Unstable` kind — ignore rather than guess a shape.\n default:\n break;\n }\n};\n\n/**\n * Install the lit-debug render layers (`lit-render` and the opt-in\n * `lit-render-verbose`).\n * Idempotent — calling again when already installed is a no-op.\n */\nexport const installRenderLayer = (\n emit: EmitFn,\n recording: RecordingFn,\n renderEnabled: LayerEnabledFn,\n verboseEnabled: LayerEnabledFn\n): void => {\n if (removeListener !== null) return;\n\n // The listener is cheap and always attached; the per-render cost lives in the\n // `emitLitDebugLogEvents` flag, which the caller toggles via\n // `setRenderDebugEnabled` only while actively capturing.\n const handler = (e: Event) =>\n onLitDebug(e, emit, recording, renderEnabled, verboseEnabled);\n window.addEventListener('lit-debug', handler);\n removeListener = () => window.removeEventListener('lit-debug', handler);\n};\n\n/**\n * Toggle Lit's debug event system. Enabling makes lit-html dispatch a\n * CustomEvent on every render (dev-only; no-op in prod builds), so the caller\n * keeps it off unless the render layer is actively recording.\n */\nexport const setRenderDebugEnabled = (enabled: boolean): void => {\n (globalThis as {emitLitDebugLogEvents?: boolean}).emitLitDebugLogEvents =\n enabled;\n};\n\n/** Remove the listener and clear the Lit debug flag. */\nexport const uninstallRenderLayer = (): void => {\n removeListener?.();\n removeListener = null;\n setRenderDebugEnabled(false);\n};\n"]}
@@ -1,8 +1,3 @@
1
- /**
2
- * @license
3
- * Copyright 2026 Google LLC
4
- * SPDX-License-Identifier: BSD-3-Clause
5
- */
6
1
  /**
7
2
  * Buffered transport for timeline events.
8
3
  *
@@ -1 +1 @@
1
- {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../../src/lib/runtime/timeline/transport.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AAEtD,KAAK,SAAS,GAAG,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;AAmB7C;;;;GAIG;AACH,eAAO,MAAM,YAAY,QAAS,SAAS,KAAG,IAe7C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,OAAQ,MAAM,IAAI,KAAG,IAMrD,CAAC;AAaF;;;;GAIG;AACH,eAAO,MAAM,IAAI,UAAW,aAAa,KAAG,IAc3C,CAAC"}
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../../src/lib/runtime/timeline/transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AAEtD,KAAK,SAAS,GAAG,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;AAmB7C;;;;GAIG;AACH,eAAO,MAAM,YAAY,QAAS,SAAS,KAAG,IAe7C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,OAAQ,MAAM,IAAI,KAAG,IAMrD,CAAC;AAaF;;;;GAIG;AACH,eAAO,MAAM,IAAI,UAAW,aAAa,KAAG,IAc3C,CAAC"}
@@ -1,7 +1,14 @@
1
1
  /**
2
- * @license
3
- * Copyright 2026 Google LLC
4
- * SPDX-License-Identifier: BSD-3-Clause
2
+ * Buffered transport for timeline events.
3
+ *
4
+ * Forwards events over the page channel (`../page-channel.ts`), which is
5
+ * Vite's HMR WebSocket by default and can be pointed at a standalone
6
+ * devframe server instead. Which carrier is in use is not this module's
7
+ * concern.
8
+ *
9
+ * Batching: we coalesce events with `queueMicrotask` so a burst of
10
+ * commit/set-part events from a single render doesn't hammer the channel
11
+ * with one message per event.
5
12
  */
6
13
  const queue = [];
7
14
  let flushScheduled = false;
@@ -1 +1 @@
1
- {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../src/lib/runtime/timeline/transport.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAoBH,MAAM,KAAK,GAAoB,EAAE,CAAC;AAClC,IAAI,cAAc,GAAG,KAAK,CAAC;AAC3B,IAAI,SAAS,GAAqB,IAAI,CAAC;AAEvC;;;;;;GAMG;AACH,MAAM,WAAW,GAAG,IAAI,CAAC;AAEzB,kFAAkF;AAClF,oEAAoE;AACpE,MAAM,gBAAgB,GAAsB,EAAE,CAAC;AAE/C;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAc,EAAQ,EAAE;IACnD,SAAS,GAAG,GAAG,CAAC;IAChB,6DAA6D;IAC7D,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;QACxC,cAAc,GAAG,IAAI,CAAC;QACtB,cAAc,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IACD,iEAAiE;IACjE,KAAK,MAAM,EAAE,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,IAAI,CAAC;YACH,EAAE,EAAE,CAAC;QACP,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC;AACH,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,EAAc,EAAQ,EAAE;IAC3D,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACvB,cAAc,CAAC,EAAE,CAAC,CAAC;IACrB,CAAC;SAAM,CAAC;QACN,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,KAAK,GAAG,GAAS,EAAE;IACvB,cAAc,GAAG,KAAK,CAAC;IACvB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,SAAS,KAAK,IAAI;QAAE,OAAO;IACrD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,CAAC;QACH,SAAS,CAAC,IAAI,CAAC,yBAAyB,EAAE,EAAC,MAAM,EAAE,KAAK,EAAC,CAAC,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACP,kEAAkE;IACpE,CAAC;AACH,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,KAAoB,EAAQ,EAAE;IACjD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACvB,uEAAuE;QACvE,wEAAwE;QACxE,IAAI,KAAK,CAAC,MAAM,GAAG,WAAW,EAAE,CAAC;YAC/B,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,WAAW,CAAC,CAAC;QAC9C,CAAC;QACD,OAAO;IACT,CAAC;IACD,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,cAAc,GAAG,IAAI,CAAC;QACtB,cAAc,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;AACH,CAAC,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * Buffered transport for timeline events.\n *\n * Forwards events over the page channel (`../page-channel.ts`), which is\n * Vite's HMR WebSocket by default and can be pointed at a standalone\n * devframe server instead. Which carrier is in use is not this module's\n * concern.\n *\n * Batching: we coalesce events with `queueMicrotask` so a burst of\n * commit/set-part events from a single render doesn't hammer the channel\n * with one message per event.\n */\n\nimport type {TimelineEvent} from '../../../types/timeline.js';\nimport type {PageTransport} from '../page-channel.js';\n\ntype HotClient = Pick<PageTransport, 'send'>;\n\nconst queue: TimelineEvent[] = [];\nlet flushScheduled = false;\nlet hotClient: HotClient | null = null;\n\n/**\n * Cap on events retained while no hot client is connected. Without a client\n * `flush()` cannot drain the queue, so an uncapped buffer would grow for the\n * whole session (in production, or before `install.ts` wires the client).\n * We keep only the most recent events; the retained tail flushes if a client\n * later connects.\n */\nconst MAX_PENDING = 1000;\n\n// Callbacks registered before the hot client was available (e.g. addTimelineLayer\n// called at module init time before install.ts has set the client).\nconst pendingCallbacks: Array<() => void> = [];\n\n/**\n * Register the HMR hot client.\n * Called by install.ts after import.meta.hot check.\n * Flushes any queued events and fires pending one-shot callbacks.\n */\nexport const setHotClient = (hot: HotClient): void => {\n hotClient = hot;\n // Drain any events that arrived before the client was wired.\n if (queue.length > 0 && !flushScheduled) {\n flushScheduled = true;\n queueMicrotask(flush);\n }\n // Fire one-shot callbacks (e.g. addTimelineLayer announcements).\n for (const cb of pendingCallbacks.splice(0)) {\n try {\n cb();\n } catch {\n // ignore\n }\n }\n};\n\n/**\n * Register a callback to be invoked once the HMR client is available.\n * If the client is already set the callback is fired on the next microtask.\n */\nexport const setHotClientCallback = (cb: () => void): void => {\n if (hotClient !== null) {\n queueMicrotask(cb);\n } else {\n pendingCallbacks.push(cb);\n }\n};\n\nconst flush = (): void => {\n flushScheduled = false;\n if (queue.length === 0 || hotClient === null) return;\n const batch = queue.splice(0);\n try {\n hotClient.send('lit:timeline:push-event', {events: batch});\n } catch {\n // HMR channel may be temporarily unavailable; events are dropped.\n }\n};\n\n/**\n * Enqueue a timeline event for forwarding to the Vite server.\n * Batches via microtask so a single synchronous render burst\n * doesn't send dozens of individual messages.\n */\nexport const emit = (event: TimelineEvent): void => {\n queue.push(event);\n if (hotClient === null) {\n // No consumer yet: bound the buffer instead of scheduling a flush that\n // would only no-op. `setHotClient` drains the retained tail on connect.\n if (queue.length > MAX_PENDING) {\n queue.splice(0, queue.length - MAX_PENDING);\n }\n return;\n }\n if (!flushScheduled) {\n flushScheduled = true;\n queueMicrotask(flush);\n }\n};\n"]}
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../src/lib/runtime/timeline/transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,MAAM,KAAK,GAAoB,EAAE,CAAC;AAClC,IAAI,cAAc,GAAG,KAAK,CAAC;AAC3B,IAAI,SAAS,GAAqB,IAAI,CAAC;AAEvC;;;;;;GAMG;AACH,MAAM,WAAW,GAAG,IAAI,CAAC;AAEzB,kFAAkF;AAClF,oEAAoE;AACpE,MAAM,gBAAgB,GAAsB,EAAE,CAAC;AAE/C;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAc,EAAQ,EAAE;IACnD,SAAS,GAAG,GAAG,CAAC;IAChB,6DAA6D;IAC7D,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;QACxC,cAAc,GAAG,IAAI,CAAC;QACtB,cAAc,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IACD,iEAAiE;IACjE,KAAK,MAAM,EAAE,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,IAAI,CAAC;YACH,EAAE,EAAE,CAAC;QACP,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC;AACH,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,EAAc,EAAQ,EAAE;IAC3D,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACvB,cAAc,CAAC,EAAE,CAAC,CAAC;IACrB,CAAC;SAAM,CAAC;QACN,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,KAAK,GAAG,GAAS,EAAE;IACvB,cAAc,GAAG,KAAK,CAAC;IACvB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,SAAS,KAAK,IAAI;QAAE,OAAO;IACrD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,CAAC;QACH,SAAS,CAAC,IAAI,CAAC,yBAAyB,EAAE,EAAC,MAAM,EAAE,KAAK,EAAC,CAAC,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACP,kEAAkE;IACpE,CAAC;AACH,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,KAAoB,EAAQ,EAAE;IACjD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACvB,uEAAuE;QACvE,wEAAwE;QACxE,IAAI,KAAK,CAAC,MAAM,GAAG,WAAW,EAAE,CAAC;YAC/B,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,WAAW,CAAC,CAAC;QAC9C,CAAC;QACD,OAAO;IACT,CAAC;IACD,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,cAAc,GAAG,IAAI,CAAC;QACtB,cAAc,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;AACH,CAAC,CAAC","sourcesContent":["/**\n * Buffered transport for timeline events.\n *\n * Forwards events over the page channel (`../page-channel.ts`), which is\n * Vite's HMR WebSocket by default and can be pointed at a standalone\n * devframe server instead. Which carrier is in use is not this module's\n * concern.\n *\n * Batching: we coalesce events with `queueMicrotask` so a burst of\n * commit/set-part events from a single render doesn't hammer the channel\n * with one message per event.\n */\n\nimport type {TimelineEvent} from '../../../types/timeline.js';\nimport type {PageTransport} from '../page-channel.js';\n\ntype HotClient = Pick<PageTransport, 'send'>;\n\nconst queue: TimelineEvent[] = [];\nlet flushScheduled = false;\nlet hotClient: HotClient | null = null;\n\n/**\n * Cap on events retained while no hot client is connected. Without a client\n * `flush()` cannot drain the queue, so an uncapped buffer would grow for the\n * whole session (in production, or before `install.ts` wires the client).\n * We keep only the most recent events; the retained tail flushes if a client\n * later connects.\n */\nconst MAX_PENDING = 1000;\n\n// Callbacks registered before the hot client was available (e.g. addTimelineLayer\n// called at module init time before install.ts has set the client).\nconst pendingCallbacks: Array<() => void> = [];\n\n/**\n * Register the HMR hot client.\n * Called by install.ts after import.meta.hot check.\n * Flushes any queued events and fires pending one-shot callbacks.\n */\nexport const setHotClient = (hot: HotClient): void => {\n hotClient = hot;\n // Drain any events that arrived before the client was wired.\n if (queue.length > 0 && !flushScheduled) {\n flushScheduled = true;\n queueMicrotask(flush);\n }\n // Fire one-shot callbacks (e.g. addTimelineLayer announcements).\n for (const cb of pendingCallbacks.splice(0)) {\n try {\n cb();\n } catch {\n // ignore\n }\n }\n};\n\n/**\n * Register a callback to be invoked once the HMR client is available.\n * If the client is already set the callback is fired on the next microtask.\n */\nexport const setHotClientCallback = (cb: () => void): void => {\n if (hotClient !== null) {\n queueMicrotask(cb);\n } else {\n pendingCallbacks.push(cb);\n }\n};\n\nconst flush = (): void => {\n flushScheduled = false;\n if (queue.length === 0 || hotClient === null) return;\n const batch = queue.splice(0);\n try {\n hotClient.send('lit:timeline:push-event', {events: batch});\n } catch {\n // HMR channel may be temporarily unavailable; events are dropped.\n }\n};\n\n/**\n * Enqueue a timeline event for forwarding to the Vite server.\n * Batches via microtask so a single synchronous render burst\n * doesn't send dozens of individual messages.\n */\nexport const emit = (event: TimelineEvent): void => {\n queue.push(event);\n if (hotClient === null) {\n // No consumer yet: bound the buffer instead of scheduling a flush that\n // would only no-op. `setHotClient` drains the retained tail on connect.\n if (queue.length > MAX_PENDING) {\n queue.splice(0, queue.length - MAX_PENDING);\n }\n return;\n }\n if (!flushScheduled) {\n flushScheduled = true;\n queueMicrotask(flush);\n }\n};\n"]}
@@ -1,8 +1,3 @@
1
- /**
2
- * @license
3
- * Copyright 2026 Google LLC
4
- * SPDX-License-Identifier: BSD-3-Clause
5
- */
6
1
  import { LitElement } from 'lit';
7
2
  export interface TabItem {
8
3
  id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"segmented-tabs.d.ts","sourceRoot":"","sources":["../src/lib/segmented-tabs.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAC,UAAU,EAAqB,MAAM,KAAK,CAAC;AAInD,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,CAAC;AAErC;;;;;GAKG;AACH,qBACa,aAAc,SAAQ,UAAU;IAC3C,OAAgB,MAAM,4BAkEpB;IAE+B,KAAK,EAAE,OAAO,EAAE,CAAC;IAE9B,KAAK,EAAE,MAAM,CAAC;IAEd,IAAI,EAAE,UAAU,CAAC;IAErC,cAKC;IAED,OAAO,CAAC,OAAO;IAWN,MAAM,oCA+Bd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,gBAAgB,EAAE,aAAa,CAAC;KACjC;CACF"}
1
+ {"version":3,"file":"segmented-tabs.d.ts","sourceRoot":"","sources":["../src/lib/segmented-tabs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAqB,MAAM,KAAK,CAAC;AAInD,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,CAAC;AAErC;;;;;GAKG;AACH,qBACa,aAAc,SAAQ,UAAU;IAC3C,OAAgB,MAAM,4BAkEpB;IAE+B,KAAK,EAAE,OAAO,EAAE,CAAC;IAE9B,KAAK,EAAE,MAAM,CAAC;IAEd,IAAI,EAAE,UAAU,CAAC;IAErC,cAKC;IAED,OAAO,CAAC,OAAO;IAWN,MAAM,oCA+Bd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,gBAAgB,EAAE,aAAa,CAAC;KACjC;CACF"}
@@ -1,8 +1,3 @@
1
- /**
2
- * @license
3
- * Copyright 2026 Google LLC
4
- * SPDX-License-Identifier: BSD-3-Clause
5
- */
6
1
  var __decorate =
7
2
  (this && this.__decorate) ||
8
3
  function (decorators, target, key, desc) {
@@ -1 +1 @@
1
- {"version":3,"file":"segmented-tabs.js","sourceRoot":"","sources":["../src/lib/segmented-tabs.ts"],"names":[],"mappings":"AAAA;;;;GAIG;;;;;;;AAEH,OAAO,EAAC,UAAU,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAC,MAAM,KAAK,CAAC;AACnD,OAAO,EAAC,aAAa,EAAE,QAAQ,EAAC,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAYnC;;;;;GAKG;AAEI,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,UAAU;aAC3B,WAAM,GAAG;QACvB,MAAM;QACN,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA+DF;KACF,AAlEqB,CAkEpB;IAQF;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAEO,OAAO,CAAC,EAAU;QACxB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,QAAQ,EAAE;YACxB,MAAM,EAAE,EAAC,KAAK,EAAE,EAAE,EAAC;YACnB,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;SACf,CAAC,CACH,CAAC;IACJ,CAAC;IAEQ,MAAM;QACb,OAAO,IAAI,CAAA;QACP,IAAI,CAAC,KAAK,CAAC,GAAG,CACd,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAA;;;4BAGM,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,KAAK;oBAC9B,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;qBACrC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;;cAGlC,IAAI,CAAC,IAAI;YACP,CAAC,CAAC,IAAI,CAAA;;;;;8BAKQ,IAAI,CAAC,IAAI;yBACd;YACT,CAAC,CAAC,OACN;cACE,IAAI,CAAC,KAAK;cAEV,IAAI,CAAC,KAAK;YACR,CAAC,CAAC,IAAI,CAAA,uBAAuB,IAAI,CAAC,KAAK,SAAS;YAChD,CAAC,CAAC,OACN;;SAEH,CACF;KACF,CAAC;IACJ,CAAC;CACF,CAAA;AAxDkC;IAAhC,QAAQ,CAAC,EAAC,IAAI,EAAE,KAAK,EAAC,CAAC;4CAA0B;AAE9B;IAAnB,QAAQ,EAAE;4CAAuB;AAEd;IAAnB,QAAQ,EAAE;2CAA0B;AAzE1B,aAAa;IADzB,aAAa,CAAC,gBAAgB,CAAC;GACnB,aAAa,CA6HzB","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nimport {LitElement, html, css, nothing} from 'lit';\nimport {customElement, property} from 'lit/decorators.js';\nimport {tokens} from './tokens.js';\n\nexport interface TabItem {\n id: string;\n label: string;\n icon?: string;\n /** Optional count pill trailing the label. Hidden when absent or zero. */\n badge?: number;\n}\n\nexport type SegTabSize = 'sm' | 'md';\n\n/**\n * Inline segmented tab control. Renders a horizontal row of text-only tabs\n * with the active one highlighted by the accent color.\n *\n * Matches the SegmentedTabs spec from the Lit Design System devtools kit.\n */\n@customElement('segmented-tabs')\nexport class SegmentedTabs extends LitElement {\n static override styles = [\n tokens,\n css`\n :host {\n display: flex;\n gap: var(--lit-devtools-space-1);\n align-self: stretch;\n }\n button {\n appearance: none;\n display: flex;\n align-items: center;\n gap: var(--lit-devtools-space-2);\n border: 0;\n background: none;\n font: inherit;\n color: var(--lit-devtools-text-muted);\n padding: 0 var(--lit-devtools-space-5);\n cursor: pointer;\n border-bottom: 2px solid transparent;\n white-space: nowrap;\n transition:\n color var(--lit-devtools-dur-fast) var(--lit-devtools-ease-standard),\n border-color var(--lit-devtools-dur-fast)\n var(--lit-devtools-ease-standard),\n background var(--lit-devtools-dur-fast)\n var(--lit-devtools-ease-standard);\n }\n button:hover {\n color: var(--lit-devtools-text);\n background: var(--lit-devtools-surface-hover);\n }\n button.active {\n color: var(--lit-devtools-accent);\n border-bottom-color: var(--lit-devtools-accent);\n }\n button:focus-visible {\n outline: 2px solid var(--lit-devtools-accent-ring);\n outline-offset: -2px;\n }\n button svg {\n width: 18px;\n height: 18px;\n flex-shrink: 0;\n }\n .badge {\n flex-shrink: 0;\n min-width: 16px;\n padding: 0 var(--lit-devtools-space-1);\n border-radius: var(--lit-devtools-radius-pill);\n background: var(--lit-devtools-error-soft);\n color: var(--lit-devtools-error);\n font-size: var(--lit-devtools-text-xs);\n line-height: 16px;\n text-align: center;\n }\n :host([size='sm']) button {\n font-size: var(--lit-devtools-text-xs);\n padding: 0 var(--lit-devtools-space-4);\n }\n :host([size='md']) button,\n :host(:not([size])) button {\n font-size: var(--lit-devtools-text-sm);\n padding: 0 var(--lit-devtools-space-5);\n }\n `,\n ];\n\n @property({type: Array}) declare items: TabItem[];\n\n @property() declare value: string;\n\n @property() declare size: SegTabSize;\n\n constructor() {\n super();\n this.items = [];\n this.value = '';\n this.size = 'md';\n }\n\n private _select(id: string): void {\n this.value = id;\n this.dispatchEvent(\n new CustomEvent('change', {\n detail: {value: id},\n bubbles: true,\n composed: true,\n })\n );\n }\n\n override render() {\n return html`\n ${this.items.map(\n (item) => html`\n <button\n role=\"tab\"\n aria-selected=${item.id === this.value}\n class=${item.id === this.value ? 'active' : ''}\n @click=${() => this._select(item.id)}\n >\n ${\n item.icon\n ? html`<svg\n viewBox=\"0 0 256 256\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d=${item.icon} />\n </svg>`\n : nothing\n }\n ${item.label}\n ${\n item.badge\n ? html`<span class=\"badge\">${item.badge}</span>`\n : nothing\n }\n </button>\n `\n )}\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'segmented-tabs': SegmentedTabs;\n }\n}\n"]}
1
+ {"version":3,"file":"segmented-tabs.js","sourceRoot":"","sources":["../src/lib/segmented-tabs.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAC,UAAU,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAC,MAAM,KAAK,CAAC;AACnD,OAAO,EAAC,aAAa,EAAE,QAAQ,EAAC,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAYnC;;;;;GAKG;AAEI,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,UAAU;aAC3B,WAAM,GAAG;QACvB,MAAM;QACN,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA+DF;KACF,AAlEqB,CAkEpB;IAQF;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAEO,OAAO,CAAC,EAAU;QACxB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,QAAQ,EAAE;YACxB,MAAM,EAAE,EAAC,KAAK,EAAE,EAAE,EAAC;YACnB,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;SACf,CAAC,CACH,CAAC;IACJ,CAAC;IAEQ,MAAM;QACb,OAAO,IAAI,CAAA;QACP,IAAI,CAAC,KAAK,CAAC,GAAG,CACd,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAA;;;4BAGM,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,KAAK;oBAC9B,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;qBACrC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;;cAGlC,IAAI,CAAC,IAAI;YACP,CAAC,CAAC,IAAI,CAAA;;;;;8BAKQ,IAAI,CAAC,IAAI;yBACd;YACT,CAAC,CAAC,OACN;cACE,IAAI,CAAC,KAAK;cAEV,IAAI,CAAC,KAAK;YACR,CAAC,CAAC,IAAI,CAAA,uBAAuB,IAAI,CAAC,KAAK,SAAS;YAChD,CAAC,CAAC,OACN;;SAEH,CACF;KACF,CAAC;IACJ,CAAC;CACF,CAAA;AAxDkC;IAAhC,QAAQ,CAAC,EAAC,IAAI,EAAE,KAAK,EAAC,CAAC;4CAA0B;AAE9B;IAAnB,QAAQ,EAAE;4CAAuB;AAEd;IAAnB,QAAQ,EAAE;2CAA0B;AAzE1B,aAAa;IADzB,aAAa,CAAC,gBAAgB,CAAC;GACnB,aAAa,CA6HzB","sourcesContent":["import {LitElement, html, css, nothing} from 'lit';\nimport {customElement, property} from 'lit/decorators.js';\nimport {tokens} from './tokens.js';\n\nexport interface TabItem {\n id: string;\n label: string;\n icon?: string;\n /** Optional count pill trailing the label. Hidden when absent or zero. */\n badge?: number;\n}\n\nexport type SegTabSize = 'sm' | 'md';\n\n/**\n * Inline segmented tab control. Renders a horizontal row of text-only tabs\n * with the active one highlighted by the accent color.\n *\n * Matches the SegmentedTabs spec from the Lit Design System devtools kit.\n */\n@customElement('segmented-tabs')\nexport class SegmentedTabs extends LitElement {\n static override styles = [\n tokens,\n css`\n :host {\n display: flex;\n gap: var(--lit-devtools-space-1);\n align-self: stretch;\n }\n button {\n appearance: none;\n display: flex;\n align-items: center;\n gap: var(--lit-devtools-space-2);\n border: 0;\n background: none;\n font: inherit;\n color: var(--lit-devtools-text-muted);\n padding: 0 var(--lit-devtools-space-5);\n cursor: pointer;\n border-bottom: 2px solid transparent;\n white-space: nowrap;\n transition:\n color var(--lit-devtools-dur-fast) var(--lit-devtools-ease-standard),\n border-color var(--lit-devtools-dur-fast)\n var(--lit-devtools-ease-standard),\n background var(--lit-devtools-dur-fast)\n var(--lit-devtools-ease-standard);\n }\n button:hover {\n color: var(--lit-devtools-text);\n background: var(--lit-devtools-surface-hover);\n }\n button.active {\n color: var(--lit-devtools-accent);\n border-bottom-color: var(--lit-devtools-accent);\n }\n button:focus-visible {\n outline: 2px solid var(--lit-devtools-accent-ring);\n outline-offset: -2px;\n }\n button svg {\n width: 18px;\n height: 18px;\n flex-shrink: 0;\n }\n .badge {\n flex-shrink: 0;\n min-width: 16px;\n padding: 0 var(--lit-devtools-space-1);\n border-radius: var(--lit-devtools-radius-pill);\n background: var(--lit-devtools-error-soft);\n color: var(--lit-devtools-error);\n font-size: var(--lit-devtools-text-xs);\n line-height: 16px;\n text-align: center;\n }\n :host([size='sm']) button {\n font-size: var(--lit-devtools-text-xs);\n padding: 0 var(--lit-devtools-space-4);\n }\n :host([size='md']) button,\n :host(:not([size])) button {\n font-size: var(--lit-devtools-text-sm);\n padding: 0 var(--lit-devtools-space-5);\n }\n `,\n ];\n\n @property({type: Array}) declare items: TabItem[];\n\n @property() declare value: string;\n\n @property() declare size: SegTabSize;\n\n constructor() {\n super();\n this.items = [];\n this.value = '';\n this.size = 'md';\n }\n\n private _select(id: string): void {\n this.value = id;\n this.dispatchEvent(\n new CustomEvent('change', {\n detail: {value: id},\n bubbles: true,\n composed: true,\n })\n );\n }\n\n override render() {\n return html`\n ${this.items.map(\n (item) => html`\n <button\n role=\"tab\"\n aria-selected=${item.id === this.value}\n class=${item.id === this.value ? 'active' : ''}\n @click=${() => this._select(item.id)}\n >\n ${\n item.icon\n ? html`<svg\n viewBox=\"0 0 256 256\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d=${item.icon} />\n </svg>`\n : nothing\n }\n ${item.label}\n ${\n item.badge\n ? html`<span class=\"badge\">${item.badge}</span>`\n : nothing\n }\n </button>\n `\n )}\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'segmented-tabs': SegmentedTabs;\n }\n}\n"]}
package/lib/snapshot.d.ts CHANGED
@@ -1,7 +1,15 @@
1
1
  /**
2
- * @license
3
- * Copyright 2026 Google LLC
4
- * SPDX-License-Identifier: BSD-3-Clause
2
+ * Freezing a live session into a static panel someone else can open.
3
+ *
4
+ * Capture needs no transport: by the time a developer wants to export, the
5
+ * node side is already holding the timeline buffer, the component tree, the
6
+ * details of everything that was inspected, and the HMR incompatibility list.
7
+ * The export reads its own state and hands it to devframe's build adapter as
8
+ * a second, replaying definition.
9
+ *
10
+ * The output is a plain directory: the panel SPA, a `__connection.json` that
11
+ * says `backend: 'static'`, and the baked RPC dump. It is mount-path agnostic,
12
+ * so it works opened from a file server at any base — zip it onto an issue.
5
13
  */
6
14
  import type { FeatureSettings } from '../types/timeline.js';
7
15
  import type { SessionSnapshot } from '../types/snapshot.js';
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../src/lib/snapshot.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkBH,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,sBAAsB,CAAC;AAE1D,+EAA+E;AAC/E,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,aACd,eAAe,WAChB;IACP,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,KACA,OAAO,CAAC,mBAAmB,CAyC7B,CAAC"}
1
+ {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../src/lib/snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,sBAAsB,CAAC;AAE1D,+EAA+E;AAC/E,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,aACd,eAAe,WAChB;IACP,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,KACA,OAAO,CAAC,mBAAmB,CAyC7B,CAAC"}
package/lib/snapshot.js CHANGED
@@ -1,8 +1,3 @@
1
- /**
2
- * @license
3
- * Copyright 2026 Google LLC
4
- * SPDX-License-Identifier: BSD-3-Clause
5
- */
6
1
  /**
7
2
  * Freezing a live session into a static panel someone else can open.
8
3
  *
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../src/lib/snapshot.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAC,iBAAiB,EAAC,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAC,gBAAgB,EAAC,MAAM,sBAAsB,CAAC;AAYtD,yEAAyE;AACzE,MAAM,UAAU,GAAG,CAAC,KAA+B,EAAU,EAAE,CAC7D,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;AAE1E;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAChC,QAAyB,EACzB,OAIC,EAC6B,EAAE;IAChC,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAC;IAC9D,0EAA0E;IAC1E,4EAA4E;IAC5E,2EAA2E;IAC3E,4CAA4C;IAC5C,MAAM,EAAC,UAAU,EAAC,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IAC7C,MAAM,EAAC,IAAI,EAAC,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;IACzC,IACE,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC;QAC1B,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,EACtD,CAAC;QACD,MAAM,IAAI,KAAK,CACb,kBAAkB,OAAO,CAAC,MAAM,iCAAiC;YAC/D,wBAAwB,CAC3B,CAAC;IACJ,CAAC;IACD,MAAM,UAAU,GAAG,iBAAiB,CAAC;QACnC,qEAAqE;QACrE,8DAA8D;QAC9D,MAAM,EAAE,gBAAgB,EAAE;QAC1B,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ;QAChC,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,MAAM,EAAE,QAAQ;KACjB,CAAC,CAAC;IAEH,MAAM,WAAW,CAAC,UAAU,EAAE;QAC5B,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,wEAAwE;QACxE,0EAA0E;QAC1E,sCAAsC;QACtC,KAAK,EAAE,IAAI;KACZ,CAAC,CAAC;IAEH,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM;QAC9B,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC;QACtC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM;KACjC,CAAC;AACJ,CAAC,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * Freezing a live session into a static panel someone else can open.\n *\n * Capture needs no transport: by the time a developer wants to export, the\n * node side is already holding the timeline buffer, the component tree, the\n * details of everything that was inspected, and the HMR incompatibility list.\n * The export reads its own state and hands it to devframe's build adapter as\n * a second, replaying definition.\n *\n * The output is a plain directory: the panel SPA, a `__connection.json` that\n * says `backend: 'static'`, and the baked RPC dump. It is mount-path agnostic,\n * so it works opened from a file server at any base — zip it onto an issue.\n */\n\nimport {createLitDevframe} from './devframe/definition.js';\nimport {createNullSource} from './devframe/source.js';\nimport type {FeatureSettings} from '../types/timeline.js';\nimport type {SessionSnapshot} from '../types/snapshot.js';\n\n/** What {@link buildSnapshot} reports back to whoever asked for the export. */\nexport interface SnapshotBuildResult {\n outDir: string;\n events: number;\n components: number;\n details: number;\n}\n\n/** Count the nodes of a tree, so the caller can say what it exported. */\nconst countNodes = (nodes: SessionSnapshot['roots']): number =>\n nodes.reduce((total, node) => total + 1 + countNodes(node.children), 0);\n\n/**\n * Write `snapshot` to `outDir` as a self-contained static panel, replacing an\n * earlier snapshot there. Any other existing directory is refused.\n *\n * The build adapter is imported dynamically: it reaches for `node:fs`, and\n * `definition.ts` is deliberately framework- and environment-neutral, so a\n * static import would drag filesystem code into every context that merely\n * builds the definition.\n */\nexport const buildSnapshot = async (\n snapshot: SessionSnapshot,\n options: {\n outDir: string;\n features: FeatureSettings | null;\n clientAssets?: string;\n }\n): Promise<SnapshotBuildResult> => {\n const {createBuild} = await import('devframe/adapters/build');\n // `createBuild` deletes `outDir` recursively before writing. Replacing an\n // earlier export is the point, but a typo'd `outDir` that names the project\n // (or `src`) must not cost the developer their tree: only a directory that\n // already holds a snapshot may be replaced.\n const {existsSync} = await import('node:fs');\n const {join} = await import('node:path');\n if (\n existsSync(options.outDir) &&\n !existsSync(join(options.outDir, '__connection.json'))\n ) {\n throw new Error(\n `[lit-devtools] ${options.outDir} exists and is not a snapshot; ` +\n 'refusing to replace it'\n );\n }\n const definition = createLitDevframe({\n // Nothing to attach to: the page this session describes is gone, and\n // every answer the frozen panel needs is already in `replay`.\n source: createNullSource(),\n version: snapshot.version,\n features: () => options.features,\n clientAssets: options.clientAssets,\n replay: snapshot,\n });\n\n await createBuild(definition, {\n outDir: options.outDir,\n // The Vite plugin declares `capabilities.build: false` because there is\n // nothing to render during `vite build` — a *recorded* session is the one\n // case where a build does make sense.\n force: true,\n });\n\n return {\n outDir: options.outDir,\n events: snapshot.events.length,\n components: countNodes(snapshot.roots),\n details: snapshot.details.length,\n };\n};\n"]}
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../src/lib/snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAC,iBAAiB,EAAC,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAC,gBAAgB,EAAC,MAAM,sBAAsB,CAAC;AAYtD,yEAAyE;AACzE,MAAM,UAAU,GAAG,CAAC,KAA+B,EAAU,EAAE,CAC7D,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;AAE1E;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAChC,QAAyB,EACzB,OAIC,EAC6B,EAAE;IAChC,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAC;IAC9D,0EAA0E;IAC1E,4EAA4E;IAC5E,2EAA2E;IAC3E,4CAA4C;IAC5C,MAAM,EAAC,UAAU,EAAC,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IAC7C,MAAM,EAAC,IAAI,EAAC,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;IACzC,IACE,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC;QAC1B,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,EACtD,CAAC;QACD,MAAM,IAAI,KAAK,CACb,kBAAkB,OAAO,CAAC,MAAM,iCAAiC;YAC/D,wBAAwB,CAC3B,CAAC;IACJ,CAAC;IACD,MAAM,UAAU,GAAG,iBAAiB,CAAC;QACnC,qEAAqE;QACrE,8DAA8D;QAC9D,MAAM,EAAE,gBAAgB,EAAE;QAC1B,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ;QAChC,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,MAAM,EAAE,QAAQ;KACjB,CAAC,CAAC;IAEH,MAAM,WAAW,CAAC,UAAU,EAAE;QAC5B,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,wEAAwE;QACxE,0EAA0E;QAC1E,sCAAsC;QACtC,KAAK,EAAE,IAAI;KACZ,CAAC,CAAC;IAEH,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM;QAC9B,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC;QACtC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM;KACjC,CAAC;AACJ,CAAC,CAAC","sourcesContent":["/**\n * Freezing a live session into a static panel someone else can open.\n *\n * Capture needs no transport: by the time a developer wants to export, the\n * node side is already holding the timeline buffer, the component tree, the\n * details of everything that was inspected, and the HMR incompatibility list.\n * The export reads its own state and hands it to devframe's build adapter as\n * a second, replaying definition.\n *\n * The output is a plain directory: the panel SPA, a `__connection.json` that\n * says `backend: 'static'`, and the baked RPC dump. It is mount-path agnostic,\n * so it works opened from a file server at any base — zip it onto an issue.\n */\n\nimport {createLitDevframe} from './devframe/definition.js';\nimport {createNullSource} from './devframe/source.js';\nimport type {FeatureSettings} from '../types/timeline.js';\nimport type {SessionSnapshot} from '../types/snapshot.js';\n\n/** What {@link buildSnapshot} reports back to whoever asked for the export. */\nexport interface SnapshotBuildResult {\n outDir: string;\n events: number;\n components: number;\n details: number;\n}\n\n/** Count the nodes of a tree, so the caller can say what it exported. */\nconst countNodes = (nodes: SessionSnapshot['roots']): number =>\n nodes.reduce((total, node) => total + 1 + countNodes(node.children), 0);\n\n/**\n * Write `snapshot` to `outDir` as a self-contained static panel, replacing an\n * earlier snapshot there. Any other existing directory is refused.\n *\n * The build adapter is imported dynamically: it reaches for `node:fs`, and\n * `definition.ts` is deliberately framework- and environment-neutral, so a\n * static import would drag filesystem code into every context that merely\n * builds the definition.\n */\nexport const buildSnapshot = async (\n snapshot: SessionSnapshot,\n options: {\n outDir: string;\n features: FeatureSettings | null;\n clientAssets?: string;\n }\n): Promise<SnapshotBuildResult> => {\n const {createBuild} = await import('devframe/adapters/build');\n // `createBuild` deletes `outDir` recursively before writing. Replacing an\n // earlier export is the point, but a typo'd `outDir` that names the project\n // (or `src`) must not cost the developer their tree: only a directory that\n // already holds a snapshot may be replaced.\n const {existsSync} = await import('node:fs');\n const {join} = await import('node:path');\n if (\n existsSync(options.outDir) &&\n !existsSync(join(options.outDir, '__connection.json'))\n ) {\n throw new Error(\n `[lit-devtools] ${options.outDir} exists and is not a snapshot; ` +\n 'refusing to replace it'\n );\n }\n const definition = createLitDevframe({\n // Nothing to attach to: the page this session describes is gone, and\n // every answer the frozen panel needs is already in `replay`.\n source: createNullSource(),\n version: snapshot.version,\n features: () => options.features,\n clientAssets: options.clientAssets,\n replay: snapshot,\n });\n\n await createBuild(definition, {\n outDir: options.outDir,\n // The Vite plugin declares `capabilities.build: false` because there is\n // nothing to render during `vite build` — a *recorded* session is the one\n // case where a build does make sense.\n force: true,\n });\n\n return {\n outDir: options.outDir,\n events: snapshot.events.length,\n components: countNodes(snapshot.roots),\n details: snapshot.details.length,\n };\n};\n"]}
@@ -1,8 +1,3 @@
1
- /**
2
- * @license
3
- * Copyright 2026 Google LLC
4
- * SPDX-License-Identifier: BSD-3-Clause
5
- */
6
1
  import type MagicString from 'magic-string';
7
2
  /** Stable key shared between transform output and runtime resolution. */
8
3
  export declare const SOURCE_META_KEY = "@lit-labs/vite-plugin-lit#source";
@@ -1 +1 @@
1
- {"version":3,"file":"source-meta.d.ts","sourceRoot":"","sources":["../src/lib/source-meta.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,WAAW,MAAM,cAAc,CAAC;AAE5C,yEAAyE;AACzE,eAAO,MAAM,eAAe,qCAAqC,CAAC;AAElE;;;GAGG;AACH,eAAO,MAAM,eAAe,mDAAqC,CAAC;AAElE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,uDAAuD;AACvD,eAAO,MAAM,YAAY,SAAU,MAAM,SAAS,MAAM,KAAG,MAClB,CAAC;AAsL1C;;;GAGG;AACH,eAAO,MAAM,gBAAgB,SACrB,MAAM,YACF,MAAM,MACZ,WAAW,KACd,OAiEF,CAAC"}
1
+ {"version":3,"file":"source-meta.d.ts","sourceRoot":"","sources":["../src/lib/source-meta.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,WAAW,MAAM,cAAc,CAAC;AAE5C,yEAAyE;AACzE,eAAO,MAAM,eAAe,qCAAqC,CAAC;AAElE;;;GAGG;AACH,eAAO,MAAM,eAAe,mDAAqC,CAAC;AAElE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,uDAAuD;AACvD,eAAO,MAAM,YAAY,SAAU,MAAM,SAAS,MAAM,KAAG,MAClB,CAAC;AAsL1C;;;GAGG;AACH,eAAO,MAAM,gBAAgB,SACrB,MAAM,YACF,MAAM,MACZ,WAAW,KACd,OAiEF,CAAC"}
@@ -1,8 +1,3 @@
1
- /**
2
- * @license
3
- * Copyright 2026 Google LLC
4
- * SPDX-License-Identifier: BSD-3-Clause
5
- */
6
1
  /** Stable key shared between transform output and runtime resolution. */
7
2
  export const SOURCE_META_KEY = '@lit-labs/vite-plugin-lit#source';
8
3
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"source-meta.js","sourceRoot":"","sources":["../src/lib/source-meta.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nimport type MagicString from 'magic-string';\n\n/** Stable key shared between transform output and runtime resolution. */\nexport const SOURCE_META_KEY = '@lit-labs/vite-plugin-lit#source';\n\n/**\n * The expression string used in generated code to reference the shared\n * symbol at runtime.\n */\nexport const SOURCE_META_SYM = `Symbol.for('${SOURCE_META_KEY}')`;\n\nexport interface InjectedSourceMeta {\n filePath: string;\n lineNumber: number;\n componentName?: string;\n}\n\n/** 1-based line number for an index in source text. */\nexport const lineNumberAt = (code: string, index: number): number =>\n code.slice(0, index).split('\\n').length;\n\n/**\n * Finds the `{` that opens the body of the class starting at `classStart`:\n * the first one at the top level of the heading. The heading can hold braces\n * of its own — type literals in generic arguments\n * (`extends Dialog<{open: boolean}>`), options passed to a mixin\n * (`extends Mixin(Base, {shadow: true})`) — so anything nested in `<…>`,\n * `(…)` or `[…]` is skipped, along with strings and comments. The `>` of an\n * arrow type (`() => void`) doesn't close a `<`.\n */\nconst findClassBodyOpen = (code: string, classStart: number): number => {\n let depth = 0;\n for (let i = classStart + 'class'.length; i < code.length; i++) {\n const ch = code[i];\n if (ch === '\"' || ch === \"'\" || ch === '`') {\n i++;\n while (i < code.length && code[i] !== ch) {\n if (code[i] === '\\\\') i++;\n i++;\n }\n } else if (ch === '/' && code[i + 1] === '/') {\n i = code.indexOf('\\n', i);\n if (i === -1) return -1;\n } else if (ch === '/' && code[i + 1] === '*') {\n i = code.indexOf('*/', i + 2);\n if (i === -1) return -1;\n i++;\n } else if (ch === '{') {\n if (depth === 0) return i;\n depth++;\n } else if (ch === '(' || ch === '[' || ch === '<') {\n depth++;\n } else if (ch === '}' || ch === ')' || ch === ']') {\n depth--;\n } else if (ch === '>' && code[i - 1] !== '=') {\n depth--;\n }\n }\n return -1;\n};\n\n/**\n * Finds the index after the closing `}` of a class body starting at\n * `classStart`. Skips braces inside strings, comments, regex literals, and\n * template literals — including code in `${…}` interpolations, where nested\n * templates (Lit's `html\\`…\\`` inside `.map()` etc.) recurse arbitrarily.\n */\nconst findClassBodyEnd = (code: string, classStart: number): number => {\n const open = findClassBodyOpen(code, classStart);\n if (open === -1) return -1;\n // Brace depth of the code scope currently being scanned. Entering a `${…}`\n // interpolation pushes the enclosing scope's depth and restarts at 1 (the\n // `${` counts as the open brace); balancing it pops back into the template.\n let depth = 1;\n const interpolationStack: number[] = [];\n let inTemplate = false;\n let i = open + 1;\n while (i < code.length) {\n const ch = code[i];\n if (inTemplate) {\n if (ch === '\\\\') {\n i += 2;\n continue;\n }\n if (ch === '`') {\n inTemplate = false;\n i++;\n continue;\n }\n if (ch === '$' && code[i + 1] === '{') {\n interpolationStack.push(depth);\n depth = 1;\n inTemplate = false;\n i += 2;\n continue;\n }\n i++;\n continue;\n }\n if (ch === '\"' || ch === \"'\") {\n const quote = ch;\n i++;\n while (i < code.length && code[i] !== quote) {\n if (code[i] === '\\\\') i++;\n i++;\n }\n i++;\n continue;\n }\n if (ch === '`') {\n inTemplate = true;\n i++;\n continue;\n }\n if (ch === '/') {\n const next = code[i + 1];\n if (next === '/') {\n i = code.indexOf('\\n', i);\n if (i === -1) return -1;\n continue;\n }\n if (next === '*') {\n i = code.indexOf('*/', i + 2);\n if (i === -1) return -1;\n i += 2;\n continue;\n }\n // Regex literal vs division: scan back over whitespace to the last\n // significant char — a regex can only follow an operator, opening\n // punctuation, or a keyword like `return`. `a / b` has an identifier\n // there, so it's division and scans on as plain code.\n let j = i - 1;\n while (j >= 0 && /\\s/.test(code[j])) j--;\n const prev = j >= 0 ? code[j] : '';\n const regexPossible =\n j < 0 ||\n /[=:(,+\\-!&|?{}[;]/.test(prev) ||\n /(?:^|[^\\w$])(?:return|typeof|case|instanceof|in|of|new|delete|void|throw|do|else|yield|await)$/.test(\n code.slice(Math.max(0, j - 11), j + 1)\n );\n if (regexPossible) {\n let k = i + 1;\n let inCharClass = false;\n while (\n k < code.length &&\n code[k] !== '\\n' &&\n (inCharClass || code[k] !== '/')\n ) {\n if (code[k] === '\\\\') k++;\n else if (code[k] === '[') inCharClass = true;\n else if (code[k] === ']') inCharClass = false;\n k++;\n }\n if (code[k] === '/') {\n i = k + 1;\n continue;\n }\n // No closing `/` before the line ends — not a regex after all.\n }\n }\n if (ch === '{') {\n depth++;\n } else if (ch === '}') {\n depth--;\n if (depth === 0) {\n const enclosing = interpolationStack.pop();\n if (enclosing === undefined) {\n return i + 1;\n }\n depth = enclosing;\n inTemplate = true;\n }\n }\n i++;\n }\n return -1;\n};\n\nconst makeAssignment = (\n className: string,\n filePath: string,\n lineNumber: number\n) =>\n `${className}[${SOURCE_META_SYM}]={filePath:${JSON.stringify(filePath)},lineNumber:${lineNumber},componentName:${JSON.stringify(className)}};`;\n\n/**\n * True when `className` is declared at module top level (column 0). Nested\n * declarations are skipped deliberately: the metadata assignment for this path\n * is appended at the end of the module, where a function/block-scoped binding\n * would not be in scope (a `ReferenceError` at module evaluation).\n */\nconst isClassDeclaredInModule = (code: string, className: string): boolean =>\n new RegExp(\n `^(?:export\\\\s+)?(?:class|let|const|var)\\\\s+${className}\\\\b`,\n 'm'\n ).test(code);\n\n/** True when `index` starts a line (module top level in emitted output). */\nconst isAtLineStart = (code: string, index: number): boolean =>\n index === 0 || code[index - 1] === '\\n';\n\n/**\n * Injects component source metadata onto custom element class constructors.\n * Returns whether any injection was made.\n */\nexport const injectSourceMeta = (\n code: string,\n filePath: string,\n ms: MagicString\n): boolean => {\n if (code.includes(SOURCE_META_SYM)) {\n return false;\n }\n let changed = false;\n const injected = new Set<string>();\n\n const injectAtClassEnd = (\n className: string,\n matchIndex: number,\n match: string\n ) => {\n if (injected.has(className)) return;\n const classOffset = match.indexOf('class');\n if (classOffset === -1) return;\n const classStart = matchIndex + classOffset;\n const end = findClassBodyEnd(code, classStart);\n if (end === -1) return;\n // Report the match start (the `@customElement` decorator) rather than the\n // `class` keyword, so the overlay points at the top of the component.\n const line = lineNumberAt(code, matchIndex);\n // Insert right after the class body so the assignment lives in the same\n // scope as the declaration — appending at module end breaks for a class\n // declared inside a function or block.\n ms.appendLeft(end, '\\n' + makeAssignment(className, filePath, line));\n injected.add(className);\n changed = true;\n };\n\n // @customElement(...) class Foo (any whitespace between them)\n for (const m of code.matchAll(\n /@customElement\\s*\\([^)]*\\)\\s+(?:export\\s+)?class\\s+(\\w+)/g\n )) {\n injectAtClassEnd(m[1], m.index, m[0]);\n }\n\n // customElements.define('tag', ClassName)\n for (const m of code.matchAll(\n /customElements\\.define\\s*\\(\\s*['\"][^'\"]+['\"]\\s*,\\s*(\\w+)/g\n )) {\n const className = m[1];\n if (injected.has(className) || !isClassDeclaredInModule(code, className)) {\n continue;\n }\n const line = lineNumberAt(code, m.index);\n ms.append('\\n' + makeAssignment(className, filePath, line));\n injected.add(className);\n changed = true;\n }\n\n // TypeScript experimental-decorators / esbuild output\n // e.g. `Foo = __decorateClass([customElement(...)], Foo)`\n // `Foo = _decorate([customElement(...)], Foo)`\n for (const m of code.matchAll(\n /(\\w+)\\s*=\\s*__decorate\\w*\\(\\s*\\[[\\s\\S]*?customElement\\s*\\([^)]*\\)[\\s\\S]*?\\],\\s*\\1\\)/g\n )) {\n const className = m[1];\n if (injected.has(className) || !isAtLineStart(code, m.index)) continue;\n const line = lineNumberAt(code, m.index);\n ms.append('\\n' + makeAssignment(className, filePath, line));\n injected.add(className);\n changed = true;\n }\n\n return changed;\n};\n"]}
1
+ {"version":3,"file":"source-meta.js","sourceRoot":"","sources":["../src/lib/source-meta.ts"],"names":[],"mappings":"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","sourcesContent":["import type MagicString from 'magic-string';\n\n/** Stable key shared between transform output and runtime resolution. */\nexport const SOURCE_META_KEY = '@lit-labs/vite-plugin-lit#source';\n\n/**\n * The expression string used in generated code to reference the shared\n * symbol at runtime.\n */\nexport const SOURCE_META_SYM = `Symbol.for('${SOURCE_META_KEY}')`;\n\nexport interface InjectedSourceMeta {\n filePath: string;\n lineNumber: number;\n componentName?: string;\n}\n\n/** 1-based line number for an index in source text. */\nexport const lineNumberAt = (code: string, index: number): number =>\n code.slice(0, index).split('\\n').length;\n\n/**\n * Finds the `{` that opens the body of the class starting at `classStart`:\n * the first one at the top level of the heading. The heading can hold braces\n * of its own — type literals in generic arguments\n * (`extends Dialog<{open: boolean}>`), options passed to a mixin\n * (`extends Mixin(Base, {shadow: true})`) — so anything nested in `<…>`,\n * `(…)` or `[…]` is skipped, along with strings and comments. The `>` of an\n * arrow type (`() => void`) doesn't close a `<`.\n */\nconst findClassBodyOpen = (code: string, classStart: number): number => {\n let depth = 0;\n for (let i = classStart + 'class'.length; i < code.length; i++) {\n const ch = code[i];\n if (ch === '\"' || ch === \"'\" || ch === '`') {\n i++;\n while (i < code.length && code[i] !== ch) {\n if (code[i] === '\\\\') i++;\n i++;\n }\n } else if (ch === '/' && code[i + 1] === '/') {\n i = code.indexOf('\\n', i);\n if (i === -1) return -1;\n } else if (ch === '/' && code[i + 1] === '*') {\n i = code.indexOf('*/', i + 2);\n if (i === -1) return -1;\n i++;\n } else if (ch === '{') {\n if (depth === 0) return i;\n depth++;\n } else if (ch === '(' || ch === '[' || ch === '<') {\n depth++;\n } else if (ch === '}' || ch === ')' || ch === ']') {\n depth--;\n } else if (ch === '>' && code[i - 1] !== '=') {\n depth--;\n }\n }\n return -1;\n};\n\n/**\n * Finds the index after the closing `}` of a class body starting at\n * `classStart`. Skips braces inside strings, comments, regex literals, and\n * template literals — including code in `${…}` interpolations, where nested\n * templates (Lit's `html\\`…\\`` inside `.map()` etc.) recurse arbitrarily.\n */\nconst findClassBodyEnd = (code: string, classStart: number): number => {\n const open = findClassBodyOpen(code, classStart);\n if (open === -1) return -1;\n // Brace depth of the code scope currently being scanned. Entering a `${…}`\n // interpolation pushes the enclosing scope's depth and restarts at 1 (the\n // `${` counts as the open brace); balancing it pops back into the template.\n let depth = 1;\n const interpolationStack: number[] = [];\n let inTemplate = false;\n let i = open + 1;\n while (i < code.length) {\n const ch = code[i];\n if (inTemplate) {\n if (ch === '\\\\') {\n i += 2;\n continue;\n }\n if (ch === '`') {\n inTemplate = false;\n i++;\n continue;\n }\n if (ch === '$' && code[i + 1] === '{') {\n interpolationStack.push(depth);\n depth = 1;\n inTemplate = false;\n i += 2;\n continue;\n }\n i++;\n continue;\n }\n if (ch === '\"' || ch === \"'\") {\n const quote = ch;\n i++;\n while (i < code.length && code[i] !== quote) {\n if (code[i] === '\\\\') i++;\n i++;\n }\n i++;\n continue;\n }\n if (ch === '`') {\n inTemplate = true;\n i++;\n continue;\n }\n if (ch === '/') {\n const next = code[i + 1];\n if (next === '/') {\n i = code.indexOf('\\n', i);\n if (i === -1) return -1;\n continue;\n }\n if (next === '*') {\n i = code.indexOf('*/', i + 2);\n if (i === -1) return -1;\n i += 2;\n continue;\n }\n // Regex literal vs division: scan back over whitespace to the last\n // significant char — a regex can only follow an operator, opening\n // punctuation, or a keyword like `return`. `a / b` has an identifier\n // there, so it's division and scans on as plain code.\n let j = i - 1;\n while (j >= 0 && /\\s/.test(code[j])) j--;\n const prev = j >= 0 ? code[j] : '';\n const regexPossible =\n j < 0 ||\n /[=:(,+\\-!&|?{}[;]/.test(prev) ||\n /(?:^|[^\\w$])(?:return|typeof|case|instanceof|in|of|new|delete|void|throw|do|else|yield|await)$/.test(\n code.slice(Math.max(0, j - 11), j + 1)\n );\n if (regexPossible) {\n let k = i + 1;\n let inCharClass = false;\n while (\n k < code.length &&\n code[k] !== '\\n' &&\n (inCharClass || code[k] !== '/')\n ) {\n if (code[k] === '\\\\') k++;\n else if (code[k] === '[') inCharClass = true;\n else if (code[k] === ']') inCharClass = false;\n k++;\n }\n if (code[k] === '/') {\n i = k + 1;\n continue;\n }\n // No closing `/` before the line ends — not a regex after all.\n }\n }\n if (ch === '{') {\n depth++;\n } else if (ch === '}') {\n depth--;\n if (depth === 0) {\n const enclosing = interpolationStack.pop();\n if (enclosing === undefined) {\n return i + 1;\n }\n depth = enclosing;\n inTemplate = true;\n }\n }\n i++;\n }\n return -1;\n};\n\nconst makeAssignment = (\n className: string,\n filePath: string,\n lineNumber: number\n) =>\n `${className}[${SOURCE_META_SYM}]={filePath:${JSON.stringify(filePath)},lineNumber:${lineNumber},componentName:${JSON.stringify(className)}};`;\n\n/**\n * True when `className` is declared at module top level (column 0). Nested\n * declarations are skipped deliberately: the metadata assignment for this path\n * is appended at the end of the module, where a function/block-scoped binding\n * would not be in scope (a `ReferenceError` at module evaluation).\n */\nconst isClassDeclaredInModule = (code: string, className: string): boolean =>\n new RegExp(\n `^(?:export\\\\s+)?(?:class|let|const|var)\\\\s+${className}\\\\b`,\n 'm'\n ).test(code);\n\n/** True when `index` starts a line (module top level in emitted output). */\nconst isAtLineStart = (code: string, index: number): boolean =>\n index === 0 || code[index - 1] === '\\n';\n\n/**\n * Injects component source metadata onto custom element class constructors.\n * Returns whether any injection was made.\n */\nexport const injectSourceMeta = (\n code: string,\n filePath: string,\n ms: MagicString\n): boolean => {\n if (code.includes(SOURCE_META_SYM)) {\n return false;\n }\n let changed = false;\n const injected = new Set<string>();\n\n const injectAtClassEnd = (\n className: string,\n matchIndex: number,\n match: string\n ) => {\n if (injected.has(className)) return;\n const classOffset = match.indexOf('class');\n if (classOffset === -1) return;\n const classStart = matchIndex + classOffset;\n const end = findClassBodyEnd(code, classStart);\n if (end === -1) return;\n // Report the match start (the `@customElement` decorator) rather than the\n // `class` keyword, so the overlay points at the top of the component.\n const line = lineNumberAt(code, matchIndex);\n // Insert right after the class body so the assignment lives in the same\n // scope as the declaration — appending at module end breaks for a class\n // declared inside a function or block.\n ms.appendLeft(end, '\\n' + makeAssignment(className, filePath, line));\n injected.add(className);\n changed = true;\n };\n\n // @customElement(...) class Foo (any whitespace between them)\n for (const m of code.matchAll(\n /@customElement\\s*\\([^)]*\\)\\s+(?:export\\s+)?class\\s+(\\w+)/g\n )) {\n injectAtClassEnd(m[1], m.index, m[0]);\n }\n\n // customElements.define('tag', ClassName)\n for (const m of code.matchAll(\n /customElements\\.define\\s*\\(\\s*['\"][^'\"]+['\"]\\s*,\\s*(\\w+)/g\n )) {\n const className = m[1];\n if (injected.has(className) || !isClassDeclaredInModule(code, className)) {\n continue;\n }\n const line = lineNumberAt(code, m.index);\n ms.append('\\n' + makeAssignment(className, filePath, line));\n injected.add(className);\n changed = true;\n }\n\n // TypeScript experimental-decorators / esbuild output\n // e.g. `Foo = __decorateClass([customElement(...)], Foo)`\n // `Foo = _decorate([customElement(...)], Foo)`\n for (const m of code.matchAll(\n /(\\w+)\\s*=\\s*__decorate\\w*\\(\\s*\\[[\\s\\S]*?customElement\\s*\\([^)]*\\)[\\s\\S]*?\\],\\s*\\1\\)/g\n )) {\n const className = m[1];\n if (injected.has(className) || !isAtLineStart(code, m.index)) continue;\n const line = lineNumberAt(code, m.index);\n ms.append('\\n' + makeAssignment(className, filePath, line));\n injected.add(className);\n changed = true;\n }\n\n return changed;\n};\n"]}
@@ -1,8 +1,3 @@
1
- /**
2
- * @license
3
- * Copyright 2026 Google LLC
4
- * SPDX-License-Identifier: BSD-3-Clause
5
- */
6
1
  /**
7
2
  * Derivation over recorded timeline events.
8
3
  *
@@ -1 +1 @@
1
- {"version":3,"file":"derive.d.ts","sourceRoot":"","sources":["../../src/lib/timeline/derive.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,yBAAyB,CAAC;AAc3D;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACnC,IAAI,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC7B,gEAAgE;IAChE,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAED,4CAA4C;AAC5C,MAAM,WAAW,WAAW;IAC1B,2DAA2D;IAC3D,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,gFAAgF;IAChF,KAAK,CAAC,EAAE;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC;CACxE;AAED,wDAAwD;AACxD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,OAAO,EAAE,KAAK,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IAC7C,MAAM,CAAC,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC;CACvC;AAwBD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,OAAO,WAAY,SAAS,aAAa,EAAE,KAAG,YAAY,EA0DtE,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,UAClB,SAAS,YAAY,EAAE,KAC7B,WAAW,EAuCb,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,WAAY,SAAS,WAAW,EAAE,KAAG,eAAe,EAoDtE,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,WACjB,SAAS,WAAW,EAAE,UACtB,SAAS,aAAa,EAAE,wBAE/B,WAAW,EA4Bb,CAAC"}
1
+ {"version":3,"file":"derive.d.ts","sourceRoot":"","sources":["../../src/lib/timeline/derive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,yBAAyB,CAAC;AAc3D;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACnC,IAAI,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC7B,gEAAgE;IAChE,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAED,4CAA4C;AAC5C,MAAM,WAAW,WAAW;IAC1B,2DAA2D;IAC3D,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,gFAAgF;IAChF,KAAK,CAAC,EAAE;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC;CACxE;AAED,wDAAwD;AACxD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,OAAO,EAAE,KAAK,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IAC7C,MAAM,CAAC,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC;CACvC;AAwBD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,OAAO,WAAY,SAAS,aAAa,EAAE,KAAG,YAAY,EA0DtE,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,UAClB,SAAS,YAAY,EAAE,KAC7B,WAAW,EAuCb,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,WAAY,SAAS,WAAW,EAAE,KAAG,eAAe,EAoDtE,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,WACjB,SAAS,WAAW,EAAE,UACtB,SAAS,aAAa,EAAE,wBAE/B,WAAW,EA4Bb,CAAC"}
@@ -1,7 +1,26 @@
1
1
  /**
2
- * @license
3
- * Copyright 2026 Google LLC
4
- * SPDX-License-Identifier: BSD-3-Clause
2
+ * Derivation over recorded timeline events.
3
+ *
4
+ * The capture layers emit one event per phase boundary, which is the right
5
+ * wire format and the wrong thing to read: a single update tick of one
6
+ * component is five to ten rows whose durations the reader has to subtract by
7
+ * hand. Everything needed to do better is already on the events — `groupId`
8
+ * pairs a start with its end, `data.changed` names the reactive properties
9
+ * that caused the update — so this module turns a flat event list into the
10
+ * three shapes the panel and agents actually ask for:
11
+ *
12
+ * - {@link TimelineSpan} — a start/end pair collapsed into one entry with a
13
+ * duration ("`update` took 1.8ms").
14
+ * - {@link UpdateCycle} — one component's whole update tick, with the changed
15
+ * property keys that triggered it ("`<hmr-counter>` updated because
16
+ * `count` changed").
17
+ * - {@link ComponentRollup} — per-component totals over a recording ("this
18
+ * component updated 340 times for 120ms").
19
+ *
20
+ * Pure and dependency-free by design: it imports only the shared event types,
21
+ * so the panel derives client-side over its 5000-event buffer and
22
+ * `devframe/definition.ts` — which must stay framework-neutral — can derive
23
+ * server-side over the ring buffer for the agent-facing summary.
5
24
  */
6
25
  /** Layer whose events describe Lit update ticks. */
7
26
  const LIFECYCLE_LAYER_ID = 'lit-lifecycle';
@@ -1 +1 @@
1
- {"version":3,"file":"derive.js","sourceRoot":"","sources":["../../src/lib/timeline/derive.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * Derivation over recorded timeline events.\n *\n * The capture layers emit one event per phase boundary, which is the right\n * wire format and the wrong thing to read: a single update tick of one\n * component is five to ten rows whose durations the reader has to subtract by\n * hand. Everything needed to do better is already on the events — `groupId`\n * pairs a start with its end, `data.changed` names the reactive properties\n * that caused the update — so this module turns a flat event list into the\n * three shapes the panel and agents actually ask for:\n *\n * - {@link TimelineSpan} — a start/end pair collapsed into one entry with a\n * duration (\"`update` took 1.8ms\").\n * - {@link UpdateCycle} — one component's whole update tick, with the changed\n * property keys that triggered it (\"`<hmr-counter>` updated because\n * `count` changed\").\n * - {@link ComponentRollup} — per-component totals over a recording (\"this\n * component updated 340 times for 120ms\").\n *\n * Pure and dependency-free by design: it imports only the shared event types,\n * so the panel derives client-side over its 5000-event buffer and\n * `devframe/definition.ts` — which must stay framework-neutral — can derive\n * server-side over the ring buffer for the agent-facing summary.\n */\n\nimport type {TimelineEvent} from '../../types/timeline.js';\n\n/** Layer whose events describe Lit update ticks. */\nconst LIFECYCLE_LAYER_ID = 'lit-lifecycle';\n\n/** Layers whose events are developer input, for {@link attributeInput}. */\nconst INPUT_LAYER_IDS: readonly string[] = ['mouse', 'keyboard'];\n\n/** The phase that brackets an entire update tick. */\nconst ROOT_PHASE = 'performUpdate';\n\nconst START_SUFFIX = ':start';\nconst END_SUFFIX = ':end';\n\n/**\n * A start/end pair collapsed into one entry, or a point event that never had\n * an end to begin with.\n */\nexport interface TimelineSpan {\n layerId: string;\n /**\n * Stable across re-derivation of the same events, which a Lit `repeat()`\n * key and a selection comparison both need — the span objects themselves\n * are rebuilt whenever the event buffer changes.\n */\n key: string;\n /** The event title with its `:start` / `:end` suffix removed. */\n name: string;\n /** Pairing id as emitted; `undefined` for point events. */\n groupId?: number | string;\n start: number;\n /** Absent while the span is still open, or if its end was never recorded. */\n end?: number;\n /** `end - start`. Absent for open spans and for point events. */\n duration?: number;\n /** Reactive property keys that caused this update, where the phase has them. */\n changed?: string[];\n subtitle?: string;\n logType?: TimelineEvent['logType'];\n meta?: TimelineEvent['meta'];\n /** The events this span was built from, for the detail pane. */\n events: TimelineEvent[];\n}\n\n/** One component's complete update tick. */\nexport interface UpdateCycle {\n /** The `${elementId}:${tick}` groupId the phases share. */\n key: string;\n elementId: number;\n tagName: string;\n source?: {file: string; line: number};\n start: number;\n /** The `performUpdate` span's duration — see {@link toUpdateCycles}. */\n duration?: number;\n /** Union of the changed reactive property keys across the tick's phases. */\n changed: string[];\n phases: TimelineSpan[];\n /** The input event this update followed, if any. See {@link attributeInput}. */\n cause?: {layerId: string; type: string; detail?: string; time: number};\n}\n\n/** Per-component totals over a set of update cycles. */\nexport interface ComponentRollup {\n tagName: string;\n /** Every instance of this component that updated, in first-seen order. */\n elementIds: number[];\n updates: number;\n /** Summed `performUpdate` durations; excludes cycles with no measured end. */\n totalMs: number;\n maxMs: number;\n /** Changed-key frequency across the cycles, most frequent first. */\n reasons: Array<{key: string; count: number}>;\n source?: {file: string; line: number};\n}\n\n/** Reads `data.changed` defensively — `data` is `unknown` on the wire. */\nconst changedOf = (event: TimelineEvent): string[] | undefined => {\n const data = event.data;\n if (data === null || typeof data !== 'object') return undefined;\n const changed = (data as {changed?: unknown}).changed;\n if (!Array.isArray(changed)) return undefined;\n const keys = changed.filter((key): key is string => typeof key === 'string');\n return keys.length > 0 ? keys : undefined;\n};\n\nconst pointSpan = (event: TimelineEvent, index: number): TimelineSpan => ({\n layerId: event.layerId,\n key: `${event.layerId}:point:${index}`,\n name: event.title ?? event.layerId,\n start: event.time,\n changed: changedOf(event),\n subtitle: event.subtitle,\n logType: event.logType,\n meta: event.meta,\n events: [event],\n});\n\n/**\n * Collapses `:start` / `:end` event pairs into spans, passing anything else\n * through as a point span.\n *\n * Pairing is keyed on **layer + groupId + phase name**, never on `groupId`\n * alone: a whole update tick shares one groupId (`runtime/timeline/\n * lifecycle.ts` builds it as `${elementId}:${tick}`), so matching on the id\n * would marry `willUpdate:start` to `performUpdate:end`. Each phase occurs at\n * most once per tick, which makes the triple unique.\n *\n * Unmatched halves survive rather than disappear — the buffer is a bounded\n * ring, so its oldest end and its newest start routinely have no partner, and\n * an update that is still running has a genuinely open span.\n */\nexport const toSpans = (events: readonly TimelineEvent[]): TimelineSpan[] => {\n const spans: TimelineSpan[] = [];\n const open = new Map<string, TimelineSpan>();\n\n events.forEach((event, index) => {\n const title = event.title ?? event.layerId;\n const isStart = title.endsWith(START_SUFFIX);\n const isEnd = !isStart && title.endsWith(END_SUFFIX);\n\n if (event.groupId === undefined || (!isStart && !isEnd)) {\n spans.push(pointSpan(event, index));\n return;\n }\n\n const name = title.slice(\n 0,\n -(isStart ? START_SUFFIX.length : END_SUFFIX.length)\n );\n const key = `${event.layerId}:${event.groupId}:${name}`;\n\n if (isStart) {\n const span: TimelineSpan = {\n layerId: event.layerId,\n key,\n name,\n groupId: event.groupId,\n start: event.time,\n changed: changedOf(event),\n subtitle: event.subtitle,\n logType: event.logType,\n meta: event.meta,\n events: [event],\n };\n open.set(key, span);\n // Pushed on its start, so the list is already in start order and an\n // open span keeps its place instead of appearing when it finally ends.\n spans.push(span);\n return;\n }\n\n const span = open.get(key);\n if (span === undefined) {\n spans.push(pointSpan(event, index));\n return;\n }\n open.delete(key);\n span.events.push(event);\n // A negative delta means the buffer straddles a clock reset (the runtime\n // re-zeroes on the rising edge of recording). Report no duration rather\n // than a negative one; the span stays open, which is what it honestly is.\n if (event.time >= span.start) {\n span.end = event.time;\n span.duration = event.time - span.start;\n }\n span.changed ??= changedOf(event);\n });\n\n return spans.sort((a, b) => a.start - b.start);\n};\n\n/**\n * Groups lifecycle spans into update ticks.\n *\n * `duration` is taken from the `performUpdate` span alone, never from a sum of\n * the phases: `willUpdate` / `update` / `updated` all run *inside*\n * `performUpdate`, so summing counts the same milliseconds several times over.\n *\n * `changed` is the union across the tick's phases because only the phases that\n * receive a `PropertyValues` argument carry it — `performUpdate` takes none,\n * so the bracketing span is always silent about the reason.\n */\nexport const toUpdateCycles = (\n spans: readonly TimelineSpan[]\n): UpdateCycle[] => {\n const byGroup = new Map<string, UpdateCycle>();\n\n for (const span of spans) {\n const elementId = span.meta?.elementId;\n if (\n span.layerId !== LIFECYCLE_LAYER_ID ||\n span.groupId === undefined ||\n elementId === undefined\n ) {\n // Point lifecycle events (connect/disconnect) have no groupId and are\n // not update ticks; other layers are not this function's business.\n continue;\n }\n\n const key = String(span.groupId);\n let cycle = byGroup.get(key);\n if (cycle === undefined) {\n cycle = {\n key,\n elementId,\n tagName: span.meta?.tagName ?? 'unknown',\n source: span.meta?.source,\n start: span.start,\n changed: [],\n phases: [],\n };\n byGroup.set(key, cycle);\n }\n\n cycle.phases.push(span);\n if (span.start < cycle.start) cycle.start = span.start;\n if (span.name === ROOT_PHASE) cycle.duration = span.duration;\n for (const changedKey of span.changed ?? []) {\n if (!cycle.changed.includes(changedKey)) cycle.changed.push(changedKey);\n }\n }\n\n return [...byGroup.values()].sort((a, b) => a.start - b.start);\n};\n\n/**\n * Totals update cycles per component tag.\n *\n * Grouped by tag rather than by instance because the question this answers is\n * \"which *component* re-renders too much\" — a list of 200 rows each updating\n * twice is one component's problem, not 200. The instance ids are kept so the\n * caller can still drill in.\n */\nexport const rollup = (cycles: readonly UpdateCycle[]): ComponentRollup[] => {\n const byTag = new Map<\n string,\n {entry: ComponentRollup; reasons: Map<string, number>}\n >();\n\n for (const cycle of cycles) {\n let record = byTag.get(cycle.tagName);\n if (record === undefined) {\n record = {\n entry: {\n tagName: cycle.tagName,\n elementIds: [],\n updates: 0,\n totalMs: 0,\n maxMs: 0,\n reasons: [],\n source: cycle.source,\n },\n reasons: new Map(),\n };\n byTag.set(cycle.tagName, record);\n }\n\n const {entry, reasons} = record;\n entry.updates++;\n if (!entry.elementIds.includes(cycle.elementId)) {\n entry.elementIds.push(cycle.elementId);\n }\n entry.source ??= cycle.source;\n // An open or clock-straddling cycle contributes a count but no time —\n // better than inventing one, and the count is what flags a hot component.\n if (cycle.duration !== undefined) {\n entry.totalMs += cycle.duration;\n if (cycle.duration > entry.maxMs) entry.maxMs = cycle.duration;\n }\n for (const key of cycle.changed) {\n reasons.set(key, (reasons.get(key) ?? 0) + 1);\n }\n }\n\n const entries: ComponentRollup[] = [];\n for (const {entry, reasons} of byTag.values()) {\n entry.reasons = [...reasons]\n .map(([key, count]) => ({key, count}))\n .sort((a, b) => b.count - a.count || a.key.localeCompare(b.key));\n entries.push(entry);\n }\n\n // Slowest first, then most frequent: a component with no measured durations\n // still sorts above a quiet one.\n return entries.sort((a, b) => b.totalMs - a.totalMs || b.updates - a.updates);\n};\n\n/**\n * Attributes each update cycle to the input event that preceded it, within\n * `windowMs`.\n *\n * This is what the mouse and keyboard layers are for. On their own they\n * duplicate what the browser's own event log already shows; joined to the\n * updates they precede they answer the question the raw layers only imply —\n * an update with a cause is an interaction, and an update without one is a\n * timer, a signal, or a stray `requestUpdate()`.\n *\n * Returns a new array; cycles with no cause are returned as-is.\n */\nexport const attributeInput = (\n cycles: readonly UpdateCycle[],\n events: readonly TimelineEvent[],\n windowMs = 200\n): UpdateCycle[] => {\n const inputs = events\n .filter((event) => INPUT_LAYER_IDS.includes(event.layerId))\n .sort((a, b) => a.time - b.time);\n if (inputs.length === 0) return [...cycles];\n\n // Both sides are sorted by time, so one forward pass suffices.\n let cursor = 0;\n return cycles.map((cycle) => {\n while (\n cursor + 1 < inputs.length &&\n inputs[cursor + 1]!.time <= cycle.start\n ) {\n cursor++;\n }\n const candidate = inputs[cursor]!;\n const delta = cycle.start - candidate.time;\n if (delta < 0 || delta > windowMs) return cycle;\n return {\n ...cycle,\n cause: {\n layerId: candidate.layerId,\n type: candidate.title ?? candidate.layerId,\n detail: candidate.subtitle,\n time: candidate.time,\n },\n };\n });\n};\n"]}
1
+ {"version":3,"file":"derive.js","sourceRoot":"","sources":["../../src/lib/timeline/derive.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Derivation over recorded timeline events.\n *\n * The capture layers emit one event per phase boundary, which is the right\n * wire format and the wrong thing to read: a single update tick of one\n * component is five to ten rows whose durations the reader has to subtract by\n * hand. Everything needed to do better is already on the events — `groupId`\n * pairs a start with its end, `data.changed` names the reactive properties\n * that caused the update — so this module turns a flat event list into the\n * three shapes the panel and agents actually ask for:\n *\n * - {@link TimelineSpan} — a start/end pair collapsed into one entry with a\n * duration (\"`update` took 1.8ms\").\n * - {@link UpdateCycle} — one component's whole update tick, with the changed\n * property keys that triggered it (\"`<hmr-counter>` updated because\n * `count` changed\").\n * - {@link ComponentRollup} — per-component totals over a recording (\"this\n * component updated 340 times for 120ms\").\n *\n * Pure and dependency-free by design: it imports only the shared event types,\n * so the panel derives client-side over its 5000-event buffer and\n * `devframe/definition.ts` — which must stay framework-neutral — can derive\n * server-side over the ring buffer for the agent-facing summary.\n */\n\nimport type {TimelineEvent} from '../../types/timeline.js';\n\n/** Layer whose events describe Lit update ticks. */\nconst LIFECYCLE_LAYER_ID = 'lit-lifecycle';\n\n/** Layers whose events are developer input, for {@link attributeInput}. */\nconst INPUT_LAYER_IDS: readonly string[] = ['mouse', 'keyboard'];\n\n/** The phase that brackets an entire update tick. */\nconst ROOT_PHASE = 'performUpdate';\n\nconst START_SUFFIX = ':start';\nconst END_SUFFIX = ':end';\n\n/**\n * A start/end pair collapsed into one entry, or a point event that never had\n * an end to begin with.\n */\nexport interface TimelineSpan {\n layerId: string;\n /**\n * Stable across re-derivation of the same events, which a Lit `repeat()`\n * key and a selection comparison both need — the span objects themselves\n * are rebuilt whenever the event buffer changes.\n */\n key: string;\n /** The event title with its `:start` / `:end` suffix removed. */\n name: string;\n /** Pairing id as emitted; `undefined` for point events. */\n groupId?: number | string;\n start: number;\n /** Absent while the span is still open, or if its end was never recorded. */\n end?: number;\n /** `end - start`. Absent for open spans and for point events. */\n duration?: number;\n /** Reactive property keys that caused this update, where the phase has them. */\n changed?: string[];\n subtitle?: string;\n logType?: TimelineEvent['logType'];\n meta?: TimelineEvent['meta'];\n /** The events this span was built from, for the detail pane. */\n events: TimelineEvent[];\n}\n\n/** One component's complete update tick. */\nexport interface UpdateCycle {\n /** The `${elementId}:${tick}` groupId the phases share. */\n key: string;\n elementId: number;\n tagName: string;\n source?: {file: string; line: number};\n start: number;\n /** The `performUpdate` span's duration — see {@link toUpdateCycles}. */\n duration?: number;\n /** Union of the changed reactive property keys across the tick's phases. */\n changed: string[];\n phases: TimelineSpan[];\n /** The input event this update followed, if any. See {@link attributeInput}. */\n cause?: {layerId: string; type: string; detail?: string; time: number};\n}\n\n/** Per-component totals over a set of update cycles. */\nexport interface ComponentRollup {\n tagName: string;\n /** Every instance of this component that updated, in first-seen order. */\n elementIds: number[];\n updates: number;\n /** Summed `performUpdate` durations; excludes cycles with no measured end. */\n totalMs: number;\n maxMs: number;\n /** Changed-key frequency across the cycles, most frequent first. */\n reasons: Array<{key: string; count: number}>;\n source?: {file: string; line: number};\n}\n\n/** Reads `data.changed` defensively — `data` is `unknown` on the wire. */\nconst changedOf = (event: TimelineEvent): string[] | undefined => {\n const data = event.data;\n if (data === null || typeof data !== 'object') return undefined;\n const changed = (data as {changed?: unknown}).changed;\n if (!Array.isArray(changed)) return undefined;\n const keys = changed.filter((key): key is string => typeof key === 'string');\n return keys.length > 0 ? keys : undefined;\n};\n\nconst pointSpan = (event: TimelineEvent, index: number): TimelineSpan => ({\n layerId: event.layerId,\n key: `${event.layerId}:point:${index}`,\n name: event.title ?? event.layerId,\n start: event.time,\n changed: changedOf(event),\n subtitle: event.subtitle,\n logType: event.logType,\n meta: event.meta,\n events: [event],\n});\n\n/**\n * Collapses `:start` / `:end` event pairs into spans, passing anything else\n * through as a point span.\n *\n * Pairing is keyed on **layer + groupId + phase name**, never on `groupId`\n * alone: a whole update tick shares one groupId (`runtime/timeline/\n * lifecycle.ts` builds it as `${elementId}:${tick}`), so matching on the id\n * would marry `willUpdate:start` to `performUpdate:end`. Each phase occurs at\n * most once per tick, which makes the triple unique.\n *\n * Unmatched halves survive rather than disappear — the buffer is a bounded\n * ring, so its oldest end and its newest start routinely have no partner, and\n * an update that is still running has a genuinely open span.\n */\nexport const toSpans = (events: readonly TimelineEvent[]): TimelineSpan[] => {\n const spans: TimelineSpan[] = [];\n const open = new Map<string, TimelineSpan>();\n\n events.forEach((event, index) => {\n const title = event.title ?? event.layerId;\n const isStart = title.endsWith(START_SUFFIX);\n const isEnd = !isStart && title.endsWith(END_SUFFIX);\n\n if (event.groupId === undefined || (!isStart && !isEnd)) {\n spans.push(pointSpan(event, index));\n return;\n }\n\n const name = title.slice(\n 0,\n -(isStart ? START_SUFFIX.length : END_SUFFIX.length)\n );\n const key = `${event.layerId}:${event.groupId}:${name}`;\n\n if (isStart) {\n const span: TimelineSpan = {\n layerId: event.layerId,\n key,\n name,\n groupId: event.groupId,\n start: event.time,\n changed: changedOf(event),\n subtitle: event.subtitle,\n logType: event.logType,\n meta: event.meta,\n events: [event],\n };\n open.set(key, span);\n // Pushed on its start, so the list is already in start order and an\n // open span keeps its place instead of appearing when it finally ends.\n spans.push(span);\n return;\n }\n\n const span = open.get(key);\n if (span === undefined) {\n spans.push(pointSpan(event, index));\n return;\n }\n open.delete(key);\n span.events.push(event);\n // A negative delta means the buffer straddles a clock reset (the runtime\n // re-zeroes on the rising edge of recording). Report no duration rather\n // than a negative one; the span stays open, which is what it honestly is.\n if (event.time >= span.start) {\n span.end = event.time;\n span.duration = event.time - span.start;\n }\n span.changed ??= changedOf(event);\n });\n\n return spans.sort((a, b) => a.start - b.start);\n};\n\n/**\n * Groups lifecycle spans into update ticks.\n *\n * `duration` is taken from the `performUpdate` span alone, never from a sum of\n * the phases: `willUpdate` / `update` / `updated` all run *inside*\n * `performUpdate`, so summing counts the same milliseconds several times over.\n *\n * `changed` is the union across the tick's phases because only the phases that\n * receive a `PropertyValues` argument carry it — `performUpdate` takes none,\n * so the bracketing span is always silent about the reason.\n */\nexport const toUpdateCycles = (\n spans: readonly TimelineSpan[]\n): UpdateCycle[] => {\n const byGroup = new Map<string, UpdateCycle>();\n\n for (const span of spans) {\n const elementId = span.meta?.elementId;\n if (\n span.layerId !== LIFECYCLE_LAYER_ID ||\n span.groupId === undefined ||\n elementId === undefined\n ) {\n // Point lifecycle events (connect/disconnect) have no groupId and are\n // not update ticks; other layers are not this function's business.\n continue;\n }\n\n const key = String(span.groupId);\n let cycle = byGroup.get(key);\n if (cycle === undefined) {\n cycle = {\n key,\n elementId,\n tagName: span.meta?.tagName ?? 'unknown',\n source: span.meta?.source,\n start: span.start,\n changed: [],\n phases: [],\n };\n byGroup.set(key, cycle);\n }\n\n cycle.phases.push(span);\n if (span.start < cycle.start) cycle.start = span.start;\n if (span.name === ROOT_PHASE) cycle.duration = span.duration;\n for (const changedKey of span.changed ?? []) {\n if (!cycle.changed.includes(changedKey)) cycle.changed.push(changedKey);\n }\n }\n\n return [...byGroup.values()].sort((a, b) => a.start - b.start);\n};\n\n/**\n * Totals update cycles per component tag.\n *\n * Grouped by tag rather than by instance because the question this answers is\n * \"which *component* re-renders too much\" — a list of 200 rows each updating\n * twice is one component's problem, not 200. The instance ids are kept so the\n * caller can still drill in.\n */\nexport const rollup = (cycles: readonly UpdateCycle[]): ComponentRollup[] => {\n const byTag = new Map<\n string,\n {entry: ComponentRollup; reasons: Map<string, number>}\n >();\n\n for (const cycle of cycles) {\n let record = byTag.get(cycle.tagName);\n if (record === undefined) {\n record = {\n entry: {\n tagName: cycle.tagName,\n elementIds: [],\n updates: 0,\n totalMs: 0,\n maxMs: 0,\n reasons: [],\n source: cycle.source,\n },\n reasons: new Map(),\n };\n byTag.set(cycle.tagName, record);\n }\n\n const {entry, reasons} = record;\n entry.updates++;\n if (!entry.elementIds.includes(cycle.elementId)) {\n entry.elementIds.push(cycle.elementId);\n }\n entry.source ??= cycle.source;\n // An open or clock-straddling cycle contributes a count but no time —\n // better than inventing one, and the count is what flags a hot component.\n if (cycle.duration !== undefined) {\n entry.totalMs += cycle.duration;\n if (cycle.duration > entry.maxMs) entry.maxMs = cycle.duration;\n }\n for (const key of cycle.changed) {\n reasons.set(key, (reasons.get(key) ?? 0) + 1);\n }\n }\n\n const entries: ComponentRollup[] = [];\n for (const {entry, reasons} of byTag.values()) {\n entry.reasons = [...reasons]\n .map(([key, count]) => ({key, count}))\n .sort((a, b) => b.count - a.count || a.key.localeCompare(b.key));\n entries.push(entry);\n }\n\n // Slowest first, then most frequent: a component with no measured durations\n // still sorts above a quiet one.\n return entries.sort((a, b) => b.totalMs - a.totalMs || b.updates - a.updates);\n};\n\n/**\n * Attributes each update cycle to the input event that preceded it, within\n * `windowMs`.\n *\n * This is what the mouse and keyboard layers are for. On their own they\n * duplicate what the browser's own event log already shows; joined to the\n * updates they precede they answer the question the raw layers only imply —\n * an update with a cause is an interaction, and an update without one is a\n * timer, a signal, or a stray `requestUpdate()`.\n *\n * Returns a new array; cycles with no cause are returned as-is.\n */\nexport const attributeInput = (\n cycles: readonly UpdateCycle[],\n events: readonly TimelineEvent[],\n windowMs = 200\n): UpdateCycle[] => {\n const inputs = events\n .filter((event) => INPUT_LAYER_IDS.includes(event.layerId))\n .sort((a, b) => a.time - b.time);\n if (inputs.length === 0) return [...cycles];\n\n // Both sides are sorted by time, so one forward pass suffices.\n let cursor = 0;\n return cycles.map((cycle) => {\n while (\n cursor + 1 < inputs.length &&\n inputs[cursor + 1]!.time <= cycle.start\n ) {\n cursor++;\n }\n const candidate = inputs[cursor]!;\n const delta = cycle.start - candidate.time;\n if (delta < 0 || delta > windowMs) return cycle;\n return {\n ...cycle,\n cause: {\n layerId: candidate.layerId,\n type: candidate.title ?? candidate.layerId,\n detail: candidate.subtitle,\n time: candidate.time,\n },\n };\n });\n};\n"]}
@@ -1,8 +1,3 @@
1
- /**
2
- * @license
3
- * Copyright 2026 Google LLC
4
- * SPDX-License-Identifier: BSD-3-Clause
5
- */
6
1
  /**
7
2
  * The Timeline's element and regex filters, as pure functions.
8
3
  *
@@ -1 +1 @@
1
- {"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../src/lib/timeline/filter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAE9C;;;;GAIG;AACH,eAAO,MAAM,YAAY,WACf,MAAM,KACb;IAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAOtC,CAAC;AAEF;yEACyE;AACzE,eAAO,MAAM,YAAY,SAAU,YAAY,KAAG,MAGnC,CAAC;AAEhB;;;GAGG;AACH,eAAO,MAAM,WAAW,UACf,SAAS,YAAY,EAAE,aACnB,MAAM,GAAG,IAAI,MACpB,MAAM,GAAG,IAAI,KAChB,YAAY,EAKZ,CAAC;AAEJ,wEAAwE;AACxE,eAAO,MAAM,YAAY,WACf,SAAS,aAAa,EAAE,KAC/B,KAAK,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAC,CASjC,CAAC"}
1
+ {"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../src/lib/timeline/filter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAE9C;;;;GAIG;AACH,eAAO,MAAM,YAAY,WACf,MAAM,KACb;IAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAOtC,CAAC;AAEF;yEACyE;AACzE,eAAO,MAAM,YAAY,SAAU,YAAY,KAAG,MAGnC,CAAC;AAEhB;;;GAGG;AACH,eAAO,MAAM,WAAW,UACf,SAAS,YAAY,EAAE,aACnB,MAAM,GAAG,IAAI,MACpB,MAAM,GAAG,IAAI,KAChB,YAAY,EAKZ,CAAC;AAEJ,wEAAwE;AACxE,eAAO,MAAM,YAAY,WACf,SAAS,aAAa,EAAE,KAC/B,KAAK,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAC,CASjC,CAAC"}