@oddsquad/vite-plugin-lit 0.2.3 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/LICENSE +28 -0
  3. package/README.md +157 -0
  4. package/bin.mjs +154 -0
  5. package/client.d.ts +61 -0
  6. package/dist/client/assets/browser-agent-rpc-BXhoSh1z-CdtPhBL-.js +69 -0
  7. package/dist/client/assets/browser-agent-rpc-BXhoSh1z-CdtPhBL-.js.map +1 -0
  8. package/dist/client/assets/flow-DK8vmxvN.js +745 -0
  9. package/dist/client/assets/flow-DK8vmxvN.js.map +1 -0
  10. package/dist/client/assets/index-DVe6M4HV.js +10614 -0
  11. package/dist/client/assets/index-DVe6M4HV.js.map +1 -0
  12. package/{panel → dist/client}/index.html +1 -0
  13. package/index.d.ts.map +1 -1
  14. package/index.js +2 -2
  15. package/index.js.map +1 -1
  16. package/lib/color-scheme.d.ts.map +1 -1
  17. package/lib/color-scheme.js +17 -21
  18. package/lib/color-scheme.js.map +1 -1
  19. package/lib/devframe/definition.d.ts +45 -0
  20. package/lib/devframe/definition.d.ts.map +1 -0
  21. package/lib/devframe/definition.js +547 -0
  22. package/lib/devframe/definition.js.map +1 -0
  23. package/lib/devframe/icon.d.ts +8 -0
  24. package/lib/devframe/icon.d.ts.map +1 -0
  25. package/lib/devframe/icon.js +21 -0
  26. package/lib/devframe/icon.js.map +1 -0
  27. package/lib/devframe/paths.d.ts +12 -0
  28. package/lib/devframe/paths.d.ts.map +1 -0
  29. package/lib/devframe/paths.js +38 -0
  30. package/lib/devframe/paths.js.map +1 -0
  31. package/lib/devframe/protocol.d.ts +218 -0
  32. package/lib/devframe/protocol.d.ts.map +1 -0
  33. package/lib/devframe/protocol.js +77 -0
  34. package/lib/devframe/protocol.js.map +1 -0
  35. package/lib/devframe/source.d.ts +49 -0
  36. package/lib/devframe/source.d.ts.map +1 -0
  37. package/lib/devframe/source.js +23 -0
  38. package/lib/devframe/source.js.map +1 -0
  39. package/lib/devframe/vite.d.ts +116 -0
  40. package/lib/devframe/vite.d.ts.map +1 -0
  41. package/lib/devframe/vite.js +292 -0
  42. package/lib/devframe/vite.js.map +1 -0
  43. package/lib/http.d.ts +29 -0
  44. package/lib/http.d.ts.map +1 -0
  45. package/lib/http.js +35 -0
  46. package/lib/http.js.map +1 -0
  47. package/lib/icons.d.ts +2 -0
  48. package/lib/icons.d.ts.map +1 -1
  49. package/lib/icons.js +10 -4
  50. package/lib/icons.js.map +1 -1
  51. package/lib/options.d.ts +131 -0
  52. package/lib/options.d.ts.map +1 -0
  53. package/lib/options.js +128 -0
  54. package/lib/options.js.map +1 -0
  55. package/lib/plugin.d.ts +6 -137
  56. package/lib/plugin.d.ts.map +1 -1
  57. package/lib/plugin.js +280 -677
  58. package/lib/plugin.js.map +1 -1
  59. package/lib/plugins/css-literals.d.ts +15 -0
  60. package/lib/plugins/css-literals.d.ts.map +1 -0
  61. package/lib/plugins/css-literals.js +154 -0
  62. package/lib/plugins/css-literals.js.map +1 -0
  63. package/lib/plugins/css-queries.d.ts +20 -0
  64. package/lib/plugins/css-queries.d.ts.map +1 -0
  65. package/lib/plugins/css-queries.js +139 -0
  66. package/lib/plugins/css-queries.js.map +1 -0
  67. package/lib/plugins/open-in-editor.d.ts +16 -0
  68. package/lib/plugins/open-in-editor.d.ts.map +1 -0
  69. package/lib/plugins/open-in-editor.js +91 -0
  70. package/lib/plugins/open-in-editor.js.map +1 -0
  71. package/lib/plugins/shared.d.ts +13 -0
  72. package/lib/plugins/shared.d.ts.map +1 -0
  73. package/lib/plugins/shared.js +23 -0
  74. package/lib/plugins/shared.js.map +1 -0
  75. package/lib/plugins/timeline-virtual.d.ts +19 -0
  76. package/lib/plugins/timeline-virtual.d.ts.map +1 -0
  77. package/lib/plugins/timeline-virtual.js +53 -0
  78. package/lib/plugins/timeline-virtual.js.map +1 -0
  79. package/lib/runtime/css.d.ts +2 -2
  80. package/lib/runtime/css.d.ts.map +1 -1
  81. package/lib/runtime/css.js +41 -34
  82. package/lib/runtime/css.js.map +1 -1
  83. package/lib/runtime/edge-panel.d.ts.map +1 -1
  84. package/lib/runtime/edge-panel.js +82 -91
  85. package/lib/runtime/edge-panel.js.map +1 -1
  86. package/lib/runtime/fonts.d.ts.map +1 -1
  87. package/lib/runtime/fonts.js +1 -1
  88. package/lib/runtime/fonts.js.map +1 -1
  89. package/lib/runtime/indicator.d.ts.map +1 -1
  90. package/lib/runtime/indicator.js +71 -74
  91. package/lib/runtime/indicator.js.map +1 -1
  92. package/lib/runtime/inspector/collect.d.ts.map +1 -1
  93. package/lib/runtime/inspector/collect.js +83 -90
  94. package/lib/runtime/inspector/collect.js.map +1 -1
  95. package/lib/runtime/inspector/highlight.d.ts +16 -0
  96. package/lib/runtime/inspector/highlight.d.ts.map +1 -0
  97. package/lib/runtime/inspector/highlight.js +66 -0
  98. package/lib/runtime/inspector/highlight.js.map +1 -0
  99. package/lib/runtime/inspector/install.d.ts.map +1 -1
  100. package/lib/runtime/inspector/install.js +230 -205
  101. package/lib/runtime/inspector/install.js.map +1 -1
  102. package/lib/runtime/inspector/serialize.d.ts.map +1 -1
  103. package/lib/runtime/inspector/serialize.js +86 -107
  104. package/lib/runtime/inspector/serialize.js.map +1 -1
  105. package/lib/runtime/intern.d.ts.map +1 -1
  106. package/lib/runtime/intern.js +31 -29
  107. package/lib/runtime/intern.js.map +1 -1
  108. package/lib/runtime/overrides.d.ts.map +1 -1
  109. package/lib/runtime/overrides.js +14 -13
  110. package/lib/runtime/overrides.js.map +1 -1
  111. package/lib/runtime/patch.d.ts +8 -0
  112. package/lib/runtime/patch.d.ts.map +1 -1
  113. package/lib/runtime/patch.js +321 -282
  114. package/lib/runtime/patch.js.map +1 -1
  115. package/lib/runtime/source-meta.d.ts.map +1 -1
  116. package/lib/runtime/source-meta.js +1 -1
  117. package/lib/runtime/source-meta.js.map +1 -1
  118. package/lib/runtime/source-overlay/editors.d.ts.map +1 -1
  119. package/lib/runtime/source-overlay/editors.js +27 -27
  120. package/lib/runtime/source-overlay/editors.js.map +1 -1
  121. package/lib/runtime/source-overlay/mask-path.d.ts.map +1 -1
  122. package/lib/runtime/source-overlay/mask-path.js +15 -15
  123. package/lib/runtime/source-overlay/mask-path.js.map +1 -1
  124. package/lib/runtime/source-overlay/overlay-element.d.ts.map +1 -1
  125. package/lib/runtime/source-overlay/overlay-element.js +359 -355
  126. package/lib/runtime/source-overlay/overlay-element.js.map +1 -1
  127. package/lib/runtime/source-overlay/source-host.d.ts.map +1 -1
  128. package/lib/runtime/source-overlay/source-host.js +64 -71
  129. package/lib/runtime/source-overlay/source-host.js.map +1 -1
  130. package/lib/runtime/source-overlay/template.d.ts.map +1 -1
  131. package/lib/runtime/source-overlay/template.js +3 -3
  132. package/lib/runtime/source-overlay/template.js.map +1 -1
  133. package/lib/runtime/source-overlay.d.ts.map +1 -1
  134. package/lib/runtime/source-overlay.js +5 -2
  135. package/lib/runtime/source-overlay.js.map +1 -1
  136. package/lib/runtime/timeline/clock.d.ts.map +1 -1
  137. package/lib/runtime/timeline/clock.js +2 -2
  138. package/lib/runtime/timeline/clock.js.map +1 -1
  139. package/lib/runtime/timeline/flash.d.ts +39 -0
  140. package/lib/runtime/timeline/flash.d.ts.map +1 -0
  141. package/lib/runtime/timeline/flash.js +169 -0
  142. package/lib/runtime/timeline/flash.js.map +1 -0
  143. package/lib/runtime/timeline/identity.d.ts.map +1 -1
  144. package/lib/runtime/timeline/identity.js +27 -27
  145. package/lib/runtime/timeline/identity.js.map +1 -1
  146. package/lib/runtime/timeline/input.d.ts.map +1 -1
  147. package/lib/runtime/timeline/input.js +54 -67
  148. package/lib/runtime/timeline/input.js.map +1 -1
  149. package/lib/runtime/timeline/install.d.ts.map +1 -1
  150. package/lib/runtime/timeline/install.js +47 -33
  151. package/lib/runtime/timeline/install.js.map +1 -1
  152. package/lib/runtime/timeline/lifecycle.d.ts +8 -0
  153. package/lib/runtime/timeline/lifecycle.d.ts.map +1 -1
  154. package/lib/runtime/timeline/lifecycle.js +149 -133
  155. package/lib/runtime/timeline/lifecycle.js.map +1 -1
  156. package/lib/runtime/timeline/public-api.d.ts +2 -2
  157. package/lib/runtime/timeline/public-api.d.ts.map +1 -1
  158. package/lib/runtime/timeline/public-api.js +11 -11
  159. package/lib/runtime/timeline/public-api.js.map +1 -1
  160. package/lib/runtime/timeline/render.d.ts +15 -6
  161. package/lib/runtime/timeline/render.d.ts.map +1 -1
  162. package/lib/runtime/timeline/render.js +212 -78
  163. package/lib/runtime/timeline/render.js.map +1 -1
  164. package/lib/runtime/timeline/transport.d.ts.map +1 -1
  165. package/lib/runtime/timeline/transport.js +39 -43
  166. package/lib/runtime/timeline/transport.js.map +1 -1
  167. package/lib/segmented-tabs.d.ts +3 -1
  168. package/lib/segmented-tabs.d.ts.map +1 -1
  169. package/lib/segmented-tabs.js +136 -107
  170. package/lib/segmented-tabs.js.map +1 -1
  171. package/lib/snapshot.d.ts +28 -0
  172. package/lib/snapshot.d.ts.map +1 -0
  173. package/lib/snapshot.js +57 -0
  174. package/lib/snapshot.js.map +1 -0
  175. package/lib/source-meta.d.ts.map +1 -1
  176. package/lib/source-meta.js +176 -162
  177. package/lib/source-meta.js.map +1 -1
  178. package/lib/timeline/derive.d.ts +152 -0
  179. package/lib/timeline/derive.d.ts.map +1 -0
  180. package/lib/timeline/derive.js +242 -0
  181. package/lib/timeline/derive.js.map +1 -0
  182. package/lib/tokens.d.ts.map +1 -1
  183. package/lib/tokens.js +17 -18
  184. package/lib/tokens.js.map +1 -1
  185. package/lib/transform.d.ts.map +1 -1
  186. package/lib/transform.js +62 -57
  187. package/lib/transform.js.map +1 -1
  188. package/lib/types.d.ts.map +1 -1
  189. package/lib/types.js +1 -1
  190. package/lib/types.js.map +1 -1
  191. package/lib/wrap-table.d.ts.map +1 -1
  192. package/lib/wrap-table.js +19 -17
  193. package/lib/wrap-table.js.map +1 -1
  194. package/package.json +80 -13
  195. package/types/hmr-incompatibility.d.ts +59 -0
  196. package/types/hmr-incompatibility.d.ts.map +1 -0
  197. package/types/hmr-incompatibility.js +30 -0
  198. package/types/hmr-incompatibility.js.map +1 -0
  199. package/types/in-page.d.ts +49 -0
  200. package/types/in-page.d.ts.map +1 -0
  201. package/types/in-page.js +33 -0
  202. package/types/in-page.js.map +1 -0
  203. package/types/inspector.d.ts.map +1 -1
  204. package/types/inspector.js.map +1 -1
  205. package/types/snapshot.d.ts +44 -0
  206. package/types/snapshot.d.ts.map +1 -0
  207. package/types/snapshot.js +7 -0
  208. package/types/snapshot.js.map +1 -0
  209. package/types/timeline.d.ts +23 -1
  210. package/types/timeline.d.ts.map +1 -1
  211. package/types/timeline.js +2 -0
  212. package/types/timeline.js.map +1 -1
  213. package/lib/timeline-plugin.d.ts +0 -72
  214. package/lib/timeline-plugin.d.ts.map +0 -1
  215. package/lib/timeline-plugin.js +0 -376
  216. package/lib/timeline-plugin.js.map +0 -1
  217. package/panel/components-view.d.ts +0 -60
  218. package/panel/components-view.d.ts.map +0 -1
  219. package/panel/components-view.js +0 -587
  220. package/panel/components-view.js.map +0 -1
  221. package/panel/devtools-settings.d.ts +0 -41
  222. package/panel/devtools-settings.d.ts.map +0 -1
  223. package/panel/devtools-settings.js +0 -463
  224. package/panel/devtools-settings.js.map +0 -1
  225. package/panel/lit-devtools-panel.d.ts +0 -37
  226. package/panel/lit-devtools-panel.d.ts.map +0 -1
  227. package/panel/lit-devtools-panel.js +0 -185
  228. package/panel/lit-devtools-panel.js.map +0 -1
  229. package/panel/timeline-event-list.d.ts +0 -43
  230. package/panel/timeline-event-list.d.ts.map +0 -1
  231. package/panel/timeline-event-list.js +0 -416
  232. package/panel/timeline-event-list.js.map +0 -1
  233. package/panel/timeline-layers.d.ts +0 -25
  234. package/panel/timeline-layers.d.ts.map +0 -1
  235. package/panel/timeline-layers.js +0 -96
  236. package/panel/timeline-layers.js.map +0 -1
  237. package/panel/timeline-view.d.ts +0 -38
  238. package/panel/timeline-view.d.ts.map +0 -1
  239. package/panel/timeline-view.js +0 -234
  240. package/panel/timeline-view.js.map +0 -1
@@ -0,0 +1,91 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ */
6
+ import {existsSync} from 'node:fs';
7
+ import {resolve as resolvePath, sep} from 'node:path';
8
+ import {isTrustedRequest} from '../http.js';
9
+ export const OPEN_IN_EDITOR_PATH = '/__lit-open-in-editor';
10
+ export const createOpenInEditorMiddleware = (allowedRoots) => {
11
+ // First entry is the primary root: relative `file` params resolve against
12
+ // it. Every entry grants open access to files beneath it.
13
+ const roots = allowedRoots.map((r) => resolvePath(r));
14
+ return (req, res, next) => {
15
+ if (req.url === undefined) {
16
+ next();
17
+ return;
18
+ }
19
+ if (req.method !== undefined && req.method !== 'GET') {
20
+ res.statusCode = 405;
21
+ res.end('method not allowed');
22
+ return;
23
+ }
24
+ if (!isTrustedRequest(req.headers ?? {})) {
25
+ res.statusCode = 403;
26
+ res.end('forbidden');
27
+ return;
28
+ }
29
+ const query = req.url.includes('?')
30
+ ? req.url.slice(req.url.indexOf('?') + 1)
31
+ : '';
32
+ const params = new URLSearchParams(query);
33
+ const file = params.get('file');
34
+ if (file === null) {
35
+ res.statusCode = 400;
36
+ res.end('missing file parameter');
37
+ return;
38
+ }
39
+ // Confine the open to the allowed roots: resolve the requested path and
40
+ // reject anything that escapes all of them (path traversal, absolute
41
+ // paths to arbitrary files). `launch-editor` spawns the user's editor on
42
+ // this path, so an unvalidated `file` is a local-file-open /
43
+ // arg-injection vector.
44
+ const resolved = resolvePath(roots[0] ?? process.cwd(), file);
45
+ const allowed = roots.some(
46
+ (root) => resolved === root || resolved.startsWith(root + sep)
47
+ );
48
+ if (!allowed) {
49
+ res.statusCode = 403;
50
+ res.end('file outside allowed roots');
51
+ return;
52
+ }
53
+ if (!existsSync(resolved)) {
54
+ res.statusCode = 404;
55
+ res.end('file not found');
56
+ return;
57
+ }
58
+ // Coerce to integers so a crafted `line`/`column` can't smuggle extra
59
+ // shell-visible content through the `file:line:column` ref.
60
+ const line = String(
61
+ Math.max(1, Number.parseInt(params.get('line') ?? '1', 10) || 1)
62
+ );
63
+ const column = String(
64
+ Math.max(1, Number.parseInt(params.get('column') ?? '1', 10) || 1)
65
+ );
66
+ const fileRef = `${resolved}:${line}:${column}`;
67
+ import('launch-editor')
68
+ .then((mod) => {
69
+ const launch = mod.default ?? mod;
70
+ // `launch-editor` invokes the callback only on failure — synchronously
71
+ // when it can't guess an editor, later if the spawn errors. Reply `ok`
72
+ // right after launching; the guard keeps a sync failure's 500 first
73
+ // and drops a late async failure (the response is long gone).
74
+ let finished = false;
75
+ const finish = (statusCode, msg) => {
76
+ if (finished) return;
77
+ finished = true;
78
+ res.statusCode = statusCode;
79
+ res.end(msg);
80
+ };
81
+ launch(fileRef, (_fileName, errorMessage) => {
82
+ if (errorMessage !== null) {
83
+ finish(500, errorMessage);
84
+ }
85
+ });
86
+ finish(200, 'ok');
87
+ })
88
+ .catch(next);
89
+ };
90
+ };
91
+ //# sourceMappingURL=open-in-editor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-in-editor.js","sourceRoot":"","sources":["../../src/lib/plugins/open-in-editor.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 {existsSync} from 'node:fs';\nimport {resolve as resolvePath, sep} from 'node:path';\nimport {isTrustedRequest, type TrustHeaders} from '../http.js';\n\nexport const OPEN_IN_EDITOR_PATH = '/__lit-open-in-editor';\n\nexport const createOpenInEditorMiddleware = (\n allowedRoots: readonly string[]\n) => {\n // First entry is the primary root: relative `file` params resolve against\n // it. Every entry grants open access to files beneath it.\n const roots = allowedRoots.map((r) => resolvePath(r));\n return (\n req: {url?: string; method?: string; headers?: TrustHeaders},\n res: {statusCode: number; end: (msg: string) => void},\n next: (err?: unknown) => void\n ) => {\n if (req.url === undefined) {\n next();\n return;\n }\n if (req.method !== undefined && req.method !== 'GET') {\n res.statusCode = 405;\n res.end('method not allowed');\n return;\n }\n if (!isTrustedRequest(req.headers ?? {})) {\n res.statusCode = 403;\n res.end('forbidden');\n return;\n }\n const query = req.url.includes('?')\n ? req.url.slice(req.url.indexOf('?') + 1)\n : '';\n const params = new URLSearchParams(query);\n const file = params.get('file');\n if (file === null) {\n res.statusCode = 400;\n res.end('missing file parameter');\n return;\n }\n // Confine the open to the allowed roots: resolve the requested path and\n // reject anything that escapes all of them (path traversal, absolute\n // paths to arbitrary files). `launch-editor` spawns the user's editor on\n // this path, so an unvalidated `file` is a local-file-open /\n // arg-injection vector.\n const resolved = resolvePath(roots[0] ?? process.cwd(), file);\n const allowed = roots.some(\n (root) => resolved === root || resolved.startsWith(root + sep)\n );\n if (!allowed) {\n res.statusCode = 403;\n res.end('file outside allowed roots');\n return;\n }\n if (!existsSync(resolved)) {\n res.statusCode = 404;\n res.end('file not found');\n return;\n }\n // Coerce to integers so a crafted `line`/`column` can't smuggle extra\n // shell-visible content through the `file:line:column` ref.\n const line = String(\n Math.max(1, Number.parseInt(params.get('line') ?? '1', 10) || 1)\n );\n const column = String(\n Math.max(1, Number.parseInt(params.get('column') ?? '1', 10) || 1)\n );\n const fileRef = `${resolved}:${line}:${column}`;\n import('launch-editor')\n .then(\n (mod: {\n default?: (\n file: string,\n cb: (fileName: string, errorMessage: string | null) => void\n ) => void;\n }) => {\n const launch = (mod.default ?? mod) as (\n file: string,\n cb: (fileName: string, errorMessage: string | null) => void\n ) => void;\n // `launch-editor` invokes the callback only on failure — synchronously\n // when it can't guess an editor, later if the spawn errors. Reply `ok`\n // right after launching; the guard keeps a sync failure's 500 first\n // and drops a late async failure (the response is long gone).\n let finished = false;\n const finish = (statusCode: number, msg: string) => {\n if (finished) return;\n finished = true;\n res.statusCode = statusCode;\n res.end(msg);\n };\n launch(fileRef, (_fileName: string, errorMessage: string | null) => {\n if (errorMessage !== null) {\n finish(500, errorMessage);\n }\n });\n finish(200, 'ok');\n }\n )\n .catch(next);\n };\n};\n"]}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ */
6
+ /**
7
+ * Resolves a runtime module to an absolute fs path (served via `/@fs/`), so
8
+ * the plugin works from any served root. Falls back from the built `.js` to
9
+ * the `.ts` source when running un-built (e.g. under vitest).
10
+ */
11
+ export declare const resolveRuntimeModule: (name: string) => string;
12
+ export declare const JS_FILE_RE: RegExp;
13
+ //# sourceMappingURL=shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/lib/plugins/shared.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,SAAU,MAAM,KAAG,MAQnD,CAAC;AAEF,eAAO,MAAM,UAAU,QAAoB,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ */
6
+ import {existsSync} from 'node:fs';
7
+ import {fileURLToPath} from 'node:url';
8
+ /**
9
+ * Resolves a runtime module to an absolute fs path (served via `/@fs/`), so
10
+ * the plugin works from any served root. Falls back from the built `.js` to
11
+ * the `.ts` source when running un-built (e.g. under vitest).
12
+ */
13
+ export const resolveRuntimeModule = (name) => {
14
+ for (const ext of ['js', 'ts']) {
15
+ const url = new URL(`../runtime/${name}.${ext}`, import.meta.url);
16
+ if (existsSync(url)) {
17
+ return fileURLToPath(url).replace(/\\/g, '/');
18
+ }
19
+ }
20
+ throw new Error(`[lit-plugin] runtime module not found: ${name}`);
21
+ };
22
+ export const JS_FILE_RE = /\.[cm]?[jt]sx?$/;
23
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/lib/plugins/shared.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAC,UAAU,EAAC,MAAM,SAAS,CAAC;AACnC,OAAO,EAAC,aAAa,EAAC,MAAM,UAAU,CAAC;AAEvC;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,IAAY,EAAU,EAAE;IAC3D,KAAK,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAU,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,cAAc,IAAI,IAAI,GAAG,EAAE,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;QAClE,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACpB,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,0CAA0C,IAAI,EAAE,CAAC,CAAC;AACpE,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,iBAAiB,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nimport {existsSync} from 'node:fs';\nimport {fileURLToPath} from 'node:url';\n\n/**\n * Resolves a runtime module to an absolute fs path (served via `/@fs/`), so\n * the plugin works from any served root. Falls back from the built `.js` to\n * the `.ts` source when running un-built (e.g. under vitest).\n */\nexport const resolveRuntimeModule = (name: string): string => {\n for (const ext of ['js', 'ts'] as const) {\n const url = new URL(`../runtime/${name}.${ext}`, import.meta.url);\n if (existsSync(url)) {\n return fileURLToPath(url).replace(/\\\\/g, '/');\n }\n }\n throw new Error(`[lit-plugin] runtime module not found: ${name}`);\n};\n\nexport const JS_FILE_RE = /\\.[cm]?[jt]sx?$/;\n"]}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ */
6
+ import type { Plugin } from 'vite';
7
+ /**
8
+ * The public timeline API virtual module, served in dev and build alike:
9
+ * app code importing it must keep building under `vite build`, where the HMR
10
+ * plugin doesn't apply. While these hooks lived on that serve-only plugin,
11
+ * nothing claimed the specifier during a build and the bundler failed to
12
+ * resolve it.
13
+ *
14
+ * `getTimeline` is a getter, not a value: `litPlugin()` re-resolves its
15
+ * options against the loaded env in a `config` hook, which runs after the
16
+ * plugin array is built.
17
+ */
18
+ export declare const litTimelineVirtual: (getTimeline?: () => boolean) => Plugin;
19
+ //# sourceMappingURL=timeline-virtual.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline-virtual.d.ts","sourceRoot":"","sources":["../../src/lib/plugins/timeline-virtual.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,MAAM,CAAC;AASjC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB,iBAChB,MAAM,OAAO,KACzB,MA6BF,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ */
6
+ import {resolveRuntimeModule} from './shared.js';
7
+ const TIMELINE_VIRTUAL_ID = 'virtual:lit-plugin/timeline';
8
+ const TIMELINE_RESOLVED_ID = '\0virtual:lit-plugin/timeline';
9
+ const TIMELINE_STUB =
10
+ 'export const addTimelineEvent = () => {};\n' +
11
+ 'export const addTimelineLayer = () => {};\n';
12
+ /**
13
+ * The public timeline API virtual module, served in dev and build alike:
14
+ * app code importing it must keep building under `vite build`, where the HMR
15
+ * plugin doesn't apply. While these hooks lived on that serve-only plugin,
16
+ * nothing claimed the specifier during a build and the bundler failed to
17
+ * resolve it.
18
+ *
19
+ * `getTimeline` is a getter, not a value: `litPlugin()` re-resolves its
20
+ * options against the loaded env in a `config` hook, which runs after the
21
+ * plugin array is built.
22
+ */
23
+ export const litTimelineVirtual = (getTimeline = () => false) => {
24
+ let isBuild = false;
25
+ return {
26
+ name: 'lit-timeline-virtual',
27
+ configResolved(config) {
28
+ isBuild = config.command === 'build';
29
+ },
30
+ resolveId(id) {
31
+ return id === TIMELINE_VIRTUAL_ID ? TIMELINE_RESOLVED_ID : null;
32
+ },
33
+ load(id) {
34
+ if (id !== TIMELINE_RESOLVED_ID) {
35
+ return null;
36
+ }
37
+ // Under build the stub is unconditional, even with `timeline: true`.
38
+ // The runtime delivers only over `import.meta.hot`, so in a production
39
+ // bundle it is a queue that never drains; the stub keeps the transport
40
+ // out of the bundle and makes the documented "no-op in production"
41
+ // behavior true.
42
+ if (isBuild || !getTimeline()) {
43
+ return {code: TIMELINE_STUB, moduleType: 'js'};
44
+ }
45
+ const apiPath = resolveRuntimeModule('timeline/public-api');
46
+ return {
47
+ code: `export * from ${JSON.stringify(apiPath)};\n`,
48
+ moduleType: 'js',
49
+ };
50
+ },
51
+ };
52
+ };
53
+ //# sourceMappingURL=timeline-virtual.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline-virtual.js","sourceRoot":"","sources":["../../src/lib/plugins/timeline-virtual.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAC,oBAAoB,EAAC,MAAM,aAAa,CAAC;AAEjD,MAAM,mBAAmB,GAAG,6BAA6B,CAAC;AAC1D,MAAM,oBAAoB,GAAG,+BAA+B,CAAC;AAC7D,MAAM,aAAa,GACjB,6CAA6C;IAC7C,6CAA6C,CAAC;AAEhD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,WAAW,GAAkB,GAAG,EAAE,CAAC,KAAK,EAChC,EAAE;IACV,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,OAAO;QACL,IAAI,EAAE,sBAAsB;QAC5B,cAAc,CAAC,MAAM;YACnB,OAAO,GAAG,MAAM,CAAC,OAAO,KAAK,OAAO,CAAC;QACvC,CAAC;QACD,SAAS,CAAC,EAAE;YACV,OAAO,EAAE,KAAK,mBAAmB,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC;QAClE,CAAC;QACD,IAAI,CAAC,EAAE;YACL,IAAI,EAAE,KAAK,oBAAoB,EAAE,CAAC;gBAChC,OAAO,IAAI,CAAC;YACd,CAAC;YACD,qEAAqE;YACrE,uEAAuE;YACvE,uEAAuE;YACvE,mEAAmE;YACnE,iBAAiB;YACjB,IAAI,OAAO,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBAC9B,OAAO,EAAC,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,IAAI,EAAC,CAAC;YACjD,CAAC;YACD,MAAM,OAAO,GAAG,oBAAoB,CAAC,qBAAqB,CAAC,CAAC;YAC5D,OAAO;gBACL,IAAI,EAAE,iBAAiB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK;gBACnD,UAAU,EAAE,IAAI;aACjB,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nimport type {Plugin} from 'vite';\nimport {resolveRuntimeModule} from './shared.js';\n\nconst TIMELINE_VIRTUAL_ID = 'virtual:lit-plugin/timeline';\nconst TIMELINE_RESOLVED_ID = '\\0virtual:lit-plugin/timeline';\nconst TIMELINE_STUB =\n 'export const addTimelineEvent = () => {};\\n' +\n 'export const addTimelineLayer = () => {};\\n';\n\n/**\n * The public timeline API virtual module, served in dev and build alike:\n * app code importing it must keep building under `vite build`, where the HMR\n * plugin doesn't apply. While these hooks lived on that serve-only plugin,\n * nothing claimed the specifier during a build and the bundler failed to\n * resolve it.\n *\n * `getTimeline` is a getter, not a value: `litPlugin()` re-resolves its\n * options against the loaded env in a `config` hook, which runs after the\n * plugin array is built.\n */\nexport const litTimelineVirtual = (\n getTimeline: () => boolean = () => false\n): Plugin => {\n let isBuild = false;\n return {\n name: 'lit-timeline-virtual',\n configResolved(config) {\n isBuild = config.command === 'build';\n },\n resolveId(id) {\n return id === TIMELINE_VIRTUAL_ID ? TIMELINE_RESOLVED_ID : null;\n },\n load(id) {\n if (id !== TIMELINE_RESOLVED_ID) {\n return null;\n }\n // Under build the stub is unconditional, even with `timeline: true`.\n // The runtime delivers only over `import.meta.hot`, so in a production\n // bundle it is a queue that never drains; the stub keeps the transport\n // out of the bundle and makes the documented \"no-op in production\"\n // behavior true.\n if (isBuild || !getTimeline()) {\n return {code: TIMELINE_STUB, moduleType: 'js'};\n }\n const apiPath = resolveRuntimeModule('timeline/public-api');\n return {\n code: `export * from ${JSON.stringify(apiPath)};\\n`,\n moduleType: 'js',\n };\n },\n };\n};\n"]}
@@ -16,7 +16,7 @@
16
16
  * @example
17
17
  * ```ts
18
18
  * import cssUrl from './my-element.css?url';
19
- * import {devCacheBust} from '@lit-labs/vite-plugin-lit/css.js';
19
+ * import {devCacheBust} from '@oddsquad/vite-plugin-lit/css.js';
20
20
  *
21
21
  * const href = devCacheBust(cssUrl); // module scope
22
22
  * html`<link rel="stylesheet" href="${href}" />`;
@@ -67,7 +67,7 @@ export interface UrlSheet {
67
67
  *
68
68
  * @example
69
69
  * ```ts
70
- * import {urlSheet} from '@lit-labs/vite-plugin-lit/css.js';
70
+ * import {urlSheet} from '@oddsquad/vite-plugin-lit/css.js';
71
71
  * import sheetUrl from './utils.css?url';
72
72
  *
73
73
  * const {sheet, onHotUpdate} = urlSheet(sheetUrl);
@@ -1 +1 @@
1
- {"version":3,"file":"css.d.ts","sourceRoot":"","sources":["../../../../packages/labs/vite-plugin-lit/src/lib/runtime/css.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA4BH;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,KAAG,MAE1C,CAAC;AAqBF;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB;;;;;;;;;OASG;IACH,KAAK,EAAE,aAAa,CAAC;IACrB;;;;;;;;;;;;OAYG;IACH,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,KAAK,IAAI,CAAC;CACjE;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,QAAQ,GAAI,KAAK,MAAM,KAAG,QA2BtC,CAAC"}
1
+ {"version":3,"file":"css.d.ts","sourceRoot":"","sources":["../../src/lib/runtime/css.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA4BH;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,YAAY,QAAS,MAAM,KAAG,MAE1C,CAAC;AAqBF;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB;;;;;;;;;OASG;IACH,KAAK,EAAE,aAAa,CAAC;IACrB;;;;;;;;;;;;OAYG;IACH,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,KAAK,IAAI,CAAC;CACjE;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,QAAQ,QAAS,MAAM,KAAG,QAkCtC,CAAC"}
@@ -39,14 +39,14 @@ const isDev = () => import.meta.env?.DEV === true;
39
39
  * @example
40
40
  * ```ts
41
41
  * import cssUrl from './my-element.css?url';
42
- * import {devCacheBust} from '@lit-labs/vite-plugin-lit/css.js';
42
+ * import {devCacheBust} from '@oddsquad/vite-plugin-lit/css.js';
43
43
  *
44
44
  * const href = devCacheBust(cssUrl); // module scope
45
45
  * html`<link rel="stylesheet" href="${href}" />`;
46
46
  * ```
47
47
  */
48
48
  export const devCacheBust = (url) => {
49
- return isDev() ? `${url}?t=${Date.now()}` : url;
49
+ return isDev() ? `${url}?t=${Date.now()}` : url;
50
50
  };
51
51
  /**
52
52
  * In dev, turns a `?url`-imported CSS path into one that fetches the
@@ -61,10 +61,10 @@ export const devCacheBust = (url) => {
61
61
  * it carries `?t=…`).
62
62
  */
63
63
  const devDirect = (url) => {
64
- if (!isDev()) {
65
- return url;
66
- }
67
- return `${url}${url.includes('?') ? '&' : '?'}direct`;
64
+ if (!isDev()) {
65
+ return url;
66
+ }
67
+ return `${url}${url.includes('?') ? '&' : '?'}direct`;
68
68
  };
69
69
  /**
70
70
  * Builds a {@link UrlSheet} from a `?url`-imported CSS asset: a single
@@ -79,7 +79,7 @@ const devDirect = (url) => {
79
79
  *
80
80
  * @example
81
81
  * ```ts
82
- * import {urlSheet} from '@lit-labs/vite-plugin-lit/css.js';
82
+ * import {urlSheet} from '@oddsquad/vite-plugin-lit/css.js';
83
83
  * import sheetUrl from './utils.css?url';
84
84
  *
85
85
  * const {sheet, onHotUpdate} = urlSheet(sheetUrl);
@@ -89,31 +89,38 @@ const devDirect = (url) => {
89
89
  * ```
90
90
  */
91
91
  export const urlSheet = (url) => {
92
- const sheet = new CSSStyleSheet();
93
- // Guards against out-of-order fetch resolution: two rapid edits fire
94
- // overlapping fetches, and a slower earlier one must not land after (and
95
- // clobber) a newer one. Only the most recently issued request applies.
96
- let latest = 0;
97
- const update = (next) => {
98
- const token = ++latest;
99
- return fetch(devDirect(next))
100
- .then((r) => r.text())
101
- .then((css) => {
102
- if (token === latest) {
103
- sheet.replaceSync(css);
104
- }
105
- })
106
- .catch(() => { });
107
- };
108
- update(url);
109
- return {
110
- sheet,
111
- onHotUpdate: (mod) => {
112
- const next = mod?.['default'];
113
- if (typeof next === 'string') {
114
- update(next);
115
- }
116
- },
117
- };
92
+ const sheet = new CSSStyleSheet();
93
+ // Guards against out-of-order fetch resolution: two rapid edits fire
94
+ // overlapping fetches, and a slower earlier one must not land after (and
95
+ // clobber) a newer one. Only the most recently issued request applies.
96
+ let latest = 0;
97
+ const update = (next) => {
98
+ const token = ++latest;
99
+ return fetch(devDirect(next))
100
+ .then((r) => {
101
+ // A 404 still has a body (Vite's fallback page); don't adopt it as css.
102
+ if (!r.ok) throw new Error(`HTTP ${r.status}`);
103
+ return r.text();
104
+ })
105
+ .then((css) => {
106
+ if (token === latest) {
107
+ sheet.replaceSync(css);
108
+ }
109
+ })
110
+ .catch((err) => {
111
+ // Keep the last good sheet; just say why this update didn't land.
112
+ console.warn(`[lit-plugin] urlSheet: failed to load ${next}:`, err);
113
+ });
114
+ };
115
+ void update(url);
116
+ return {
117
+ sheet,
118
+ onHotUpdate: (mod) => {
119
+ const next = mod?.['default'];
120
+ if (typeof next === 'string') {
121
+ void update(next);
122
+ }
123
+ },
124
+ };
118
125
  };
119
- //# sourceMappingURL=css.js.map
126
+ //# sourceMappingURL=css.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"css.js","sourceRoot":"","sources":["../../../../packages/labs/vite-plugin-lit/src/lib/runtime/css.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;;GAaG;AAEH;;;;;;;GAOG;AACH,MAAM,KAAK,GAAG,GAAY,EAAE,CACzB,MAAM,CAAC,IAAgC,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;AAE7D;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAW,EAAU,EAAE;IAClD,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;AAClD,CAAC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,SAAS,GAAG,CAAC,GAAW,EAAU,EAAE;IACxC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;QACb,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,GAAG,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC;AACxD,CAAC,CAAC;AAkCF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAY,EAAE;IAChD,MAAM,KAAK,GAAG,IAAI,aAAa,EAAE,CAAC;IAClC,qEAAqE;IACrE,yEAAyE;IACzE,uEAAuE;IACvE,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,MAAM,MAAM,GAAG,CAAC,IAAY,EAAiB,EAAE;QAC7C,MAAM,KAAK,GAAG,EAAE,MAAM,CAAC;QACvB,OAAO,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;aAC1B,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aACrB,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;YACZ,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;gBACrB,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;QACH,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACrB,CAAC,CAAC;IACF,MAAM,CAAC,GAAG,CAAC,CAAC;IACZ,OAAO;QACL,KAAK;QACL,WAAW,EAAE,CAAC,GAAG,EAAE,EAAE;YACnB,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAC9B,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC7B,MAAM,CAAC,IAAI,CAAC,CAAC;YACf,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * Browser helpers for referencing CSS files from shadow roots via Vite's\n * `?url` imports.\n *\n * A `?url` import yields a real stylesheet URL — the dev server serves the\n * file as CSS, and `vite build` emits it as a hashed `.css` asset. That\n * makes it the right base for `<link>` hrefs and `@import url()`s inside\n * shadow roots. The one gap is dev HMR: the imported URL string is identical\n * across module re-executions, so the browser would keep the stale\n * stylesheet. These helpers close that gap.\n *\n * This module is dependency-free and must stay safe to load in any\n * environment.\n */\n\n/**\n * Vite's dev flag. Accessed as a direct member expression (`import.meta.env.DEV`)\n * so the bundler can statically replace it per key. Aliasing the whole object\n * (`const env = import.meta.env`) instead defeats that replacement and makes\n * Vite inline the ENTIRE serialized `import.meta.env` — every env var — into the\n * consumer bundle. Optional chaining keeps this safe where `import.meta.env` is\n * absent (non-Vite runtimes).\n */\nconst isDev = (): boolean =>\n (import.meta as {env?: {DEV?: boolean}}).env?.DEV === true;\n\n/**\n * Appends a cache-busting query to a `?url`-imported CSS file URL in dev.\n *\n * Call this at *module scope* (not in `render()`, where every render would\n * refetch): each HMR re-execution then yields a fresh href and the browser\n * refetches the changed stylesheet.\n *\n * In production builds the URL is a content-hashed asset, so the input is\n * returned unchanged.\n *\n * @example\n * ```ts\n * import cssUrl from './my-element.css?url';\n * import {devCacheBust} from '@lit-labs/vite-plugin-lit/css.js';\n *\n * const href = devCacheBust(cssUrl); // module scope\n * html`<link rel=\"stylesheet\" href=\"${href}\" />`;\n * ```\n */\nexport const devCacheBust = (url: string): string => {\n return isDev() ? `${url}?t=${Date.now()}` : url;\n};\n\n/**\n * In dev, turns a `?url`-imported CSS path into one that fetches the\n * *compiled CSS bytes* (`text/css`). Vite serves a `?url` CSS path as a JS\n * module (`__vite__updateStyle(…)`), so a plain `fetch().text()` returns\n * JavaScript; the `direct` query makes it return the stylesheet instead,\n * pipeline-processed the same way the build asset is. In production the URL\n * is already a real `.css` asset, so it's returned unchanged.\n *\n * Joined with `?` or `&` depending on whether the URL already carries a query\n * (a freshly started dev server yields a bare path; after an HMR cache-bust\n * it carries `?t=…`).\n */\nconst devDirect = (url: string): string => {\n if (!isDev()) {\n return url;\n }\n return `${url}${url.includes('?') ? '&' : '?'}direct`;\n};\n\n/**\n * A shared `CSSStyleSheet` backed by a `?url` CSS asset, plus the callback to\n * hot-swap it in place. Returned by {@link urlSheet}.\n */\nexport interface UrlSheet {\n /**\n * The constructed stylesheet. Adopt it from any number of components\n * (`static styles = [sheet]`); an edit to the source CSS re-fetches and\n * `replaceSync()`s it, updating every shadow root that adopted it without\n * re-rendering a component or reloading the page.\n *\n * It is empty until the first fetch resolves, so expect a brief flash of\n * unstyled content on initial load — the cost of keeping the CSS as a real\n * asset rather than inlining it into the JS bundle.\n */\n sheet: CSSStyleSheet;\n /**\n * Vite HMR accept callback for the `?url` dependency. Wire it up with the\n * *same literal specifier* you imported — Vite resolves accepted deps by\n * static analysis, so the string has to appear in your module:\n *\n * ```ts\n * import.meta.hot?.accept('./utils.css?url', onHotUpdate);\n * ```\n *\n * Typed to match Vite's accept callback (`ModuleNamespace | undefined`) so\n * it drops straight in; the new module's `default` export is the updated\n * `?url` string.\n */\n onHotUpdate: (mod: Record<string, unknown> | undefined) => void;\n}\n\n/**\n * Builds a {@link UrlSheet} from a `?url`-imported CSS asset: a single\n * constructed `CSSStyleSheet`, shareable across shadow roots via\n * `adoptedStyleSheets`, that hot-swaps in place on edits — no component\n * re-render, no full-page reload.\n *\n * `?url` keeps the stylesheet as a standalone, pipeline-processed `.css` file\n * in the build output (unlike `?inline`/`?raw`, which inline it into the JS\n * chunk). The file is read into the sheet at runtime via `fetch()`, with the\n * dev/build path difference handled internally.\n *\n * @example\n * ```ts\n * import {urlSheet} from '@lit-labs/vite-plugin-lit/css.js';\n * import sheetUrl from './utils.css?url';\n *\n * const {sheet, onHotUpdate} = urlSheet(sheetUrl);\n * export default sheet; // `static styles = [sheet]` in components\n *\n * import.meta.hot?.accept('./utils.css?url', onHotUpdate);\n * ```\n */\nexport const urlSheet = (url: string): UrlSheet => {\n const sheet = new CSSStyleSheet();\n // Guards against out-of-order fetch resolution: two rapid edits fire\n // overlapping fetches, and a slower earlier one must not land after (and\n // clobber) a newer one. Only the most recently issued request applies.\n let latest = 0;\n const update = (next: string): Promise<void> => {\n const token = ++latest;\n return fetch(devDirect(next))\n .then((r) => r.text())\n .then((css) => {\n if (token === latest) {\n sheet.replaceSync(css);\n }\n })\n .catch(() => {});\n };\n update(url);\n return {\n sheet,\n onHotUpdate: (mod) => {\n const next = mod?.['default'];\n if (typeof next === 'string') {\n update(next);\n }\n },\n };\n};\n"]}
1
+ {"version":3,"file":"css.js","sourceRoot":"","sources":["../../src/lib/runtime/css.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;;GAaG;AAEH;;;;;;;GAOG;AACH,MAAM,KAAK,GAAG,GAAY,EAAE,CACzB,OAAO,IAAgC,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;AAE7D;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAW,EAAU,EAAE;IAClD,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;AAClD,CAAC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,SAAS,GAAG,CAAC,GAAW,EAAU,EAAE;IACxC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;QACb,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,GAAG,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC;AACxD,CAAC,CAAC;AAkCF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAY,EAAE;IAChD,MAAM,KAAK,GAAG,IAAI,aAAa,EAAE,CAAC;IAClC,qEAAqE;IACrE,yEAAyE;IACzE,uEAAuE;IACvE,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,MAAM,MAAM,GAAG,CAAC,IAAY,EAAiB,EAAE;QAC7C,MAAM,KAAK,GAAG,EAAE,MAAM,CAAC;QACvB,OAAO,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;aAC1B,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;YACV,wEAAwE;YACxE,IAAI,CAAC,CAAC,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;YAC/C,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QAClB,CAAC,CAAC;aACD,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;YACZ,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;gBACrB,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;QACH,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;YACtB,kEAAkE;YAClE,OAAO,CAAC,IAAI,CAAC,yCAAyC,IAAI,GAAG,EAAE,GAAG,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;IACF,KAAK,MAAM,CAAC,GAAG,CAAC,CAAC;IACjB,OAAO;QACL,KAAK;QACL,WAAW,EAAE,CAAC,GAAG,EAAE,EAAE;YACnB,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAC9B,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC7B,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * Browser helpers for referencing CSS files from shadow roots via Vite's\n * `?url` imports.\n *\n * A `?url` import yields a real stylesheet URL — the dev server serves the\n * file as CSS, and `vite build` emits it as a hashed `.css` asset. That\n * makes it the right base for `<link>` hrefs and `@import url()`s inside\n * shadow roots. The one gap is dev HMR: the imported URL string is identical\n * across module re-executions, so the browser would keep the stale\n * stylesheet. These helpers close that gap.\n *\n * This module is dependency-free and must stay safe to load in any\n * environment.\n */\n\n/**\n * Vite's dev flag. Accessed as a direct member expression (`import.meta.env.DEV`)\n * so the bundler can statically replace it per key. Aliasing the whole object\n * (`const env = import.meta.env`) instead defeats that replacement and makes\n * Vite inline the ENTIRE serialized `import.meta.env` — every env var — into the\n * consumer bundle. Optional chaining keeps this safe where `import.meta.env` is\n * absent (non-Vite runtimes).\n */\nconst isDev = (): boolean =>\n (import.meta as {env?: {DEV?: boolean}}).env?.DEV === true;\n\n/**\n * Appends a cache-busting query to a `?url`-imported CSS file URL in dev.\n *\n * Call this at *module scope* (not in `render()`, where every render would\n * refetch): each HMR re-execution then yields a fresh href and the browser\n * refetches the changed stylesheet.\n *\n * In production builds the URL is a content-hashed asset, so the input is\n * returned unchanged.\n *\n * @example\n * ```ts\n * import cssUrl from './my-element.css?url';\n * import {devCacheBust} from '@oddsquad/vite-plugin-lit/css.js';\n *\n * const href = devCacheBust(cssUrl); // module scope\n * html`<link rel=\"stylesheet\" href=\"${href}\" />`;\n * ```\n */\nexport const devCacheBust = (url: string): string => {\n return isDev() ? `${url}?t=${Date.now()}` : url;\n};\n\n/**\n * In dev, turns a `?url`-imported CSS path into one that fetches the\n * *compiled CSS bytes* (`text/css`). Vite serves a `?url` CSS path as a JS\n * module (`__vite__updateStyle(…)`), so a plain `fetch().text()` returns\n * JavaScript; the `direct` query makes it return the stylesheet instead,\n * pipeline-processed the same way the build asset is. In production the URL\n * is already a real `.css` asset, so it's returned unchanged.\n *\n * Joined with `?` or `&` depending on whether the URL already carries a query\n * (a freshly started dev server yields a bare path; after an HMR cache-bust\n * it carries `?t=…`).\n */\nconst devDirect = (url: string): string => {\n if (!isDev()) {\n return url;\n }\n return `${url}${url.includes('?') ? '&' : '?'}direct`;\n};\n\n/**\n * A shared `CSSStyleSheet` backed by a `?url` CSS asset, plus the callback to\n * hot-swap it in place. Returned by {@link urlSheet}.\n */\nexport interface UrlSheet {\n /**\n * The constructed stylesheet. Adopt it from any number of components\n * (`static styles = [sheet]`); an edit to the source CSS re-fetches and\n * `replaceSync()`s it, updating every shadow root that adopted it without\n * re-rendering a component or reloading the page.\n *\n * It is empty until the first fetch resolves, so expect a brief flash of\n * unstyled content on initial load — the cost of keeping the CSS as a real\n * asset rather than inlining it into the JS bundle.\n */\n sheet: CSSStyleSheet;\n /**\n * Vite HMR accept callback for the `?url` dependency. Wire it up with the\n * *same literal specifier* you imported — Vite resolves accepted deps by\n * static analysis, so the string has to appear in your module:\n *\n * ```ts\n * import.meta.hot?.accept('./utils.css?url', onHotUpdate);\n * ```\n *\n * Typed to match Vite's accept callback (`ModuleNamespace | undefined`) so\n * it drops straight in; the new module's `default` export is the updated\n * `?url` string.\n */\n onHotUpdate: (mod: Record<string, unknown> | undefined) => void;\n}\n\n/**\n * Builds a {@link UrlSheet} from a `?url`-imported CSS asset: a single\n * constructed `CSSStyleSheet`, shareable across shadow roots via\n * `adoptedStyleSheets`, that hot-swaps in place on edits — no component\n * re-render, no full-page reload.\n *\n * `?url` keeps the stylesheet as a standalone, pipeline-processed `.css` file\n * in the build output (unlike `?inline`/`?raw`, which inline it into the JS\n * chunk). The file is read into the sheet at runtime via `fetch()`, with the\n * dev/build path difference handled internally.\n *\n * @example\n * ```ts\n * import {urlSheet} from '@oddsquad/vite-plugin-lit/css.js';\n * import sheetUrl from './utils.css?url';\n *\n * const {sheet, onHotUpdate} = urlSheet(sheetUrl);\n * export default sheet; // `static styles = [sheet]` in components\n *\n * import.meta.hot?.accept('./utils.css?url', onHotUpdate);\n * ```\n */\nexport const urlSheet = (url: string): UrlSheet => {\n const sheet = new CSSStyleSheet();\n // Guards against out-of-order fetch resolution: two rapid edits fire\n // overlapping fetches, and a slower earlier one must not land after (and\n // clobber) a newer one. Only the most recently issued request applies.\n let latest = 0;\n const update = (next: string): Promise<void> => {\n const token = ++latest;\n return fetch(devDirect(next))\n .then((r) => {\n // A 404 still has a body (Vite's fallback page); don't adopt it as css.\n if (!r.ok) throw new Error(`HTTP ${r.status}`);\n return r.text();\n })\n .then((css) => {\n if (token === latest) {\n sheet.replaceSync(css);\n }\n })\n .catch((err: unknown) => {\n // Keep the last good sheet; just say why this update didn't land.\n console.warn(`[lit-plugin] urlSheet: failed to load ${next}:`, err);\n });\n };\n void update(url);\n return {\n sheet,\n onHotUpdate: (mod) => {\n const next = mod?.['default'];\n if (typeof next === 'string') {\n void update(next);\n }\n },\n };\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"edge-panel.d.ts","sourceRoot":"","sources":["../../../../packages/labs/vite-plugin-lit/src/lib/runtime/edge-panel.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAoBH,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAyCD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAC5B,UAAU,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,KACrC,CAAC,MAAM,IAAI,CA+Db,CAAC"}
1
+ {"version":3,"file":"edge-panel.d.ts","sourceRoot":"","sources":["../../src/lib/runtime/edge-panel.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAoBH,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAyCD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,aAClB,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,KACrC,CAAC,MAAM,IAAI,CA+Db,CAAC"}
@@ -19,11 +19,11 @@ const PANEL_ID = 'vite-devtools-edge-panel';
19
19
  const GAP = 12;
20
20
  /** Tolerance (px) for treating the panel as touching a viewport edge. */
21
21
  const EDGE = 2;
22
- const ZERO = { top: 0, right: 0, bottom: 0, left: 0 };
22
+ const ZERO = {top: 0, right: 0, bottom: 0, left: 0};
23
23
  const findPanel = () => {
24
- const host = document.querySelector(HOST_TAG);
25
- const root = host?.shadowRoot;
26
- return root?.getElementById(PANEL_ID) ?? null;
24
+ const host = document.querySelector(HOST_TAG);
25
+ const root = host?.shadowRoot;
26
+ return root?.getElementById(PANEL_ID) ?? null;
27
27
  };
28
28
  /**
29
29
  * Inset (px + gap) the docked panel occupies, on the single edge it's docked
@@ -33,34 +33,27 @@ const findPanel = () => {
33
33
  * wrongly flag a full-width bottom panel as also docked left and right.)
34
34
  */
35
35
  const computeInsets = () => {
36
- const panel = findPanel();
37
- if (panel === null)
38
- return ZERO;
39
- const r = panel.getBoundingClientRect();
40
- if (r.width === 0 || r.height === 0)
41
- return ZERO;
42
- // Use the layout viewport (excludes scrollbars) — a fixed `right:0`/`bottom:0`
43
- // panel aligns to clientWidth/Height, not innerWidth/Height, so comparing
44
- // against the latter would miss a full-width panel whenever a scrollbar is
45
- // present.
46
- const vw = document.documentElement.clientWidth;
47
- const vh = document.documentElement.clientHeight;
48
- const spansWidth = r.left <= EDGE && r.right >= vw - EDGE;
49
- const spansHeight = r.top <= EDGE && r.bottom >= vh - EDGE;
50
- const insets = { ...ZERO };
51
- if (spansWidth && !spansHeight) {
52
- if (r.top <= EDGE)
53
- insets.top = r.bottom + GAP;
54
- else if (r.bottom >= vh - EDGE)
55
- insets.bottom = vh - r.top + GAP;
56
- }
57
- else if (spansHeight && !spansWidth) {
58
- if (r.left <= EDGE)
59
- insets.left = r.right + GAP;
60
- else if (r.right >= vw - EDGE)
61
- insets.right = vw - r.left + GAP;
62
- }
63
- return insets;
36
+ const panel = findPanel();
37
+ if (panel === null) return ZERO;
38
+ const r = panel.getBoundingClientRect();
39
+ if (r.width === 0 || r.height === 0) return ZERO;
40
+ // Use the layout viewport (excludes scrollbars) — a fixed `right:0`/`bottom:0`
41
+ // panel aligns to clientWidth/Height, not innerWidth/Height, so comparing
42
+ // against the latter would miss a full-width panel whenever a scrollbar is
43
+ // present.
44
+ const vw = document.documentElement.clientWidth;
45
+ const vh = document.documentElement.clientHeight;
46
+ const spansWidth = r.left <= EDGE && r.right >= vw - EDGE;
47
+ const spansHeight = r.top <= EDGE && r.bottom >= vh - EDGE;
48
+ const insets = {...ZERO};
49
+ if (spansWidth && !spansHeight) {
50
+ if (r.top <= EDGE) insets.top = r.bottom + GAP;
51
+ else if (r.bottom >= vh - EDGE) insets.bottom = vh - r.top + GAP;
52
+ } else if (spansHeight && !spansWidth) {
53
+ if (r.left <= EDGE) insets.left = r.right + GAP;
54
+ else if (r.right >= vw - EDGE) insets.right = vw - r.left + GAP;
55
+ }
56
+ return insets;
64
57
  };
65
58
  /**
66
59
  * Calls `onChange` with the current insets and again whenever they change — the
@@ -68,63 +61,61 @@ const computeInsets = () => {
68
61
  * mounting after us. Returns a disposer.
69
62
  */
70
63
  export const observeEdgeInsets = (onChange) => {
71
- let raf = 0;
72
- let last = '';
73
- let observedPanel = null;
74
- let observingRoot = false;
75
- const emit = () => {
76
- raf = 0;
77
- const insets = computeInsets();
78
- const key = `${insets.top}|${insets.right}|${insets.bottom}|${insets.left}`;
79
- if (key !== last) {
80
- last = key;
81
- onChange(insets);
82
- }
83
- };
84
- const schedule = () => {
85
- if (raf === 0)
86
- raf = requestAnimationFrame(emit);
87
- };
88
- const ro = new ResizeObserver(schedule);
89
- // Re-attach on any devtools DOM change (panel mounting, docking to a new edge)
90
- // then recompute; cheap thanks to the rAF + diff above.
91
- const mo = new MutationObserver(() => attach());
92
- const attach = () => {
93
- const host = document.querySelector(HOST_TAG);
94
- const root = host?.shadowRoot;
95
- if (root && !observingRoot) {
96
- observingRoot = true;
97
- mo.observe(root, {
98
- childList: true,
99
- subtree: true,
100
- attributes: true,
101
- attributeFilter: ['style', 'class'],
102
- });
103
- }
104
- const panel = findPanel();
105
- if (panel !== null && panel !== observedPanel) {
106
- observedPanel = panel;
107
- ro.observe(panel);
108
- }
109
- schedule();
110
- };
111
- // The devtools host mounts asynchronously; poll until it's present, then let
112
- // the observers drive updates.
113
- let tries = 0;
114
- const poll = () => {
115
- attach();
116
- if (!observingRoot && tries++ < 60) {
117
- setTimeout(poll, 250);
118
- }
119
- };
120
- poll();
121
- window.addEventListener('resize', schedule);
122
- return () => {
123
- window.removeEventListener('resize', schedule);
124
- ro.disconnect();
125
- mo.disconnect();
126
- if (raf !== 0)
127
- cancelAnimationFrame(raf);
128
- };
64
+ let raf = 0;
65
+ let last = '';
66
+ let observedPanel = null;
67
+ let observingRoot = false;
68
+ const emit = () => {
69
+ raf = 0;
70
+ const insets = computeInsets();
71
+ const key = `${insets.top}|${insets.right}|${insets.bottom}|${insets.left}`;
72
+ if (key !== last) {
73
+ last = key;
74
+ onChange(insets);
75
+ }
76
+ };
77
+ const schedule = () => {
78
+ if (raf === 0) raf = requestAnimationFrame(emit);
79
+ };
80
+ const ro = new ResizeObserver(schedule);
81
+ // Re-attach on any devtools DOM change (panel mounting, docking to a new edge)
82
+ // then recompute; cheap thanks to the rAF + diff above.
83
+ const mo = new MutationObserver(() => attach());
84
+ const attach = () => {
85
+ const host = document.querySelector(HOST_TAG);
86
+ const root = host?.shadowRoot;
87
+ if (root && !observingRoot) {
88
+ observingRoot = true;
89
+ mo.observe(root, {
90
+ childList: true,
91
+ subtree: true,
92
+ attributes: true,
93
+ attributeFilter: ['style', 'class'],
94
+ });
95
+ }
96
+ const panel = findPanel();
97
+ if (panel !== null && panel !== observedPanel) {
98
+ observedPanel = panel;
99
+ ro.observe(panel);
100
+ }
101
+ schedule();
102
+ };
103
+ // The devtools host mounts asynchronously; poll until it's present, then let
104
+ // the observers drive updates.
105
+ let tries = 0;
106
+ const poll = () => {
107
+ attach();
108
+ if (!observingRoot && tries++ < 60) {
109
+ setTimeout(poll, 250);
110
+ }
111
+ };
112
+ poll();
113
+ window.addEventListener('resize', schedule);
114
+ return () => {
115
+ window.removeEventListener('resize', schedule);
116
+ ro.disconnect();
117
+ mo.disconnect();
118
+ if (raf !== 0) cancelAnimationFrame(raf);
119
+ };
129
120
  };
130
- //# sourceMappingURL=edge-panel.js.map
121
+ //# sourceMappingURL=edge-panel.js.map