@oddsquad/vite-plugin-lit 0.2.3 → 0.3.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 (210) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/LICENSE +28 -0
  3. package/README.md +153 -0
  4. package/bin.mjs +154 -0
  5. package/client.d.ts +61 -0
  6. package/dist/client/assets/browser-agent-rpc-BXhoSh1z-BvWe4sTJ.js +69 -0
  7. package/dist/client/assets/browser-agent-rpc-BXhoSh1z-BvWe4sTJ.js.map +1 -0
  8. package/dist/client/assets/index-CFrVgNfS.js +9740 -0
  9. package/dist/client/assets/index-CFrVgNfS.js.map +1 -0
  10. package/{panel → dist/client}/index.html +1 -0
  11. package/index.d.ts.map +1 -1
  12. package/index.js +2 -2
  13. package/index.js.map +1 -1
  14. package/lib/color-scheme.d.ts.map +1 -1
  15. package/lib/color-scheme.js +17 -21
  16. package/lib/color-scheme.js.map +1 -1
  17. package/lib/devframe/definition.d.ts +45 -0
  18. package/lib/devframe/definition.d.ts.map +1 -0
  19. package/lib/devframe/definition.js +547 -0
  20. package/lib/devframe/definition.js.map +1 -0
  21. package/lib/devframe/icon.d.ts +8 -0
  22. package/lib/devframe/icon.d.ts.map +1 -0
  23. package/lib/devframe/icon.js +21 -0
  24. package/lib/devframe/icon.js.map +1 -0
  25. package/lib/devframe/paths.d.ts +12 -0
  26. package/lib/devframe/paths.d.ts.map +1 -0
  27. package/lib/devframe/paths.js +38 -0
  28. package/lib/devframe/paths.js.map +1 -0
  29. package/lib/devframe/protocol.d.ts +218 -0
  30. package/lib/devframe/protocol.d.ts.map +1 -0
  31. package/lib/devframe/protocol.js +76 -0
  32. package/lib/devframe/protocol.js.map +1 -0
  33. package/lib/devframe/source.d.ts +49 -0
  34. package/lib/devframe/source.d.ts.map +1 -0
  35. package/lib/devframe/source.js +23 -0
  36. package/lib/devframe/source.js.map +1 -0
  37. package/lib/devframe/vite.d.ts +116 -0
  38. package/lib/devframe/vite.d.ts.map +1 -0
  39. package/lib/devframe/vite.js +291 -0
  40. package/lib/devframe/vite.js.map +1 -0
  41. package/lib/http.d.ts +29 -0
  42. package/lib/http.d.ts.map +1 -0
  43. package/lib/http.js +35 -0
  44. package/lib/http.js.map +1 -0
  45. package/lib/icons.d.ts +2 -0
  46. package/lib/icons.d.ts.map +1 -1
  47. package/lib/icons.js +10 -4
  48. package/lib/icons.js.map +1 -1
  49. package/lib/plugin.d.ts +15 -4
  50. package/lib/plugin.d.ts.map +1 -1
  51. package/lib/plugin.js +640 -574
  52. package/lib/plugin.js.map +1 -1
  53. package/lib/runtime/css.d.ts +2 -2
  54. package/lib/runtime/css.d.ts.map +1 -1
  55. package/lib/runtime/css.js +34 -34
  56. package/lib/runtime/css.js.map +1 -1
  57. package/lib/runtime/edge-panel.d.ts.map +1 -1
  58. package/lib/runtime/edge-panel.js +82 -91
  59. package/lib/runtime/edge-panel.js.map +1 -1
  60. package/lib/runtime/fonts.d.ts.map +1 -1
  61. package/lib/runtime/fonts.js +1 -1
  62. package/lib/runtime/fonts.js.map +1 -1
  63. package/lib/runtime/indicator.d.ts.map +1 -1
  64. package/lib/runtime/indicator.js +71 -74
  65. package/lib/runtime/indicator.js.map +1 -1
  66. package/lib/runtime/inspector/collect.d.ts.map +1 -1
  67. package/lib/runtime/inspector/collect.js +83 -90
  68. package/lib/runtime/inspector/collect.js.map +1 -1
  69. package/lib/runtime/inspector/highlight.d.ts +16 -0
  70. package/lib/runtime/inspector/highlight.d.ts.map +1 -0
  71. package/lib/runtime/inspector/highlight.js +66 -0
  72. package/lib/runtime/inspector/highlight.js.map +1 -0
  73. package/lib/runtime/inspector/install.d.ts.map +1 -1
  74. package/lib/runtime/inspector/install.js +180 -205
  75. package/lib/runtime/inspector/install.js.map +1 -1
  76. package/lib/runtime/inspector/serialize.d.ts.map +1 -1
  77. package/lib/runtime/inspector/serialize.js +86 -107
  78. package/lib/runtime/inspector/serialize.js.map +1 -1
  79. package/lib/runtime/intern.d.ts.map +1 -1
  80. package/lib/runtime/intern.js +31 -29
  81. package/lib/runtime/intern.js.map +1 -1
  82. package/lib/runtime/overrides.d.ts.map +1 -1
  83. package/lib/runtime/overrides.js +14 -13
  84. package/lib/runtime/overrides.js.map +1 -1
  85. package/lib/runtime/patch.d.ts +8 -0
  86. package/lib/runtime/patch.d.ts.map +1 -1
  87. package/lib/runtime/patch.js +321 -282
  88. package/lib/runtime/patch.js.map +1 -1
  89. package/lib/runtime/source-meta.d.ts.map +1 -1
  90. package/lib/runtime/source-meta.js +1 -1
  91. package/lib/runtime/source-meta.js.map +1 -1
  92. package/lib/runtime/source-overlay/editors.d.ts.map +1 -1
  93. package/lib/runtime/source-overlay/editors.js +27 -27
  94. package/lib/runtime/source-overlay/editors.js.map +1 -1
  95. package/lib/runtime/source-overlay/mask-path.d.ts.map +1 -1
  96. package/lib/runtime/source-overlay/mask-path.js +15 -15
  97. package/lib/runtime/source-overlay/mask-path.js.map +1 -1
  98. package/lib/runtime/source-overlay/overlay-element.d.ts.map +1 -1
  99. package/lib/runtime/source-overlay/overlay-element.js +347 -356
  100. package/lib/runtime/source-overlay/overlay-element.js.map +1 -1
  101. package/lib/runtime/source-overlay/source-host.d.ts.map +1 -1
  102. package/lib/runtime/source-overlay/source-host.js +64 -71
  103. package/lib/runtime/source-overlay/source-host.js.map +1 -1
  104. package/lib/runtime/source-overlay/template.d.ts.map +1 -1
  105. package/lib/runtime/source-overlay/template.js +3 -3
  106. package/lib/runtime/source-overlay/template.js.map +1 -1
  107. package/lib/runtime/source-overlay.d.ts.map +1 -1
  108. package/lib/runtime/source-overlay.js +5 -2
  109. package/lib/runtime/source-overlay.js.map +1 -1
  110. package/lib/runtime/timeline/clock.d.ts.map +1 -1
  111. package/lib/runtime/timeline/clock.js +2 -2
  112. package/lib/runtime/timeline/clock.js.map +1 -1
  113. package/lib/runtime/timeline/flash.d.ts +39 -0
  114. package/lib/runtime/timeline/flash.d.ts.map +1 -0
  115. package/lib/runtime/timeline/flash.js +169 -0
  116. package/lib/runtime/timeline/flash.js.map +1 -0
  117. package/lib/runtime/timeline/identity.d.ts.map +1 -1
  118. package/lib/runtime/timeline/identity.js +27 -27
  119. package/lib/runtime/timeline/identity.js.map +1 -1
  120. package/lib/runtime/timeline/input.d.ts.map +1 -1
  121. package/lib/runtime/timeline/input.js +54 -67
  122. package/lib/runtime/timeline/input.js.map +1 -1
  123. package/lib/runtime/timeline/install.d.ts.map +1 -1
  124. package/lib/runtime/timeline/install.js +38 -29
  125. package/lib/runtime/timeline/install.js.map +1 -1
  126. package/lib/runtime/timeline/lifecycle.d.ts +8 -0
  127. package/lib/runtime/timeline/lifecycle.d.ts.map +1 -1
  128. package/lib/runtime/timeline/lifecycle.js +149 -133
  129. package/lib/runtime/timeline/lifecycle.js.map +1 -1
  130. package/lib/runtime/timeline/public-api.d.ts.map +1 -1
  131. package/lib/runtime/timeline/public-api.js +9 -9
  132. package/lib/runtime/timeline/public-api.js.map +1 -1
  133. package/lib/runtime/timeline/render.d.ts.map +1 -1
  134. package/lib/runtime/timeline/render.js +70 -75
  135. package/lib/runtime/timeline/render.js.map +1 -1
  136. package/lib/runtime/timeline/transport.d.ts.map +1 -1
  137. package/lib/runtime/timeline/transport.js +39 -43
  138. package/lib/runtime/timeline/transport.js.map +1 -1
  139. package/lib/segmented-tabs.d.ts +3 -1
  140. package/lib/segmented-tabs.d.ts.map +1 -1
  141. package/lib/segmented-tabs.js +136 -107
  142. package/lib/segmented-tabs.js.map +1 -1
  143. package/lib/snapshot.d.ts +28 -0
  144. package/lib/snapshot.d.ts.map +1 -0
  145. package/lib/snapshot.js +57 -0
  146. package/lib/snapshot.js.map +1 -0
  147. package/lib/source-meta.d.ts.map +1 -1
  148. package/lib/source-meta.js +176 -162
  149. package/lib/source-meta.js.map +1 -1
  150. package/lib/timeline/derive.d.ts +152 -0
  151. package/lib/timeline/derive.d.ts.map +1 -0
  152. package/lib/timeline/derive.js +242 -0
  153. package/lib/timeline/derive.js.map +1 -0
  154. package/lib/timeline-plugin.d.ts.map +1 -1
  155. package/lib/timeline-plugin.js +304 -321
  156. package/lib/timeline-plugin.js.map +1 -1
  157. package/lib/tokens.d.ts.map +1 -1
  158. package/lib/tokens.js +17 -18
  159. package/lib/tokens.js.map +1 -1
  160. package/lib/transform.d.ts.map +1 -1
  161. package/lib/transform.js +62 -57
  162. package/lib/transform.js.map +1 -1
  163. package/lib/types.d.ts.map +1 -1
  164. package/lib/types.js +1 -1
  165. package/lib/types.js.map +1 -1
  166. package/lib/wrap-table.d.ts.map +1 -1
  167. package/lib/wrap-table.js +19 -17
  168. package/lib/wrap-table.js.map +1 -1
  169. package/package.json +77 -13
  170. package/types/hmr-incompatibility.d.ts +59 -0
  171. package/types/hmr-incompatibility.d.ts.map +1 -0
  172. package/types/hmr-incompatibility.js +30 -0
  173. package/types/hmr-incompatibility.js.map +1 -0
  174. package/types/in-page.d.ts +49 -0
  175. package/types/in-page.d.ts.map +1 -0
  176. package/types/in-page.js +33 -0
  177. package/types/in-page.js.map +1 -0
  178. package/types/inspector.d.ts.map +1 -1
  179. package/types/inspector.js.map +1 -1
  180. package/types/snapshot.d.ts +44 -0
  181. package/types/snapshot.d.ts.map +1 -0
  182. package/types/snapshot.js +7 -0
  183. package/types/snapshot.js.map +1 -0
  184. package/types/timeline.d.ts +11 -0
  185. package/types/timeline.d.ts.map +1 -1
  186. package/types/timeline.js.map +1 -1
  187. package/panel/components-view.d.ts +0 -60
  188. package/panel/components-view.d.ts.map +0 -1
  189. package/panel/components-view.js +0 -587
  190. package/panel/components-view.js.map +0 -1
  191. package/panel/devtools-settings.d.ts +0 -41
  192. package/panel/devtools-settings.d.ts.map +0 -1
  193. package/panel/devtools-settings.js +0 -463
  194. package/panel/devtools-settings.js.map +0 -1
  195. package/panel/lit-devtools-panel.d.ts +0 -37
  196. package/panel/lit-devtools-panel.d.ts.map +0 -1
  197. package/panel/lit-devtools-panel.js +0 -185
  198. package/panel/lit-devtools-panel.js.map +0 -1
  199. package/panel/timeline-event-list.d.ts +0 -43
  200. package/panel/timeline-event-list.d.ts.map +0 -1
  201. package/panel/timeline-event-list.js +0 -416
  202. package/panel/timeline-event-list.js.map +0 -1
  203. package/panel/timeline-layers.d.ts +0 -25
  204. package/panel/timeline-layers.d.ts.map +0 -1
  205. package/panel/timeline-layers.js +0 -96
  206. package/panel/timeline-layers.js.map +0 -1
  207. package/panel/timeline-view.d.ts +0 -38
  208. package/panel/timeline-view.d.ts.map +0 -1
  209. package/panel/timeline-view.js +0 -234
  210. package/panel/timeline-view.js.map +0 -1
@@ -1,587 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2026 Google LLC
4
- * SPDX-License-Identifier: BSD-3-Clause
5
- */
6
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
7
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
8
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
9
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
10
- return c > 3 && r && Object.defineProperty(target, key, r), r;
11
- };
12
- import { LitElement, html, css, nothing } from 'lit';
13
- import { customElement, state } from 'lit/decorators.js';
14
- import { tokens } from '../lib/tokens.js';
15
- import { INSPECT_PATH, INSPECT_SSE_EVENT, } from '../types/inspector.js';
16
- /** localStorage key remembering the opt-in live-tree toggle. */
17
- const LIVE_LS_KEY = 'lit-devtools-components-live';
18
- /**
19
- * The Components view: a hierarchical tree of the page's Lit elements (left)
20
- * and a details pane for the selected one (right). A tab of the DevTools panel
21
- * shell (\`lit-devtools-panel\`).
22
- *
23
- * It can't touch the page DOM directly (separate iframe), so it drives the
24
- * page's inspector runtime over the transport: it POSTs {@link InspectorCommand}s
25
- * to {@link INSPECT_PATH} and receives {@link InspectorMessage}s on the shared
26
- * SSE stream's `inspect` event. An overlay inspect-pick arrives as a `pick`
27
- * message; the view selects that node and asks its host to switch to this tab.
28
- */
29
- let ComponentsView = class ComponentsView extends LitElement {
30
- constructor() {
31
- super(...arguments);
32
- this._roots = [];
33
- this._selectedId = null;
34
- this._details = null;
35
- /** True when the selected element is no longer in the page (removed / GC'd). */
36
- this._gone = false;
37
- this._expanded = new Set();
38
- this._picking = false;
39
- /** Opt-in live tree (MutationObserver in the page); persisted, default off. */
40
- this._live = false;
41
- this._es = null;
42
- /** Refresh the tree (and re-arm watch / live mode) once the SSE connects. */
43
- this._onOpen = () => {
44
- this._post({ type: 'tree' });
45
- if (this._selectedId !== null) {
46
- this._post({ type: 'watch', id: this._selectedId });
47
- }
48
- if (this._live)
49
- this._post({ type: 'observe', enabled: true });
50
- };
51
- this._onMessage = (e) => {
52
- let msg;
53
- try {
54
- msg = JSON.parse(e.data);
55
- }
56
- catch {
57
- return;
58
- }
59
- switch (msg.type) {
60
- case 'ready':
61
- // Runtime (re)connected — refresh the tree and re-arm any selection.
62
- this._post({ type: 'tree' });
63
- if (this._selectedId !== null) {
64
- this._post({ type: 'watch', id: this._selectedId });
65
- }
66
- break;
67
- case 'tree':
68
- this._roots = msg.roots;
69
- // Re-reveal the selection against the fresh tree: a just-picked node may
70
- // not have existed in the previous _roots, so the reveal in _select()
71
- // found no ancestors to expand and the node stayed hidden.
72
- if (this._selectedId !== null) {
73
- this._revealAncestors(this._selectedId);
74
- }
75
- break;
76
- case 'details':
77
- if (msg.details.id === this._selectedId) {
78
- this._details = msg.details;
79
- this._gone = false;
80
- }
81
- break;
82
- case 'gone':
83
- if (msg.id === this._selectedId) {
84
- this._details = null;
85
- this._gone = true;
86
- }
87
- break;
88
- case 'pick':
89
- this._picking = false;
90
- this._select(msg.id);
91
- // Bring this tab to the front so the pick is visible.
92
- this.dispatchEvent(new CustomEvent('inspector-activate', { bubbles: true, composed: true }));
93
- break;
94
- }
95
- };
96
- }
97
- static { this.styles = [
98
- tokens,
99
- css `
100
- :host {
101
- display: flex;
102
- flex-direction: column;
103
- flex: 1;
104
- overflow: hidden;
105
- }
106
- :host([hidden]) {
107
- display: none;
108
- }
109
- .toolbar {
110
- display: flex;
111
- align-items: center;
112
- gap: var(--lit-devtools-space-4);
113
- padding: var(--lit-devtools-space-3) var(--lit-devtools-space-5);
114
- border-bottom: 1px solid var(--lit-devtools-border);
115
- background: var(--lit-devtools-surface-low);
116
- flex-shrink: 0;
117
- }
118
- .spacer {
119
- flex: 1;
120
- }
121
- button {
122
- padding: var(--lit-devtools-space-2) var(--lit-devtools-space-5);
123
- border-radius: var(--lit-devtools-radius-sm);
124
- border: 1px solid var(--lit-devtools-border);
125
- background: var(--lit-devtools-surface-elevated);
126
- color: var(--lit-devtools-text);
127
- font-size: var(--lit-devtools-text-2xs);
128
- cursor: pointer;
129
- }
130
- button:hover {
131
- background: var(--lit-devtools-surface-hover);
132
- border-color: var(--lit-devtools-border-strong);
133
- }
134
- button.pick.active,
135
- button.live.active {
136
- border-color: var(--lit-devtools-accent);
137
- background: var(--lit-devtools-accent-soft);
138
- color: var(--lit-devtools-accent);
139
- }
140
- button:disabled {
141
- opacity: 0.4;
142
- cursor: default;
143
- }
144
- .body {
145
- display: flex;
146
- flex: 1;
147
- overflow: hidden;
148
- }
149
- .tree {
150
- flex: 1;
151
- overflow: auto;
152
- padding: var(--lit-devtools-space-2) 0;
153
- min-width: 0;
154
- }
155
- .empty {
156
- padding: var(--lit-devtools-space-6);
157
- color: var(--lit-devtools-text-muted);
158
- font-size: var(--lit-devtools-text-xs);
159
- }
160
- .row {
161
- display: flex;
162
- align-items: center;
163
- gap: var(--lit-devtools-space-2);
164
- padding: 1px var(--lit-devtools-space-5);
165
- white-space: nowrap;
166
- cursor: pointer;
167
- font-family: var(--lit-devtools-font-mono);
168
- font-size: var(--lit-devtools-text-xs);
169
- line-height: 18px;
170
- }
171
- .row:hover {
172
- background: var(--lit-devtools-surface-hover);
173
- }
174
- .row.selected {
175
- background: var(--lit-devtools-surface-active);
176
- }
177
- .twisty {
178
- width: 12px;
179
- text-align: center;
180
- color: var(--lit-devtools-text-muted);
181
- flex-shrink: 0;
182
- }
183
- .twisty.leaf {
184
- visibility: hidden;
185
- }
186
- .tag {
187
- color: var(--lit-devtools-accent);
188
- }
189
- .tag .punct {
190
- color: var(--lit-devtools-text-muted);
191
- }
192
- .details {
193
- width: 340px;
194
- flex-shrink: 0;
195
- border-left: 1px solid var(--lit-devtools-border);
196
- overflow: auto;
197
- padding: var(--lit-devtools-space-5) var(--lit-devtools-space-5);
198
- font-size: var(--lit-devtools-text-xs);
199
- }
200
- .details h2 {
201
- font-size: var(--lit-devtools-text-xs);
202
- font-family: var(--lit-devtools-font-mono);
203
- color: var(--lit-devtools-accent);
204
- margin: 0 0 var(--lit-devtools-space-1);
205
- }
206
- .src {
207
- background: none;
208
- border: 0;
209
- padding: 0;
210
- color: var(--lit-devtools-text-link);
211
- font-size: var(--lit-devtools-text-2xs);
212
- cursor: pointer;
213
- text-decoration: underline;
214
- word-break: break-all;
215
- text-align: left;
216
- }
217
- section {
218
- margin-top: var(--lit-devtools-space-5);
219
- }
220
- section > .label {
221
- text-transform: uppercase;
222
- letter-spacing: var(--lit-devtools-tracking-caps);
223
- font-size: var(--lit-devtools-text-2xs);
224
- color: var(--lit-devtools-text-muted);
225
- margin-bottom: var(--lit-devtools-space-2);
226
- }
227
- table {
228
- width: 100%;
229
- border-collapse: collapse;
230
- font-family: var(--lit-devtools-font-mono);
231
- }
232
- td {
233
- padding: 2px var(--lit-devtools-space-4) 2px 0;
234
- vertical-align: top;
235
- word-break: break-word;
236
- }
237
- td.name {
238
- color: var(--lit-devtools-text);
239
- white-space: nowrap;
240
- }
241
- td.val {
242
- color: var(--lit-devtools-warning);
243
- width: 100%;
244
- }
245
- .badge {
246
- display: inline-block;
247
- margin-left: var(--lit-devtools-space-2);
248
- padding: 0 var(--lit-devtools-space-2);
249
- border-radius: var(--lit-devtools-radius-xs);
250
- font-size: 9px;
251
- background: var(--lit-devtools-surface-elevated);
252
- color: var(--lit-devtools-text-secondary);
253
- vertical-align: middle;
254
- }
255
- .flags {
256
- display: flex;
257
- gap: var(--lit-devtools-space-4);
258
- flex-wrap: wrap;
259
- }
260
- .flag {
261
- padding: 1px var(--lit-devtools-space-4);
262
- border-radius: var(--lit-devtools-radius-xs);
263
- background: var(--lit-devtools-surface-elevated);
264
- color: var(--lit-devtools-text-secondary);
265
- font-size: var(--lit-devtools-text-2xs);
266
- }
267
- .flag.on {
268
- background: var(--lit-devtools-accent-soft);
269
- color: var(--lit-devtools-accent);
270
- }
271
- .placeholder {
272
- color: var(--lit-devtools-text-muted);
273
- padding: var(--lit-devtools-space-8) 0;
274
- text-align: center;
275
- }
276
- `,
277
- ]; }
278
- connectedCallback() {
279
- super.connectedCallback();
280
- this._live = localStorage.getItem(LIVE_LS_KEY) === 'true';
281
- this._es = new EventSource('/__lit-devtools-events');
282
- this._es.addEventListener(INSPECT_SSE_EVENT, this._onMessage);
283
- // Request only once the stream is open — a command sent before we're
284
- // subscribed would have its reply broadcast before we could receive it.
285
- this._es.addEventListener('open', this._onOpen);
286
- }
287
- disconnectedCallback() {
288
- super.disconnectedCallback();
289
- this._es?.removeEventListener(INSPECT_SSE_EVENT, this._onMessage);
290
- this._es?.removeEventListener('open', this._onOpen);
291
- this._es?.close();
292
- this._es = null;
293
- this._post({ type: 'watch', id: null });
294
- if (this._live)
295
- this._post({ type: 'observe', enabled: false });
296
- }
297
- // ---------------------------------------------------------------------------
298
- // Transport
299
- // ---------------------------------------------------------------------------
300
- _post(cmd) {
301
- fetch(INSPECT_PATH, {
302
- method: 'POST',
303
- headers: { 'Content-Type': 'application/json' },
304
- body: JSON.stringify(cmd),
305
- }).catch((err) => {
306
- console.warn('[lit-devtools] inspector POST failed', err);
307
- });
308
- }
309
- // ---------------------------------------------------------------------------
310
- // Selection / expansion
311
- // ---------------------------------------------------------------------------
312
- /**
313
- * Select an element by id from outside (e.g. a timeline event's "inspect"
314
- * link). Same as a tree click; the host is responsible for switching tabs.
315
- */
316
- selectById(id) {
317
- this._select(id);
318
- }
319
- _select(id) {
320
- if (this._selectedId === id)
321
- return;
322
- if (this._selectedId !== null) {
323
- this._post({ type: 'watch', id: null });
324
- }
325
- this._selectedId = id;
326
- this._details = null;
327
- this._gone = false;
328
- this._revealAncestors(id);
329
- this._post({ type: 'tree' }); // refresh in case the picked node is new
330
- this._post({ type: 'details', id });
331
- this._post({ type: 'watch', id });
332
- }
333
- /** Expand every ancestor of `id` so the selected node is visible. */
334
- _revealAncestors(id) {
335
- const path = findAncestors(this._roots, id);
336
- if (path === null)
337
- return;
338
- const next = new Set(this._expanded);
339
- for (const ancestorId of path)
340
- next.add(ancestorId);
341
- this._expanded = next;
342
- }
343
- _toggleExpand(id) {
344
- const next = new Set(this._expanded);
345
- if (next.has(id))
346
- next.delete(id);
347
- else
348
- next.add(id);
349
- this._expanded = next;
350
- }
351
- // ---------------------------------------------------------------------------
352
- // Actions
353
- // ---------------------------------------------------------------------------
354
- _refresh() {
355
- this._post({ type: 'tree' });
356
- if (this._selectedId !== null) {
357
- this._post({ type: 'details', id: this._selectedId });
358
- }
359
- }
360
- _togglePick() {
361
- this._picking = !this._picking;
362
- this._post({ type: 'pick' });
363
- }
364
- _toggleLive() {
365
- this._live = !this._live;
366
- try {
367
- localStorage.setItem(LIVE_LS_KEY, String(this._live));
368
- }
369
- catch {
370
- // ignore (private/storage unavailable)
371
- }
372
- this._post({ type: 'observe', enabled: this._live });
373
- // Leaving live mode, pull one fresh tree so it doesn't go stale silently.
374
- if (!this._live)
375
- this._post({ type: 'tree' });
376
- }
377
- _highlight(id) {
378
- this._post({ type: 'highlight', id });
379
- }
380
- _openSource() {
381
- const src = this._details?.source;
382
- if (src === undefined)
383
- return;
384
- const params = new URLSearchParams({
385
- file: src.file,
386
- line: String(src.line),
387
- });
388
- fetch(`/__lit-open-in-editor?${params.toString()}`)
389
- .then(async (res) => {
390
- if (!res.ok) {
391
- console.warn(`[lit-devtools] open-in-editor failed (${res.status})`, await res.text());
392
- }
393
- })
394
- .catch((err) => {
395
- console.warn('[lit-devtools] open-in-editor failed', err);
396
- });
397
- }
398
- // ---------------------------------------------------------------------------
399
- // Render
400
- // ---------------------------------------------------------------------------
401
- _renderNode(node, depth) {
402
- const hasChildren = node.children.length > 0;
403
- const expanded = this._expanded.has(node.id);
404
- return html `
405
- <div
406
- class="row ${node.id === this._selectedId ? 'selected' : ''}"
407
- style="padding-left:${8 + depth * 14}px"
408
- @click=${() => this._select(node.id)}
409
- @mouseenter=${() => this._highlight(node.id)}
410
- >
411
- <span
412
- class="twisty ${hasChildren ? '' : 'leaf'}"
413
- @click=${(e) => {
414
- e.stopPropagation();
415
- this._toggleExpand(node.id);
416
- }}
417
- >${hasChildren ? (expanded ? '▾' : '▸') : '•'}</span
418
- >
419
- <span class="tag"
420
- ><span class="punct">&lt;</span>${node.tagName}<span class="punct"
421
- >&gt;</span
422
- ></span
423
- >
424
- </div>
425
- ${hasChildren && expanded
426
- ? node.children.map((c) => this._renderNode(c, depth + 1))
427
- : nothing}
428
- `;
429
- }
430
- _renderPropTable(props) {
431
- return html `
432
- <table>
433
- ${props.map((p) => html `
434
- <tr>
435
- <td class="name">
436
- ${p.name}${p.reflects
437
- ? html `<span class="badge" title="reflects to attribute"
438
- >${typeof p.attribute === 'string'
439
- ? p.attribute
440
- : 'attr'}</span
441
- >`
442
- : nothing}
443
- </td>
444
- <td class="val">${p.value}</td>
445
- </tr>
446
- `)}
447
- </table>
448
- `;
449
- }
450
- _renderDetails() {
451
- const d = this._details;
452
- if (d === null) {
453
- let message;
454
- if (this._gone) {
455
- message = 'This element is no longer in the page.';
456
- }
457
- else if (this._selectedId === null) {
458
- message = 'Select a component to inspect.';
459
- }
460
- else {
461
- message = 'Loading…';
462
- }
463
- return html `<div class="placeholder">${message}</div>`;
464
- }
465
- const props = d.properties.filter((p) => !p.state);
466
- const stateProps = d.properties.filter((p) => p.state);
467
- return html `
468
- <h2>&lt;${d.tagName}&gt;</h2>
469
- ${d.source !== undefined
470
- ? html `<button class="src" @click=${this._openSource}>
471
- ${d.source.file}:${d.source.line}
472
- </button>`
473
- : nothing}
474
- <section>
475
- <div class="flags">
476
- <span class="flag ${d.flags.hasUpdated ? 'on' : ''}">updated</span>
477
- <span class="flag ${d.flags.isUpdatePending ? 'on' : ''}"
478
- >update pending</span
479
- >
480
- <span class="flag ${d.flags.hasShadowRoot ? 'on' : ''}"
481
- >shadow root</span
482
- >
483
- </div>
484
- </section>
485
- ${props.length > 0
486
- ? html `<section>
487
- <div class="label">Properties</div>
488
- ${this._renderPropTable(props)}
489
- </section>`
490
- : nothing}
491
- ${stateProps.length > 0
492
- ? html `<section>
493
- <div class="label">State</div>
494
- ${this._renderPropTable(stateProps)}
495
- </section>`
496
- : nothing}
497
- ${d.attributes.length > 0
498
- ? html `<section>
499
- <div class="label">Attributes</div>
500
- <table>
501
- ${d.attributes.map((a) => html `<tr>
502
- <td class="name">${a.name}</td>
503
- <td class="val">${a.value}</td>
504
- </tr>`)}
505
- </table>
506
- </section>`
507
- : nothing}
508
- `;
509
- }
510
- render() {
511
- return html `
512
- <div class="toolbar">
513
- <button
514
- class="pick ${this._picking ? 'active' : ''}"
515
- title="Pick an element on the page (Meta+Shift+E)"
516
- @click=${this._togglePick}
517
- >
518
- ⌖ Pick
519
- </button>
520
- <span class="spacer"></span>
521
- <button
522
- class="live ${this._live ? 'active' : ''}"
523
- title="Update the tree automatically as the page changes"
524
- @click=${this._toggleLive}
525
- >
526
- ${this._live ? '● Live' : '○ Live'}
527
- </button>
528
- <button @click=${this._refresh} ?disabled=${this._live}>Refresh</button>
529
- </div>
530
- <div class="body">
531
- <div class="tree" @mouseleave=${() => this._highlight(null)}>
532
- ${this._roots.length === 0
533
- ? html `<div class="empty">
534
- No Lit components found on the page.
535
- </div>`
536
- : this._roots.map((n) => this._renderNode(n, 0))}
537
- </div>
538
- <div class="details">${this._renderDetails()}</div>
539
- </div>
540
- `;
541
- }
542
- };
543
- __decorate([
544
- state()
545
- ], ComponentsView.prototype, "_roots", void 0);
546
- __decorate([
547
- state()
548
- ], ComponentsView.prototype, "_selectedId", void 0);
549
- __decorate([
550
- state()
551
- ], ComponentsView.prototype, "_details", void 0);
552
- __decorate([
553
- state()
554
- ], ComponentsView.prototype, "_gone", void 0);
555
- __decorate([
556
- state()
557
- ], ComponentsView.prototype, "_expanded", void 0);
558
- __decorate([
559
- state()
560
- ], ComponentsView.prototype, "_picking", void 0);
561
- __decorate([
562
- state()
563
- ], ComponentsView.prototype, "_live", void 0);
564
- ComponentsView = __decorate([
565
- customElement('components-view')
566
- ], ComponentsView);
567
- export { ComponentsView };
568
- /**
569
- * Returns the ids of every ancestor of `id` (nearest last), or `null` if `id`
570
- * isn't in the tree. The target id itself is not included.
571
- */
572
- const findAncestors = (nodes, id) => {
573
- const trail = [];
574
- const walk = (list) => {
575
- for (const node of list) {
576
- if (node.id === id)
577
- return true;
578
- trail.push(node.id);
579
- if (walk(node.children))
580
- return true;
581
- trail.pop();
582
- }
583
- return false;
584
- };
585
- return walk(nodes) ? [...trail] : null;
586
- };
587
- //# sourceMappingURL=components-view.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"components-view.js","sourceRoot":"","sources":["../../../packages/labs/vite-plugin-lit/src/panel/components-view.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 {LitElement, html, css, nothing, type TemplateResult} from 'lit';\nimport {customElement, state} from 'lit/decorators.js';\nimport {tokens} from '../lib/tokens.js';\nimport {\n INSPECT_PATH,\n INSPECT_SSE_EVENT,\n type InspectorCommand,\n type InspectorDetails,\n type InspectorMessage,\n type InspectorTreeNode,\n} from '../types/inspector.js';\n\n/** localStorage key remembering the opt-in live-tree toggle. */\nconst LIVE_LS_KEY = 'lit-devtools-components-live';\n\n/**\n * The Components view: a hierarchical tree of the page's Lit elements (left)\n * and a details pane for the selected one (right). A tab of the DevTools panel\n * shell (\\`lit-devtools-panel\\`).\n *\n * It can't touch the page DOM directly (separate iframe), so it drives the\n * page's inspector runtime over the transport: it POSTs {@link InspectorCommand}s\n * to {@link INSPECT_PATH} and receives {@link InspectorMessage}s on the shared\n * SSE stream's `inspect` event. An overlay inspect-pick arrives as a `pick`\n * message; the view selects that node and asks its host to switch to this tab.\n */\n@customElement('components-view')\nexport class ComponentsView extends LitElement {\n static override styles = [\n tokens,\n css`\n :host {\n display: flex;\n flex-direction: column;\n flex: 1;\n overflow: hidden;\n }\n :host([hidden]) {\n display: none;\n }\n .toolbar {\n display: flex;\n align-items: center;\n gap: var(--lit-devtools-space-4);\n padding: var(--lit-devtools-space-3) var(--lit-devtools-space-5);\n border-bottom: 1px solid var(--lit-devtools-border);\n background: var(--lit-devtools-surface-low);\n flex-shrink: 0;\n }\n .spacer {\n flex: 1;\n }\n button {\n padding: var(--lit-devtools-space-2) var(--lit-devtools-space-5);\n border-radius: var(--lit-devtools-radius-sm);\n border: 1px solid var(--lit-devtools-border);\n background: var(--lit-devtools-surface-elevated);\n color: var(--lit-devtools-text);\n font-size: var(--lit-devtools-text-2xs);\n cursor: pointer;\n }\n button:hover {\n background: var(--lit-devtools-surface-hover);\n border-color: var(--lit-devtools-border-strong);\n }\n button.pick.active,\n button.live.active {\n border-color: var(--lit-devtools-accent);\n background: var(--lit-devtools-accent-soft);\n color: var(--lit-devtools-accent);\n }\n button:disabled {\n opacity: 0.4;\n cursor: default;\n }\n .body {\n display: flex;\n flex: 1;\n overflow: hidden;\n }\n .tree {\n flex: 1;\n overflow: auto;\n padding: var(--lit-devtools-space-2) 0;\n min-width: 0;\n }\n .empty {\n padding: var(--lit-devtools-space-6);\n color: var(--lit-devtools-text-muted);\n font-size: var(--lit-devtools-text-xs);\n }\n .row {\n display: flex;\n align-items: center;\n gap: var(--lit-devtools-space-2);\n padding: 1px var(--lit-devtools-space-5);\n white-space: nowrap;\n cursor: pointer;\n font-family: var(--lit-devtools-font-mono);\n font-size: var(--lit-devtools-text-xs);\n line-height: 18px;\n }\n .row:hover {\n background: var(--lit-devtools-surface-hover);\n }\n .row.selected {\n background: var(--lit-devtools-surface-active);\n }\n .twisty {\n width: 12px;\n text-align: center;\n color: var(--lit-devtools-text-muted);\n flex-shrink: 0;\n }\n .twisty.leaf {\n visibility: hidden;\n }\n .tag {\n color: var(--lit-devtools-accent);\n }\n .tag .punct {\n color: var(--lit-devtools-text-muted);\n }\n .details {\n width: 340px;\n flex-shrink: 0;\n border-left: 1px solid var(--lit-devtools-border);\n overflow: auto;\n padding: var(--lit-devtools-space-5) var(--lit-devtools-space-5);\n font-size: var(--lit-devtools-text-xs);\n }\n .details h2 {\n font-size: var(--lit-devtools-text-xs);\n font-family: var(--lit-devtools-font-mono);\n color: var(--lit-devtools-accent);\n margin: 0 0 var(--lit-devtools-space-1);\n }\n .src {\n background: none;\n border: 0;\n padding: 0;\n color: var(--lit-devtools-text-link);\n font-size: var(--lit-devtools-text-2xs);\n cursor: pointer;\n text-decoration: underline;\n word-break: break-all;\n text-align: left;\n }\n section {\n margin-top: var(--lit-devtools-space-5);\n }\n section > .label {\n text-transform: uppercase;\n letter-spacing: var(--lit-devtools-tracking-caps);\n font-size: var(--lit-devtools-text-2xs);\n color: var(--lit-devtools-text-muted);\n margin-bottom: var(--lit-devtools-space-2);\n }\n table {\n width: 100%;\n border-collapse: collapse;\n font-family: var(--lit-devtools-font-mono);\n }\n td {\n padding: 2px var(--lit-devtools-space-4) 2px 0;\n vertical-align: top;\n word-break: break-word;\n }\n td.name {\n color: var(--lit-devtools-text);\n white-space: nowrap;\n }\n td.val {\n color: var(--lit-devtools-warning);\n width: 100%;\n }\n .badge {\n display: inline-block;\n margin-left: var(--lit-devtools-space-2);\n padding: 0 var(--lit-devtools-space-2);\n border-radius: var(--lit-devtools-radius-xs);\n font-size: 9px;\n background: var(--lit-devtools-surface-elevated);\n color: var(--lit-devtools-text-secondary);\n vertical-align: middle;\n }\n .flags {\n display: flex;\n gap: var(--lit-devtools-space-4);\n flex-wrap: wrap;\n }\n .flag {\n padding: 1px var(--lit-devtools-space-4);\n border-radius: var(--lit-devtools-radius-xs);\n background: var(--lit-devtools-surface-elevated);\n color: var(--lit-devtools-text-secondary);\n font-size: var(--lit-devtools-text-2xs);\n }\n .flag.on {\n background: var(--lit-devtools-accent-soft);\n color: var(--lit-devtools-accent);\n }\n .placeholder {\n color: var(--lit-devtools-text-muted);\n padding: var(--lit-devtools-space-8) 0;\n text-align: center;\n }\n `,\n ];\n\n @state() private _roots: InspectorTreeNode[] = [];\n @state() private _selectedId: number | null = null;\n @state() private _details: InspectorDetails | null = null;\n /** True when the selected element is no longer in the page (removed / GC'd). */\n @state() private _gone = false;\n @state() private _expanded = new Set<number>();\n @state() private _picking = false;\n /** Opt-in live tree (MutationObserver in the page); persisted, default off. */\n @state() private _live = false;\n\n private _es: EventSource | null = null;\n\n override connectedCallback() {\n super.connectedCallback();\n this._live = localStorage.getItem(LIVE_LS_KEY) === 'true';\n this._es = new EventSource('/__lit-devtools-events');\n this._es.addEventListener(INSPECT_SSE_EVENT, this._onMessage);\n // Request only once the stream is open — a command sent before we're\n // subscribed would have its reply broadcast before we could receive it.\n this._es.addEventListener('open', this._onOpen);\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this._es?.removeEventListener(INSPECT_SSE_EVENT, this._onMessage);\n this._es?.removeEventListener('open', this._onOpen);\n this._es?.close();\n this._es = null;\n this._post({type: 'watch', id: null});\n if (this._live) this._post({type: 'observe', enabled: false});\n }\n\n /** Refresh the tree (and re-arm watch / live mode) once the SSE connects. */\n private _onOpen = (): void => {\n this._post({type: 'tree'});\n if (this._selectedId !== null) {\n this._post({type: 'watch', id: this._selectedId});\n }\n if (this._live) this._post({type: 'observe', enabled: true});\n };\n\n // ---------------------------------------------------------------------------\n // Transport\n // ---------------------------------------------------------------------------\n\n private _post(cmd: InspectorCommand): void {\n fetch(INSPECT_PATH, {\n method: 'POST',\n headers: {'Content-Type': 'application/json'},\n body: JSON.stringify(cmd),\n }).catch((err) => {\n console.warn('[lit-devtools] inspector POST failed', err);\n });\n }\n\n private _onMessage = (e: Event): void => {\n let msg: InspectorMessage;\n try {\n msg = JSON.parse((e as MessageEvent<string>).data) as InspectorMessage;\n } catch {\n return;\n }\n switch (msg.type) {\n case 'ready':\n // Runtime (re)connected — refresh the tree and re-arm any selection.\n this._post({type: 'tree'});\n if (this._selectedId !== null) {\n this._post({type: 'watch', id: this._selectedId});\n }\n break;\n case 'tree':\n this._roots = msg.roots;\n // Re-reveal the selection against the fresh tree: a just-picked node may\n // not have existed in the previous _roots, so the reveal in _select()\n // found no ancestors to expand and the node stayed hidden.\n if (this._selectedId !== null) {\n this._revealAncestors(this._selectedId);\n }\n break;\n case 'details':\n if (msg.details.id === this._selectedId) {\n this._details = msg.details;\n this._gone = false;\n }\n break;\n case 'gone':\n if (msg.id === this._selectedId) {\n this._details = null;\n this._gone = true;\n }\n break;\n case 'pick':\n this._picking = false;\n this._select(msg.id);\n // Bring this tab to the front so the pick is visible.\n this.dispatchEvent(\n new CustomEvent('inspector-activate', {bubbles: true, composed: true})\n );\n break;\n }\n };\n\n // ---------------------------------------------------------------------------\n // Selection / expansion\n // ---------------------------------------------------------------------------\n\n /**\n * Select an element by id from outside (e.g. a timeline event's \"inspect\"\n * link). Same as a tree click; the host is responsible for switching tabs.\n */\n selectById(id: number): void {\n this._select(id);\n }\n\n private _select(id: number): void {\n if (this._selectedId === id) return;\n if (this._selectedId !== null) {\n this._post({type: 'watch', id: null});\n }\n this._selectedId = id;\n this._details = null;\n this._gone = false;\n this._revealAncestors(id);\n this._post({type: 'tree'}); // refresh in case the picked node is new\n this._post({type: 'details', id});\n this._post({type: 'watch', id});\n }\n\n /** Expand every ancestor of `id` so the selected node is visible. */\n private _revealAncestors(id: number): void {\n const path = findAncestors(this._roots, id);\n if (path === null) return;\n const next = new Set(this._expanded);\n for (const ancestorId of path) next.add(ancestorId);\n this._expanded = next;\n }\n\n private _toggleExpand(id: number): void {\n const next = new Set(this._expanded);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n this._expanded = next;\n }\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n private _refresh(): void {\n this._post({type: 'tree'});\n if (this._selectedId !== null) {\n this._post({type: 'details', id: this._selectedId});\n }\n }\n\n private _togglePick(): void {\n this._picking = !this._picking;\n this._post({type: 'pick'});\n }\n\n private _toggleLive(): void {\n this._live = !this._live;\n try {\n localStorage.setItem(LIVE_LS_KEY, String(this._live));\n } catch {\n // ignore (private/storage unavailable)\n }\n this._post({type: 'observe', enabled: this._live});\n // Leaving live mode, pull one fresh tree so it doesn't go stale silently.\n if (!this._live) this._post({type: 'tree'});\n }\n\n private _highlight(id: number | null): void {\n this._post({type: 'highlight', id});\n }\n\n private _openSource(): void {\n const src = this._details?.source;\n if (src === undefined) return;\n const params = new URLSearchParams({\n file: src.file,\n line: String(src.line),\n });\n fetch(`/__lit-open-in-editor?${params.toString()}`)\n .then(async (res) => {\n if (!res.ok) {\n console.warn(\n `[lit-devtools] open-in-editor failed (${res.status})`,\n await res.text()\n );\n }\n })\n .catch((err) => {\n console.warn('[lit-devtools] open-in-editor failed', err);\n });\n }\n\n // ---------------------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------------------\n\n private _renderNode(node: InspectorTreeNode, depth: number): TemplateResult {\n const hasChildren = node.children.length > 0;\n const expanded = this._expanded.has(node.id);\n return html`\n <div\n class=\"row ${node.id === this._selectedId ? 'selected' : ''}\"\n style=\"padding-left:${8 + depth * 14}px\"\n @click=${() => this._select(node.id)}\n @mouseenter=${() => this._highlight(node.id)}\n >\n <span\n class=\"twisty ${hasChildren ? '' : 'leaf'}\"\n @click=${(e: Event) => {\n e.stopPropagation();\n this._toggleExpand(node.id);\n }}\n >${hasChildren ? (expanded ? '▾' : '▸') : '•'}</span\n >\n <span class=\"tag\"\n ><span class=\"punct\">&lt;</span>${node.tagName}<span class=\"punct\"\n >&gt;</span\n ></span\n >\n </div>\n ${hasChildren && expanded\n ? node.children.map((c) => this._renderNode(c, depth + 1))\n : nothing}\n `;\n }\n\n private _renderPropTable(\n props: InspectorDetails['properties']\n ): TemplateResult {\n return html`\n <table>\n ${props.map(\n (p) => html`\n <tr>\n <td class=\"name\">\n ${p.name}${p.reflects\n ? html`<span class=\"badge\" title=\"reflects to attribute\"\n >${typeof p.attribute === 'string'\n ? p.attribute\n : 'attr'}</span\n >`\n : nothing}\n </td>\n <td class=\"val\">${p.value}</td>\n </tr>\n `\n )}\n </table>\n `;\n }\n\n private _renderDetails(): TemplateResult {\n const d = this._details;\n if (d === null) {\n let message: string;\n if (this._gone) {\n message = 'This element is no longer in the page.';\n } else if (this._selectedId === null) {\n message = 'Select a component to inspect.';\n } else {\n message = 'Loading…';\n }\n return html`<div class=\"placeholder\">${message}</div>`;\n }\n const props = d.properties.filter((p) => !p.state);\n const stateProps = d.properties.filter((p) => p.state);\n return html`\n <h2>&lt;${d.tagName}&gt;</h2>\n ${d.source !== undefined\n ? html`<button class=\"src\" @click=${this._openSource}>\n ${d.source.file}:${d.source.line}\n </button>`\n : nothing}\n <section>\n <div class=\"flags\">\n <span class=\"flag ${d.flags.hasUpdated ? 'on' : ''}\">updated</span>\n <span class=\"flag ${d.flags.isUpdatePending ? 'on' : ''}\"\n >update pending</span\n >\n <span class=\"flag ${d.flags.hasShadowRoot ? 'on' : ''}\"\n >shadow root</span\n >\n </div>\n </section>\n ${props.length > 0\n ? html`<section>\n <div class=\"label\">Properties</div>\n ${this._renderPropTable(props)}\n </section>`\n : nothing}\n ${stateProps.length > 0\n ? html`<section>\n <div class=\"label\">State</div>\n ${this._renderPropTable(stateProps)}\n </section>`\n : nothing}\n ${d.attributes.length > 0\n ? html`<section>\n <div class=\"label\">Attributes</div>\n <table>\n ${d.attributes.map(\n (a) =>\n html`<tr>\n <td class=\"name\">${a.name}</td>\n <td class=\"val\">${a.value}</td>\n </tr>`\n )}\n </table>\n </section>`\n : nothing}\n `;\n }\n\n override render() {\n return html`\n <div class=\"toolbar\">\n <button\n class=\"pick ${this._picking ? 'active' : ''}\"\n title=\"Pick an element on the page (Meta+Shift+E)\"\n @click=${this._togglePick}\n >\n ⌖ Pick\n </button>\n <span class=\"spacer\"></span>\n <button\n class=\"live ${this._live ? 'active' : ''}\"\n title=\"Update the tree automatically as the page changes\"\n @click=${this._toggleLive}\n >\n ${this._live ? '● Live' : '○ Live'}\n </button>\n <button @click=${this._refresh} ?disabled=${this._live}>Refresh</button>\n </div>\n <div class=\"body\">\n <div class=\"tree\" @mouseleave=${() => this._highlight(null)}>\n ${this._roots.length === 0\n ? html`<div class=\"empty\">\n No Lit components found on the page.\n </div>`\n : this._roots.map((n) => this._renderNode(n, 0))}\n </div>\n <div class=\"details\">${this._renderDetails()}</div>\n </div>\n `;\n }\n}\n\n/**\n * Returns the ids of every ancestor of `id` (nearest last), or `null` if `id`\n * isn't in the tree. The target id itself is not included.\n */\nconst findAncestors = (\n nodes: InspectorTreeNode[],\n id: number\n): number[] | null => {\n const trail: number[] = [];\n const walk = (list: InspectorTreeNode[]): boolean => {\n for (const node of list) {\n if (node.id === id) return true;\n trail.push(node.id);\n if (walk(node.children)) return true;\n trail.pop();\n }\n return false;\n };\n return walk(nodes) ? [...trail] : null;\n};\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'components-view': ComponentsView;\n }\n}\n"]}