@oddsquad/vite-plugin-lit 0.4.0 → 0.6.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 (100) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/README.md +16 -5
  3. package/bin.mjs +16 -12
  4. package/dist/client/assets/{browser-agent-rpc-BXhoSh1z-CdtPhBL-.js → browser-agent-rpc-BXhoSh1z-DXAVFObe.js} +2 -2
  5. package/dist/client/assets/{browser-agent-rpc-BXhoSh1z-CdtPhBL-.js.map → browser-agent-rpc-BXhoSh1z-DXAVFObe.js.map} +1 -1
  6. package/dist/client/assets/{index-DVe6M4HV.js → index-DVr5EnyB.js} +1859 -751
  7. package/dist/client/assets/index-DVr5EnyB.js.map +1 -0
  8. package/dist/client/index.html +11 -1
  9. package/lib/devframe/definition.d.ts +7 -0
  10. package/lib/devframe/definition.d.ts.map +1 -1
  11. package/lib/devframe/definition.js +56 -11
  12. package/lib/devframe/definition.js.map +1 -1
  13. package/lib/devframe/launch-editor.d.ts +20 -0
  14. package/lib/devframe/launch-editor.d.ts.map +1 -0
  15. package/lib/devframe/launch-editor.js +40 -0
  16. package/lib/devframe/launch-editor.js.map +1 -0
  17. package/lib/devframe/protocol.d.ts +31 -4
  18. package/lib/devframe/protocol.d.ts.map +1 -1
  19. package/lib/devframe/protocol.js +21 -3
  20. package/lib/devframe/protocol.js.map +1 -1
  21. package/lib/devframe/rpc-source.d.ts +44 -0
  22. package/lib/devframe/rpc-source.d.ts.map +1 -0
  23. package/lib/devframe/rpc-source.js +150 -0
  24. package/lib/devframe/rpc-source.js.map +1 -0
  25. package/lib/devframe/source.d.ts +12 -0
  26. package/lib/devframe/source.d.ts.map +1 -1
  27. package/lib/devframe/source.js +12 -0
  28. package/lib/devframe/source.js.map +1 -1
  29. package/lib/devframe/vite.d.ts +2 -0
  30. package/lib/devframe/vite.d.ts.map +1 -1
  31. package/lib/devframe/vite.js +3 -9
  32. package/lib/devframe/vite.js.map +1 -1
  33. package/lib/options.d.ts +6 -1
  34. package/lib/options.d.ts.map +1 -1
  35. package/lib/options.js +65 -18
  36. package/lib/options.js.map +1 -1
  37. package/lib/override-baselines.d.ts +17 -0
  38. package/lib/override-baselines.d.ts.map +1 -0
  39. package/lib/override-baselines.js +25 -0
  40. package/lib/override-baselines.js.map +1 -0
  41. package/lib/plugin.d.ts.map +1 -1
  42. package/lib/plugin.js +8 -0
  43. package/lib/plugin.js.map +1 -1
  44. package/lib/plugins/open-in-editor.d.ts.map +1 -1
  45. package/lib/plugins/open-in-editor.js +6 -1
  46. package/lib/plugins/open-in-editor.js.map +1 -1
  47. package/lib/runtime/indicator.js.map +1 -1
  48. package/lib/runtime/inspector/install.js +4 -2
  49. package/lib/runtime/inspector/install.js.map +1 -1
  50. package/lib/runtime/inspector/serialize.d.ts.map +1 -1
  51. package/lib/runtime/inspector/serialize.js +20 -0
  52. package/lib/runtime/inspector/serialize.js.map +1 -1
  53. package/lib/runtime/overrides.d.ts +4 -10
  54. package/lib/runtime/overrides.d.ts.map +1 -1
  55. package/lib/runtime/overrides.js +5 -3
  56. package/lib/runtime/overrides.js.map +1 -1
  57. package/lib/runtime/page-channel.d.ts +52 -0
  58. package/lib/runtime/page-channel.d.ts.map +1 -0
  59. package/lib/runtime/page-channel.js +67 -0
  60. package/lib/runtime/page-channel.js.map +1 -0
  61. package/lib/runtime/patch.d.ts.map +1 -1
  62. package/lib/runtime/patch.js +2 -1
  63. package/lib/runtime/patch.js.map +1 -1
  64. package/lib/runtime/rpc-transport.d.ts +46 -0
  65. package/lib/runtime/rpc-transport.d.ts.map +1 -0
  66. package/lib/runtime/rpc-transport.js +82 -0
  67. package/lib/runtime/rpc-transport.js.map +1 -0
  68. package/lib/runtime/source-overlay/overlay-element.d.ts.map +1 -1
  69. package/lib/runtime/source-overlay/overlay-element.js +13 -3
  70. package/lib/runtime/source-overlay/overlay-element.js.map +1 -1
  71. package/lib/runtime/timeline/chrome-tracks.d.ts +22 -0
  72. package/lib/runtime/timeline/chrome-tracks.d.ts.map +1 -0
  73. package/lib/runtime/timeline/chrome-tracks.js +74 -0
  74. package/lib/runtime/timeline/chrome-tracks.js.map +1 -0
  75. package/lib/runtime/timeline/clock.d.ts +6 -0
  76. package/lib/runtime/timeline/clock.d.ts.map +1 -1
  77. package/lib/runtime/timeline/clock.js +6 -0
  78. package/lib/runtime/timeline/clock.js.map +1 -1
  79. package/lib/runtime/timeline/install.js +42 -13
  80. package/lib/runtime/timeline/install.js.map +1 -1
  81. package/lib/runtime/timeline/public-api.d.ts.map +1 -1
  82. package/lib/runtime/timeline/public-api.js +11 -3
  83. package/lib/runtime/timeline/public-api.js.map +1 -1
  84. package/lib/runtime/timeline/transport.d.ts +6 -9
  85. package/lib/runtime/timeline/transport.d.ts.map +1 -1
  86. package/lib/runtime/timeline/transport.js.map +1 -1
  87. package/lib/timeline/filter.d.ts +38 -0
  88. package/lib/timeline/filter.d.ts.map +1 -0
  89. package/lib/timeline/filter.js +44 -0
  90. package/lib/timeline/filter.js.map +1 -0
  91. package/lib/timeline/tracks.d.ts +113 -0
  92. package/lib/timeline/tracks.d.ts.map +1 -0
  93. package/lib/timeline/tracks.js +168 -0
  94. package/lib/timeline/tracks.js.map +1 -0
  95. package/package.json +6 -1
  96. package/types/timeline.d.ts +44 -0
  97. package/types/timeline.d.ts.map +1 -1
  98. package/types/timeline.js +2 -0
  99. package/types/timeline.js.map +1 -1
  100. package/dist/client/assets/index-DVe6M4HV.js.map +0 -1
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ */
6
+ import type { PageTransport } from './page-channel.js';
7
+ /** The slice of a scoped devframe client the transport uses. */
8
+ export interface PageRpc {
9
+ callEvent(method: string, ...args: unknown[]): void;
10
+ register(fn: {
11
+ name: string;
12
+ type: 'event';
13
+ handler: (...args: any[]) => void;
14
+ }): void;
15
+ }
16
+ /**
17
+ * A {@link PageTransport} over a devframe RPC client: `send` becomes a
18
+ * `page-send` event, and `page-receive` events fan out to the listeners
19
+ * registered with `on`.
20
+ */
21
+ export declare const createRpcTransport: (rpc: PageRpc) => PageTransport;
22
+ export interface ConnectOptions {
23
+ /**
24
+ * A bearer token the server already trusts. Without one the client falls
25
+ * back to devframe's own flow (a stored token, a magic-link code in the URL,
26
+ * or a prompt for the one-time code the server prints) unless the server was
27
+ * started with `--no-auth`.
28
+ */
29
+ authToken?: string;
30
+ }
31
+ /**
32
+ * Point this page's runtime at a standalone `lit-devtools dev` server.
33
+ *
34
+ * Resolves once the connection is trusted, after which the tree, inspector
35
+ * and timeline traffic that used to go to this page's own Vite server goes to
36
+ * `url` instead (the runtime announces itself again so the server can replay
37
+ * recording state). Returns a function that disconnects and hands the channel
38
+ * back to the carrier it replaced.
39
+ *
40
+ * The page's origin must be allowed to reach `url`; this does not set up
41
+ * cross-origin access.
42
+ *
43
+ * @param url Origin of the dev server, e.g. `http://localhost:5180/`.
44
+ */
45
+ export declare const connectToDevServer: (url: string, options?: ConnectOptions) => Promise<() => void>;
46
+ //# sourceMappingURL=rpc-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc-transport.d.ts","sourceRoot":"","sources":["../../src/lib/runtime/rpc-transport.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAmBH,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,mBAAmB,CAAC;AAErD,gEAAgE;AAChE,MAAM,WAAW,OAAO;IACtB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACpD,QAAQ,CAAC,EAAE,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,OAAO,CAAC;QACd,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;KACnC,GAAG,IAAI,CAAC;CACV;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,QAAS,OAAO,KAAG,aA4BjD,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,kBAAkB,QACxB,MAAM,YACF,cAAc,KACtB,OAAO,CAAC,MAAM,IAAI,CAepB,CAAC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ */
6
+ /**
7
+ * Carries the page channel over devframe RPC to a standalone
8
+ * `lit-devtools dev` server, so a page that is not served by a DevTools-enabled
9
+ * Vite dev server can still feed the panel. The server half is
10
+ * `devframe/rpc-source.ts`.
11
+ *
12
+ * Opt-in and explicit: nothing connects until {@link connectToDevServer} is
13
+ * called, and `devframe/client` is only imported then, so a page that never
14
+ * asks pays nothing.
15
+ */
16
+ import {
17
+ LIT_DEVFRAME_ID,
18
+ RPC_PAGE_RECEIVE,
19
+ RPC_PAGE_SEND,
20
+ } from '../devframe/protocol.js';
21
+ import {pageChannel} from './page-channel.js';
22
+ /**
23
+ * A {@link PageTransport} over a devframe RPC client: `send` becomes a
24
+ * `page-send` event, and `page-receive` events fan out to the listeners
25
+ * registered with `on`.
26
+ */
27
+ export const createRpcTransport = (rpc) => {
28
+ const listeners = new Map();
29
+ rpc.register({
30
+ name: RPC_PAGE_RECEIVE,
31
+ type: 'event',
32
+ handler: (channel, data) => {
33
+ for (const listener of listeners.get(channel) ?? []) {
34
+ try {
35
+ listener(data);
36
+ } catch (error) {
37
+ console.error(`[lit-devtools] listener for ${channel} threw`, error);
38
+ }
39
+ }
40
+ },
41
+ });
42
+ return {
43
+ send(channel, data) {
44
+ rpc.callEvent(RPC_PAGE_SEND, channel, data);
45
+ },
46
+ on(channel, handler) {
47
+ let set = listeners.get(channel);
48
+ if (set === undefined) listeners.set(channel, (set = new Set()));
49
+ set.add(handler);
50
+ return () => void set.delete(handler);
51
+ },
52
+ };
53
+ };
54
+ /**
55
+ * Point this page's runtime at a standalone `lit-devtools dev` server.
56
+ *
57
+ * Resolves once the connection is trusted, after which the tree, inspector
58
+ * and timeline traffic that used to go to this page's own Vite server goes to
59
+ * `url` instead (the runtime announces itself again so the server can replay
60
+ * recording state). Returns a function that disconnects and hands the channel
61
+ * back to the carrier it replaced.
62
+ *
63
+ * The page's origin must be allowed to reach `url`; this does not set up
64
+ * cross-origin access.
65
+ *
66
+ * @param url Origin of the dev server, e.g. `http://localhost:5180/`.
67
+ */
68
+ export const connectToDevServer = async (url, options = {}) => {
69
+ const {getDevframeRpcClient} = await import('devframe/client');
70
+ const client = await getDevframeRpcClient({
71
+ baseURL: url,
72
+ authToken: options.authToken,
73
+ });
74
+ await client.ensureTrusted();
75
+ const previous = pageChannel.transport;
76
+ pageChannel.attach(createRpcTransport(client.scope(LIT_DEVFRAME_ID).rpc));
77
+ return () => {
78
+ client.close?.();
79
+ if (previous !== undefined) pageChannel.attach(previous);
80
+ };
81
+ };
82
+ //# sourceMappingURL=rpc-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc-transport.js","sourceRoot":"","sources":["../../src/lib/runtime/rpc-transport.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;GASG;AAEH,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,aAAa,GACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAC,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAa9C;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,GAAY,EAAiB,EAAE;IAChE,MAAM,SAAS,GAAG,IAAI,GAAG,EAAwC,CAAC;IAElE,GAAG,CAAC,QAAQ,CAAC;QACX,IAAI,EAAE,gBAAgB;QACtB,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,CAAC,OAAe,EAAE,IAAc,EAAE,EAAE;YAC3C,KAAK,MAAM,QAAQ,IAAI,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;gBACpD,IAAI,CAAC;oBACH,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACjB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,OAAO,CAAC,KAAK,CAAC,+BAA+B,OAAO,QAAQ,EAAE,KAAK,CAAC,CAAC;gBACvE,CAAC;YACH,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IAEH,OAAO;QACL,IAAI,CAAC,OAAO,EAAE,IAAI;YAChB,GAAG,CAAC,SAAS,CAAC,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAC9C,CAAC;QACD,EAAE,CAAC,OAAO,EAAE,OAAO;YACjB,IAAI,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACjC,IAAI,GAAG,KAAK,SAAS;gBAAE,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC;YACjE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACjB,OAAO,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACxC,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AAYF;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,EACrC,GAAW,EACX,OAAO,GAAmB,EAAE,EACP,EAAE;IACvB,MAAM,EAAC,oBAAoB,EAAC,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAC/D,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC;QACxC,OAAO,EAAE,GAAG;QACZ,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC,CAAC;IACH,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC;IAE7B,MAAM,QAAQ,GAAG,WAAW,CAAC,SAAS,CAAC;IACvC,WAAW,CAAC,MAAM,CAAC,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAE1E,OAAO,GAAG,EAAE;QACV,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;QACjB,IAAI,QAAQ,KAAK,SAAS;YAAE,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC3D,CAAC,CAAC;AACJ,CAAC,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * Carries the page channel over devframe RPC to a standalone\n * `lit-devtools dev` server, so a page that is not served by a DevTools-enabled\n * Vite dev server can still feed the panel. The server half is\n * `devframe/rpc-source.ts`.\n *\n * Opt-in and explicit: nothing connects until {@link connectToDevServer} is\n * called, and `devframe/client` is only imported then, so a page that never\n * asks pays nothing.\n */\n\nimport {\n LIT_DEVFRAME_ID,\n RPC_PAGE_RECEIVE,\n RPC_PAGE_SEND,\n} from '../devframe/protocol.js';\nimport {pageChannel} from './page-channel.js';\nimport type {PageTransport} from './page-channel.js';\n\n/** The slice of a scoped devframe client the transport uses. */\nexport interface PageRpc {\n callEvent(method: string, ...args: unknown[]): void;\n register(fn: {\n name: string;\n type: 'event';\n handler: (...args: any[]) => void;\n }): void;\n}\n\n/**\n * A {@link PageTransport} over a devframe RPC client: `send` becomes a\n * `page-send` event, and `page-receive` events fan out to the listeners\n * registered with `on`.\n */\nexport const createRpcTransport = (rpc: PageRpc): PageTransport => {\n const listeners = new Map<string, Set<(data: unknown) => void>>();\n\n rpc.register({\n name: RPC_PAGE_RECEIVE,\n type: 'event',\n handler: (channel: string, data?: unknown) => {\n for (const listener of listeners.get(channel) ?? []) {\n try {\n listener(data);\n } catch (error) {\n console.error(`[lit-devtools] listener for ${channel} threw`, error);\n }\n }\n },\n });\n\n return {\n send(channel, data) {\n rpc.callEvent(RPC_PAGE_SEND, channel, data);\n },\n on(channel, handler) {\n let set = listeners.get(channel);\n if (set === undefined) listeners.set(channel, (set = new Set()));\n set.add(handler);\n return () => void set.delete(handler);\n },\n };\n};\n\nexport interface ConnectOptions {\n /**\n * A bearer token the server already trusts. Without one the client falls\n * back to devframe's own flow (a stored token, a magic-link code in the URL,\n * or a prompt for the one-time code the server prints) unless the server was\n * started with `--no-auth`.\n */\n authToken?: string;\n}\n\n/**\n * Point this page's runtime at a standalone `lit-devtools dev` server.\n *\n * Resolves once the connection is trusted, after which the tree, inspector\n * and timeline traffic that used to go to this page's own Vite server goes to\n * `url` instead (the runtime announces itself again so the server can replay\n * recording state). Returns a function that disconnects and hands the channel\n * back to the carrier it replaced.\n *\n * The page's origin must be allowed to reach `url`; this does not set up\n * cross-origin access.\n *\n * @param url Origin of the dev server, e.g. `http://localhost:5180/`.\n */\nexport const connectToDevServer = async (\n url: string,\n options: ConnectOptions = {}\n): Promise<() => void> => {\n const {getDevframeRpcClient} = await import('devframe/client');\n const client = await getDevframeRpcClient({\n baseURL: url,\n authToken: options.authToken,\n });\n await client.ensureTrusted();\n\n const previous = pageChannel.transport;\n pageChannel.attach(createRpcTransport(client.scope(LIT_DEVFRAME_ID).rpc));\n\n return () => {\n client.close?.();\n if (previous !== undefined) pageChannel.attach(previous);\n };\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"overlay-element.d.ts","sourceRoot":"","sources":["../../../src/lib/runtime/source-overlay/overlay-element.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAC,WAAW,EAAE,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAmB9D,MAAM,WAAW,wBAAwB;IACvC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,KAAK,OAAO,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IACvC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AA4YD,eAAO,MAAM,iBAAiB,iBACf,wBAAwB,SAMtC,CAAC;AAEF,eAAO,MAAM,mBAAmB,YAK/B,CAAC"}
1
+ {"version":3,"file":"overlay-element.d.ts","sourceRoot":"","sources":["../../../src/lib/runtime/source-overlay/overlay-element.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAC,WAAW,EAAE,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAoB9D,MAAM,WAAW,wBAAwB;IACvC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,KAAK,OAAO,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IACvC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAqZD,eAAO,MAAM,iBAAiB,iBACf,wBAAwB,SAMtC,CAAC;AAEF,eAAO,MAAM,mBAAmB,YAK/B,CAAC"}
@@ -13,6 +13,7 @@ import {buildSpotlightClipPath} from './mask-path.js';
13
13
  import {OVERLAY_HTML} from './template.js';
14
14
  import {observeEdgeInsets} from '../edge-panel.js';
15
15
  import {subscribeOverride} from '../overrides.js';
16
+ import {pageChannel} from '../page-channel.js';
16
17
  import {injectTokens} from '../../tokens.js';
17
18
  import {idOf} from '../timeline/identity.js';
18
19
  import {
@@ -73,7 +74,8 @@ class LitSourceOverlay extends HTMLElement {
73
74
  document.addEventListener('mousemove', this.#onTrackMouse, true);
74
75
  document.addEventListener('keydown', this.#onKeyDown, true);
75
76
  const hot = import.meta.hot;
76
- this.#hot = hot;
77
+ if (hot !== undefined) pageChannel.useViteHot(hot);
78
+ this.#hot = hot === undefined ? undefined : pageChannel;
77
79
  if (hot !== undefined && this.#hotOff === undefined) {
78
80
  // Removed again in disconnectedCallback, so a re-attached overlay
79
81
  // doesn't stack duplicates and a detached one stops reacting.
@@ -81,12 +83,15 @@ class LitSourceOverlay extends HTMLElement {
81
83
  ['vite:beforeFullReload', () => this.deactivate()],
82
84
  ['vite:ws:disconnect', () => (this.#connected = false)],
83
85
  ['vite:ws:connect', () => (this.#connected = true)],
84
- // Toggle from the Vite DevTools command/shortcut (handler runs server-side).
85
- [INSPECT_OVERLAY_TOGGLE_CHANNEL, () => this.toggle()],
86
86
  ];
87
87
  for (const [event, cb] of handlers) hot.on(event, cb);
88
+ // Toggle from the Vite DevTools command/shortcut (handler runs server-side).
89
+ const offToggle = pageChannel.on(INSPECT_OVERLAY_TOGGLE_CHANNEL, () =>
90
+ this.toggle()
91
+ );
88
92
  this.#hotOff = () => {
89
93
  for (const [event, cb] of handlers) hot.off(event, cb);
94
+ offToggle();
90
95
  };
91
96
  }
92
97
  // Keep the (bottom-fixed) tooltip clear of the Vite DevTools edge panel.
@@ -177,6 +182,11 @@ class LitSourceOverlay extends HTMLElement {
177
182
  file: path,
178
183
  line: String(lineNumber),
179
184
  });
185
+ // Name the editor the developer picked (config, env or the panel's
186
+ // override) so the server opens that one; custom editors and an unset
187
+ // choice send nothing and the server auto-detects.
188
+ const {editor} = this.#options;
189
+ if (typeof editor === 'string') params.set('editor', editor);
180
190
  const res = await fetch(`${endpoint}?${params.toString()}`);
181
191
  if (res.ok) return;
182
192
  } catch {
@@ -1 +1 @@
1
- {"version":3,"file":"overlay-element.js","sourceRoot":"","sources":["../../../src/lib/runtime/source-overlay/overlay-element.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nimport type {ElementInfo, EditorConfig} from '../../types.js';\nimport {BUILTIN_EDITORS, resolveEditor} from './editors.js';\nimport {\n defaultResolver,\n findSourceAtPoint,\n findSourceHost,\n type ElementResolver,\n} from './source-host.js';\nimport {buildSpotlightClipPath} from './mask-path.js';\nimport {OVERLAY_HTML} from './template.js';\nimport {observeEdgeInsets} from '../edge-panel.js';\nimport {subscribeOverride} from '../overrides.js';\nimport {injectTokens} from '../../tokens.js';\nimport {idOf} from '../timeline/identity.js';\nimport {\n INSPECT_OVERLAY_TOGGLE_CHANNEL,\n INSPECT_DATA_CHANNEL,\n} from '../../../types/inspector.js';\n\nexport interface SourceOverlayInitOptions {\n key?: string;\n editor?: EditorConfig | string;\n workspaceRoot?: string;\n throttleMs?: number;\n exclude?: (el: Element) => boolean;\n onSelect?: (info: ElementInfo) => void;\n openInEditorPath?: string;\n}\n\nclass LitSourceOverlay extends HTMLElement {\n #active = false;\n #hot: {send: (event: string, data: unknown) => void} | undefined;\n #options: SourceOverlayInitOptions = {};\n #editor: EditorConfig = BUILTIN_EDITORS.vscode;\n #resolver: ElementResolver = defaultResolver;\n #dialog: HTMLDialogElement;\n #mask: HTMLElement;\n #highlight: HTMLElement;\n #tooltip: HTMLElement;\n #tag: HTMLElement;\n #path: HTMLElement;\n #info: ElementInfo | null = null;\n #targetEl: Element | null = null;\n #throttleTimer: ReturnType<typeof setTimeout> | undefined;\n #scrollTimer: ReturnType<typeof setTimeout> | undefined;\n #resizeObserver: ResizeObserver | undefined;\n #cursorStyle: HTMLStyleElement | null = null;\n // Whether the Vite HMR WebSocket is currently connected. Used to suppress the\n // editor-URL-scheme fallback once the dev server is gone — otherwise a failed\n // open-in-editor fetch would navigate the tab to `vscode://…`.\n #connected = true;\n #lastMouseX = 0;\n #lastMouseY = 0;\n #edgeDispose: (() => void) | undefined;\n #overrideSubscribed = false;\n #hotOff: (() => void) | undefined;\n\n constructor() {\n super();\n const root = this.attachShadow({mode: 'closed'});\n root.innerHTML = OVERLAY_HTML;\n this.#dialog = root.getElementById('overlay') as HTMLDialogElement;\n this.#mask = root.getElementById('mask')!;\n this.#highlight = root.getElementById('highlight')!;\n this.#tooltip = root.getElementById('tooltip')!;\n this.#tag = root.getElementById('tag')!;\n this.#path = root.getElementById('path')!;\n root.getElementById('open')!.addEventListener('click', (e) => {\n e.stopPropagation();\n if (this.#info !== null) this.#select(this.#info, true);\n });\n root.getElementById('copy')!.addEventListener('click', (e) => {\n e.stopPropagation();\n if (this.#info === null) return;\n const text = `${this.#normalizePath(this.#info.source.filePath)}:${this.#info.source.lineNumber}`;\n void navigator.clipboard?.writeText(text);\n });\n this.#dialog.addEventListener('cancel', (e) => e.preventDefault());\n }\n\n connectedCallback() {\n injectTokens();\n document.addEventListener('mousemove', this.#onTrackMouse, true);\n document.addEventListener('keydown', this.#onKeyDown, true);\n const hot = (\n import.meta as {\n hot?: {\n on: (event: string, cb: (data?: unknown) => void) => void;\n off: (event: string, cb: (data?: unknown) => void) => void;\n send: (event: string, data: unknown) => void;\n };\n }\n ).hot;\n this.#hot = hot;\n if (hot !== undefined && this.#hotOff === undefined) {\n // Removed again in disconnectedCallback, so a re-attached overlay\n // doesn't stack duplicates and a detached one stops reacting.\n const handlers: Array<[string, (data?: unknown) => void]> = [\n ['vite:beforeFullReload', () => this.deactivate()],\n ['vite:ws:disconnect', () => (this.#connected = false)],\n ['vite:ws:connect', () => (this.#connected = true)],\n // Toggle from the Vite DevTools command/shortcut (handler runs server-side).\n [INSPECT_OVERLAY_TOGGLE_CHANNEL, () => this.toggle()],\n ];\n for (const [event, cb] of handlers) hot.on(event, cb);\n this.#hotOff = () => {\n for (const [event, cb] of handlers) hot.off(event, cb);\n };\n }\n // Keep the (bottom-fixed) tooltip clear of the Vite DevTools edge panel.\n this.#edgeDispose = observeEdgeInsets((insets) => {\n this.style.setProperty('--edge-bottom', `${insets.bottom}px`);\n });\n // Apply the panel's editor override live (and on load). Merge so other\n // configured options (key, throttle, …) survive.\n if (!this.#overrideSubscribed) {\n this.#overrideSubscribed = true;\n subscribeOverride(hot, (o) => {\n if (o.sourceOverlayEditor !== undefined) {\n this.#options = {...this.#options, editor: o.sourceOverlayEditor};\n this.#editor = resolveEditor(o.sourceOverlayEditor);\n }\n });\n }\n }\n\n disconnectedCallback() {\n document.removeEventListener('mousemove', this.#onTrackMouse, true);\n document.removeEventListener('keydown', this.#onKeyDown, true);\n this.deactivate();\n this.#edgeDispose?.();\n this.#edgeDispose = undefined;\n this.#hotOff?.();\n this.#hotOff = undefined;\n }\n\n configure(options: SourceOverlayInitOptions) {\n this.#options = options;\n this.#editor = resolveEditor(options.editor);\n }\n\n activate() {\n if (this.#active) return;\n this.#active = true;\n this.#dialog.showModal();\n this.#mask.style.background = 'rgba(0,0,0,0.35)';\n // The overlay is pointer-events:none, so the cursor reflects the hovered\n // page element. Force a crosshair while inspecting. The closed shadow DOM\n // tooltip is unaffected, so its buttons keep their own pointer cursor.\n if (this.#cursorStyle === null) {\n this.#cursorStyle = document.createElement('style');\n this.#cursorStyle.textContent = '*{cursor:crosshair !important}';\n }\n document.head.append(this.#cursorStyle);\n document.addEventListener('mousemove', this.#onMouseMove, true);\n document.addEventListener('click', this.#onClick, true);\n window.addEventListener('scroll', this.#onScrollOrResize, {passive: true});\n window.addEventListener('resize', this.#onScrollOrResize, {passive: true});\n void this.#resolveAt(this.#lastMouseX, this.#lastMouseY);\n }\n\n deactivate() {\n if (!this.#active) return;\n this.#active = false;\n this.#dialog.close();\n this.#mask.style.background = 'rgba(0,0,0,0)';\n this.#cursorStyle?.remove();\n document.removeEventListener('mousemove', this.#onMouseMove, true);\n document.removeEventListener('click', this.#onClick, true);\n window.removeEventListener('scroll', this.#onScrollOrResize);\n window.removeEventListener('resize', this.#onScrollOrResize);\n if (this.#throttleTimer !== undefined) {\n clearTimeout(this.#throttleTimer);\n this.#throttleTimer = undefined;\n }\n if (this.#scrollTimer !== undefined) {\n clearTimeout(this.#scrollTimer);\n this.#scrollTimer = undefined;\n }\n this.#clearTarget();\n }\n\n toggle() {\n if (this.#active) this.deactivate();\n else this.activate();\n }\n\n #normalizePath(filePath: string): string {\n const root = this.#options.workspaceRoot;\n if (root !== undefined && filePath.startsWith(root)) {\n const rest = filePath.slice(root.length);\n return rest.startsWith('/') ? rest.slice(1) : rest;\n }\n return filePath;\n }\n\n async #openInEditor(filePath: string, lineNumber: number) {\n const path = this.#normalizePath(filePath);\n const endpoint = this.#options.openInEditorPath ?? '/__lit-open-in-editor';\n try {\n const params = new URLSearchParams({\n file: path,\n line: String(lineNumber),\n });\n const res = await fetch(`${endpoint}?${params.toString()}`);\n if (res.ok) return;\n } catch {\n // Fall back to editor URL schemes (e.g. StackBlitz previews).\n }\n // Skip the URL-scheme fallback when the dev server is gone: a fetch failure\n // there means \"server quit\", not \"no endpoint\", and navigating the tab to\n // `vscode://…` on shutdown is jarring and unwanted.\n if (!this.#connected) return;\n window.open(this.#editor.url(path, lineNumber), '_self');\n }\n\n #updateHighlightRect() {\n if (this.#targetEl === null) return;\n const rect = this.#targetEl.getBoundingClientRect();\n const raw = getComputedStyle(this)\n .getPropertyValue('--lit-devtools-radius')\n .trim();\n const r = parseFloat(raw) || 6;\n // The tinted box hugs the element's exact rect — that's the boundary being\n // picked; only the spotlight cutout gets the breathing room of `r`.\n this.#highlight.style.display = 'block';\n this.#highlight.style.left = `${rect.left}px`;\n this.#highlight.style.top = `${rect.top}px`;\n this.#highlight.style.width = `${rect.width}px`;\n this.#highlight.style.height = `${rect.height}px`;\n this.#mask.style.clipPath = buildSpotlightClipPath(\n rect.left - r,\n rect.top - r,\n rect.width + 2 * r,\n rect.height + 2 * r,\n r\n );\n }\n\n #showTooltip() {\n if (this.#info === null) return;\n this.#tag.textContent = `<${this.#info.tagName}>`;\n this.#path.textContent = `${this.#normalizePath(this.#info.source.filePath)}:${this.#info.source.lineNumber}`;\n this.#tooltip.style.display = 'flex';\n }\n\n #clearTarget() {\n this.#targetEl = null;\n this.#info = null;\n this.#highlight.style.display = 'none';\n this.#highlight.style.left = '0';\n this.#highlight.style.top = '0';\n this.#highlight.style.width = '0';\n this.#highlight.style.height = '0';\n this.#mask.style.clipPath = 'none';\n this.#tooltip.style.display = 'none';\n if (this.#resizeObserver !== undefined) {\n this.#resizeObserver.disconnect();\n this.#resizeObserver = undefined;\n }\n }\n\n #shouldSkip(el: Element): boolean {\n if (el === this.#dialog || this.#dialog.contains(el)) return true;\n if (el.tagName === 'IFRAME') return true;\n // Never target devtools' own injected elements (indicator, overlay).\n const tag = el.tagName.toLowerCase();\n if (tag === 'lit-source-overlay' || tag.startsWith('lit-devtools-')) {\n return true;\n }\n const exclude = this.#options.exclude;\n return exclude !== undefined && exclude(el);\n }\n\n async #resolveAt(x: number, y: number) {\n this.#lastMouseX = x;\n this.#lastMouseY = y;\n const el = findSourceAtPoint(x, y, this.#dialog);\n if (el === null || this.#shouldSkip(el)) {\n this.#clearTarget();\n return;\n }\n const host = findSourceHost(el);\n if (host === null) {\n this.#clearTarget();\n return;\n }\n if (host === this.#targetEl && this.#info !== null) {\n this.#updateHighlightRect();\n return;\n }\n this.#targetEl = host;\n if (this.#resizeObserver === undefined) {\n this.#resizeObserver = new ResizeObserver(() =>\n this.#updateHighlightRect()\n );\n } else {\n this.#resizeObserver.disconnect();\n }\n this.#resizeObserver.observe(host);\n const resolved = await this.#resolver.resolveElementInfo(el);\n if (resolved === null) {\n this.#clearTarget();\n return;\n }\n this.#info = resolved;\n this.#updateHighlightRect();\n this.#showTooltip();\n }\n\n #onTrackMouse = (event: MouseEvent) => {\n this.#lastMouseX = event.clientX;\n this.#lastMouseY = event.clientY;\n };\n\n #onKeyDown = (event: KeyboardEvent) => {\n if ((event.metaKey || event.ctrlKey) && event.shiftKey && !event.altKey) {\n const pressed = event.key.toLowerCase();\n const hotkey = (this.#options.key ?? 's').toLowerCase();\n if (pressed === hotkey) {\n event.preventDefault();\n this.toggle();\n }\n }\n if (this.#active && event.key === 'Escape') {\n event.preventDefault();\n event.stopPropagation();\n }\n };\n\n #onMouseMove = (event: MouseEvent) => {\n if (!this.#active) return;\n // Keep the current selection while hovering the tooltip so its buttons stay\n // clickable — the tooltip isn't a source element, so re-resolving here would\n // clear the target and hide the panel out from under the pointer.\n if (this.#pointInTooltip(event.clientX, event.clientY)) return;\n const throttleMs = this.#options.throttleMs ?? 50;\n if (this.#throttleTimer !== undefined) return;\n this.#throttleTimer = setTimeout(() => {\n this.#throttleTimer = undefined;\n // Resolve against the latest pointer position (kept current by\n // #onTrackMouse), not the coords captured when this timer was scheduled\n // ~throttleMs ago — otherwise the highlight lags the cursor during\n // continuous movement.\n const x = this.#lastMouseX;\n const y = this.#lastMouseY;\n if (this.#pointInTooltip(x, y)) return;\n void this.#resolveAt(x, y);\n }, throttleMs);\n };\n\n #select(info: ElementInfo, openInEditor = false) {\n const target = this.#targetEl;\n // Cancel the whole selection mode on any deliberate pick, before acting —\n // the editor may open via a URL scheme that doesn't navigate this tab away,\n // so we can't rely on the open outcome to dismiss the inspector.\n this.deactivate();\n this.#options.onSelect?.(info);\n if (openInEditor) {\n void this.#openInEditor(info.source.filePath, info.source.lineNumber);\n return;\n }\n // Report the picked element to the DevTools panel, which selects it in the\n // Components tree. Identity matches the inspector runtime via idOf().\n if (target !== null) {\n this.#hot?.send(INSPECT_DATA_CHANNEL, {type: 'pick', id: idOf(target)});\n this.#openDevtoolsPanel();\n }\n }\n\n /**\n * Bring the Lit DevTools dock entry to the front so a pick is visible even\n * when the panel was closed. The panel mirrors this from its own\n * `inspector-activate` handler, but only once its iframe is mounted — and the\n * @vitejs/devtools shell does not mount that iframe until the entry has been\n * opened at least once. This overlay always runs on the page, so calling\n * `switchEntry` here covers the cold-start case where no panel exists yet to\n * receive the `pick` message.\n */\n #openDevtoolsPanel() {\n try {\n const ctx = (\n window as unknown as Record<\n string,\n undefined | {docks?: {switchEntry?: (id: string) => Promise<boolean>}}\n >\n ).__VITE_DEVTOOLS_CLIENT_CONTEXT__;\n void ctx?.docks?.switchEntry?.('lit-devtools');\n } catch {\n // Not running inside the DevTools shell — ignore.\n }\n }\n\n #pointInTooltip(x: number, y: number): boolean {\n if (this.#tooltip.style.display === 'none') return false;\n const r = this.#tooltip.getBoundingClientRect();\n return x >= r.left && x <= r.right && y >= r.top && y <= r.bottom;\n }\n\n #onClick = (event: MouseEvent) => {\n if (!this.#active || this.#info === null) return;\n // Clicks on the tooltip panel are handled by its own buttons (open/copy).\n // The overlay's shadow root is closed, so we detect this by hit-rect rather\n // than inspecting the event path, and let the event reach those buttons.\n if (this.#pointInTooltip(event.clientX, event.clientY)) return;\n event.preventDefault();\n event.stopPropagation();\n this.#select(this.#info, event.metaKey || event.ctrlKey);\n };\n\n #onScrollOrResize = () => {\n if (this.#scrollTimer !== undefined) clearTimeout(this.#scrollTimer);\n this.#scrollTimer = setTimeout(() => {\n this.#scrollTimer = undefined;\n if (this.#targetEl !== null) {\n this.#updateHighlightRect();\n }\n }, 50);\n };\n}\n\ncustomElements.define('lit-source-overlay', LitSourceOverlay);\n\nexport const initSourceOverlay = (\n initOptions: SourceOverlayInitOptions = {}\n) => {\n if (typeof window === 'undefined') return;\n const el = document.createElement('lit-source-overlay') as LitSourceOverlay;\n el.configure(initOptions);\n document.body.append(el);\n};\n\nexport const toggleSourceOverlay = () => {\n const el = document.querySelector(\n 'lit-source-overlay'\n ) as LitSourceOverlay | null;\n el?.toggle();\n};\n"]}
1
+ {"version":3,"file":"overlay-element.js","sourceRoot":"","sources":["../../../src/lib/runtime/source-overlay/overlay-element.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nimport type {ElementInfo, EditorConfig} from '../../types.js';\nimport {BUILTIN_EDITORS, resolveEditor} from './editors.js';\nimport {\n defaultResolver,\n findSourceAtPoint,\n findSourceHost,\n type ElementResolver,\n} from './source-host.js';\nimport {buildSpotlightClipPath} from './mask-path.js';\nimport {OVERLAY_HTML} from './template.js';\nimport {observeEdgeInsets} from '../edge-panel.js';\nimport {subscribeOverride} from '../overrides.js';\nimport {pageChannel} from '../page-channel.js';\nimport {injectTokens} from '../../tokens.js';\nimport {idOf} from '../timeline/identity.js';\nimport {\n INSPECT_OVERLAY_TOGGLE_CHANNEL,\n INSPECT_DATA_CHANNEL,\n} from '../../../types/inspector.js';\n\nexport interface SourceOverlayInitOptions {\n key?: string;\n editor?: EditorConfig | string;\n workspaceRoot?: string;\n throttleMs?: number;\n exclude?: (el: Element) => boolean;\n onSelect?: (info: ElementInfo) => void;\n openInEditorPath?: string;\n}\n\nclass LitSourceOverlay extends HTMLElement {\n #active = false;\n #hot: typeof pageChannel | undefined;\n #options: SourceOverlayInitOptions = {};\n #editor: EditorConfig = BUILTIN_EDITORS.vscode;\n #resolver: ElementResolver = defaultResolver;\n #dialog: HTMLDialogElement;\n #mask: HTMLElement;\n #highlight: HTMLElement;\n #tooltip: HTMLElement;\n #tag: HTMLElement;\n #path: HTMLElement;\n #info: ElementInfo | null = null;\n #targetEl: Element | null = null;\n #throttleTimer: ReturnType<typeof setTimeout> | undefined;\n #scrollTimer: ReturnType<typeof setTimeout> | undefined;\n #resizeObserver: ResizeObserver | undefined;\n #cursorStyle: HTMLStyleElement | null = null;\n // Whether the Vite HMR WebSocket is currently connected. Used to suppress the\n // editor-URL-scheme fallback once the dev server is gone — otherwise a failed\n // open-in-editor fetch would navigate the tab to `vscode://…`.\n #connected = true;\n #lastMouseX = 0;\n #lastMouseY = 0;\n #edgeDispose: (() => void) | undefined;\n #overrideSubscribed = false;\n #hotOff: (() => void) | undefined;\n\n constructor() {\n super();\n const root = this.attachShadow({mode: 'closed'});\n root.innerHTML = OVERLAY_HTML;\n this.#dialog = root.getElementById('overlay') as HTMLDialogElement;\n this.#mask = root.getElementById('mask')!;\n this.#highlight = root.getElementById('highlight')!;\n this.#tooltip = root.getElementById('tooltip')!;\n this.#tag = root.getElementById('tag')!;\n this.#path = root.getElementById('path')!;\n root.getElementById('open')!.addEventListener('click', (e) => {\n e.stopPropagation();\n if (this.#info !== null) this.#select(this.#info, true);\n });\n root.getElementById('copy')!.addEventListener('click', (e) => {\n e.stopPropagation();\n if (this.#info === null) return;\n const text = `${this.#normalizePath(this.#info.source.filePath)}:${this.#info.source.lineNumber}`;\n void navigator.clipboard?.writeText(text);\n });\n this.#dialog.addEventListener('cancel', (e) => e.preventDefault());\n }\n\n connectedCallback() {\n injectTokens();\n document.addEventListener('mousemove', this.#onTrackMouse, true);\n document.addEventListener('keydown', this.#onKeyDown, true);\n const hot = (\n import.meta as {\n hot?: {\n on: (event: string, cb: (data?: unknown) => void) => void;\n off: (event: string, cb: (data?: unknown) => void) => void;\n send: (event: string, data: unknown) => void;\n };\n }\n ).hot;\n if (hot !== undefined) pageChannel.useViteHot(hot);\n this.#hot = hot === undefined ? undefined : pageChannel;\n if (hot !== undefined && this.#hotOff === undefined) {\n // Removed again in disconnectedCallback, so a re-attached overlay\n // doesn't stack duplicates and a detached one stops reacting.\n const handlers: Array<[string, (data?: unknown) => void]> = [\n ['vite:beforeFullReload', () => this.deactivate()],\n ['vite:ws:disconnect', () => (this.#connected = false)],\n ['vite:ws:connect', () => (this.#connected = true)],\n ];\n for (const [event, cb] of handlers) hot.on(event, cb);\n // Toggle from the Vite DevTools command/shortcut (handler runs server-side).\n const offToggle = pageChannel.on(INSPECT_OVERLAY_TOGGLE_CHANNEL, () =>\n this.toggle()\n );\n this.#hotOff = () => {\n for (const [event, cb] of handlers) hot.off(event, cb);\n offToggle();\n };\n }\n // Keep the (bottom-fixed) tooltip clear of the Vite DevTools edge panel.\n this.#edgeDispose = observeEdgeInsets((insets) => {\n this.style.setProperty('--edge-bottom', `${insets.bottom}px`);\n });\n // Apply the panel's editor override live (and on load). Merge so other\n // configured options (key, throttle, …) survive.\n if (!this.#overrideSubscribed) {\n this.#overrideSubscribed = true;\n subscribeOverride(hot, (o) => {\n if (o.sourceOverlayEditor !== undefined) {\n this.#options = {...this.#options, editor: o.sourceOverlayEditor};\n this.#editor = resolveEditor(o.sourceOverlayEditor);\n }\n });\n }\n }\n\n disconnectedCallback() {\n document.removeEventListener('mousemove', this.#onTrackMouse, true);\n document.removeEventListener('keydown', this.#onKeyDown, true);\n this.deactivate();\n this.#edgeDispose?.();\n this.#edgeDispose = undefined;\n this.#hotOff?.();\n this.#hotOff = undefined;\n }\n\n configure(options: SourceOverlayInitOptions) {\n this.#options = options;\n this.#editor = resolveEditor(options.editor);\n }\n\n activate() {\n if (this.#active) return;\n this.#active = true;\n this.#dialog.showModal();\n this.#mask.style.background = 'rgba(0,0,0,0.35)';\n // The overlay is pointer-events:none, so the cursor reflects the hovered\n // page element. Force a crosshair while inspecting. The closed shadow DOM\n // tooltip is unaffected, so its buttons keep their own pointer cursor.\n if (this.#cursorStyle === null) {\n this.#cursorStyle = document.createElement('style');\n this.#cursorStyle.textContent = '*{cursor:crosshair !important}';\n }\n document.head.append(this.#cursorStyle);\n document.addEventListener('mousemove', this.#onMouseMove, true);\n document.addEventListener('click', this.#onClick, true);\n window.addEventListener('scroll', this.#onScrollOrResize, {passive: true});\n window.addEventListener('resize', this.#onScrollOrResize, {passive: true});\n void this.#resolveAt(this.#lastMouseX, this.#lastMouseY);\n }\n\n deactivate() {\n if (!this.#active) return;\n this.#active = false;\n this.#dialog.close();\n this.#mask.style.background = 'rgba(0,0,0,0)';\n this.#cursorStyle?.remove();\n document.removeEventListener('mousemove', this.#onMouseMove, true);\n document.removeEventListener('click', this.#onClick, true);\n window.removeEventListener('scroll', this.#onScrollOrResize);\n window.removeEventListener('resize', this.#onScrollOrResize);\n if (this.#throttleTimer !== undefined) {\n clearTimeout(this.#throttleTimer);\n this.#throttleTimer = undefined;\n }\n if (this.#scrollTimer !== undefined) {\n clearTimeout(this.#scrollTimer);\n this.#scrollTimer = undefined;\n }\n this.#clearTarget();\n }\n\n toggle() {\n if (this.#active) this.deactivate();\n else this.activate();\n }\n\n #normalizePath(filePath: string): string {\n const root = this.#options.workspaceRoot;\n if (root !== undefined && filePath.startsWith(root)) {\n const rest = filePath.slice(root.length);\n return rest.startsWith('/') ? rest.slice(1) : rest;\n }\n return filePath;\n }\n\n async #openInEditor(filePath: string, lineNumber: number) {\n const path = this.#normalizePath(filePath);\n const endpoint = this.#options.openInEditorPath ?? '/__lit-open-in-editor';\n try {\n const params = new URLSearchParams({\n file: path,\n line: String(lineNumber),\n });\n // Name the editor the developer picked (config, env or the panel's\n // override) so the server opens that one; custom editors and an unset\n // choice send nothing and the server auto-detects.\n const {editor} = this.#options;\n if (typeof editor === 'string') params.set('editor', editor);\n const res = await fetch(`${endpoint}?${params.toString()}`);\n if (res.ok) return;\n } catch {\n // Fall back to editor URL schemes (e.g. StackBlitz previews).\n }\n // Skip the URL-scheme fallback when the dev server is gone: a fetch failure\n // there means \"server quit\", not \"no endpoint\", and navigating the tab to\n // `vscode://…` on shutdown is jarring and unwanted.\n if (!this.#connected) return;\n window.open(this.#editor.url(path, lineNumber), '_self');\n }\n\n #updateHighlightRect() {\n if (this.#targetEl === null) return;\n const rect = this.#targetEl.getBoundingClientRect();\n const raw = getComputedStyle(this)\n .getPropertyValue('--lit-devtools-radius')\n .trim();\n const r = parseFloat(raw) || 6;\n // The tinted box hugs the element's exact rect — that's the boundary being\n // picked; only the spotlight cutout gets the breathing room of `r`.\n this.#highlight.style.display = 'block';\n this.#highlight.style.left = `${rect.left}px`;\n this.#highlight.style.top = `${rect.top}px`;\n this.#highlight.style.width = `${rect.width}px`;\n this.#highlight.style.height = `${rect.height}px`;\n this.#mask.style.clipPath = buildSpotlightClipPath(\n rect.left - r,\n rect.top - r,\n rect.width + 2 * r,\n rect.height + 2 * r,\n r\n );\n }\n\n #showTooltip() {\n if (this.#info === null) return;\n this.#tag.textContent = `<${this.#info.tagName}>`;\n this.#path.textContent = `${this.#normalizePath(this.#info.source.filePath)}:${this.#info.source.lineNumber}`;\n this.#tooltip.style.display = 'flex';\n }\n\n #clearTarget() {\n this.#targetEl = null;\n this.#info = null;\n this.#highlight.style.display = 'none';\n this.#highlight.style.left = '0';\n this.#highlight.style.top = '0';\n this.#highlight.style.width = '0';\n this.#highlight.style.height = '0';\n this.#mask.style.clipPath = 'none';\n this.#tooltip.style.display = 'none';\n if (this.#resizeObserver !== undefined) {\n this.#resizeObserver.disconnect();\n this.#resizeObserver = undefined;\n }\n }\n\n #shouldSkip(el: Element): boolean {\n if (el === this.#dialog || this.#dialog.contains(el)) return true;\n if (el.tagName === 'IFRAME') return true;\n // Never target devtools' own injected elements (indicator, overlay).\n const tag = el.tagName.toLowerCase();\n if (tag === 'lit-source-overlay' || tag.startsWith('lit-devtools-')) {\n return true;\n }\n const exclude = this.#options.exclude;\n return exclude !== undefined && exclude(el);\n }\n\n async #resolveAt(x: number, y: number) {\n this.#lastMouseX = x;\n this.#lastMouseY = y;\n const el = findSourceAtPoint(x, y, this.#dialog);\n if (el === null || this.#shouldSkip(el)) {\n this.#clearTarget();\n return;\n }\n const host = findSourceHost(el);\n if (host === null) {\n this.#clearTarget();\n return;\n }\n if (host === this.#targetEl && this.#info !== null) {\n this.#updateHighlightRect();\n return;\n }\n this.#targetEl = host;\n if (this.#resizeObserver === undefined) {\n this.#resizeObserver = new ResizeObserver(() =>\n this.#updateHighlightRect()\n );\n } else {\n this.#resizeObserver.disconnect();\n }\n this.#resizeObserver.observe(host);\n const resolved = await this.#resolver.resolveElementInfo(el);\n if (resolved === null) {\n this.#clearTarget();\n return;\n }\n this.#info = resolved;\n this.#updateHighlightRect();\n this.#showTooltip();\n }\n\n #onTrackMouse = (event: MouseEvent) => {\n this.#lastMouseX = event.clientX;\n this.#lastMouseY = event.clientY;\n };\n\n #onKeyDown = (event: KeyboardEvent) => {\n if ((event.metaKey || event.ctrlKey) && event.shiftKey && !event.altKey) {\n const pressed = event.key.toLowerCase();\n const hotkey = (this.#options.key ?? 's').toLowerCase();\n if (pressed === hotkey) {\n event.preventDefault();\n this.toggle();\n }\n }\n if (this.#active && event.key === 'Escape') {\n event.preventDefault();\n event.stopPropagation();\n }\n };\n\n #onMouseMove = (event: MouseEvent) => {\n if (!this.#active) return;\n // Keep the current selection while hovering the tooltip so its buttons stay\n // clickable — the tooltip isn't a source element, so re-resolving here would\n // clear the target and hide the panel out from under the pointer.\n if (this.#pointInTooltip(event.clientX, event.clientY)) return;\n const throttleMs = this.#options.throttleMs ?? 50;\n if (this.#throttleTimer !== undefined) return;\n this.#throttleTimer = setTimeout(() => {\n this.#throttleTimer = undefined;\n // Resolve against the latest pointer position (kept current by\n // #onTrackMouse), not the coords captured when this timer was scheduled\n // ~throttleMs ago — otherwise the highlight lags the cursor during\n // continuous movement.\n const x = this.#lastMouseX;\n const y = this.#lastMouseY;\n if (this.#pointInTooltip(x, y)) return;\n void this.#resolveAt(x, y);\n }, throttleMs);\n };\n\n #select(info: ElementInfo, openInEditor = false) {\n const target = this.#targetEl;\n // Cancel the whole selection mode on any deliberate pick, before acting —\n // the editor may open via a URL scheme that doesn't navigate this tab away,\n // so we can't rely on the open outcome to dismiss the inspector.\n this.deactivate();\n this.#options.onSelect?.(info);\n if (openInEditor) {\n void this.#openInEditor(info.source.filePath, info.source.lineNumber);\n return;\n }\n // Report the picked element to the DevTools panel, which selects it in the\n // Components tree. Identity matches the inspector runtime via idOf().\n if (target !== null) {\n this.#hot?.send(INSPECT_DATA_CHANNEL, {type: 'pick', id: idOf(target)});\n this.#openDevtoolsPanel();\n }\n }\n\n /**\n * Bring the Lit DevTools dock entry to the front so a pick is visible even\n * when the panel was closed. The panel mirrors this from its own\n * `inspector-activate` handler, but only once its iframe is mounted — and the\n * @vitejs/devtools shell does not mount that iframe until the entry has been\n * opened at least once. This overlay always runs on the page, so calling\n * `switchEntry` here covers the cold-start case where no panel exists yet to\n * receive the `pick` message.\n */\n #openDevtoolsPanel() {\n try {\n const ctx = (\n window as unknown as Record<\n string,\n undefined | {docks?: {switchEntry?: (id: string) => Promise<boolean>}}\n >\n ).__VITE_DEVTOOLS_CLIENT_CONTEXT__;\n void ctx?.docks?.switchEntry?.('lit-devtools');\n } catch {\n // Not running inside the DevTools shell — ignore.\n }\n }\n\n #pointInTooltip(x: number, y: number): boolean {\n if (this.#tooltip.style.display === 'none') return false;\n const r = this.#tooltip.getBoundingClientRect();\n return x >= r.left && x <= r.right && y >= r.top && y <= r.bottom;\n }\n\n #onClick = (event: MouseEvent) => {\n if (!this.#active || this.#info === null) return;\n // Clicks on the tooltip panel are handled by its own buttons (open/copy).\n // The overlay's shadow root is closed, so we detect this by hit-rect rather\n // than inspecting the event path, and let the event reach those buttons.\n if (this.#pointInTooltip(event.clientX, event.clientY)) return;\n event.preventDefault();\n event.stopPropagation();\n this.#select(this.#info, event.metaKey || event.ctrlKey);\n };\n\n #onScrollOrResize = () => {\n if (this.#scrollTimer !== undefined) clearTimeout(this.#scrollTimer);\n this.#scrollTimer = setTimeout(() => {\n this.#scrollTimer = undefined;\n if (this.#targetEl !== null) {\n this.#updateHighlightRect();\n }\n }, 50);\n };\n}\n\ncustomElements.define('lit-source-overlay', LitSourceOverlay);\n\nexport const initSourceOverlay = (\n initOptions: SourceOverlayInitOptions = {}\n) => {\n if (typeof window === 'undefined') return;\n const el = document.createElement('lit-source-overlay') as LitSourceOverlay;\n el.configure(initOptions);\n document.body.append(el);\n};\n\nexport const toggleSourceOverlay = () => {\n const el = document.querySelector(\n 'lit-source-overlay'\n ) as LitSourceOverlay | null;\n el?.toggle();\n};\n"]}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ */
6
+ /**
7
+ * Mirrors timeline events into Chrome DevTools' Performance panel as custom
8
+ * tracks, via `console.timeStamp(label, start, end, track, group, color)`.
9
+ *
10
+ * Start/end are `performance.now()` values. Paired `:start`/`:end` events
11
+ * become a range; everything else becomes a zero-length marker.
12
+ */
13
+ import type { TimelineEvent } from '../../../types/timeline.js';
14
+ type TrackColor = 'primary' | 'primary-light' | 'primary-dark' | 'secondary' | 'secondary-light' | 'secondary-dark' | 'tertiary' | 'tertiary-light' | 'tertiary-dark' | 'error';
15
+ export type TimeStamp = (label: string, start: number, end: number, track: string, group: string, color: TrackColor) => void;
16
+ export interface ChromeTracksSink {
17
+ push(event: TimelineEvent): void;
18
+ reset(): void;
19
+ }
20
+ export declare const createChromeTracksSink: (stamp?: TimeStamp, toPerf?: (t: number) => number) => ChromeTracksSink;
21
+ export {};
22
+ //# sourceMappingURL=chrome-tracks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chrome-tracks.d.ts","sourceRoot":"","sources":["../../../src/lib/runtime/timeline/chrome-tracks.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;GAMG;AAEH,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,4BAA4B,CAAC;AAG9D,KAAK,UAAU,GACX,SAAS,GACT,eAAe,GACf,cAAc,GACd,WAAW,GACX,iBAAiB,GACjB,gBAAgB,GAChB,UAAU,GACV,gBAAgB,GAChB,eAAe,GACf,OAAO,CAAC;AAEZ,MAAM,MAAM,SAAS,GAAG,CACtB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,UAAU,KACd,IAAI,CAAC;AAEV,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IACjC,KAAK,IAAI,IAAI,CAAC;CACf;AAuBD,eAAO,MAAM,sBAAsB,WAC1B,SAAS,WACR,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,KAC5B,gBAgDF,CAAC"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ */
6
+ import {toPerfTime} from './clock.js';
7
+ const GROUP = 'Lit';
8
+ const MAX_PENDING = 1000;
9
+ const TRACKS = {
10
+ 'lit-lifecycle': {track: 'Lifecycle', color: 'primary', lit: true},
11
+ 'lit-render': {track: 'Render', color: 'secondary', lit: true},
12
+ 'lit-render-verbose': {
13
+ track: 'Render (verbose)',
14
+ color: 'secondary-light',
15
+ lit: true,
16
+ },
17
+ mouse: {track: 'Input', color: 'tertiary', lit: false},
18
+ keyboard: {track: 'Input', color: 'tertiary', lit: false},
19
+ };
20
+ const consoleStamp = (...args) => {
21
+ const c = console;
22
+ if (typeof c.timeStamp === 'function') c.timeStamp(...args);
23
+ };
24
+ export const createChromeTracksSink = (
25
+ stamp = consoleStamp,
26
+ toPerf = toPerfTime
27
+ ) => {
28
+ // Start times are converted at receipt because the clock epoch can reset
29
+ // before the matching :end arrives.
30
+ const pending = new Map();
31
+ return {
32
+ push(event) {
33
+ const cfg = TRACKS[event.layerId];
34
+ if (cfg === undefined) return;
35
+ const title = event.title ?? '';
36
+ const isError = event.logType === 'error';
37
+ const isStart = title.endsWith(':start');
38
+ const isEnd = title.endsWith(':end');
39
+ const phase =
40
+ isStart || isEnd ? title.slice(0, title.lastIndexOf(':')) : title;
41
+ const tag = cfg.lit ? (event.meta?.tagName ?? event.subtitle) : undefined;
42
+ const label = tag ? `<${tag}> ${phase}` : phase;
43
+ if (isStart) {
44
+ const key = `${event.layerId}|${event.groupId}|${phase}`;
45
+ pending.delete(key);
46
+ pending.set(key, {start: toPerf(event.time), error: isError});
47
+ if (pending.size > MAX_PENDING) {
48
+ const oldest = pending.keys().next().value;
49
+ if (oldest !== undefined) pending.delete(oldest);
50
+ }
51
+ } else if (isEnd) {
52
+ const key = `${event.layerId}|${event.groupId}|${phase}`;
53
+ const p = pending.get(key);
54
+ if (p === undefined) return;
55
+ pending.delete(key);
56
+ stamp(
57
+ label,
58
+ p.start,
59
+ toPerf(event.time),
60
+ cfg.track,
61
+ GROUP,
62
+ p.error || isError ? 'error' : cfg.color
63
+ );
64
+ } else {
65
+ const t = toPerf(event.time);
66
+ stamp(label, t, t, cfg.track, GROUP, isError ? 'error' : cfg.color);
67
+ }
68
+ },
69
+ reset() {
70
+ pending.clear();
71
+ },
72
+ };
73
+ };
74
+ //# sourceMappingURL=chrome-tracks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chrome-tracks.js","sourceRoot":"","sources":["../../../src/lib/runtime/timeline/chrome-tracks.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 * Mirrors timeline events into Chrome DevTools' Performance panel as custom\n * tracks, via `console.timeStamp(label, start, end, track, group, color)`.\n *\n * Start/end are `performance.now()` values. Paired `:start`/`:end` events\n * become a range; everything else becomes a zero-length marker.\n */\n\nimport type {TimelineEvent} from '../../../types/timeline.js';\nimport {toPerfTime} from './clock.js';\n\ntype TrackColor =\n | 'primary'\n | 'primary-light'\n | 'primary-dark'\n | 'secondary'\n | 'secondary-light'\n | 'secondary-dark'\n | 'tertiary'\n | 'tertiary-light'\n | 'tertiary-dark'\n | 'error';\n\nexport type TimeStamp = (\n label: string,\n start: number,\n end: number,\n track: string,\n group: string,\n color: TrackColor\n) => void;\n\nexport interface ChromeTracksSink {\n push(event: TimelineEvent): void;\n reset(): void;\n}\n\nconst GROUP = 'Lit';\nconst MAX_PENDING = 1000;\n\nconst TRACKS: Record<string, {track: string; color: TrackColor; lit: boolean}> =\n {\n 'lit-lifecycle': {track: 'Lifecycle', color: 'primary', lit: true},\n 'lit-render': {track: 'Render', color: 'secondary', lit: true},\n 'lit-render-verbose': {\n track: 'Render (verbose)',\n color: 'secondary-light',\n lit: true,\n },\n mouse: {track: 'Input', color: 'tertiary', lit: false},\n keyboard: {track: 'Input', color: 'tertiary', lit: false},\n };\n\nconst consoleStamp: TimeStamp = (...args) => {\n const c = console as unknown as {timeStamp?: TimeStamp};\n if (typeof c.timeStamp === 'function') c.timeStamp(...args);\n};\n\nexport const createChromeTracksSink = (\n stamp: TimeStamp = consoleStamp,\n toPerf: (t: number) => number = toPerfTime\n): ChromeTracksSink => {\n // Start times are converted at receipt because the clock epoch can reset\n // before the matching :end arrives.\n const pending = new Map<string, {start: number; error: boolean}>();\n\n return {\n push(event) {\n const cfg = TRACKS[event.layerId];\n if (cfg === undefined) return;\n const title = event.title ?? '';\n const isError = event.logType === 'error';\n const isStart = title.endsWith(':start');\n const isEnd = title.endsWith(':end');\n const phase =\n isStart || isEnd ? title.slice(0, title.lastIndexOf(':')) : title;\n const tag = cfg.lit ? (event.meta?.tagName ?? event.subtitle) : undefined;\n const label = tag ? `<${tag}> ${phase}` : phase;\n\n if (isStart) {\n const key = `${event.layerId}|${event.groupId}|${phase}`;\n pending.delete(key);\n pending.set(key, {start: toPerf(event.time), error: isError});\n if (pending.size > MAX_PENDING) {\n const oldest = pending.keys().next().value;\n if (oldest !== undefined) pending.delete(oldest);\n }\n } else if (isEnd) {\n const key = `${event.layerId}|${event.groupId}|${phase}`;\n const p = pending.get(key);\n if (p === undefined) return;\n pending.delete(key);\n stamp(\n label,\n p.start,\n toPerf(event.time),\n cfg.track,\n GROUP,\n p.error || isError ? 'error' : cfg.color\n );\n } else {\n const t = toPerf(event.time);\n stamp(label, t, t, cfg.track, GROUP, isError ? 'error' : cfg.color);\n }\n },\n reset() {\n pending.clear();\n },\n };\n};\n"]}
@@ -7,4 +7,10 @@
7
7
  export declare const resetClock: () => void;
8
8
  /** Milliseconds since the last {@link resetClock}. */
9
9
  export declare const now: () => number;
10
+ /**
11
+ * Convert a recording-relative time (from {@link now}) back to a
12
+ * `performance.now()` value, i.e. milliseconds since `performance.timeOrigin`.
13
+ * Chrome DevTools' `console.timeStamp` expects that timebase.
14
+ */
15
+ export declare const toPerfTime: (t: number) => number;
10
16
  //# sourceMappingURL=clock.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"clock.d.ts","sourceRoot":"","sources":["../../../src/lib/runtime/timeline/clock.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAcH,qEAAqE;AACrE,eAAO,MAAM,UAAU,QAAO,IAE7B,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,GAAG,QAAO,MAAmC,CAAC"}
1
+ {"version":3,"file":"clock.d.ts","sourceRoot":"","sources":["../../../src/lib/runtime/timeline/clock.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAcH,qEAAqE;AACrE,eAAO,MAAM,UAAU,QAAO,IAE7B,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,GAAG,QAAO,MAAmC,CAAC;AAE3D;;;;GAIG;AACH,eAAO,MAAM,UAAU,MAAO,MAAM,KAAG,MAAmB,CAAC"}
@@ -19,4 +19,10 @@ export const resetClock = () => {
19
19
  };
20
20
  /** Milliseconds since the last {@link resetClock}. */
21
21
  export const now = () => performance.now() - epoch;
22
+ /**
23
+ * Convert a recording-relative time (from {@link now}) back to a
24
+ * `performance.now()` value, i.e. milliseconds since `performance.timeOrigin`.
25
+ * Chrome DevTools' `console.timeStamp` expects that timebase.
26
+ */
27
+ export const toPerfTime = (t) => t + epoch;
22
28
  //# sourceMappingURL=clock.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"clock.js","sourceRoot":"","sources":["../../../src/lib/runtime/timeline/clock.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;GAQG;AAEH,IAAI,KAAK,GAAG,CAAC,CAAC;AAEd,qEAAqE;AACrE,MAAM,CAAC,MAAM,UAAU,GAAG,GAAS,EAAE;IACnC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;AAC5B,CAAC,CAAC;AAEF,sDAAsD;AACtD,MAAM,CAAC,MAAM,GAAG,GAAG,GAAW,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * Recording-relative clock for the timeline.\n *\n * Built-in capture layers timestamp events with {@link now} rather than raw\n * `performance.now()`, so event times read as \"ms since recording started\"\n * (the first event is ~0) instead of \"ms since the app page loaded\" — which is\n * also meaningless to the panel, an iframe with its own time origin. The origin\n * is re-zeroed on each rising edge of recording via {@link resetClock}.\n */\n\nlet epoch = 0;\n\n/** Re-zero the clock; called when recording transitions off → on. */\nexport const resetClock = (): void => {\n epoch = performance.now();\n};\n\n/** Milliseconds since the last {@link resetClock}. */\nexport const now = (): number => performance.now() - epoch;\n"]}
1
+ {"version":3,"file":"clock.js","sourceRoot":"","sources":["../../../src/lib/runtime/timeline/clock.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;GAQG;AAEH,IAAI,KAAK,GAAG,CAAC,CAAC;AAEd,qEAAqE;AACrE,MAAM,CAAC,MAAM,UAAU,GAAG,GAAS,EAAE;IACnC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;AAC5B,CAAC,CAAC;AAEF,sDAAsD;AACtD,MAAM,CAAC,MAAM,GAAG,GAAG,GAAW,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;AAE3D;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * Recording-relative clock for the timeline.\n *\n * Built-in capture layers timestamp events with {@link now} rather than raw\n * `performance.now()`, so event times read as \"ms since recording started\"\n * (the first event is ~0) instead of \"ms since the app page loaded\" — which is\n * also meaningless to the panel, an iframe with its own time origin. The origin\n * is re-zeroed on each rising edge of recording via {@link resetClock}.\n */\n\nlet epoch = 0;\n\n/** Re-zero the clock; called when recording transitions off → on. */\nexport const resetClock = (): void => {\n epoch = performance.now();\n};\n\n/** Milliseconds since the last {@link resetClock}. */\nexport const now = (): number => performance.now() - epoch;\n\n/**\n * Convert a recording-relative time (from {@link now}) back to a\n * `performance.now()` value, i.e. milliseconds since `performance.timeOrigin`.\n * Chrome DevTools' `console.timeStamp` expects that timebase.\n */\nexport const toPerfTime = (t: number): number => t + epoch;\n"]}
@@ -11,15 +11,20 @@
11
11
  * transport.
12
12
  *
13
13
  * Recording starts off; the panel iframe toggles it via the Vite HMR channel
14
- * (Phase 0/1) or devframe shared state (Phase 2+).
14
+ * (Phase 0/1) or devframe shared state (Phase 2+). Layers capture while the
15
+ * panel is recording OR the "chrome performance tracks" preference is on; the
16
+ * panel transport only receives events while recording, the Chrome tracks sink
17
+ * only while the preference is on.
15
18
  */
16
19
  import {emit, setHotClient} from './transport.js';
17
20
  import {resetClock} from './clock.js';
21
+ import {createChromeTracksSink} from './chrome-tracks.js';
18
22
  import {installLifecycleLayer, setUpdateHook} from './lifecycle.js';
19
23
  import {installRenderLayer, setRenderDebugEnabled} from './render.js';
20
24
  import {installMouseLayer, installKeyboardLayer} from './input.js';
21
25
  import {flashUpdate, setFlashEnabled, setFlashRamp} from './flash.js';
22
26
  import {subscribeOverride} from '../overrides.js';
27
+ import {pageChannel} from '../page-channel.js';
23
28
  // ---------------------------------------------------------------------------
24
29
  // Recording state — written by the panel toggle, read by all capture layers.
25
30
  // ---------------------------------------------------------------------------
@@ -31,41 +36,61 @@ const state = {
31
36
  mouseEventEnabled: false,
32
37
  keyboardEventEnabled: false,
33
38
  };
34
- const recording = () => state.recordingState;
39
+ // Mirror to Chrome DevTools' Performance panel; a page-side preference driven
40
+ // by the settings override, independent of panel recording.
41
+ let chromeTracks = false;
42
+ const sink = createChromeTracksSink();
43
+ // Layers run when either consumer wants events.
44
+ const capturing = () => state.recordingState || chromeTracks;
45
+ const out = (e) => {
46
+ if (state.recordingState) emit(e);
47
+ if (chromeTracks) sink.push(e);
48
+ };
35
49
  const lifecycleEnabled = () => state.litLifecycleEnabled;
36
50
  const renderEnabled = () => state.litRenderEnabled;
37
51
  const renderVerboseEnabled = () => state.litRenderVerboseEnabled;
38
52
  const mouseEnabled = () => state.mouseEventEnabled;
39
53
  const keyboardEnabled = () => state.keyboardEventEnabled;
40
- // Drive Lit's debug event flag from recording × (render-layer-enabled OR
54
+ // Drive Lit's debug event flag from capturing × (render-layer-enabled OR
41
55
  // verbose-layer-enabled) so lit-html only pays the per-render CustomEvent
42
56
  // dispatch cost while we're actually capturing one of the two render layers.
43
57
  const syncRenderDebug = () => {
44
58
  setRenderDebugEnabled(
45
- state.recordingState &&
46
- (state.litRenderEnabled || state.litRenderVerboseEnabled)
59
+ capturing() && (state.litRenderEnabled || state.litRenderVerboseEnabled)
47
60
  );
48
61
  };
49
62
  // ---------------------------------------------------------------------------
50
63
  // Capture layer installation
51
64
  // ---------------------------------------------------------------------------
52
- installLifecycleLayer(emit, recording, lifecycleEnabled);
53
- installRenderLayer(emit, recording, renderEnabled, renderVerboseEnabled);
54
- installMouseLayer(emit, recording, mouseEnabled);
55
- installKeyboardLayer(emit, recording, keyboardEnabled);
65
+ installLifecycleLayer(out, capturing, lifecycleEnabled);
66
+ installRenderLayer(out, capturing, renderEnabled, renderVerboseEnabled);
67
+ installMouseLayer(out, capturing, mouseEnabled);
68
+ installKeyboardLayer(out, capturing, keyboardEnabled);
56
69
  // Flash-on-update rides the lifecycle wrappers but not the recording gate:
57
70
  // it's a page-side visual the panel toggles as a preference, so it follows the
58
71
  // settings override (read at boot, pushed live) rather than the layer state.
59
72
  setUpdateHook(flashUpdate);
73
+ // ---------------------------------------------------------------------------
74
+ // Page channel wiring
75
+ // ---------------------------------------------------------------------------
76
+ // `import.meta.hot` exists in Vite dev builds; the tsconfig lib set doesn't
77
+ // include it, so we access it through the un-typed global shape.
60
78
  const hot = import.meta.hot;
61
79
  subscribeOverride(hot, (o) => {
62
80
  setFlashEnabled(o.flashUpdates ?? false);
63
81
  setFlashRamp(o.flashUpdatesRamp ?? false);
82
+ const next = o.chromeTracks ?? false;
83
+ if (next !== chromeTracks) {
84
+ chromeTracks = next;
85
+ if (!next) sink.reset();
86
+ syncRenderDebug();
87
+ }
64
88
  });
65
89
  if (hot !== undefined) {
66
- setHotClient(hot);
90
+ pageChannel.useViteHot(hot);
91
+ setHotClient(pageChannel);
67
92
  // Panel → app: toggle recording and per-layer flags.
68
- hot.on('lit:timeline:recording-changed', (data) => {
93
+ pageChannel.on('lit:timeline:recording-changed', (data) => {
69
94
  const next = data.recording;
70
95
  // Re-zero the timeline clock on the rising edge so event times read as
71
96
  // "ms since recording started" rather than since page load.
@@ -73,11 +98,15 @@ if (hot !== undefined) {
73
98
  state.recordingState = next;
74
99
  syncRenderDebug();
75
100
  });
76
- hot.on('lit:timeline:layers-changed', (data) => {
101
+ pageChannel.on('lit:timeline:layers-changed', (data) => {
77
102
  Object.assign(state, data);
78
103
  syncRenderDebug();
79
104
  });
80
105
  // Announce readiness so the panel can detect the runtime.
81
- hot.send('lit:timeline:runtime-ready', {});
106
+ pageChannel.send('lit:timeline:runtime-ready', {});
107
+ // A carrier attached later starts with no idea a runtime exists.
108
+ pageChannel.onAttach(() =>
109
+ pageChannel.send('lit:timeline:runtime-ready', {})
110
+ );
82
111
  }
83
112
  //# sourceMappingURL=install.js.map