one 1.2.83 → 1.2.84

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 (288) hide show
  1. package/devtools/dev.mjs +44 -0
  2. package/devtools/devtools.mjs +540 -0
  3. package/devtools/source-inspector.mjs +201 -0
  4. package/dist/cjs/cli/daemon.cjs +136 -0
  5. package/dist/cjs/cli/daemon.js +112 -0
  6. package/dist/cjs/cli/daemon.js.map +6 -0
  7. package/dist/cjs/cli/daemon.native.js +173 -0
  8. package/dist/cjs/cli/daemon.native.js.map +1 -0
  9. package/dist/cjs/createHandleRequest.cjs +15 -8
  10. package/dist/cjs/createHandleRequest.js +10 -6
  11. package/dist/cjs/createHandleRequest.js.map +1 -1
  12. package/dist/cjs/createHandleRequest.native.js +8 -3
  13. package/dist/cjs/createHandleRequest.native.js.map +1 -1
  14. package/dist/cjs/daemon/index.cjs +24 -0
  15. package/dist/cjs/daemon/index.js +21 -0
  16. package/dist/cjs/daemon/index.js.map +6 -0
  17. package/dist/cjs/daemon/index.native.js +27 -0
  18. package/dist/cjs/daemon/index.native.js.map +1 -0
  19. package/dist/cjs/daemon/ipc.cjs +235 -0
  20. package/dist/cjs/daemon/ipc.js +204 -0
  21. package/dist/cjs/daemon/ipc.js.map +6 -0
  22. package/dist/cjs/daemon/ipc.native.js +276 -0
  23. package/dist/cjs/daemon/ipc.native.js.map +1 -0
  24. package/dist/cjs/daemon/picker.cjs +223 -0
  25. package/dist/cjs/daemon/picker.js +191 -0
  26. package/dist/cjs/daemon/picker.js.map +6 -0
  27. package/dist/cjs/daemon/picker.native.js +308 -0
  28. package/dist/cjs/daemon/picker.native.js.map +1 -0
  29. package/dist/cjs/daemon/proxy.cjs +75 -0
  30. package/dist/cjs/daemon/proxy.js +70 -0
  31. package/dist/cjs/daemon/proxy.js.map +6 -0
  32. package/dist/cjs/daemon/proxy.native.js +81 -0
  33. package/dist/cjs/daemon/proxy.native.js.map +1 -0
  34. package/dist/cjs/daemon/registry.cjs +85 -0
  35. package/dist/cjs/daemon/registry.js +81 -0
  36. package/dist/cjs/daemon/registry.js.map +6 -0
  37. package/dist/cjs/daemon/registry.native.js +120 -0
  38. package/dist/cjs/daemon/registry.native.js.map +1 -0
  39. package/dist/cjs/daemon/server.cjs +178 -0
  40. package/dist/cjs/daemon/server.js +179 -0
  41. package/dist/cjs/daemon/server.js.map +6 -0
  42. package/dist/cjs/daemon/server.native.js +200 -0
  43. package/dist/cjs/daemon/server.native.js.map +1 -0
  44. package/dist/cjs/daemon/tui.cjs +223 -0
  45. package/dist/cjs/daemon/tui.js +192 -0
  46. package/dist/cjs/daemon/tui.js.map +6 -0
  47. package/dist/cjs/daemon/tui.native.js +234 -0
  48. package/dist/cjs/daemon/tui.native.js.map +1 -0
  49. package/dist/cjs/daemon/types.cjs +16 -0
  50. package/dist/cjs/daemon/types.js +14 -0
  51. package/dist/cjs/daemon/types.js.map +6 -0
  52. package/dist/cjs/daemon/types.native.js +19 -0
  53. package/dist/cjs/daemon/types.native.js.map +1 -0
  54. package/dist/cjs/daemon/utils.cjs +74 -0
  55. package/dist/cjs/daemon/utils.js +65 -0
  56. package/dist/cjs/daemon/utils.js.map +6 -0
  57. package/dist/cjs/daemon/utils.native.js +83 -0
  58. package/dist/cjs/daemon/utils.native.js.map +1 -0
  59. package/dist/cjs/fork/createMemoryHistory.cjs +22 -8
  60. package/dist/cjs/fork/createMemoryHistory.js +20 -6
  61. package/dist/cjs/fork/createMemoryHistory.js.map +1 -1
  62. package/dist/cjs/fork/createMemoryHistory.native.js +22 -8
  63. package/dist/cjs/fork/createMemoryHistory.native.js.map +1 -1
  64. package/dist/cjs/fork/useLinking.cjs +52 -13
  65. package/dist/cjs/fork/useLinking.js +35 -10
  66. package/dist/cjs/fork/useLinking.js.map +1 -1
  67. package/dist/cjs/index.cjs +6 -2
  68. package/dist/cjs/index.js +4 -2
  69. package/dist/cjs/index.js.map +2 -2
  70. package/dist/cjs/index.native.js +6 -2
  71. package/dist/cjs/index.native.js.map +1 -1
  72. package/dist/cjs/router/linkingConfig.cjs +13 -2
  73. package/dist/cjs/router/linkingConfig.js +14 -5
  74. package/dist/cjs/router/linkingConfig.js.map +1 -1
  75. package/dist/cjs/router/linkingConfig.native.js +10 -1
  76. package/dist/cjs/router/linkingConfig.native.js.map +1 -1
  77. package/dist/cjs/router/routeMask.cjs +137 -0
  78. package/dist/cjs/router/routeMask.js +127 -0
  79. package/dist/cjs/router/routeMask.js.map +6 -0
  80. package/dist/cjs/router/routeMask.native.js +160 -0
  81. package/dist/cjs/router/routeMask.native.js.map +1 -0
  82. package/dist/cjs/router/router.cjs +26 -3
  83. package/dist/cjs/router/router.js +23 -3
  84. package/dist/cjs/router/router.js.map +1 -1
  85. package/dist/cjs/router/router.native.js +26 -3
  86. package/dist/cjs/router/router.native.js.map +1 -1
  87. package/dist/cjs/server/PreloadScripts.native.js +45 -39
  88. package/dist/cjs/server/PreloadScripts.native.js.map +1 -6
  89. package/dist/cjs/vite/DevHead.cjs +2 -909
  90. package/dist/cjs/vite/DevHead.js +1 -917
  91. package/dist/cjs/vite/DevHead.js.map +1 -1
  92. package/dist/cjs/vite/DevHead.native.js +1 -882
  93. package/dist/cjs/vite/DevHead.native.js.map +1 -1
  94. package/dist/cjs/vite/one.cjs +4 -1
  95. package/dist/cjs/vite/one.js +4 -2
  96. package/dist/cjs/vite/one.js.map +1 -1
  97. package/dist/cjs/vite/one.native.js +4 -1
  98. package/dist/cjs/vite/one.native.js.map +1 -1
  99. package/dist/cjs/vite/plugins/devtoolsPlugin.cjs +55 -0
  100. package/dist/cjs/vite/plugins/devtoolsPlugin.js +49 -0
  101. package/dist/cjs/vite/plugins/devtoolsPlugin.js.map +6 -0
  102. package/dist/cjs/vite/plugins/devtoolsPlugin.native.js +58 -0
  103. package/dist/cjs/vite/plugins/devtoolsPlugin.native.js.map +1 -0
  104. package/dist/cjs/vite/plugins/fileSystemRouterPlugin.cjs +1 -6
  105. package/dist/cjs/vite/plugins/fileSystemRouterPlugin.js +1 -6
  106. package/dist/cjs/vite/plugins/fileSystemRouterPlugin.js.map +1 -1
  107. package/dist/cjs/vite/plugins/fileSystemRouterPlugin.native.js +1 -6
  108. package/dist/cjs/vite/plugins/fileSystemRouterPlugin.native.js.map +1 -1
  109. package/dist/cjs/vite/plugins/virtualEntryPlugin.cjs +7 -1
  110. package/dist/cjs/vite/plugins/virtualEntryPlugin.js +5 -1
  111. package/dist/cjs/vite/plugins/virtualEntryPlugin.js.map +1 -1
  112. package/dist/cjs/vite/plugins/virtualEntryPlugin.native.js +8 -1
  113. package/dist/cjs/vite/plugins/virtualEntryPlugin.native.js.map +1 -1
  114. package/dist/esm/cli/daemon.js +89 -0
  115. package/dist/esm/cli/daemon.js.map +6 -0
  116. package/dist/esm/cli/daemon.mjs +102 -0
  117. package/dist/esm/cli/daemon.mjs.map +1 -0
  118. package/dist/esm/cli/daemon.native.js +136 -0
  119. package/dist/esm/cli/daemon.native.js.map +1 -0
  120. package/dist/esm/createHandleRequest.js +10 -5
  121. package/dist/esm/createHandleRequest.js.map +1 -1
  122. package/dist/esm/createHandleRequest.mjs +15 -8
  123. package/dist/esm/createHandleRequest.mjs.map +1 -1
  124. package/dist/esm/createHandleRequest.native.js +8 -3
  125. package/dist/esm/createHandleRequest.native.js.map +1 -1
  126. package/dist/esm/daemon/index.js +8 -0
  127. package/dist/esm/daemon/index.js.map +6 -0
  128. package/dist/esm/daemon/index.mjs +8 -0
  129. package/dist/esm/daemon/index.mjs.map +1 -0
  130. package/dist/esm/daemon/index.native.js +8 -0
  131. package/dist/esm/daemon/index.native.js.map +1 -0
  132. package/dist/esm/daemon/ipc.js +192 -0
  133. package/dist/esm/daemon/ipc.js.map +6 -0
  134. package/dist/esm/daemon/ipc.mjs +191 -0
  135. package/dist/esm/daemon/ipc.mjs.map +1 -0
  136. package/dist/esm/daemon/ipc.native.js +229 -0
  137. package/dist/esm/daemon/ipc.native.js.map +1 -0
  138. package/dist/esm/daemon/picker.js +169 -0
  139. package/dist/esm/daemon/picker.js.map +6 -0
  140. package/dist/esm/daemon/picker.mjs +186 -0
  141. package/dist/esm/daemon/picker.mjs.map +1 -0
  142. package/dist/esm/daemon/picker.native.js +268 -0
  143. package/dist/esm/daemon/picker.native.js.map +1 -0
  144. package/dist/esm/daemon/proxy.js +47 -0
  145. package/dist/esm/daemon/proxy.js.map +6 -0
  146. package/dist/esm/daemon/proxy.mjs +40 -0
  147. package/dist/esm/daemon/proxy.mjs.map +1 -0
  148. package/dist/esm/daemon/proxy.native.js +43 -0
  149. package/dist/esm/daemon/proxy.native.js.map +1 -0
  150. package/dist/esm/daemon/registry.js +65 -0
  151. package/dist/esm/daemon/registry.js.map +6 -0
  152. package/dist/esm/daemon/registry.mjs +53 -0
  153. package/dist/esm/daemon/registry.mjs.map +1 -0
  154. package/dist/esm/daemon/registry.native.js +85 -0
  155. package/dist/esm/daemon/registry.native.js.map +1 -0
  156. package/dist/esm/daemon/server.js +167 -0
  157. package/dist/esm/daemon/server.js.map +6 -0
  158. package/dist/esm/daemon/server.mjs +143 -0
  159. package/dist/esm/daemon/server.mjs.map +1 -0
  160. package/dist/esm/daemon/server.native.js +162 -0
  161. package/dist/esm/daemon/server.native.js.map +1 -0
  162. package/dist/esm/daemon/tui.js +171 -0
  163. package/dist/esm/daemon/tui.js.map +6 -0
  164. package/dist/esm/daemon/tui.mjs +187 -0
  165. package/dist/esm/daemon/tui.mjs.map +1 -0
  166. package/dist/esm/daemon/tui.native.js +195 -0
  167. package/dist/esm/daemon/tui.native.js.map +1 -0
  168. package/dist/esm/daemon/types.js +1 -0
  169. package/dist/esm/daemon/types.js.map +6 -0
  170. package/dist/esm/daemon/types.mjs +2 -0
  171. package/dist/esm/daemon/types.mjs.map +1 -0
  172. package/dist/esm/daemon/types.native.js +2 -0
  173. package/dist/esm/daemon/types.native.js.map +1 -0
  174. package/dist/esm/daemon/utils.js +42 -0
  175. package/dist/esm/daemon/utils.js.map +6 -0
  176. package/dist/esm/daemon/utils.mjs +39 -0
  177. package/dist/esm/daemon/utils.mjs.map +1 -0
  178. package/dist/esm/daemon/utils.native.js +45 -0
  179. package/dist/esm/daemon/utils.native.js.map +1 -0
  180. package/dist/esm/fork/createMemoryHistory.js +20 -6
  181. package/dist/esm/fork/createMemoryHistory.js.map +1 -1
  182. package/dist/esm/fork/createMemoryHistory.mjs +22 -8
  183. package/dist/esm/fork/createMemoryHistory.mjs.map +1 -1
  184. package/dist/esm/fork/createMemoryHistory.native.js +22 -8
  185. package/dist/esm/fork/createMemoryHistory.native.js.map +1 -1
  186. package/dist/esm/fork/useLinking.js +35 -9
  187. package/dist/esm/fork/useLinking.js.map +1 -1
  188. package/dist/esm/fork/useLinking.mjs +52 -13
  189. package/dist/esm/fork/useLinking.mjs.map +1 -1
  190. package/dist/esm/index.js +4 -0
  191. package/dist/esm/index.js.map +1 -1
  192. package/dist/esm/index.mjs +3 -1
  193. package/dist/esm/index.mjs.map +1 -1
  194. package/dist/esm/index.native.js +3 -1
  195. package/dist/esm/index.native.js.map +1 -1
  196. package/dist/esm/router/linkingConfig.js +14 -4
  197. package/dist/esm/router/linkingConfig.js.map +1 -1
  198. package/dist/esm/router/linkingConfig.mjs +12 -1
  199. package/dist/esm/router/linkingConfig.mjs.map +1 -1
  200. package/dist/esm/router/linkingConfig.native.js +10 -1
  201. package/dist/esm/router/linkingConfig.native.js.map +1 -1
  202. package/dist/esm/router/routeMask.js +111 -0
  203. package/dist/esm/router/routeMask.js.map +6 -0
  204. package/dist/esm/router/routeMask.mjs +108 -0
  205. package/dist/esm/router/routeMask.mjs.map +1 -0
  206. package/dist/esm/router/routeMask.native.js +128 -0
  207. package/dist/esm/router/routeMask.native.js.map +1 -0
  208. package/dist/esm/router/router.js +23 -2
  209. package/dist/esm/router/router.js.map +1 -1
  210. package/dist/esm/router/router.mjs +24 -3
  211. package/dist/esm/router/router.mjs.map +1 -1
  212. package/dist/esm/router/router.native.js +24 -3
  213. package/dist/esm/router/router.native.js.map +1 -1
  214. package/dist/esm/server/PreloadScripts.native.js +29 -33
  215. package/dist/esm/server/PreloadScripts.native.js.map +1 -6
  216. package/dist/esm/vite/DevHead.js +1 -917
  217. package/dist/esm/vite/DevHead.js.map +1 -1
  218. package/dist/esm/vite/DevHead.mjs +2 -909
  219. package/dist/esm/vite/DevHead.mjs.map +1 -1
  220. package/dist/esm/vite/DevHead.native.js +0 -881
  221. package/dist/esm/vite/DevHead.native.js.map +1 -1
  222. package/dist/esm/vite/one.js +4 -1
  223. package/dist/esm/vite/one.js.map +1 -1
  224. package/dist/esm/vite/one.mjs +4 -1
  225. package/dist/esm/vite/one.mjs.map +1 -1
  226. package/dist/esm/vite/one.native.js +4 -1
  227. package/dist/esm/vite/one.native.js.map +1 -1
  228. package/dist/esm/vite/plugins/devtoolsPlugin.js +33 -0
  229. package/dist/esm/vite/plugins/devtoolsPlugin.js.map +6 -0
  230. package/dist/esm/vite/plugins/devtoolsPlugin.mjs +31 -0
  231. package/dist/esm/vite/plugins/devtoolsPlugin.mjs.map +1 -0
  232. package/dist/esm/vite/plugins/devtoolsPlugin.native.js +31 -0
  233. package/dist/esm/vite/plugins/devtoolsPlugin.native.js.map +1 -0
  234. package/dist/esm/vite/plugins/fileSystemRouterPlugin.js +1 -6
  235. package/dist/esm/vite/plugins/fileSystemRouterPlugin.js.map +1 -1
  236. package/dist/esm/vite/plugins/fileSystemRouterPlugin.mjs +1 -6
  237. package/dist/esm/vite/plugins/fileSystemRouterPlugin.mjs.map +1 -1
  238. package/dist/esm/vite/plugins/fileSystemRouterPlugin.native.js +1 -6
  239. package/dist/esm/vite/plugins/fileSystemRouterPlugin.native.js.map +1 -1
  240. package/dist/esm/vite/plugins/virtualEntryPlugin.js +5 -1
  241. package/dist/esm/vite/plugins/virtualEntryPlugin.js.map +1 -1
  242. package/dist/esm/vite/plugins/virtualEntryPlugin.mjs +7 -1
  243. package/dist/esm/vite/plugins/virtualEntryPlugin.mjs.map +1 -1
  244. package/dist/esm/vite/plugins/virtualEntryPlugin.native.js +8 -1
  245. package/dist/esm/vite/plugins/virtualEntryPlugin.native.js.map +1 -1
  246. package/package.json +12 -10
  247. package/src/createHandleRequest.ts +16 -3
  248. package/src/fork/createMemoryHistory.tsx +39 -4
  249. package/src/fork/useLinking.ts +83 -12
  250. package/src/index.ts +3 -0
  251. package/src/router/linkingConfig.ts +21 -4
  252. package/src/router/routeMask.ts +293 -0
  253. package/src/router/router.ts +53 -1
  254. package/src/vite/DevHead.tsx +1 -924
  255. package/src/vite/one.ts +4 -0
  256. package/src/vite/plugins/devtoolsPlugin.ts +45 -0
  257. package/src/vite/plugins/fileSystemRouterPlugin.tsx +2 -7
  258. package/src/vite/plugins/virtualEntryPlugin.ts +12 -3
  259. package/src/vite/types.ts +1 -0
  260. package/types/cli/daemon.d.ts.map +1 -0
  261. package/types/createHandleRequest.d.ts.map +1 -1
  262. package/types/daemon/index.d.ts.map +1 -0
  263. package/types/daemon/ipc.d.ts.map +1 -0
  264. package/types/daemon/picker.d.ts.map +1 -0
  265. package/types/daemon/proxy.d.ts.map +1 -0
  266. package/types/daemon/registry.d.ts.map +1 -0
  267. package/types/daemon/server.d.ts.map +1 -0
  268. package/types/daemon/tui.d.ts.map +1 -0
  269. package/types/daemon/types.d.ts.map +1 -0
  270. package/types/daemon/utils.d.ts.map +1 -0
  271. package/types/fork/createMemoryHistory.d.ts +6 -2
  272. package/types/fork/createMemoryHistory.d.ts.map +1 -1
  273. package/types/fork/useLinking.d.ts.map +1 -1
  274. package/types/index.d.ts +2 -0
  275. package/types/index.d.ts.map +1 -1
  276. package/types/router/linkingConfig.d.ts.map +1 -1
  277. package/types/router/routeMask.d.ts +130 -0
  278. package/types/router/routeMask.d.ts.map +1 -0
  279. package/types/router/router.d.ts +23 -0
  280. package/types/router/router.d.ts.map +1 -1
  281. package/types/vite/DevHead.d.ts.map +1 -1
  282. package/types/vite/one.d.ts.map +1 -1
  283. package/types/vite/plugins/devtoolsPlugin.d.ts +5 -0
  284. package/types/vite/plugins/devtoolsPlugin.d.ts.map +1 -0
  285. package/types/vite/plugins/fileSystemRouterPlugin.d.ts.map +1 -1
  286. package/types/vite/plugins/virtualEntryPlugin.d.ts +1 -3
  287. package/types/vite/plugins/virtualEntryPlugin.d.ts.map +1 -1
  288. package/types/vite/types.d.ts.map +1 -1
@@ -1,886 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { VIRTUAL_SSR_CSS_HREF } from "../constants.native.js";
3
- var ROUTE_HMR_SCRIPT = 'import { createHotContext } from "/@vite/client"; const hot = createHotContext("/__one_route_hmr"); hot.on("one:route-update", (data) => { if (window.__oneRouteCache) { if (data?.file) { window.__oneRouteCache.clearFile(data.file); } else { window.__oneRouteCache.clear(); } } window.dispatchEvent(new CustomEvent("one-hmr-update")); });',
4
- LOADER_HMR_SCRIPT = 'import { createHotContext } from "/@vite/client"; const hot = createHotContext("/__one_loader_hmr"); hot.on("one:loader-data-update", async (data) => { if (data?.routePaths && window.__oneRefetchLoader) { const currentPath = window.location.pathname.replace(/\\/$/, "") || "/"; for (const routePath of data.routePaths) { if (routePath === currentPath) { try { await window.__oneRefetchLoader(routePath); } catch (err) { console.error("[one] Error refetching loader:", err); } } } } });',
5
- REACT_REFRESH_SCRIPT = 'import { injectIntoGlobalHook } from "/@react-refresh"; injectIntoGlobalHook(window); window.$RefreshReg$ = () => {}; window.$RefreshSig$ = () => (type) => type;',
6
- ONE_DEVTOOLS_SCRIPT = `
7
- (function() {
8
- try {
9
- var host = null;
10
- var shadow = null;
11
- var spotlightDialog = null;
12
- var panelDialog = null;
13
- var panel = null;
14
- var activeTab = 'seo';
15
- var isDragging = false;
16
- var dragOffset = { x: 0, y: 0 };
17
- var panelPos = { x: 20, y: 20 };
18
- var snappedEdge = { h: null, v: null };
19
- var removalObserver = null;
20
-
21
- var LOGO_SVG = '<svg width="24" height="24" viewBox="0 0 100 100"><circle cx="50" cy="50" r="48" fill="#FCD34D" stroke="#222" stroke-width="2"/><circle cx="50" cy="35" r="16" fill="white"/><text x="50" y="41" text-anchor="middle" font-family="system-ui" font-size="16" font-weight="bold" fill="#222">1</text></svg>';
22
-
23
- function escapeHtml(str) {
24
- if (!str) return '';
25
- return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
26
- }
27
-
28
- function createHost() {
29
- if (host) return;
30
- host = document.createElement('div');
31
- host.id = 'one-devtools';
32
- shadow = host.attachShadow({ mode: 'open' });
33
-
34
- var css = \`
35
- * { box-sizing: border-box; margin: 0; padding: 0; }
36
-
37
- dialog {
38
- border: none;
39
- padding: 0;
40
- background: transparent;
41
- max-width: none;
42
- max-height: none;
43
- overflow: visible;
44
- }
45
- dialog::backdrop {
46
- background: transparent;
47
- }
48
- #spotlight-dialog::backdrop {
49
- background: rgba(0,0,0,0.3);
50
- backdrop-filter: blur(8px);
51
- }
52
-
53
- .spotlight {
54
- display: flex;
55
- align-items: center;
56
- justify-content: center;
57
- position: fixed;
58
- inset: 0;
59
- }
60
-
61
- .spotlight-box {
62
- background: #1a1a1a;
63
- border-radius: 12px;
64
- width: 320px;
65
- max-width: 90vw;
66
- overflow: hidden;
67
- box-shadow: 0 16px 48px rgba(0,0,0,0.5);
68
- }
69
-
70
- .spotlight-header {
71
- display: flex;
72
- align-items: center;
73
- padding: 12px 16px;
74
- border-bottom: 1px solid #252525;
75
- gap: 10px;
76
- }
77
- .spotlight-header svg { width: 20px; height: 20px; flex-shrink: 0; }
78
- .spotlight-header-title { font: 13px system-ui, sans-serif; color: #ccc; flex: 1; }
79
- .spotlight-header-version { font: 11px system-ui, sans-serif; color: #666; }
80
-
81
- .spotlight-item {
82
- display: flex;
83
- align-items: center;
84
- gap: 12px;
85
- padding: 12px 16px;
86
- color: #ccc;
87
- font: 13px system-ui, sans-serif;
88
- cursor: pointer;
89
- transition: background 0.1s;
90
- border-bottom: 1px solid #252525;
91
- }
92
- .spotlight-item:last-child { border-bottom: none; }
93
- .spotlight-item:hover { background: #252525; color: #fff; }
94
- .spotlight-item .key {
95
- background: #333;
96
- color: #888;
97
- padding: 2px 6px;
98
- border-radius: 4px;
99
- font-size: 11px;
100
- margin-left: auto;
101
- }
102
-
103
- .panel-dialog {
104
- position: fixed;
105
- margin: 0;
106
- inset: unset;
107
- z-index: 2147483647;
108
- }
109
- .panel-dialog::backdrop {
110
- display: none;
111
- }
112
-
113
- .panel {
114
- width: 420px;
115
- max-width: calc(100vw - 40px);
116
- max-height: calc(100vh - 40px);
117
- background: #161616;
118
- border-radius: 10px;
119
- box-shadow: 0 12px 40px rgba(0,0,0,0.4);
120
- display: flex;
121
- flex-direction: column;
122
- overflow: hidden;
123
- font: 13px system-ui, sans-serif;
124
- color: #ccc;
125
- }
126
-
127
- .panel-header {
128
- display: flex;
129
- align-items: center;
130
- padding: 8px 12px;
131
- background: #1a1a1a;
132
- cursor: grab;
133
- user-select: none;
134
- gap: 8px;
135
- }
136
- .panel-header:active { cursor: grabbing; }
137
- .panel-header svg { width: 18px; height: 18px; }
138
- .panel-title { font-weight: 500; color: #999; font-size: 12px; flex: 1; }
139
- .panel-close {
140
- background: none;
141
- border: none;
142
- color: #666;
143
- cursor: pointer;
144
- padding: 4px;
145
- font-size: 16px;
146
- line-height: 1;
147
- }
148
- .panel-close:hover { color: #fff; }
149
-
150
- .tabs {
151
- display: flex;
152
- background: #1a1a1a;
153
- padding: 0 8px;
154
- gap: 2px;
155
- overflow-x: auto;
156
- }
157
- .tab {
158
- padding: 8px 12px;
159
- background: none;
160
- border: none;
161
- color: #666;
162
- font: 12px system-ui, sans-serif;
163
- cursor: pointer;
164
- border-bottom: 2px solid transparent;
165
- transition: all 0.1s;
166
- }
167
- .tab:hover { color: #999; }
168
- .tab.active { color: #fff; border-bottom-color: #666; }
169
-
170
- .content {
171
- flex: 1;
172
- overflow-y: auto;
173
- padding: 12px;
174
- min-height: 200px;
175
- max-height: calc(100vh - 140px);
176
- }
177
-
178
- .section { margin-bottom: 12px; }
179
- .section-title { font-size: 11px; color: #666; margin-bottom: 6px; text-transform: uppercase; letter-spacing: 0.5px; }
180
-
181
- .info-row {
182
- display: flex;
183
- gap: 12px;
184
- padding: 8px 0;
185
- border-bottom: 1px solid #222;
186
- }
187
- .info-row:last-child { border-bottom: none; }
188
- .info-label { color: #666; font-size: 11px; width: 90px; flex-shrink: 0; padding-top: 1px; }
189
- .info-value { color: #ccc; font-family: monospace; font-size: 12px; word-break: break-word; line-height: 1.4; flex: 1; }
190
-
191
- .badge {
192
- display: inline-block;
193
- padding: 2px 6px;
194
- border-radius: 4px;
195
- font-size: 10px;
196
- text-transform: uppercase;
197
- }
198
- .badge-error { background: #3a2020; color: #f87171; }
199
- .badge-warn { background: #3a3520; color: #fbbf24; }
200
- .badge-info { background: #202a3a; color: #60a5fa; }
201
- .badge-success { background: #1a3a20; color: #4ade80; }
202
-
203
- .empty { text-align: center; color: #555; padding: 24px; }
204
-
205
- .error-item {
206
- background: #1e1e1e;
207
- border-radius: 6px;
208
- padding: 10px;
209
- margin-bottom: 8px;
210
- border-left: 3px solid #666;
211
- }
212
- .error-item.error { border-left-color: #f87171; }
213
- .error-msg { color: #f87171; font-family: monospace; font-size: 12px; margin-top: 6px; }
214
-
215
- .timing-bar {
216
- height: 16px;
217
- background: #252525;
218
- border-radius: 4px;
219
- overflow: hidden;
220
- display: flex;
221
- margin: 4px 0;
222
- }
223
- .timing-segment { height: 100%; display: flex; align-items: center; justify-content: center; font-size: 9px; color: #fff; }
224
- .timing-module { background: #555; }
225
- .timing-exec { background: #888; }
226
-
227
- .preview-card {
228
- background: #1e1e1e;
229
- border-radius: 6px;
230
- padding: 10px;
231
- margin-bottom: 10px;
232
- }
233
- .preview-title { font-size: 11px; color: #666; margin-bottom: 6px; }
234
-
235
- .issue-item {
236
- display: flex;
237
- align-items: center;
238
- gap: 8px;
239
- padding: 6px 0;
240
- font-size: 12px;
241
- }
242
- .issue-icon { font-size: 10px; }
243
- \`;
244
-
245
- shadow.innerHTML = '<style>' + css + '</style><dialog id="spotlight-dialog"><div class="spotlight"><div class="spotlight-box" id="spotlight-box"></div></div></dialog><dialog class="panel-dialog" id="panel-dialog"><div class="panel" id="panel"></div></dialog>';
246
- document.body.appendChild(host);
247
-
248
- setupSpotlight();
249
- setupPanel();
250
- setupKeyboard();
251
- setupRemovalObserver();
252
- }
253
-
254
- // watch for React hydration removing our element and re-create it
255
- function setupRemovalObserver() {
256
- if (removalObserver) return;
257
- removalObserver = new MutationObserver(function(mutations) {
258
- for (var i = 0; i < mutations.length; i++) {
259
- var mutation = mutations[i];
260
- if (mutation.type === 'childList') {
261
- for (var j = 0; j < mutation.removedNodes.length; j++) {
262
- var node = mutation.removedNodes[j];
263
- if (node === host) {
264
- // our element was removed (likely by React hydration), re-create it
265
- host = null;
266
- shadow = null;
267
- spotlightDialog = null;
268
- panelDialog = null;
269
- panel = null;
270
- setTimeout(createHost, 0);
271
- return;
272
- }
273
- }
274
- }
275
- }
276
- });
277
- removalObserver.observe(document.body, { childList: true });
278
- }
279
-
280
- function setupSpotlight() {
281
- spotlightDialog = shadow.getElementById('spotlight-dialog');
282
- var box = shadow.getElementById('spotlight-box');
283
-
284
- var items = [
285
- { id: 'seo', name: 'SEO Preview', key: '\u2325S' },
286
- { id: 'route', name: 'Route Info', key: '\u2325R' },
287
- { id: 'loader', name: 'Loader Timing', key: '\u2325L' },
288
- { id: 'errors', name: 'Errors', key: '\u2325E' },
289
- ];
290
-
291
- var header = '<div class="spotlight-header">' + LOGO_SVG + '<span class="spotlight-header-title">Dev Tools</span><span class="spotlight-header-version">v1.2.57</span></div>';
292
- box.innerHTML = header + items.map(function(item) {
293
- return '<div class="spotlight-item" data-tab="' + item.id + '"><span>' + item.name + '</span><span class="key">' + item.key + '</span></div>';
294
- }).join('');
295
-
296
- box.addEventListener('click', function(e) {
297
- var item = e.target.closest('.spotlight-item');
298
- if (item) {
299
- activeTab = item.dataset.tab;
300
- hideSpotlight();
301
- showPanel();
302
- }
303
- });
304
-
305
- // close on backdrop click
306
- spotlightDialog.addEventListener('click', function(e) {
307
- if (e.target === spotlightDialog) spotlightDialog.close();
308
- });
309
- }
310
-
311
- function setupPanel() {
312
- panelDialog = shadow.getElementById('panel-dialog');
313
- panel = shadow.getElementById('panel');
314
- panel.innerHTML = '<div class="panel-header" id="panel-header">' + LOGO_SVG + '<span class="panel-title">DevTools</span><button class="panel-close" id="panel-close">\xD7</button></div><div class="tabs" id="tabs"><button class="tab active" data-tab="seo">SEO</button><button class="tab" data-tab="route">Route</button><button class="tab" data-tab="loader">Loader</button><button class="tab" data-tab="errors">Errors</button></div><div class="content" id="content"></div>';
315
-
316
- shadow.getElementById('panel-close').addEventListener('click', hidePanel);
317
-
318
- var tabs = shadow.getElementById('tabs');
319
- tabs.addEventListener('click', function(e) {
320
- var tab = e.target.closest('.tab');
321
- if (tab) {
322
- activeTab = tab.dataset.tab;
323
- updateTabs();
324
- updateContent();
325
- }
326
- });
327
-
328
- setupDrag();
329
- }
330
-
331
- function setupDrag() {
332
- var header = shadow.getElementById('panel-header');
333
-
334
- header.addEventListener('mousedown', function(e) {
335
- if (e.target.closest('.panel-close')) return;
336
- isDragging = true;
337
- var rect = panelDialog.getBoundingClientRect();
338
- dragOffset.x = e.clientX - rect.left;
339
- dragOffset.y = e.clientY - rect.top;
340
- // Store current position before resetting snap state
341
- panelPos.x = rect.left;
342
- panelPos.y = rect.top;
343
- snappedEdge = { h: null, v: null };
344
- });
345
-
346
- document.addEventListener('mousemove', function(e) {
347
- if (!isDragging) return;
348
- var x = e.clientX - dragOffset.x;
349
- var y = e.clientY - dragOffset.y;
350
- var snapDist = 20;
351
- var w = window.innerWidth;
352
- var h = window.innerHeight;
353
- var pw = panelDialog.offsetWidth;
354
- var ph = panelDialog.offsetHeight;
355
- var pad = 10;
356
-
357
- var snapH = null;
358
- var snapV = null;
359
-
360
- if (x < snapDist) { snapH = 'left'; }
361
- else if (x + pw > w - snapDist) { snapH = 'right'; }
362
- if (y < snapDist) { snapV = 'top'; }
363
- else if (y + ph > h - snapDist) { snapV = 'bottom'; }
364
-
365
- snappedEdge = { h: snapH, v: snapV };
366
-
367
- // Apply horizontal positioning
368
- if (snapH === 'left') {
369
- panelDialog.style.left = pad + 'px';
370
- panelDialog.style.right = 'auto';
371
- } else if (snapH === 'right') {
372
- panelDialog.style.left = 'auto';
373
- panelDialog.style.right = pad + 'px';
374
- } else {
375
- panelDialog.style.left = x + 'px';
376
- panelDialog.style.right = 'auto';
377
- panelPos.x = x;
378
- }
379
-
380
- // Apply vertical positioning
381
- if (snapV === 'top') {
382
- panelDialog.style.top = pad + 'px';
383
- panelDialog.style.bottom = 'auto';
384
- } else if (snapV === 'bottom') {
385
- panelDialog.style.top = 'auto';
386
- panelDialog.style.bottom = pad + 'px';
387
- } else {
388
- panelDialog.style.top = y + 'px';
389
- panelDialog.style.bottom = 'auto';
390
- panelPos.y = y;
391
- }
392
- });
393
-
394
- document.addEventListener('mouseup', function() {
395
- isDragging = false;
396
- });
397
- }
398
-
399
- var keyboardSetup = false;
400
- function setupKeyboard() {
401
- if (keyboardSetup) return;
402
- keyboardSetup = true;
403
- document.addEventListener('keydown', function(e) {
404
- if (e.altKey && e.code === 'Space') {
405
- e.preventDefault();
406
- toggleSpotlight();
407
- } else if (e.altKey) {
408
- var tabMap = { KeyS: 'seo', KeyR: 'route', KeyL: 'loader', KeyE: 'errors' };
409
- var tab = tabMap[e.code];
410
- if (tab) {
411
- e.preventDefault();
412
- activeTab = tab;
413
- hideSpotlight();
414
- showPanel();
415
- }
416
- } else if (e.code === 'Escape') {
417
- // dialogs handle escape natively, but we need to handle the case where escape is pressed
418
- // when only one is open
419
- if (spotlightDialog && spotlightDialog.open) spotlightDialog.close();
420
- else if (panelDialog && panelDialog.open) panelDialog.close();
421
- }
422
- });
423
- }
424
-
425
- function toggleSpotlight() {
426
- if (spotlightDialog && spotlightDialog.open) hideSpotlight();
427
- else showSpotlight();
428
- }
429
-
430
- function showSpotlight() {
431
- if (!host) createHost();
432
- spotlightDialog.showModal();
433
- }
434
-
435
- function hideSpotlight() {
436
- spotlightDialog.close();
437
- }
438
-
439
- function showPanel() {
440
- if (!host) createHost();
441
- var pad = 10;
442
- // Apply horizontal positioning based on snap state
443
- if (snappedEdge.h === 'left') {
444
- panelDialog.style.left = pad + 'px';
445
- panelDialog.style.right = 'auto';
446
- } else if (snappedEdge.h === 'right') {
447
- panelDialog.style.left = 'auto';
448
- panelDialog.style.right = pad + 'px';
449
- } else {
450
- panelDialog.style.left = panelPos.x + 'px';
451
- panelDialog.style.right = 'auto';
452
- }
453
- // Apply vertical positioning based on snap state
454
- if (snappedEdge.v === 'top') {
455
- panelDialog.style.top = pad + 'px';
456
- panelDialog.style.bottom = 'auto';
457
- } else if (snappedEdge.v === 'bottom') {
458
- panelDialog.style.top = 'auto';
459
- panelDialog.style.bottom = pad + 'px';
460
- } else {
461
- panelDialog.style.top = panelPos.y + 'px';
462
- panelDialog.style.bottom = 'auto';
463
- }
464
- panelDialog.show();
465
- updateTabs();
466
- updateContent();
467
- }
468
-
469
- function hidePanel() {
470
- panelDialog.close();
471
- }
472
-
473
- function updateTabs() {
474
- shadow.querySelectorAll('.tab').forEach(function(t) {
475
- t.classList.toggle('active', t.dataset.tab === activeTab);
476
- });
477
- }
478
-
479
- function updateContent() {
480
- var content = shadow.getElementById('content');
481
- if (activeTab === 'seo') content.innerHTML = getSeoContent();
482
- else if (activeTab === 'route') content.innerHTML = getRouteContent();
483
- else if (activeTab === 'loader') content.innerHTML = getLoaderContent();
484
- else if (activeTab === 'errors') content.innerHTML = getErrorsContent();
485
- }
486
-
487
- function getSeoContent() {
488
- var title = document.title || '';
489
- var desc = document.querySelector('meta[name="description"]')?.content || '';
490
- var ogTitle = document.querySelector('meta[property="og:title"]')?.content || '';
491
- var ogDesc = document.querySelector('meta[property="og:description"]')?.content || '';
492
- var ogImage = document.querySelector('meta[property="og:image"]')?.content || '';
493
-
494
- var issues = [];
495
- if (!title) issues.push({ type: 'error', msg: 'Missing title' });
496
- else if (title.length > 60) issues.push({ type: 'warn', msg: 'Title too long (>60)' });
497
- if (!desc) issues.push({ type: 'error', msg: 'Missing description' });
498
- else if (desc.length > 160) issues.push({ type: 'warn', msg: 'Description too long (>160)' });
499
- if (!ogTitle) issues.push({ type: 'warn', msg: 'Missing og:title' });
500
- if (!ogImage) issues.push({ type: 'warn', msg: 'Missing og:image' });
501
-
502
- var html = '';
503
- if (issues.length) {
504
- html += '<div class="section"><div class="section-title">Issues</div>';
505
- issues.forEach(function(i) {
506
- html += '<div class="issue-item"><span class="issue-icon">' + (i.type === 'error' ? '\u2716' : '\u26A0') + '</span><span>' + escapeHtml(i.msg) + '</span></div>';
507
- });
508
- html += '</div>';
509
- }
510
-
511
- html += '<div class="section"><div class="section-title">Google Preview</div><div class="preview-card" style="background:#fff;color:#202124;padding:12px;border-radius:8px;">';
512
- html += '<div style="font-size:12px;color:#202124;margin-bottom:2px;">' + escapeHtml(location.hostname) + '</div>';
513
- html += '<div style="font-size:16px;color:#1a0dab;margin-bottom:4px;">' + escapeHtml(title || 'No title') + '</div>';
514
- html += '<div style="font-size:13px;color:#4d5156;">' + escapeHtml(desc ? desc.slice(0,160) : 'No description') + '</div>';
515
- html += '</div></div>';
516
-
517
- if (ogImage) {
518
- html += '<div class="section"><div class="section-title">Social Preview</div>';
519
- html += '<div class="preview-card" style="background:#fff;border-radius:12px;overflow:hidden;border:1px solid #e1e8ed;">';
520
- html += '<img src="' + escapeHtml(ogImage) + '" style="width:100%;height:auto;display:block;border-bottom:1px solid #e1e8ed;" onerror="this.style.display=&quot;none&quot;" />';
521
- html += '<div style="padding:12px;">';
522
- html += '<div style="font-size:12px;color:#8899a6;text-transform:uppercase;margin-bottom:2px;">' + escapeHtml(location.hostname) + '</div>';
523
- html += '<div style="font-size:15px;color:#1c2022;font-weight:700;margin-bottom:4px;line-height:1.3;">' + escapeHtml(ogTitle || title || 'No title') + '</div>';
524
- html += '<div style="font-size:14px;color:#8899a6;line-height:1.3;">' + escapeHtml((ogDesc || desc || '').slice(0,100)) + '</div>';
525
- html += '</div></div></div>';
526
- }
527
-
528
- html += '<div class="section"><div class="section-title">Meta Tags</div>';
529
- html += '<div class="info-row"><div class="info-label">title</div><div class="info-value">' + escapeHtml(title || '-') + '</div></div>';
530
- html += '<div class="info-row"><div class="info-label">description</div><div class="info-value">' + escapeHtml(desc || '-') + '</div></div>';
531
- html += '<div class="info-row"><div class="info-label">og:title</div><div class="info-value">' + escapeHtml(ogTitle || '-') + '</div></div>';
532
- html += '<div class="info-row"><div class="info-label">og:description</div><div class="info-value">' + escapeHtml(ogDesc || '-') + '</div></div>';
533
- html += '<div class="info-row"><div class="info-label">og:image</div><div class="info-value">' + escapeHtml(ogImage || '-') + '</div></div>';
534
- html += '</div>';
535
-
536
- return html;
537
- }
538
-
539
- function getRouteContent() {
540
- var pathname = location.pathname;
541
- var segments = pathname.split('/').filter(Boolean);
542
- var search = location.search;
543
- var hash = location.hash;
544
- var devtools = window.__oneDevtools || {};
545
- var routeInfo = devtools.routeInfo || {};
546
- var params = routeInfo.params || {};
547
-
548
- var html = '<div class="section"><div class="section-title">Current Route</div>';
549
- html += '<div class="info-row"><span class="info-label">pathname</span><span class="info-value">' + escapeHtml(pathname) + '</span></div>';
550
- html += '<div class="info-row"><span class="info-label">segments</span><span class="info-value">' + (segments.length ? segments.map(function(s) { return '<span style="background:#252525;padding:2px 6px;border-radius:4px;margin-right:4px;">' + escapeHtml(s) + '</span>'; }).join('') : '/') + '</span></div>';
551
- if (search) html += '<div class="info-row"><span class="info-label">search</span><span class="info-value">' + escapeHtml(search) + '</span></div>';
552
- if (hash) html += '<div class="info-row"><span class="info-label">hash</span><span class="info-value">' + escapeHtml(hash) + '</span></div>';
553
- html += '</div>';
554
-
555
- if (Object.keys(params).length) {
556
- html += '<div class="section"><div class="section-title">Route Params</div>';
557
- Object.entries(params).forEach(function(kv) {
558
- html += '<div class="info-row"><span class="info-label">' + escapeHtml(kv[0]) + '</span><span class="info-value">' + escapeHtml(String(kv[1])) + '</span></div>';
559
- });
560
- html += '</div>';
561
- }
562
-
563
- html += '<div class="section"><div class="section-title">Full URL</div>';
564
- html += '<div style="font-family:monospace;font-size:11px;color:#666;word-break:break-all;">' + escapeHtml(location.href) + '</div>';
565
- html += '</div>';
566
-
567
- return html;
568
- }
569
-
570
- function getLoaderContent() {
571
- var devtools = window.__oneDevtools || {};
572
- var history = typeof devtools.getLoaderTimingHistory === 'function' ? devtools.getLoaderTimingHistory() || [] : [];
573
-
574
- if (!history.length) {
575
- return '<div class="empty">No loader timings recorded yet</div>';
576
- }
577
-
578
- var maxTime = Math.max.apply(null, history.map(function(t) { return t.totalTime || 0; }));
579
- var html = '';
580
-
581
- history.forEach(function(t) {
582
- var modPct = t.moduleLoadTime && t.totalTime ? (t.moduleLoadTime / t.totalTime) * 100 : 0;
583
- var execPct = t.executionTime && t.totalTime ? (t.executionTime / t.totalTime) * 100 : 0;
584
- var widthPct = t.totalTime && maxTime ? (t.totalTime / maxTime) * 100 : 0;
585
-
586
- html += '<div class="error-item' + (t.error ? ' error' : '') + '">';
587
- html += '<div style="display:flex;justify-content:space-between;align-items:center;">';
588
- html += '<span style="font-family:monospace;font-size:11px;">' + escapeHtml(t.path) + '</span>';
589
- html += '<span class="badge badge-' + (t.error ? 'error' : 'success') + '">' + (t.totalTime ? Math.round(t.totalTime) + 'ms' : '-') + '</span>';
590
- html += '</div>';
591
- if (!t.error) {
592
- html += '<div class="timing-bar" style="width:' + Math.max(20, widthPct) + '%;">';
593
- html += '<div class="timing-segment timing-module" style="width:' + modPct + '%;" title="Module: ' + Math.round(t.moduleLoadTime || 0) + 'ms"></div>';
594
- html += '<div class="timing-segment timing-exec" style="width:' + execPct + '%;" title="Exec: ' + Math.round(t.executionTime || 0) + 'ms"></div>';
595
- html += '</div>';
596
- }
597
- if (t.error) html += '<div class="error-msg">' + escapeHtml(t.error) + '</div>';
598
- html += '</div>';
599
- });
600
-
601
- return html;
602
- }
603
-
604
- function getErrorsContent() {
605
- var devtools = window.__oneDevtools || {};
606
- var errors = devtools.errorHistory || [];
607
-
608
- if (!errors.length) {
609
- return '<div class="empty">\u2713 No errors recorded</div>';
610
- }
611
-
612
- var html = '';
613
- errors.forEach(function(err) {
614
- html += '<div class="error-item error">';
615
- html += '<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;">';
616
- html += '<span class="badge badge-error">' + escapeHtml(err.type || 'error') + '</span>';
617
- html += '<span style="font-size:11px;color:#666;">' + new Date(err.timestamp).toLocaleTimeString() + '</span>';
618
- html += '</div>';
619
- html += '<div class="error-msg">' + escapeHtml(err.error?.message || 'Unknown error') + '</div>';
620
- html += '</div>';
621
- });
622
-
623
- return html;
624
- }
625
-
626
- // Initialize after React hydration completes
627
- // use requestIdleCallback to wait for the browser to be idle (after hydration)
628
- function initAfterHydration() {
629
- if (typeof requestIdleCallback !== 'undefined') {
630
- requestIdleCallback(createHost, { timeout: 3000 });
631
- } else {
632
- setTimeout(createHost, 100);
633
- }
634
- }
635
-
636
- if (document.readyState === 'complete') {
637
- initAfterHydration();
638
- } else {
639
- window.addEventListener('load', initAfterHydration);
640
- }
641
-
642
- // Listen for events
643
- window.addEventListener('one-loader-timing', function() {
644
- if (panelDialog && panelDialog.open && activeTab === 'loader') updateContent();
645
- });
646
- window.addEventListener('one-error', function(e) {
647
- var devtools = window.__oneDevtools = window.__oneDevtools || {};
648
- devtools.errorHistory = devtools.errorHistory || [];
649
- devtools.errorHistory.unshift(e.detail);
650
- if (devtools.errorHistory.length > 20) devtools.errorHistory = devtools.errorHistory.slice(0, 20);
651
- if (panelDialog && panelDialog.open && activeTab === 'errors') updateContent();
652
- });
653
-
654
- // Update on navigation
655
- function onNavigate() {
656
- if (panelDialog && panelDialog.open) updateContent();
657
- }
658
- window.addEventListener('popstate', onNavigate);
659
- window.addEventListener('one-hmr-update', onNavigate);
660
- // Also catch pushState/replaceState
661
- var origPushState = history.pushState;
662
- var origReplaceState = history.replaceState;
663
- history.pushState = function() {
664
- origPushState.apply(this, arguments);
665
- setTimeout(onNavigate, 0);
666
- };
667
- history.replaceState = function() {
668
- origReplaceState.apply(this, arguments);
669
- setTimeout(onNavigate, 0);
670
- };
671
-
672
- } catch (e) {
673
- console.error('[One DevTools] Failed to initialize:', e);
674
- }
675
- })();
676
- `,
677
- SOURCE_INSPECTOR_SCRIPT = `
678
- (function() {
679
- try {
680
- var active = false;
681
- var host = null;
682
- var shadow = null;
683
- var overlay = null;
684
- var tag = null;
685
- var holdTimer = null;
686
- var holdDelay = 500;
687
- var mousePos = { x: 0, y: 0 };
688
- var removalObserver = null;
689
-
690
- function createHost() {
691
- if (host) return;
692
- host = document.createElement('div');
693
- host.id = 'one-source-inspector';
694
- shadow = host.attachShadow({ mode: 'open' });
695
- shadow.innerHTML = \`
696
- <style>
697
- * { box-sizing: border-box; margin: 0; padding: 0; }
698
- .overlay {
699
- position: fixed;
700
- pointer-events: none;
701
- z-index: 100000;
702
- background: rgba(100,100,100,0.2);
703
- border: 2px solid rgba(100,100,100,0.6);
704
- border-radius: 2px;
705
- transition: all 0.05s;
706
- display: none;
707
- }
708
- .tag {
709
- position: fixed;
710
- pointer-events: none;
711
- z-index: 100001;
712
- background: rgba(60,60,60,0.95);
713
- color: white;
714
- padding: 4px 8px;
715
- font-size: 12px;
716
- font-family: system-ui, -apple-system, sans-serif;
717
- border-radius: 4px;
718
- white-space: nowrap;
719
- box-shadow: 0 2px 8px rgba(0,0,0,0.3);
720
- display: none;
721
- }
722
- </style>
723
- <div class="overlay"></div>
724
- <div class="tag"></div>
725
- \`;
726
- document.body.appendChild(host);
727
- overlay = shadow.querySelector('.overlay');
728
- tag = shadow.querySelector('.tag');
729
- setupRemovalObserver();
730
- }
731
-
732
- // watch for React hydration removing our element and re-create it
733
- function setupRemovalObserver() {
734
- if (removalObserver) return;
735
- removalObserver = new MutationObserver(function(mutations) {
736
- for (var i = 0; i < mutations.length; i++) {
737
- var mutation = mutations[i];
738
- if (mutation.type === 'childList') {
739
- for (var j = 0; j < mutation.removedNodes.length; j++) {
740
- var node = mutation.removedNodes[j];
741
- if (node === host) {
742
- host = null;
743
- shadow = null;
744
- overlay = null;
745
- tag = null;
746
- // don't auto-recreate - will be created on next hover
747
- return;
748
- }
749
- }
750
- }
751
- }
752
- });
753
- removalObserver.observe(document.body, { childList: true });
754
- }
755
-
756
- function hideOverlay() {
757
- if (overlay) overlay.style.display = 'none';
758
- if (tag) tag.style.display = 'none';
759
- }
760
-
761
- function showOverlay(el, source) {
762
- if (!host) createHost();
763
- var rect = el.getBoundingClientRect();
764
- overlay.style.display = 'block';
765
- overlay.style.top = rect.top + 'px';
766
- overlay.style.left = rect.left + 'px';
767
- overlay.style.width = rect.width + 'px';
768
- overlay.style.height = rect.height + 'px';
769
- tag.style.display = 'block';
770
- tag.textContent = source;
771
- var top = rect.top - 28;
772
- if (top < 0) top = rect.bottom + 4;
773
- tag.style.top = top + 'px';
774
- tag.style.left = Math.max(4, Math.min(rect.left, window.innerWidth - 200)) + 'px';
775
- }
776
-
777
- function cancelHold() {
778
- clearTimeout(holdTimer);
779
- holdTimer = null;
780
- }
781
-
782
- function updateOverlayAtPosition(x, y) {
783
- // Use elementsFromPoint to get all elements at position, ordered from topmost/innermost to bottom
784
- var allElements = document.elementsFromPoint(x, y);
785
- // Find the first (innermost) element with data-one-source
786
- var el = null;
787
- for (var i = 0; i < allElements.length; i++) {
788
- if (allElements[i].hasAttribute('data-one-source')) {
789
- el = allElements[i];
790
- break;
791
- }
792
- }
793
- if (el) {
794
- var source = el.getAttribute('data-one-source');
795
- var lastColon = source.lastIndexOf(':');
796
- var filePath = source.slice(0, lastColon);
797
- var idx = source.slice(lastColon + 1);
798
- var info = window.__oneSourceInfo && window.__oneSourceInfo[filePath];
799
- var lineCol = info && info[idx];
800
- var displaySource = lineCol ? filePath + ':' + lineCol[0] + ':' + lineCol[1] : source;
801
- showOverlay(el, displaySource);
802
- } else {
803
- hideOverlay();
804
- }
805
- }
806
-
807
- function activate() {
808
- active = true;
809
- // Immediately show overlay at current mouse position
810
- updateOverlayAtPosition(mousePos.x, mousePos.y);
811
- }
812
-
813
- function deactivate() {
814
- cancelHold();
815
- active = false;
816
- hideOverlay();
817
- }
818
-
819
- window.addEventListener('keydown', function(e) {
820
- // Only trigger on Alt/Option key held alone
821
- if (e.key !== 'Alt') {
822
- cancelHold();
823
- return;
824
- }
825
- // Ignore if other modifier keys are pressed
826
- if (e.metaKey || e.ctrlKey || e.shiftKey) {
827
- cancelHold();
828
- return;
829
- }
830
- if (e.defaultPrevented) return;
831
- if (holdTimer) return; // already waiting
832
- holdTimer = setTimeout(activate, holdDelay);
833
- });
834
-
835
- window.addEventListener('keyup', function(e) {
836
- if (e.defaultPrevented) return;
837
- deactivate();
838
- });
839
-
840
- window.addEventListener('blur', deactivate);
841
-
842
- document.addEventListener('mousemove', function(e) {
843
- // Always track mouse position
844
- mousePos.x = e.clientX;
845
- mousePos.y = e.clientY;
846
- if (!active) return;
847
- updateOverlayAtPosition(e.clientX, e.clientY);
848
- });
849
-
850
- document.addEventListener('click', function(e) {
851
- if (!active) return;
852
- // Use elementsFromPoint to find innermost sourced element
853
- var allElements = document.elementsFromPoint(e.clientX, e.clientY);
854
- var el = null;
855
- for (var i = 0; i < allElements.length; i++) {
856
- if (allElements[i].hasAttribute('data-one-source')) {
857
- el = allElements[i];
858
- break;
859
- }
860
- }
861
- if (el) {
862
- e.preventDefault();
863
- e.stopPropagation();
864
- var source = el.getAttribute('data-one-source');
865
- // Parse source: "/path/to/file.tsx:index"
866
- var lastColon = source.lastIndexOf(':');
867
- var filePath = source.slice(0, lastColon);
868
- var idx = source.slice(lastColon + 1);
869
- // Look up actual line/column from source info
870
- var info = window.__oneSourceInfo && window.__oneSourceInfo[filePath];
871
- var lineCol = info && info[idx];
872
- var url = '/__one/open-source?source=' + encodeURIComponent(source);
873
- if (lineCol) {
874
- url += '&line=' + lineCol[0] + '&column=' + lineCol[1];
875
- }
876
- fetch(url);
877
- }
878
- }, true);
879
- } catch (e) {
880
- console.error('[Source Inspector] Failed to initialize:', e);
881
- }
882
- })();
883
- `;
884
3
  function DevHead() {
885
4
  return null;
886
5
  }