@oddsquad/vite-plugin-lit 0.2.3 → 0.4.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 (240) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/LICENSE +28 -0
  3. package/README.md +157 -0
  4. package/bin.mjs +154 -0
  5. package/client.d.ts +61 -0
  6. package/dist/client/assets/browser-agent-rpc-BXhoSh1z-CdtPhBL-.js +69 -0
  7. package/dist/client/assets/browser-agent-rpc-BXhoSh1z-CdtPhBL-.js.map +1 -0
  8. package/dist/client/assets/flow-DK8vmxvN.js +745 -0
  9. package/dist/client/assets/flow-DK8vmxvN.js.map +1 -0
  10. package/dist/client/assets/index-DVe6M4HV.js +10614 -0
  11. package/dist/client/assets/index-DVe6M4HV.js.map +1 -0
  12. package/{panel → dist/client}/index.html +1 -0
  13. package/index.d.ts.map +1 -1
  14. package/index.js +2 -2
  15. package/index.js.map +1 -1
  16. package/lib/color-scheme.d.ts.map +1 -1
  17. package/lib/color-scheme.js +17 -21
  18. package/lib/color-scheme.js.map +1 -1
  19. package/lib/devframe/definition.d.ts +45 -0
  20. package/lib/devframe/definition.d.ts.map +1 -0
  21. package/lib/devframe/definition.js +547 -0
  22. package/lib/devframe/definition.js.map +1 -0
  23. package/lib/devframe/icon.d.ts +8 -0
  24. package/lib/devframe/icon.d.ts.map +1 -0
  25. package/lib/devframe/icon.js +21 -0
  26. package/lib/devframe/icon.js.map +1 -0
  27. package/lib/devframe/paths.d.ts +12 -0
  28. package/lib/devframe/paths.d.ts.map +1 -0
  29. package/lib/devframe/paths.js +38 -0
  30. package/lib/devframe/paths.js.map +1 -0
  31. package/lib/devframe/protocol.d.ts +218 -0
  32. package/lib/devframe/protocol.d.ts.map +1 -0
  33. package/lib/devframe/protocol.js +77 -0
  34. package/lib/devframe/protocol.js.map +1 -0
  35. package/lib/devframe/source.d.ts +49 -0
  36. package/lib/devframe/source.d.ts.map +1 -0
  37. package/lib/devframe/source.js +23 -0
  38. package/lib/devframe/source.js.map +1 -0
  39. package/lib/devframe/vite.d.ts +116 -0
  40. package/lib/devframe/vite.d.ts.map +1 -0
  41. package/lib/devframe/vite.js +292 -0
  42. package/lib/devframe/vite.js.map +1 -0
  43. package/lib/http.d.ts +29 -0
  44. package/lib/http.d.ts.map +1 -0
  45. package/lib/http.js +35 -0
  46. package/lib/http.js.map +1 -0
  47. package/lib/icons.d.ts +2 -0
  48. package/lib/icons.d.ts.map +1 -1
  49. package/lib/icons.js +10 -4
  50. package/lib/icons.js.map +1 -1
  51. package/lib/options.d.ts +131 -0
  52. package/lib/options.d.ts.map +1 -0
  53. package/lib/options.js +128 -0
  54. package/lib/options.js.map +1 -0
  55. package/lib/plugin.d.ts +6 -137
  56. package/lib/plugin.d.ts.map +1 -1
  57. package/lib/plugin.js +280 -677
  58. package/lib/plugin.js.map +1 -1
  59. package/lib/plugins/css-literals.d.ts +15 -0
  60. package/lib/plugins/css-literals.d.ts.map +1 -0
  61. package/lib/plugins/css-literals.js +154 -0
  62. package/lib/plugins/css-literals.js.map +1 -0
  63. package/lib/plugins/css-queries.d.ts +20 -0
  64. package/lib/plugins/css-queries.d.ts.map +1 -0
  65. package/lib/plugins/css-queries.js +139 -0
  66. package/lib/plugins/css-queries.js.map +1 -0
  67. package/lib/plugins/open-in-editor.d.ts +16 -0
  68. package/lib/plugins/open-in-editor.d.ts.map +1 -0
  69. package/lib/plugins/open-in-editor.js +91 -0
  70. package/lib/plugins/open-in-editor.js.map +1 -0
  71. package/lib/plugins/shared.d.ts +13 -0
  72. package/lib/plugins/shared.d.ts.map +1 -0
  73. package/lib/plugins/shared.js +23 -0
  74. package/lib/plugins/shared.js.map +1 -0
  75. package/lib/plugins/timeline-virtual.d.ts +19 -0
  76. package/lib/plugins/timeline-virtual.d.ts.map +1 -0
  77. package/lib/plugins/timeline-virtual.js +53 -0
  78. package/lib/plugins/timeline-virtual.js.map +1 -0
  79. package/lib/runtime/css.d.ts +2 -2
  80. package/lib/runtime/css.d.ts.map +1 -1
  81. package/lib/runtime/css.js +41 -34
  82. package/lib/runtime/css.js.map +1 -1
  83. package/lib/runtime/edge-panel.d.ts.map +1 -1
  84. package/lib/runtime/edge-panel.js +82 -91
  85. package/lib/runtime/edge-panel.js.map +1 -1
  86. package/lib/runtime/fonts.d.ts.map +1 -1
  87. package/lib/runtime/fonts.js +1 -1
  88. package/lib/runtime/fonts.js.map +1 -1
  89. package/lib/runtime/indicator.d.ts.map +1 -1
  90. package/lib/runtime/indicator.js +71 -74
  91. package/lib/runtime/indicator.js.map +1 -1
  92. package/lib/runtime/inspector/collect.d.ts.map +1 -1
  93. package/lib/runtime/inspector/collect.js +83 -90
  94. package/lib/runtime/inspector/collect.js.map +1 -1
  95. package/lib/runtime/inspector/highlight.d.ts +16 -0
  96. package/lib/runtime/inspector/highlight.d.ts.map +1 -0
  97. package/lib/runtime/inspector/highlight.js +66 -0
  98. package/lib/runtime/inspector/highlight.js.map +1 -0
  99. package/lib/runtime/inspector/install.d.ts.map +1 -1
  100. package/lib/runtime/inspector/install.js +230 -205
  101. package/lib/runtime/inspector/install.js.map +1 -1
  102. package/lib/runtime/inspector/serialize.d.ts.map +1 -1
  103. package/lib/runtime/inspector/serialize.js +86 -107
  104. package/lib/runtime/inspector/serialize.js.map +1 -1
  105. package/lib/runtime/intern.d.ts.map +1 -1
  106. package/lib/runtime/intern.js +31 -29
  107. package/lib/runtime/intern.js.map +1 -1
  108. package/lib/runtime/overrides.d.ts.map +1 -1
  109. package/lib/runtime/overrides.js +14 -13
  110. package/lib/runtime/overrides.js.map +1 -1
  111. package/lib/runtime/patch.d.ts +8 -0
  112. package/lib/runtime/patch.d.ts.map +1 -1
  113. package/lib/runtime/patch.js +321 -282
  114. package/lib/runtime/patch.js.map +1 -1
  115. package/lib/runtime/source-meta.d.ts.map +1 -1
  116. package/lib/runtime/source-meta.js +1 -1
  117. package/lib/runtime/source-meta.js.map +1 -1
  118. package/lib/runtime/source-overlay/editors.d.ts.map +1 -1
  119. package/lib/runtime/source-overlay/editors.js +27 -27
  120. package/lib/runtime/source-overlay/editors.js.map +1 -1
  121. package/lib/runtime/source-overlay/mask-path.d.ts.map +1 -1
  122. package/lib/runtime/source-overlay/mask-path.js +15 -15
  123. package/lib/runtime/source-overlay/mask-path.js.map +1 -1
  124. package/lib/runtime/source-overlay/overlay-element.d.ts.map +1 -1
  125. package/lib/runtime/source-overlay/overlay-element.js +359 -355
  126. package/lib/runtime/source-overlay/overlay-element.js.map +1 -1
  127. package/lib/runtime/source-overlay/source-host.d.ts.map +1 -1
  128. package/lib/runtime/source-overlay/source-host.js +64 -71
  129. package/lib/runtime/source-overlay/source-host.js.map +1 -1
  130. package/lib/runtime/source-overlay/template.d.ts.map +1 -1
  131. package/lib/runtime/source-overlay/template.js +3 -3
  132. package/lib/runtime/source-overlay/template.js.map +1 -1
  133. package/lib/runtime/source-overlay.d.ts.map +1 -1
  134. package/lib/runtime/source-overlay.js +5 -2
  135. package/lib/runtime/source-overlay.js.map +1 -1
  136. package/lib/runtime/timeline/clock.d.ts.map +1 -1
  137. package/lib/runtime/timeline/clock.js +2 -2
  138. package/lib/runtime/timeline/clock.js.map +1 -1
  139. package/lib/runtime/timeline/flash.d.ts +39 -0
  140. package/lib/runtime/timeline/flash.d.ts.map +1 -0
  141. package/lib/runtime/timeline/flash.js +169 -0
  142. package/lib/runtime/timeline/flash.js.map +1 -0
  143. package/lib/runtime/timeline/identity.d.ts.map +1 -1
  144. package/lib/runtime/timeline/identity.js +27 -27
  145. package/lib/runtime/timeline/identity.js.map +1 -1
  146. package/lib/runtime/timeline/input.d.ts.map +1 -1
  147. package/lib/runtime/timeline/input.js +54 -67
  148. package/lib/runtime/timeline/input.js.map +1 -1
  149. package/lib/runtime/timeline/install.d.ts.map +1 -1
  150. package/lib/runtime/timeline/install.js +47 -33
  151. package/lib/runtime/timeline/install.js.map +1 -1
  152. package/lib/runtime/timeline/lifecycle.d.ts +8 -0
  153. package/lib/runtime/timeline/lifecycle.d.ts.map +1 -1
  154. package/lib/runtime/timeline/lifecycle.js +149 -133
  155. package/lib/runtime/timeline/lifecycle.js.map +1 -1
  156. package/lib/runtime/timeline/public-api.d.ts +2 -2
  157. package/lib/runtime/timeline/public-api.d.ts.map +1 -1
  158. package/lib/runtime/timeline/public-api.js +11 -11
  159. package/lib/runtime/timeline/public-api.js.map +1 -1
  160. package/lib/runtime/timeline/render.d.ts +15 -6
  161. package/lib/runtime/timeline/render.d.ts.map +1 -1
  162. package/lib/runtime/timeline/render.js +212 -78
  163. package/lib/runtime/timeline/render.js.map +1 -1
  164. package/lib/runtime/timeline/transport.d.ts.map +1 -1
  165. package/lib/runtime/timeline/transport.js +39 -43
  166. package/lib/runtime/timeline/transport.js.map +1 -1
  167. package/lib/segmented-tabs.d.ts +3 -1
  168. package/lib/segmented-tabs.d.ts.map +1 -1
  169. package/lib/segmented-tabs.js +136 -107
  170. package/lib/segmented-tabs.js.map +1 -1
  171. package/lib/snapshot.d.ts +28 -0
  172. package/lib/snapshot.d.ts.map +1 -0
  173. package/lib/snapshot.js +57 -0
  174. package/lib/snapshot.js.map +1 -0
  175. package/lib/source-meta.d.ts.map +1 -1
  176. package/lib/source-meta.js +176 -162
  177. package/lib/source-meta.js.map +1 -1
  178. package/lib/timeline/derive.d.ts +152 -0
  179. package/lib/timeline/derive.d.ts.map +1 -0
  180. package/lib/timeline/derive.js +242 -0
  181. package/lib/timeline/derive.js.map +1 -0
  182. package/lib/tokens.d.ts.map +1 -1
  183. package/lib/tokens.js +17 -18
  184. package/lib/tokens.js.map +1 -1
  185. package/lib/transform.d.ts.map +1 -1
  186. package/lib/transform.js +62 -57
  187. package/lib/transform.js.map +1 -1
  188. package/lib/types.d.ts.map +1 -1
  189. package/lib/types.js +1 -1
  190. package/lib/types.js.map +1 -1
  191. package/lib/wrap-table.d.ts.map +1 -1
  192. package/lib/wrap-table.js +19 -17
  193. package/lib/wrap-table.js.map +1 -1
  194. package/package.json +80 -13
  195. package/types/hmr-incompatibility.d.ts +59 -0
  196. package/types/hmr-incompatibility.d.ts.map +1 -0
  197. package/types/hmr-incompatibility.js +30 -0
  198. package/types/hmr-incompatibility.js.map +1 -0
  199. package/types/in-page.d.ts +49 -0
  200. package/types/in-page.d.ts.map +1 -0
  201. package/types/in-page.js +33 -0
  202. package/types/in-page.js.map +1 -0
  203. package/types/inspector.d.ts.map +1 -1
  204. package/types/inspector.js.map +1 -1
  205. package/types/snapshot.d.ts +44 -0
  206. package/types/snapshot.d.ts.map +1 -0
  207. package/types/snapshot.js +7 -0
  208. package/types/snapshot.js.map +1 -0
  209. package/types/timeline.d.ts +23 -1
  210. package/types/timeline.d.ts.map +1 -1
  211. package/types/timeline.js +2 -0
  212. package/types/timeline.js.map +1 -1
  213. package/lib/timeline-plugin.d.ts +0 -72
  214. package/lib/timeline-plugin.d.ts.map +0 -1
  215. package/lib/timeline-plugin.js +0 -376
  216. package/lib/timeline-plugin.js.map +0 -1
  217. package/panel/components-view.d.ts +0 -60
  218. package/panel/components-view.d.ts.map +0 -1
  219. package/panel/components-view.js +0 -587
  220. package/panel/components-view.js.map +0 -1
  221. package/panel/devtools-settings.d.ts +0 -41
  222. package/panel/devtools-settings.d.ts.map +0 -1
  223. package/panel/devtools-settings.js +0 -463
  224. package/panel/devtools-settings.js.map +0 -1
  225. package/panel/lit-devtools-panel.d.ts +0 -37
  226. package/panel/lit-devtools-panel.d.ts.map +0 -1
  227. package/panel/lit-devtools-panel.js +0 -185
  228. package/panel/lit-devtools-panel.js.map +0 -1
  229. package/panel/timeline-event-list.d.ts +0 -43
  230. package/panel/timeline-event-list.d.ts.map +0 -1
  231. package/panel/timeline-event-list.js +0 -416
  232. package/panel/timeline-event-list.js.map +0 -1
  233. package/panel/timeline-layers.d.ts +0 -25
  234. package/panel/timeline-layers.d.ts.map +0 -1
  235. package/panel/timeline-layers.js +0 -96
  236. package/panel/timeline-layers.js.map +0 -1
  237. package/panel/timeline-view.d.ts +0 -38
  238. package/panel/timeline-view.d.ts.map +0 -1
  239. package/panel/timeline-view.js +0 -234
  240. package/panel/timeline-view.js.map +0 -1
@@ -0,0 +1,66 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ */
6
+ /**
7
+ * The hover outline the panel draws over an element in the page.
8
+ *
9
+ * Its own module because two transports drive it: the in-page channel (the
10
+ * fast path, no server in the loop) and the Vite HMR command channel (the
11
+ * fallback, for a panel with no page script to handshake with). Both end up
12
+ * here, so the box is created once and behaves identically either way.
13
+ *
14
+ * Deliberately independent of the source overlay, which draws its own,
15
+ * richer highlight — this one has to work whether or not `sourceOverlay` is
16
+ * enabled.
17
+ */
18
+ import {elementById} from '../timeline/identity.js';
19
+ let box = null;
20
+ const ensureBox = () => {
21
+ if (box === null) {
22
+ box = document.createElement('div');
23
+ box.setAttribute('data-lit-devtools-highlight', '');
24
+ Object.assign(box.style, {
25
+ position: 'fixed',
26
+ zIndex: '2147483646',
27
+ pointerEvents: 'none',
28
+ background: 'rgba(77, 99, 255, 0.25)',
29
+ outline: '1px solid #4d63ff',
30
+ borderRadius: '2px',
31
+ transition: 'all 80ms ease-out',
32
+ });
33
+ document.body.append(box);
34
+ }
35
+ return box;
36
+ };
37
+ /** Draw the outline over `el`. */
38
+ export const showHighlight = (el) => {
39
+ const r = el.getBoundingClientRect();
40
+ Object.assign(ensureBox().style, {
41
+ display: 'block',
42
+ left: `${r.left}px`,
43
+ top: `${r.top}px`,
44
+ width: `${r.width}px`,
45
+ height: `${r.height}px`,
46
+ });
47
+ };
48
+ /** Hide the outline. Cheap and safe before the box has ever been built. */
49
+ export const clearHighlight = () => {
50
+ if (box !== null) box.style.display = 'none';
51
+ };
52
+ /**
53
+ * Outline the element with this id, or clear it for `null` — and also when
54
+ * the id no longer resolves, since a stale outline over the wrong element is
55
+ * worse than none.
56
+ */
57
+ export const highlightById = (id) => {
58
+ if (id === null) {
59
+ clearHighlight();
60
+ return;
61
+ }
62
+ const el = elementById(id);
63
+ if (el !== undefined) showHighlight(el);
64
+ else clearHighlight();
65
+ };
66
+ //# sourceMappingURL=highlight.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"highlight.js","sourceRoot":"","sources":["../../../src/lib/runtime/inspector/highlight.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;GAWG;AAEH,OAAO,EAAC,WAAW,EAAC,MAAM,yBAAyB,CAAC;AAEpD,IAAI,GAAG,GAAuB,IAAI,CAAC;AAEnC,MAAM,SAAS,GAAG,GAAgB,EAAE;IAClC,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACjB,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACpC,GAAG,CAAC,YAAY,CAAC,6BAA6B,EAAE,EAAE,CAAC,CAAC;QACpD,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE;YACvB,QAAQ,EAAE,OAAO;YACjB,MAAM,EAAE,YAAY;YACpB,aAAa,EAAE,MAAM;YACrB,UAAU,EAAE,yBAAyB;YACrC,OAAO,EAAE,mBAAmB;YAC5B,YAAY,EAAE,KAAK;YACnB,UAAU,EAAE,mBAAmB;SACO,CAAC,CAAC;QAC1C,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAEF,kCAAkC;AAClC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAW,EAAQ,EAAE;IACjD,MAAM,CAAC,GAAG,EAAE,CAAC,qBAAqB,EAAE,CAAC;IACrC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE;QAC/B,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,IAAI;QACnB,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI;QACjB,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,IAAI;QACrB,MAAM,EAAE,GAAG,CAAC,CAAC,MAAM,IAAI;KACxB,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,2EAA2E;AAC3E,MAAM,CAAC,MAAM,cAAc,GAAG,GAAS,EAAE;IACvC,IAAI,GAAG,KAAK,IAAI;QAAE,GAAG,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;AAC/C,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAiB,EAAQ,EAAE;IACvD,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;QAChB,cAAc,EAAE,CAAC;QACjB,OAAO;IACT,CAAC;IACD,MAAM,EAAE,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;IAC3B,IAAI,EAAE,KAAK,SAAS;QAAE,aAAa,CAAC,EAAE,CAAC,CAAC;;QACnC,cAAc,EAAE,CAAC;AACxB,CAAC,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * The hover outline the panel draws over an element in the page.\n *\n * Its own module because two transports drive it: the in-page channel (the\n * fast path, no server in the loop) and the Vite HMR command channel (the\n * fallback, for a panel with no page script to handshake with). Both end up\n * here, so the box is created once and behaves identically either way.\n *\n * Deliberately independent of the source overlay, which draws its own,\n * richer highlight — this one has to work whether or not `sourceOverlay` is\n * enabled.\n */\n\nimport {elementById} from '../timeline/identity.js';\n\nlet box: HTMLElement | null = null;\n\nconst ensureBox = (): HTMLElement => {\n if (box === null) {\n box = document.createElement('div');\n box.setAttribute('data-lit-devtools-highlight', '');\n Object.assign(box.style, {\n position: 'fixed',\n zIndex: '2147483646',\n pointerEvents: 'none',\n background: 'rgba(77, 99, 255, 0.25)',\n outline: '1px solid #4d63ff',\n borderRadius: '2px',\n transition: 'all 80ms ease-out',\n } satisfies Partial<CSSStyleDeclaration>);\n document.body.append(box);\n }\n return box;\n};\n\n/** Draw the outline over `el`. */\nexport const showHighlight = (el: Element): void => {\n const r = el.getBoundingClientRect();\n Object.assign(ensureBox().style, {\n display: 'block',\n left: `${r.left}px`,\n top: `${r.top}px`,\n width: `${r.width}px`,\n height: `${r.height}px`,\n });\n};\n\n/** Hide the outline. Cheap and safe before the box has ever been built. */\nexport const clearHighlight = (): void => {\n if (box !== null) box.style.display = 'none';\n};\n\n/**\n * Outline the element with this id, or clear it for `null` — and also when\n * the id no longer resolves, since a stale outline over the wrong element is\n * worse than none.\n */\nexport const highlightById = (id: number | null): void => {\n if (id === null) {\n clearHighlight();\n return;\n }\n const el = elementById(id);\n if (el !== undefined) showHighlight(el);\n else clearHighlight();\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../../../packages/labs/vite-plugin-lit/src/lib/runtime/inspector/install.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/lib/runtime/inspector/install.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -11,219 +11,244 @@
11
11
  * Vite HMR channel, keeps a watched element's details fresh as it updates, and
12
12
  * outlines elements the panel hovers in its tree.
13
13
  */
14
- import { elementById } from '../timeline/identity.js';
15
- import { buildTree, collectDetails } from './collect.js';
16
- import { INSPECT_CMD_CHANNEL, INSPECT_DATA_CHANNEL, } from '../../../types/inspector.js';
14
+ import {createPageScriptChannel} from 'devframe/in-page-channel';
15
+ import {elementById} from '../timeline/identity.js';
16
+ import {buildTree, collectDetails} from './collect.js';
17
+ import {clearHighlight, highlightById} from './highlight.js';
18
+ import {LIT_IN_PAGE_CHANNEL} from '../../../types/in-page.js';
19
+ import {
20
+ INSPECT_CMD_CHANNEL,
21
+ INSPECT_DATA_CHANNEL,
22
+ } from '../../../types/inspector.js';
17
23
  const hot = import.meta.hot;
24
+ // The direct panel channel, outside the `hot` gate on purpose: it is the one
25
+ // part of the inspector that does not need a dev server, which is what lets
26
+ // the hover outline keep working in a static snapshot of the panel. Answering
27
+ // handshakes costs nothing until a panel actually sends one.
28
+ if (typeof window !== 'undefined') {
29
+ const channel = createPageScriptChannel({
30
+ name: LIT_IN_PAGE_CHANNEL,
31
+ functions: {},
32
+ events: {
33
+ highlight: {handler: (id) => highlightById(id)},
34
+ },
35
+ });
36
+ // A panel that goes away mid-hover never gets to send its `highlight(null)`,
37
+ // and an outline left painted over the app is worse than a missing one.
38
+ channel.events.on('panel:disconnected', () => clearHighlight());
39
+ }
18
40
  if (hot !== undefined && typeof window !== 'undefined') {
19
- const send = (msg) => {
20
- try {
21
- hot.send(INSPECT_DATA_CHANNEL, msg);
22
- }
23
- catch {
24
- // HMR channel temporarily unavailable; the panel can re-request.
25
- }
41
+ const send = (msg) => {
42
+ try {
43
+ hot.send(INSPECT_DATA_CHANNEL, msg);
44
+ } catch {
45
+ // HMR channel temporarily unavailable; the panel can re-request.
46
+ }
47
+ };
48
+ // Hold the watched element via a WeakRef so an active watch doesn't keep a
49
+ // removed element alive: the override and `restore` only reach `el` through
50
+ // the ref, leaving the DOM as its sole strong root.
51
+ let watched = null;
52
+ const unwatch = () => {
53
+ watched?.restore();
54
+ watched = null;
55
+ };
56
+ const watch = (id) => {
57
+ unwatch();
58
+ const el = elementById(id);
59
+ if (el === undefined) {
60
+ send({type: 'gone', id});
61
+ return;
62
+ }
63
+ const hadOwn = Object.prototype.hasOwnProperty.call(el, 'updated');
64
+ // Only an *own* `updated` is stable across an HMR hot patch. A prototype
65
+ // implementation is replaced in place on every patch (`syncOwnMembers` in
66
+ // ../patch.ts), so caching it here would pin the watched instance to the
67
+ // pre-edit code for the life of the watch — resolve it through the
68
+ // prototype chain on each call instead. Our wrapper is an own property, so
69
+ // the lookup skips it and cannot recurse.
70
+ const ownPrev = hadOwn ? el.updated : undefined;
71
+ const ref = new WeakRef(el);
72
+ el.updated = function (changed) {
73
+ const current = ownPrev ?? Object.getPrototypeOf(this)?.updated;
74
+ current?.call(this, changed);
75
+ const cur = ref.deref();
76
+ if (cur !== undefined) {
77
+ send({type: 'details', details: collectDetails(cur)});
78
+ }
26
79
  };
27
- // Hold the watched element via a WeakRef so an active watch doesn't keep a
28
- // removed element alive: the override and `restore` only reach `el` through
29
- // the ref, leaving the DOM as its sole strong root.
30
- let watched = null;
31
- const unwatch = () => {
32
- watched?.restore();
33
- watched = null;
80
+ watched = {
81
+ ref,
82
+ restore: () => {
83
+ const cur = ref.deref();
84
+ if (cur === undefined) return;
85
+ if (hadOwn) cur.updated = ownPrev;
86
+ else delete cur.updated;
87
+ },
34
88
  };
35
- const watch = (id) => {
36
- unwatch();
37
- const el = elementById(id);
38
- if (el === undefined) {
39
- send({ type: 'gone', id });
40
- return;
89
+ // Push an immediate snapshot so the panel doesn't wait for the next update.
90
+ send({type: 'details', details: collectDetails(el)});
91
+ };
92
+ // -------------------------------------------------------------------------
93
+ // Opt-in live tree: watch the DOM (light + every shadow root) and push a
94
+ // fresh tree when the component hierarchy actually changes. Off by default.
95
+ // childList-only (no attributes), so cosmetic changes — including our own
96
+ // highlight box toggling — don't churn; identical rebuilds are also deduped.
97
+ // Batches that only move text or comment nodes (most Lit re-renders) are
98
+ // dropped before the debounce, and only added subtrees are walked for new
99
+ // shadow roots, so a busy page no longer costs a full-page walk per batch.
100
+ // -------------------------------------------------------------------------
101
+ let observer = null;
102
+ let observeTimer;
103
+ let lastTreeJson = '';
104
+ // Added elements whose subtrees still need their shadow roots observed.
105
+ let pendingRoots = [];
106
+ /** Observe every shadow root at or under `root` (and `root`'s subtree). */
107
+ const observeShadowRoots = (obs, root) => {
108
+ if (root instanceof Element && root.shadowRoot !== null) {
109
+ obs.observe(root.shadowRoot, {childList: true, subtree: true});
110
+ observeShadowRoots(obs, root.shadowRoot);
111
+ }
112
+ for (const el of root.querySelectorAll('*')) {
113
+ if (el.shadowRoot !== null) {
114
+ obs.observe(el.shadowRoot, {childList: true, subtree: true});
115
+ observeShadowRoots(obs, el.shadowRoot);
116
+ }
117
+ }
118
+ };
119
+ /** Re-attach the observer to the body and every shadow root in the page. */
120
+ const syncObserverTargets = (obs) => {
121
+ obs.disconnect();
122
+ obs.observe(document.body, {childList: true, subtree: true});
123
+ observeShadowRoots(obs, document);
124
+ };
125
+ const pushTreeIfChanged = () => {
126
+ const roots = buildTree();
127
+ const json = JSON.stringify(roots);
128
+ if (json === lastTreeJson) return;
129
+ lastTreeJson = json;
130
+ send({type: 'tree', roots});
131
+ };
132
+ /** Whether a subtree holds anything the tree (or observer) cares about. */
133
+ const mayHoldComponents = (node) => {
134
+ if (!(node instanceof Element)) return false;
135
+ const matters = (el) =>
136
+ el.localName.includes('-') || el.shadowRoot !== null;
137
+ if (matters(node)) return true;
138
+ for (const el of node.querySelectorAll('*')) if (matters(el)) return true;
139
+ return false;
140
+ };
141
+ const onMutation = (records) => {
142
+ // The tree only has custom elements in it, so a batch that adds or
143
+ // removes none (text, comments, plain markup) can't change it.
144
+ let relevant = false;
145
+ for (const record of records) {
146
+ for (const node of record.addedNodes) {
147
+ if (mayHoldComponents(node)) {
148
+ pendingRoots.push(node);
149
+ relevant = true;
41
150
  }
42
- const hadOwn = Object.prototype.hasOwnProperty.call(el, 'updated');
43
- const prev = el.updated;
44
- const ref = new WeakRef(el);
45
- el.updated = function (changed) {
46
- prev?.call(this, changed);
47
- const cur = ref.deref();
48
- if (cur !== undefined) {
49
- send({ type: 'details', details: collectDetails(cur) });
50
- }
51
- };
52
- watched = {
53
- ref,
54
- restore: () => {
55
- const cur = ref.deref();
56
- if (cur === undefined)
57
- return;
58
- if (hadOwn)
59
- cur.updated = prev;
60
- else
61
- delete cur.updated;
62
- },
63
- };
64
- // Push an immediate snapshot so the panel doesn't wait for the next update.
65
- send({ type: 'details', details: collectDetails(el) });
66
- };
67
- // -------------------------------------------------------------------------
68
- // Highlight box: a lightweight fixed-position outline drawn over an element
69
- // the panel hovers in its tree. Independent of the source overlay so it works
70
- // whether or not that feature is enabled.
71
- // -------------------------------------------------------------------------
72
- let highlightBox = null;
73
- const showHighlight = (el) => {
74
- if (highlightBox === null) {
75
- highlightBox = document.createElement('div');
76
- highlightBox.setAttribute('data-lit-devtools-highlight', '');
77
- Object.assign(highlightBox.style, {
78
- position: 'fixed',
79
- zIndex: '2147483646',
80
- pointerEvents: 'none',
81
- background: 'rgba(77, 99, 255, 0.25)',
82
- outline: '1px solid #4d63ff',
83
- borderRadius: '2px',
84
- transition: 'all 80ms ease-out',
85
- });
86
- document.body.append(highlightBox);
151
+ }
152
+ if (!relevant) {
153
+ for (const node of record.removedNodes) {
154
+ if (mayHoldComponents(node)) {
155
+ relevant = true;
156
+ break;
157
+ }
87
158
  }
88
- const r = el.getBoundingClientRect();
89
- Object.assign(highlightBox.style, {
90
- display: 'block',
91
- left: `${r.left}px`,
92
- top: `${r.top}px`,
93
- width: `${r.width}px`,
94
- height: `${r.height}px`,
95
- });
96
- };
97
- const clearHighlight = () => {
98
- if (highlightBox !== null)
99
- highlightBox.style.display = 'none';
100
- };
101
- // -------------------------------------------------------------------------
102
- // Opt-in live tree: watch the DOM (light + every shadow root) and push a
103
- // fresh tree when the component hierarchy actually changes. Off by default.
104
- // childList-only (no attributes), so cosmetic changes — including our own
105
- // highlight box toggling — don't churn; identical rebuilds are also deduped.
106
- // -------------------------------------------------------------------------
107
- let observer = null;
108
- let observeTimer;
109
- let lastTreeJson = '';
110
- /** Re-attach the observer to the body and every shadow root in the page. */
111
- const syncObserverTargets = (obs) => {
112
- obs.disconnect();
113
- obs.observe(document.body, { childList: true, subtree: true });
114
- const walk = (root) => {
115
- for (const el of root.querySelectorAll('*')) {
116
- if (el.shadowRoot !== null) {
117
- obs.observe(el.shadowRoot, { childList: true, subtree: true });
118
- walk(el.shadowRoot);
119
- }
120
- }
121
- };
122
- walk(document);
123
- };
124
- const pushTreeIfChanged = () => {
125
- const roots = buildTree();
126
- const json = JSON.stringify(roots);
127
- if (json === lastTreeJson)
128
- return;
129
- lastTreeJson = json;
130
- send({ type: 'tree', roots });
131
- };
132
- const onMutation = () => {
133
- if (observeTimer !== undefined)
134
- clearTimeout(observeTimer);
135
- observeTimer = setTimeout(() => {
136
- observeTimer = undefined;
137
- if (observer !== null)
138
- syncObserverTargets(observer);
139
- pushTreeIfChanged();
140
- }, 100);
141
- };
142
- const setObserving = (enabled) => {
143
- if (enabled) {
144
- if (observer === null)
145
- observer = new MutationObserver(onMutation);
146
- lastTreeJson = '';
147
- syncObserverTargets(observer);
148
- pushTreeIfChanged();
149
- }
150
- else if (observer !== null) {
151
- observer.disconnect();
152
- observer = null;
153
- if (observeTimer !== undefined) {
154
- clearTimeout(observeTimer);
155
- observeTimer = undefined;
156
- }
159
+ }
160
+ }
161
+ if (!relevant) return;
162
+ if (observeTimer !== undefined) clearTimeout(observeTimer);
163
+ observeTimer = setTimeout(() => {
164
+ observeTimer = undefined;
165
+ // Walk added subtrees now rather than on arrival: a custom element
166
+ // attaches its shadow root when it upgrades, which can be after insert.
167
+ // Removed roots need no bookkeeping; a detached shadow root just stops
168
+ // producing records.
169
+ const roots = pendingRoots;
170
+ pendingRoots = [];
171
+ if (observer !== null) {
172
+ for (const root of roots) {
173
+ if (root.isConnected) observeShadowRoots(observer, root);
157
174
  }
175
+ }
176
+ pushTreeIfChanged();
177
+ }, 100);
178
+ };
179
+ const setObserving = (enabled) => {
180
+ if (enabled) {
181
+ if (observer === null) observer = new MutationObserver(onMutation);
182
+ lastTreeJson = '';
183
+ syncObserverTargets(observer);
184
+ pushTreeIfChanged();
185
+ } else if (observer !== null) {
186
+ observer.disconnect();
187
+ observer = null;
188
+ pendingRoots = [];
189
+ if (observeTimer !== undefined) {
190
+ clearTimeout(observeTimer);
191
+ observeTimer = undefined;
192
+ }
193
+ }
194
+ };
195
+ // -------------------------------------------------------------------------
196
+ // SPA navigation: a route change swaps the component tree without any HMR
197
+ // or panel event, so the snapshot went stale until a manual refresh. Push a
198
+ // deduped tree after each navigation — twice, since routes typically
199
+ // lazy-load and render async. Redundant while the live observer watches.
200
+ // -------------------------------------------------------------------------
201
+ const onNavigation = () => {
202
+ if (observer !== null) return;
203
+ for (const delay of [150, 1000]) {
204
+ setTimeout(pushTreeIfChanged, delay);
205
+ }
206
+ };
207
+ window.addEventListener('popstate', onNavigation);
208
+ window.addEventListener('hashchange', onNavigation);
209
+ for (const method of ['pushState', 'replaceState']) {
210
+ const original = history[method].bind(history);
211
+ history[method] = (...args) => {
212
+ original(...args);
213
+ onNavigation();
158
214
  };
159
- // -------------------------------------------------------------------------
160
- // SPA navigation: a route change swaps the component tree without any HMR
161
- // or panel event, so the snapshot went stale until a manual refresh. Push a
162
- // deduped tree after each navigation — twice, since routes typically
163
- // lazy-load and render async. Redundant while the live observer watches.
164
- // -------------------------------------------------------------------------
165
- const onNavigation = () => {
166
- if (observer !== null)
167
- return;
168
- for (const delay of [150, 1000]) {
169
- setTimeout(pushTreeIfChanged, delay);
215
+ }
216
+ // -------------------------------------------------------------------------
217
+ // Command dispatch
218
+ // -------------------------------------------------------------------------
219
+ hot.on(INSPECT_CMD_CHANNEL, (data) => {
220
+ const cmd = data;
221
+ switch (cmd.type) {
222
+ case 'tree': {
223
+ const roots = buildTree();
224
+ lastTreeJson = JSON.stringify(roots);
225
+ send({type: 'tree', roots});
226
+ break;
227
+ }
228
+ case 'details': {
229
+ const el = elementById(cmd.id);
230
+ if (el !== undefined) {
231
+ send({type: 'details', details: collectDetails(el)});
232
+ } else {
233
+ send({type: 'gone', id: cmd.id});
170
234
  }
171
- };
172
- window.addEventListener('popstate', onNavigation);
173
- window.addEventListener('hashchange', onNavigation);
174
- for (const method of ['pushState', 'replaceState']) {
175
- const original = history[method].bind(history);
176
- history[method] = (...args) => {
177
- original(...args);
178
- onNavigation();
179
- };
235
+ break;
236
+ }
237
+ case 'watch':
238
+ if (cmd.id === null) unwatch();
239
+ else watch(cmd.id);
240
+ break;
241
+ case 'highlight':
242
+ // Fallback path. A panel that handshaked over the in-page channel
243
+ // emits there instead and never reaches this.
244
+ highlightById(cmd.id);
245
+ break;
246
+ case 'observe':
247
+ setObserving(cmd.enabled);
248
+ break;
180
249
  }
181
- // -------------------------------------------------------------------------
182
- // Command dispatch
183
- // -------------------------------------------------------------------------
184
- hot.on(INSPECT_CMD_CHANNEL, (data) => {
185
- const cmd = data;
186
- switch (cmd.type) {
187
- case 'tree': {
188
- const roots = buildTree();
189
- lastTreeJson = JSON.stringify(roots);
190
- send({ type: 'tree', roots });
191
- break;
192
- }
193
- case 'details': {
194
- const el = elementById(cmd.id);
195
- if (el !== undefined) {
196
- send({ type: 'details', details: collectDetails(el) });
197
- }
198
- else {
199
- send({ type: 'gone', id: cmd.id });
200
- }
201
- break;
202
- }
203
- case 'watch':
204
- if (cmd.id === null)
205
- unwatch();
206
- else
207
- watch(cmd.id);
208
- break;
209
- case 'highlight': {
210
- if (cmd.id === null) {
211
- clearHighlight();
212
- break;
213
- }
214
- const el = elementById(cmd.id);
215
- if (el !== undefined)
216
- showHighlight(el);
217
- else
218
- clearHighlight();
219
- break;
220
- }
221
- case 'observe':
222
- setObserving(cmd.enabled);
223
- break;
224
- }
225
- });
226
- // Announce readiness so a panel that loaded first re-requests the tree.
227
- send({ type: 'ready' });
250
+ });
251
+ // Announce readiness so a panel that loaded first re-requests the tree.
252
+ send({type: 'ready'});
228
253
  }
229
- //# sourceMappingURL=install.js.map
254
+ //# sourceMappingURL=install.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"install.js","sourceRoot":"","sources":["../../../../../packages/labs/vite-plugin-lit/src/lib/runtime/inspector/install.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;GAOG;AAEH,OAAO,EAAC,WAAW,EAAC,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAC,SAAS,EAAE,cAAc,EAAC,MAAM,cAAc,CAAC;AACvD,OAAO,EACL,mBAAmB,EACnB,oBAAoB,GAGrB,MAAM,6BAA6B,CAAC;AAOrC,MAAM,GAAG,GAAI,MAAM,CAAC,IAAwB,CAAC,GAAG,CAAC;AAEjD,IAAI,GAAG,KAAK,SAAS,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;IACvD,MAAM,IAAI,GAAG,CAAC,GAAqB,EAAQ,EAAE;QAC3C,IAAI,CAAC;YACH,GAAG,CAAC,IAAI,CAAC,oBAAoB,EAAE,GAAG,CAAC,CAAC;QACtC,CAAC;QAAC,MAAM,CAAC;YACP,iEAAiE;QACnE,CAAC;IACH,CAAC,CAAC;IAYF,2EAA2E;IAC3E,4EAA4E;IAC5E,oDAAoD;IACpD,IAAI,OAAO,GAA0D,IAAI,CAAC;IAE1E,MAAM,OAAO,GAAG,GAAS,EAAE;QACzB,OAAO,EAAE,OAAO,EAAE,CAAC;QACnB,OAAO,GAAG,IAAI,CAAC;IACjB,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,CAAC,EAAU,EAAQ,EAAE;QACjC,OAAO,EAAE,CAAC;QACV,MAAM,EAAE,GAAG,WAAW,CAAC,EAAE,CAA0B,CAAC;QACpD,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;YACrB,IAAI,CAAC,EAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAC,CAAC,CAAC;YACzB,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QACnE,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;QACxB,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,EAAE,CAAC,CAAC;QAC5B,EAAE,CAAC,OAAO,GAAG,UAAU,OAAgB;YACrC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC1B,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC;YACxB,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;gBACtB,IAAI,CAAC,EAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,CAAC,GAAG,CAAC,EAAC,CAAC,CAAC;YACxD,CAAC;QACH,CAAC,CAAC;QACF,OAAO,GAAG;YACR,GAAG;YACH,OAAO,EAAE,GAAG,EAAE;gBACZ,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC;gBACxB,IAAI,GAAG,KAAK,SAAS;oBAAE,OAAO;gBAC9B,IAAI,MAAM;oBAAE,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC;;oBAC1B,OAAO,GAAG,CAAC,OAAO,CAAC;YAC1B,CAAC;SACF,CAAC;QACF,4EAA4E;QAC5E,IAAI,CAAC,EAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,CAAC,EAAE,CAAC,EAAC,CAAC,CAAC;IACvD,CAAC,CAAC;IAEF,4EAA4E;IAC5E,4EAA4E;IAC5E,8EAA8E;IAC9E,0CAA0C;IAC1C,4EAA4E;IAE5E,IAAI,YAAY,GAAuB,IAAI,CAAC;IAE5C,MAAM,aAAa,GAAG,CAAC,EAAW,EAAQ,EAAE;QAC1C,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;YAC1B,YAAY,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YAC7C,YAAY,CAAC,YAAY,CAAC,6BAA6B,EAAE,EAAE,CAAC,CAAC;YAC7D,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE;gBAChC,QAAQ,EAAE,OAAO;gBACjB,MAAM,EAAE,YAAY;gBACpB,aAAa,EAAE,MAAM;gBACrB,UAAU,EAAE,yBAAyB;gBACrC,OAAO,EAAE,mBAAmB;gBAC5B,YAAY,EAAE,KAAK;gBACnB,UAAU,EAAE,mBAAmB;aACO,CAAC,CAAC;YAC1C,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACrC,CAAC;QACD,MAAM,CAAC,GAAG,EAAE,CAAC,qBAAqB,EAAE,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE;YAChC,OAAO,EAAE,OAAO;YAChB,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,IAAI;YACnB,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI;YACjB,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,IAAI;YACrB,MAAM,EAAE,GAAG,CAAC,CAAC,MAAM,IAAI;SACxB,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,GAAS,EAAE;QAChC,IAAI,YAAY,KAAK,IAAI;YAAE,YAAY,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;IACjE,CAAC,CAAC;IAEF,4EAA4E;IAC5E,yEAAyE;IACzE,4EAA4E;IAC5E,0EAA0E;IAC1E,6EAA6E;IAC7E,4EAA4E;IAE5E,IAAI,QAAQ,GAA4B,IAAI,CAAC;IAC7C,IAAI,YAAuD,CAAC;IAC5D,IAAI,YAAY,GAAG,EAAE,CAAC;IAEtB,4EAA4E;IAC5E,MAAM,mBAAmB,GAAG,CAAC,GAAqB,EAAQ,EAAE;QAC1D,GAAG,CAAC,UAAU,EAAE,CAAC;QACjB,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAC,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAC,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,CAAC,IAAgB,EAAQ,EAAE;YACtC,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC5C,IAAI,EAAE,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;oBAC3B,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,EAAC,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAC,CAAC,CAAC;oBAC7D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;gBACtB,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,CAAC;IACjB,CAAC,CAAC;IAEF,MAAM,iBAAiB,GAAG,GAAS,EAAE;QACnC,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACnC,IAAI,IAAI,KAAK,YAAY;YAAE,OAAO;QAClC,YAAY,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,EAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAC,CAAC,CAAC;IAC9B,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,GAAS,EAAE;QAC5B,IAAI,YAAY,KAAK,SAAS;YAAE,YAAY,CAAC,YAAY,CAAC,CAAC;QAC3D,YAAY,GAAG,UAAU,CAAC,GAAG,EAAE;YAC7B,YAAY,GAAG,SAAS,CAAC;YACzB,IAAI,QAAQ,KAAK,IAAI;gBAAE,mBAAmB,CAAC,QAAQ,CAAC,CAAC;YACrD,iBAAiB,EAAE,CAAC;QACtB,CAAC,EAAE,GAAG,CAAC,CAAC;IACV,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,CAAC,OAAgB,EAAQ,EAAE;QAC9C,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,QAAQ,KAAK,IAAI;gBAAE,QAAQ,GAAG,IAAI,gBAAgB,CAAC,UAAU,CAAC,CAAC;YACnE,YAAY,GAAG,EAAE,CAAC;YAClB,mBAAmB,CAAC,QAAQ,CAAC,CAAC;YAC9B,iBAAiB,EAAE,CAAC;QACtB,CAAC;aAAM,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC7B,QAAQ,CAAC,UAAU,EAAE,CAAC;YACtB,QAAQ,GAAG,IAAI,CAAC;YAChB,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;gBAC/B,YAAY,CAAC,YAAY,CAAC,CAAC;gBAC3B,YAAY,GAAG,SAAS,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF,4EAA4E;IAC5E,0EAA0E;IAC1E,4EAA4E;IAC5E,qEAAqE;IACrE,yEAAyE;IACzE,4EAA4E;IAE5E,MAAM,YAAY,GAAG,GAAS,EAAE;QAC9B,IAAI,QAAQ,KAAK,IAAI;YAAE,OAAO;QAC9B,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC;YAChC,UAAU,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;QACvC,CAAC;IACH,CAAC,CAAC;IACF,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAClD,MAAM,CAAC,gBAAgB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;IACpD,KAAK,MAAM,MAAM,IAAI,CAAC,WAAW,EAAE,cAAc,CAAU,EAAE,CAAC;QAC5D,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/C,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAsC,EAAE,EAAE;YAC9D,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC;YAClB,YAAY,EAAE,CAAC;QACjB,CAAC,CAAC;IACJ,CAAC;IAED,4EAA4E;IAC5E,mBAAmB;IACnB,4EAA4E;IAE5E,GAAG,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,IAAI,EAAE,EAAE;QACnC,MAAM,GAAG,GAAG,IAAwB,CAAC;QACrC,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;YACjB,KAAK,MAAM,CAAC,CAAC,CAAC;gBACZ,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;gBAC1B,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBACrC,IAAI,CAAC,EAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAC,CAAC,CAAC;gBAC5B,MAAM;YACR,CAAC;YACD,KAAK,SAAS,CAAC,CAAC,CAAC;gBACf,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAC/B,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;oBACrB,IAAI,CAAC,EAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,CAAC,EAAE,CAAC,EAAC,CAAC,CAAC;gBACvD,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,EAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAC,CAAC,CAAC;gBACnC,CAAC;gBACD,MAAM;YACR,CAAC;YACD,KAAK,OAAO;gBACV,IAAI,GAAG,CAAC,EAAE,KAAK,IAAI;oBAAE,OAAO,EAAE,CAAC;;oBAC1B,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACnB,MAAM;YACR,KAAK,WAAW,CAAC,CAAC,CAAC;gBACjB,IAAI,GAAG,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;oBACpB,cAAc,EAAE,CAAC;oBACjB,MAAM;gBACR,CAAC;gBACD,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAC/B,IAAI,EAAE,KAAK,SAAS;oBAAE,aAAa,CAAC,EAAE,CAAC,CAAC;;oBACnC,cAAc,EAAE,CAAC;gBACtB,MAAM;YACR,CAAC;YACD,KAAK,SAAS;gBACZ,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAC1B,MAAM;QACV,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,wEAAwE;IACxE,IAAI,CAAC,EAAC,IAAI,EAAE,OAAO,EAAC,CAAC,CAAC;AACxB,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * Components inspector runtime.\n *\n * Injected into the host page (alongside the timeline runtime) when the\n * DevTools panel is enabled. Answers the panel's tree/details requests over the\n * Vite HMR channel, keeps a watched element's details fresh as it updates, and\n * outlines elements the panel hovers in its tree.\n */\n\nimport {elementById} from '../timeline/identity.js';\nimport {buildTree, collectDetails} from './collect.js';\nimport {\n INSPECT_CMD_CHANNEL,\n INSPECT_DATA_CHANNEL,\n type InspectorCommand,\n type InspectorMessage,\n} from '../../../types/inspector.js';\n\ntype ViteHot = {\n send: (event: string, data: unknown) => void;\n on: (event: string, handler: (data: unknown) => void) => void;\n};\n\nconst hot = (import.meta as {hot?: ViteHot}).hot;\n\nif (hot !== undefined && typeof window !== 'undefined') {\n const send = (msg: InspectorMessage): void => {\n try {\n hot.send(INSPECT_DATA_CHANNEL, msg);\n } catch {\n // HMR channel temporarily unavailable; the panel can re-request.\n }\n };\n\n // -------------------------------------------------------------------------\n // Live-watch: re-push details whenever the watched element finishes updating.\n // We wrap the instance's `updated` (not the prototype) so the hook is scoped\n // to one element and trivially removable, and it works without the timeline's\n // recording gate.\n // -------------------------------------------------------------------------\n\n type Updatable = Element & {\n updated?: (changed: unknown) => void;\n };\n // Hold the watched element via a WeakRef so an active watch doesn't keep a\n // removed element alive: the override and `restore` only reach `el` through\n // the ref, leaving the DOM as its sole strong root.\n let watched: {ref: WeakRef<Updatable>; restore: () => void} | null = null;\n\n const unwatch = (): void => {\n watched?.restore();\n watched = null;\n };\n\n const watch = (id: number): void => {\n unwatch();\n const el = elementById(id) as Updatable | undefined;\n if (el === undefined) {\n send({type: 'gone', id});\n return;\n }\n const hadOwn = Object.prototype.hasOwnProperty.call(el, 'updated');\n const prev = el.updated;\n const ref = new WeakRef(el);\n el.updated = function (changed: unknown) {\n prev?.call(this, changed);\n const cur = ref.deref();\n if (cur !== undefined) {\n send({type: 'details', details: collectDetails(cur)});\n }\n };\n watched = {\n ref,\n restore: () => {\n const cur = ref.deref();\n if (cur === undefined) return;\n if (hadOwn) cur.updated = prev;\n else delete cur.updated;\n },\n };\n // Push an immediate snapshot so the panel doesn't wait for the next update.\n send({type: 'details', details: collectDetails(el)});\n };\n\n // -------------------------------------------------------------------------\n // Highlight box: a lightweight fixed-position outline drawn over an element\n // the panel hovers in its tree. Independent of the source overlay so it works\n // whether or not that feature is enabled.\n // -------------------------------------------------------------------------\n\n let highlightBox: HTMLElement | null = null;\n\n const showHighlight = (el: Element): void => {\n if (highlightBox === null) {\n highlightBox = document.createElement('div');\n highlightBox.setAttribute('data-lit-devtools-highlight', '');\n Object.assign(highlightBox.style, {\n position: 'fixed',\n zIndex: '2147483646',\n pointerEvents: 'none',\n background: 'rgba(77, 99, 255, 0.25)',\n outline: '1px solid #4d63ff',\n borderRadius: '2px',\n transition: 'all 80ms ease-out',\n } satisfies Partial<CSSStyleDeclaration>);\n document.body.append(highlightBox);\n }\n const r = el.getBoundingClientRect();\n Object.assign(highlightBox.style, {\n display: 'block',\n left: `${r.left}px`,\n top: `${r.top}px`,\n width: `${r.width}px`,\n height: `${r.height}px`,\n });\n };\n\n const clearHighlight = (): void => {\n if (highlightBox !== null) highlightBox.style.display = 'none';\n };\n\n // -------------------------------------------------------------------------\n // Opt-in live tree: watch the DOM (light + every shadow root) and push a\n // fresh tree when the component hierarchy actually changes. Off by default.\n // childList-only (no attributes), so cosmetic changes — including our own\n // highlight box toggling — don't churn; identical rebuilds are also deduped.\n // -------------------------------------------------------------------------\n\n let observer: MutationObserver | null = null;\n let observeTimer: ReturnType<typeof setTimeout> | undefined;\n let lastTreeJson = '';\n\n /** Re-attach the observer to the body and every shadow root in the page. */\n const syncObserverTargets = (obs: MutationObserver): void => {\n obs.disconnect();\n obs.observe(document.body, {childList: true, subtree: true});\n const walk = (root: ParentNode): void => {\n for (const el of root.querySelectorAll('*')) {\n if (el.shadowRoot !== null) {\n obs.observe(el.shadowRoot, {childList: true, subtree: true});\n walk(el.shadowRoot);\n }\n }\n };\n walk(document);\n };\n\n const pushTreeIfChanged = (): void => {\n const roots = buildTree();\n const json = JSON.stringify(roots);\n if (json === lastTreeJson) return;\n lastTreeJson = json;\n send({type: 'tree', roots});\n };\n\n const onMutation = (): void => {\n if (observeTimer !== undefined) clearTimeout(observeTimer);\n observeTimer = setTimeout(() => {\n observeTimer = undefined;\n if (observer !== null) syncObserverTargets(observer);\n pushTreeIfChanged();\n }, 100);\n };\n\n const setObserving = (enabled: boolean): void => {\n if (enabled) {\n if (observer === null) observer = new MutationObserver(onMutation);\n lastTreeJson = '';\n syncObserverTargets(observer);\n pushTreeIfChanged();\n } else if (observer !== null) {\n observer.disconnect();\n observer = null;\n if (observeTimer !== undefined) {\n clearTimeout(observeTimer);\n observeTimer = undefined;\n }\n }\n };\n\n // -------------------------------------------------------------------------\n // SPA navigation: a route change swaps the component tree without any HMR\n // or panel event, so the snapshot went stale until a manual refresh. Push a\n // deduped tree after each navigation — twice, since routes typically\n // lazy-load and render async. Redundant while the live observer watches.\n // -------------------------------------------------------------------------\n\n const onNavigation = (): void => {\n if (observer !== null) return;\n for (const delay of [150, 1000]) {\n setTimeout(pushTreeIfChanged, delay);\n }\n };\n window.addEventListener('popstate', onNavigation);\n window.addEventListener('hashchange', onNavigation);\n for (const method of ['pushState', 'replaceState'] as const) {\n const original = history[method].bind(history);\n history[method] = (...args: Parameters<History['pushState']>) => {\n original(...args);\n onNavigation();\n };\n }\n\n // -------------------------------------------------------------------------\n // Command dispatch\n // -------------------------------------------------------------------------\n\n hot.on(INSPECT_CMD_CHANNEL, (data) => {\n const cmd = data as InspectorCommand;\n switch (cmd.type) {\n case 'tree': {\n const roots = buildTree();\n lastTreeJson = JSON.stringify(roots);\n send({type: 'tree', roots});\n break;\n }\n case 'details': {\n const el = elementById(cmd.id);\n if (el !== undefined) {\n send({type: 'details', details: collectDetails(el)});\n } else {\n send({type: 'gone', id: cmd.id});\n }\n break;\n }\n case 'watch':\n if (cmd.id === null) unwatch();\n else watch(cmd.id);\n break;\n case 'highlight': {\n if (cmd.id === null) {\n clearHighlight();\n break;\n }\n const el = elementById(cmd.id);\n if (el !== undefined) showHighlight(el);\n else clearHighlight();\n break;\n }\n case 'observe':\n setObserving(cmd.enabled);\n break;\n }\n });\n\n // Announce readiness so a panel that loaded first re-requests the tree.\n send({type: 'ready'});\n}\n"]}
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../../src/lib/runtime/inspector/install.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 * Components inspector runtime.\n *\n * Injected into the host page (alongside the timeline runtime) when the\n * DevTools panel is enabled. Answers the panel's tree/details requests over the\n * Vite HMR channel, keeps a watched element's details fresh as it updates, and\n * outlines elements the panel hovers in its tree.\n */\n\nimport {createPageScriptChannel} from 'devframe/in-page-channel';\nimport {elementById} from '../timeline/identity.js';\nimport {buildTree, collectDetails} from './collect.js';\nimport {clearHighlight, highlightById} from './highlight.js';\nimport {\n LIT_IN_PAGE_CHANNEL,\n type LitInPageProtocol,\n} from '../../../types/in-page.js';\nimport {\n INSPECT_CMD_CHANNEL,\n INSPECT_DATA_CHANNEL,\n type InspectorCommand,\n type InspectorMessage,\n} from '../../../types/inspector.js';\n\ntype ViteHot = {\n send: (event: string, data: unknown) => void;\n on: (event: string, handler: (data: unknown) => void) => void;\n};\n\nconst hot = (import.meta as {hot?: ViteHot}).hot;\n\n// The direct panel channel, outside the `hot` gate on purpose: it is the one\n// part of the inspector that does not need a dev server, which is what lets\n// the hover outline keep working in a static snapshot of the panel. Answering\n// handshakes costs nothing until a panel actually sends one.\nif (typeof window !== 'undefined') {\n const channel = createPageScriptChannel<LitInPageProtocol>({\n name: LIT_IN_PAGE_CHANNEL,\n functions: {},\n events: {\n highlight: {handler: (id) => highlightById(id)},\n },\n });\n // A panel that goes away mid-hover never gets to send its `highlight(null)`,\n // and an outline left painted over the app is worse than a missing one.\n channel.events.on('panel:disconnected', () => clearHighlight());\n}\n\nif (hot !== undefined && typeof window !== 'undefined') {\n const send = (msg: InspectorMessage): void => {\n try {\n hot.send(INSPECT_DATA_CHANNEL, msg);\n } catch {\n // HMR channel temporarily unavailable; the panel can re-request.\n }\n };\n\n // -------------------------------------------------------------------------\n // Live-watch: re-push details whenever the watched element finishes updating.\n // We wrap the instance's `updated` (not the prototype) so the hook is scoped\n // to one element and trivially removable, and it works without the timeline's\n // recording gate.\n // -------------------------------------------------------------------------\n\n type Updatable = Element & {\n updated?: (changed: unknown) => void;\n };\n // Hold the watched element via a WeakRef so an active watch doesn't keep a\n // removed element alive: the override and `restore` only reach `el` through\n // the ref, leaving the DOM as its sole strong root.\n let watched: {ref: WeakRef<Updatable>; restore: () => void} | null = null;\n\n const unwatch = (): void => {\n watched?.restore();\n watched = null;\n };\n\n const watch = (id: number): void => {\n unwatch();\n const el = elementById(id) as Updatable | undefined;\n if (el === undefined) {\n send({type: 'gone', id});\n return;\n }\n const hadOwn = Object.prototype.hasOwnProperty.call(el, 'updated');\n // Only an *own* `updated` is stable across an HMR hot patch. A prototype\n // implementation is replaced in place on every patch (`syncOwnMembers` in\n // ../patch.ts), so caching it here would pin the watched instance to the\n // pre-edit code for the life of the watch — resolve it through the\n // prototype chain on each call instead. Our wrapper is an own property, so\n // the lookup skips it and cannot recurse.\n const ownPrev = hadOwn ? el.updated : undefined;\n const ref = new WeakRef(el);\n el.updated = function (this: Updatable, changed: unknown) {\n const current =\n ownPrev ?? (Object.getPrototypeOf(this) as Updatable | null)?.updated;\n current?.call(this, changed);\n const cur = ref.deref();\n if (cur !== undefined) {\n send({type: 'details', details: collectDetails(cur)});\n }\n };\n watched = {\n ref,\n restore: () => {\n const cur = ref.deref();\n if (cur === undefined) return;\n if (hadOwn) cur.updated = ownPrev;\n else delete cur.updated;\n },\n };\n // Push an immediate snapshot so the panel doesn't wait for the next update.\n send({type: 'details', details: collectDetails(el)});\n };\n\n // -------------------------------------------------------------------------\n // Opt-in live tree: watch the DOM (light + every shadow root) and push a\n // fresh tree when the component hierarchy actually changes. Off by default.\n // childList-only (no attributes), so cosmetic changes — including our own\n // highlight box toggling — don't churn; identical rebuilds are also deduped.\n // Batches that only move text or comment nodes (most Lit re-renders) are\n // dropped before the debounce, and only added subtrees are walked for new\n // shadow roots, so a busy page no longer costs a full-page walk per batch.\n // -------------------------------------------------------------------------\n\n let observer: MutationObserver | null = null;\n let observeTimer: ReturnType<typeof setTimeout> | undefined;\n let lastTreeJson = '';\n // Added elements whose subtrees still need their shadow roots observed.\n let pendingRoots: Element[] = [];\n\n /** Observe every shadow root at or under `root` (and `root`'s subtree). */\n const observeShadowRoots = (\n obs: MutationObserver,\n root: ParentNode\n ): void => {\n if (root instanceof Element && root.shadowRoot !== null) {\n obs.observe(root.shadowRoot, {childList: true, subtree: true});\n observeShadowRoots(obs, root.shadowRoot);\n }\n for (const el of root.querySelectorAll('*')) {\n if (el.shadowRoot !== null) {\n obs.observe(el.shadowRoot, {childList: true, subtree: true});\n observeShadowRoots(obs, el.shadowRoot);\n }\n }\n };\n\n /** Re-attach the observer to the body and every shadow root in the page. */\n const syncObserverTargets = (obs: MutationObserver): void => {\n obs.disconnect();\n obs.observe(document.body, {childList: true, subtree: true});\n observeShadowRoots(obs, document);\n };\n\n const pushTreeIfChanged = (): void => {\n const roots = buildTree();\n const json = JSON.stringify(roots);\n if (json === lastTreeJson) return;\n lastTreeJson = json;\n send({type: 'tree', roots});\n };\n\n /** Whether a subtree holds anything the tree (or observer) cares about. */\n const mayHoldComponents = (node: Node): node is Element => {\n if (!(node instanceof Element)) return false;\n const matters = (el: Element): boolean =>\n el.localName.includes('-') || el.shadowRoot !== null;\n if (matters(node)) return true;\n for (const el of node.querySelectorAll('*')) if (matters(el)) return true;\n return false;\n };\n\n const onMutation = (records: MutationRecord[]): void => {\n // The tree only has custom elements in it, so a batch that adds or\n // removes none (text, comments, plain markup) can't change it.\n let relevant = false;\n for (const record of records) {\n for (const node of record.addedNodes) {\n if (mayHoldComponents(node)) {\n pendingRoots.push(node);\n relevant = true;\n }\n }\n if (!relevant) {\n for (const node of record.removedNodes) {\n if (mayHoldComponents(node)) {\n relevant = true;\n break;\n }\n }\n }\n }\n if (!relevant) return;\n if (observeTimer !== undefined) clearTimeout(observeTimer);\n observeTimer = setTimeout(() => {\n observeTimer = undefined;\n // Walk added subtrees now rather than on arrival: a custom element\n // attaches its shadow root when it upgrades, which can be after insert.\n // Removed roots need no bookkeeping; a detached shadow root just stops\n // producing records.\n const roots = pendingRoots;\n pendingRoots = [];\n if (observer !== null) {\n for (const root of roots) {\n if (root.isConnected) observeShadowRoots(observer, root);\n }\n }\n pushTreeIfChanged();\n }, 100);\n };\n\n const setObserving = (enabled: boolean): void => {\n if (enabled) {\n if (observer === null) observer = new MutationObserver(onMutation);\n lastTreeJson = '';\n syncObserverTargets(observer);\n pushTreeIfChanged();\n } else if (observer !== null) {\n observer.disconnect();\n observer = null;\n pendingRoots = [];\n if (observeTimer !== undefined) {\n clearTimeout(observeTimer);\n observeTimer = undefined;\n }\n }\n };\n\n // -------------------------------------------------------------------------\n // SPA navigation: a route change swaps the component tree without any HMR\n // or panel event, so the snapshot went stale until a manual refresh. Push a\n // deduped tree after each navigation — twice, since routes typically\n // lazy-load and render async. Redundant while the live observer watches.\n // -------------------------------------------------------------------------\n\n const onNavigation = (): void => {\n if (observer !== null) return;\n for (const delay of [150, 1000]) {\n setTimeout(pushTreeIfChanged, delay);\n }\n };\n window.addEventListener('popstate', onNavigation);\n window.addEventListener('hashchange', onNavigation);\n for (const method of ['pushState', 'replaceState'] as const) {\n const original = history[method].bind(history);\n history[method] = (...args: Parameters<History['pushState']>) => {\n original(...args);\n onNavigation();\n };\n }\n\n // -------------------------------------------------------------------------\n // Command dispatch\n // -------------------------------------------------------------------------\n\n hot.on(INSPECT_CMD_CHANNEL, (data) => {\n const cmd = data as InspectorCommand;\n switch (cmd.type) {\n case 'tree': {\n const roots = buildTree();\n lastTreeJson = JSON.stringify(roots);\n send({type: 'tree', roots});\n break;\n }\n case 'details': {\n const el = elementById(cmd.id);\n if (el !== undefined) {\n send({type: 'details', details: collectDetails(el)});\n } else {\n send({type: 'gone', id: cmd.id});\n }\n break;\n }\n case 'watch':\n if (cmd.id === null) unwatch();\n else watch(cmd.id);\n break;\n case 'highlight':\n // Fallback path. A panel that handshaked over the in-page channel\n // emits there instead and never reaches this.\n highlightById(cmd.id);\n break;\n case 'observe':\n setObserving(cmd.enabled);\n break;\n }\n });\n\n // Announce readiness so a panel that loaded first re-requests the tree.\n send({type: 'ready'});\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../../../../../packages/labs/vite-plugin-lit/src/lib/runtime/inspector/serialize.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAaH,gEAAgE;AAChE,eAAO,MAAM,OAAO,GAAI,OAAO,OAAO,KAAG,MAWxC,CAAC;AAwFF,oEAAoE;AACpE,eAAO,MAAM,SAAS,GAAI,OAAO,OAAO,KAAG,MAM1C,CAAC"}
1
+ {"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../../../src/lib/runtime/inspector/serialize.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAaH,gEAAgE;AAChE,eAAO,MAAM,OAAO,UAAW,OAAO,KAAG,MAWxC,CAAC;AA2FF,oEAAoE;AACpE,eAAO,MAAM,SAAS,UAAW,OAAO,KAAG,MAM1C,CAAC"}