@dfosco/storyboard-core 4.2.0-beta.2 → 4.2.0-beta.21

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 (414) hide show
  1. package/commandpalette.config.json +109 -24
  2. package/dist/storyboard-ui.css +1 -1
  3. package/dist/storyboard-ui.js +17379 -28568
  4. package/dist/storyboard-ui.js.map +1 -1
  5. package/dist/tailwind.css +1 -1
  6. package/package.json +5 -2
  7. package/scaffold/agents/prompt-agent.agent.md +181 -0
  8. package/scaffold/agents/terminal-agent.agent.md +351 -0
  9. package/scaffold/codex/config.toml +246 -0
  10. package/scaffold/manifest.json +5 -0
  11. package/scaffold/skills/canvas/SKILL.md +5 -4
  12. package/scaffold/skills/ship/SKILL.md +1 -1
  13. package/scaffold/storyboard.config.json +14 -1
  14. package/scaffold/toolbar.config.json +1 -1
  15. package/src/ActionMenuButton.jsx +100 -0
  16. package/src/AutosyncMenuButton.css +67 -0
  17. package/src/AutosyncMenuButton.jsx +241 -0
  18. package/src/BranchSelect.jsx +29 -0
  19. package/src/BranchSelect.module.css +30 -0
  20. package/src/CanvasAgentsMenu.jsx +87 -0
  21. package/src/CanvasCreateMenu.jsx +609 -0
  22. package/src/CanvasSnap.css +27 -0
  23. package/src/CanvasSnap.jsx +51 -0
  24. package/src/CanvasUndoRedo.css +36 -0
  25. package/src/CanvasUndoRedo.jsx +62 -0
  26. package/src/CanvasZoomControl.css +53 -0
  27. package/src/CanvasZoomControl.jsx +49 -0
  28. package/src/CanvasZoomToFit.css +18 -0
  29. package/src/CanvasZoomToFit.jsx +26 -0
  30. package/src/CommandMenu.css +8 -0
  31. package/src/CommandMenu.jsx +286 -0
  32. package/src/CommandPalette.jsx +35 -0
  33. package/src/CommandPaletteTrigger.jsx +25 -0
  34. package/src/CommentsMenuButton.jsx +38 -0
  35. package/src/CoreUIBar.css +47 -0
  36. package/src/CoreUIBar.jsx +855 -0
  37. package/src/CreateMenuButton.jsx +116 -0
  38. package/src/HideChromeTrigger.jsx +40 -0
  39. package/src/InspectorPanel.css +109 -0
  40. package/src/InspectorPanel.jsx +629 -0
  41. package/src/PwaInstallBanner.css +42 -0
  42. package/src/PwaInstallBanner.jsx +124 -0
  43. package/src/SidePanel.jsx +260 -0
  44. package/src/ThemeMenuButton.jsx +136 -0
  45. package/src/autosync/server.js +202 -5
  46. package/src/autosync/server.test.js +112 -0
  47. package/src/canvas/__tests__/agent-integration.test.js +593 -0
  48. package/src/canvas/__tests__/helpers/browser.js +95 -0
  49. package/src/canvas/__tests__/helpers/canvas-api.js +129 -0
  50. package/src/canvas/__tests__/helpers/perf.js +118 -0
  51. package/src/canvas/__tests__/helpers/setup.js +176 -0
  52. package/src/canvas/__tests__/helpers/tmux.js +130 -0
  53. package/src/canvas/__tests__/helpers/transcript.js +129 -0
  54. package/src/canvas/__tests__/terminal-integration.test.js +175 -0
  55. package/src/canvas/hot-pool.js +757 -0
  56. package/src/canvas/materializer.js +31 -0
  57. package/src/canvas/materializer.test.js +56 -0
  58. package/src/canvas/selectedWidgets.js +65 -7
  59. package/src/canvas/server.js +1801 -22
  60. package/src/canvas/server.test.js +239 -0
  61. package/src/canvas/terminal-config.js +331 -0
  62. package/src/canvas/terminal-registry.js +38 -0
  63. package/src/canvas/terminal-server.js +1037 -29
  64. package/src/canvas/writeGuard.js +51 -3
  65. package/src/canvasConfig.js +67 -1
  66. package/src/canvasConfig.test.js +79 -1
  67. package/src/cli/agent.js +85 -0
  68. package/src/cli/branch.js +232 -0
  69. package/src/cli/canvasAdd.js +59 -12
  70. package/src/cli/canvasBatch.js +98 -0
  71. package/src/cli/canvasBounds.js +1 -1
  72. package/src/cli/canvasRead.js +1 -1
  73. package/src/cli/canvasUpdate.js +179 -0
  74. package/src/cli/create.js +38 -14
  75. package/src/cli/dev.js +157 -83
  76. package/src/cli/exit.js +23 -24
  77. package/src/cli/index.js +55 -2
  78. package/src/cli/proxy.js +96 -37
  79. package/src/cli/schemas.js +22 -4
  80. package/src/cli/server.js +148 -25
  81. package/src/cli/serverUrl.js +8 -3
  82. package/src/cli/sessions.js +131 -5
  83. package/src/cli/setup.js +109 -11
  84. package/src/cli/terminal-commands.js +16 -8
  85. package/src/cli/terminal-messaging.js +231 -0
  86. package/src/cli/terminal-welcome.js +365 -33
  87. package/src/commandActions.js +1 -0
  88. package/src/commandPaletteConfig.js +9 -0
  89. package/src/comments/auth.js +2 -1
  90. package/src/comments/ui/AuthModal.jsx +114 -0
  91. package/src/comments/ui/CommentWindow.jsx +329 -0
  92. package/src/comments/ui/CommentsDrawer.jsx +102 -0
  93. package/src/comments/ui/Composer.jsx +64 -0
  94. package/src/comments/ui/authModal.test.js +1 -1
  95. package/src/comments/ui/commentWindow.js +16 -17
  96. package/src/comments/ui/commentsDrawer.js +25 -26
  97. package/src/comments/ui/composer.js +23 -24
  98. package/src/comments/ui/index.js +2 -3
  99. package/src/configSchema.js +59 -1
  100. package/src/configStore.js +161 -0
  101. package/src/core-ui-colors.css +12 -0
  102. package/src/devtools.js +17 -19
  103. package/src/devtools.test.js +18 -9
  104. package/src/featureFlags.js +12 -5
  105. package/src/fuzzySearch.test.js +10 -0
  106. package/src/index.js +14 -2
  107. package/src/lib/components/ui/alert/alert-action.jsx +11 -0
  108. package/src/lib/components/ui/alert/alert-description.jsx +11 -0
  109. package/src/lib/components/ui/alert/alert-title.jsx +11 -0
  110. package/src/lib/components/ui/alert/alert.jsx +25 -0
  111. package/src/lib/components/ui/alert/index.js +15 -15
  112. package/src/lib/components/ui/avatar/avatar-badge.jsx +22 -0
  113. package/src/lib/components/ui/avatar/avatar-fallback.jsx +18 -0
  114. package/src/lib/components/ui/avatar/avatar-group-count.jsx +19 -0
  115. package/src/lib/components/ui/avatar/avatar-group.jsx +19 -0
  116. package/src/lib/components/ui/avatar/avatar-image.jsx +15 -0
  117. package/src/lib/components/ui/avatar/avatar.jsx +19 -0
  118. package/src/lib/components/ui/avatar/index.js +20 -20
  119. package/src/lib/components/ui/badge/badge.jsx +31 -0
  120. package/src/lib/components/ui/badge/index.js +2 -2
  121. package/src/lib/components/ui/button/button.jsx +100 -0
  122. package/src/lib/components/ui/button/index.js +9 -9
  123. package/src/lib/components/ui/card/card-action.jsx +11 -0
  124. package/src/lib/components/ui/card/card-content.jsx +11 -0
  125. package/src/lib/components/ui/card/card-description.jsx +11 -0
  126. package/src/lib/components/ui/card/card-footer.jsx +11 -0
  127. package/src/lib/components/ui/card/card-header.jsx +19 -0
  128. package/src/lib/components/ui/card/card-title.jsx +11 -0
  129. package/src/lib/components/ui/card/card.jsx +17 -0
  130. package/src/lib/components/ui/card/index.js +23 -23
  131. package/src/lib/components/ui/checkbox/checkbox.jsx +29 -0
  132. package/src/lib/components/ui/checkbox/index.js +5 -5
  133. package/src/lib/components/ui/collapsible/collapsible-content.jsx +7 -0
  134. package/src/lib/components/ui/collapsible/collapsible-trigger.jsx +7 -0
  135. package/src/lib/components/ui/collapsible/collapsible.jsx +7 -0
  136. package/src/lib/components/ui/collapsible/index.js +11 -11
  137. package/src/lib/components/ui/dialog/dialog-close.jsx +7 -0
  138. package/src/lib/components/ui/dialog/dialog-content.jsx +34 -0
  139. package/src/lib/components/ui/dialog/dialog-description.jsx +15 -0
  140. package/src/lib/components/ui/dialog/dialog-footer.jsx +23 -0
  141. package/src/lib/components/ui/dialog/dialog-header.jsx +11 -0
  142. package/src/lib/components/ui/dialog/dialog-overlay.jsx +15 -0
  143. package/src/lib/components/ui/dialog/dialog-portal.jsx +4 -0
  144. package/src/lib/components/ui/dialog/dialog-title.jsx +15 -0
  145. package/src/lib/components/ui/dialog/dialog-trigger.jsx +7 -0
  146. package/src/lib/components/ui/dialog/dialog.jsx +4 -0
  147. package/src/lib/components/ui/dialog/index.js +32 -32
  148. package/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.jsx +8 -0
  149. package/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.jsx +30 -0
  150. package/src/lib/components/ui/dropdown-menu/dropdown-menu-content.jsx +22 -0
  151. package/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.jsx +16 -0
  152. package/src/lib/components/ui/dropdown-menu/dropdown-menu-group.jsx +7 -0
  153. package/src/lib/components/ui/dropdown-menu/dropdown-menu-item.jsx +20 -0
  154. package/src/lib/components/ui/dropdown-menu/dropdown-menu-label.jsx +17 -0
  155. package/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.jsx +4 -0
  156. package/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.jsx +7 -0
  157. package/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.jsx +29 -0
  158. package/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.jsx +15 -0
  159. package/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.jsx +16 -0
  160. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.jsx +15 -0
  161. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.jsx +23 -0
  162. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.jsx +4 -0
  163. package/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.jsx +7 -0
  164. package/src/lib/components/ui/dropdown-menu/dropdown-menu.jsx +4 -0
  165. package/src/lib/components/ui/dropdown-menu/index.js +52 -52
  166. package/src/lib/components/ui/input/index.js +5 -5
  167. package/src/lib/components/ui/input/input.jsx +19 -0
  168. package/src/lib/components/ui/label/index.js +5 -5
  169. package/src/lib/components/ui/label/label.jsx +19 -0
  170. package/src/lib/components/ui/panel/index.js +21 -21
  171. package/src/lib/components/ui/panel/panel-body.jsx +11 -0
  172. package/src/lib/components/ui/panel/panel-close.jsx +16 -0
  173. package/src/lib/components/ui/panel/panel-content.jsx +29 -0
  174. package/src/lib/components/ui/panel/panel-footer.jsx +11 -0
  175. package/src/lib/components/ui/panel/panel-header.jsx +11 -0
  176. package/src/lib/components/ui/panel/panel-title.jsx +12 -0
  177. package/src/lib/components/ui/panel/panel.jsx +4 -0
  178. package/src/lib/components/ui/popover/index.js +26 -26
  179. package/src/lib/components/ui/popover/popover-close.jsx +7 -0
  180. package/src/lib/components/ui/popover/popover-content.jsx +22 -0
  181. package/src/lib/components/ui/popover/popover-description.jsx +11 -0
  182. package/src/lib/components/ui/popover/popover-header.jsx +11 -0
  183. package/src/lib/components/ui/popover/popover-portal.jsx +4 -0
  184. package/src/lib/components/ui/popover/popover-title.jsx +11 -0
  185. package/src/lib/components/ui/popover/popover-trigger.jsx +8 -0
  186. package/src/lib/components/ui/popover/popover.jsx +4 -0
  187. package/src/lib/components/ui/searchable-list.jsx +159 -0
  188. package/src/lib/components/ui/select/index.js +35 -35
  189. package/src/lib/components/ui/select/select-content.jsx +30 -0
  190. package/src/lib/components/ui/select/select-group-heading.jsx +17 -0
  191. package/src/lib/components/ui/select/select-group.jsx +15 -0
  192. package/src/lib/components/ui/select/select-item.jsx +26 -0
  193. package/src/lib/components/ui/select/select-label.jsx +11 -0
  194. package/src/lib/components/ui/select/select-portal.jsx +4 -0
  195. package/src/lib/components/ui/select/select-scroll-down-button.jsx +18 -0
  196. package/src/lib/components/ui/select/select-scroll-up-button.jsx +18 -0
  197. package/src/lib/components/ui/select/select-separator.jsx +15 -0
  198. package/src/lib/components/ui/select/select-trigger.jsx +25 -0
  199. package/src/lib/components/ui/select/select.jsx +4 -0
  200. package/src/lib/components/ui/separator/index.js +5 -5
  201. package/src/lib/components/ui/separator/separator.jsx +22 -0
  202. package/src/lib/components/ui/sheet/index.js +32 -32
  203. package/src/lib/components/ui/sheet/sheet-close.jsx +7 -0
  204. package/src/lib/components/ui/sheet/sheet-content.jsx +35 -0
  205. package/src/lib/components/ui/sheet/sheet-description.jsx +15 -0
  206. package/src/lib/components/ui/sheet/sheet-footer.jsx +11 -0
  207. package/src/lib/components/ui/sheet/sheet-header.jsx +11 -0
  208. package/src/lib/components/ui/sheet/sheet-overlay.jsx +15 -0
  209. package/src/lib/components/ui/sheet/sheet-portal.jsx +4 -0
  210. package/src/lib/components/ui/sheet/sheet-title.jsx +15 -0
  211. package/src/lib/components/ui/sheet/sheet-trigger.jsx +7 -0
  212. package/src/lib/components/ui/sheet/sheet.jsx +4 -0
  213. package/src/lib/components/ui/textarea/index.js +5 -5
  214. package/src/lib/components/ui/textarea/textarea.jsx +18 -0
  215. package/src/lib/components/ui/toggle/index.js +6 -9
  216. package/src/lib/components/ui/toggle/toggle.jsx +36 -0
  217. package/src/lib/components/ui/toggle-group/index.js +8 -8
  218. package/src/lib/components/ui/toggle-group/toggle-group-item.jsx +29 -0
  219. package/src/lib/components/ui/toggle-group/toggle-group.jsx +43 -0
  220. package/src/lib/components/ui/tooltip/index.js +3 -3
  221. package/src/lib/components/ui/tooltip/tooltip-content.jsx +21 -0
  222. package/src/lib/components/ui/tooltip/tooltip-trigger.jsx +23 -0
  223. package/src/lib/components/ui/tooltip/tooltip.jsx +11 -0
  224. package/src/lib/components/ui/trigger-button/index.js +3 -3
  225. package/src/lib/components/ui/trigger-button/trigger-button.css +38 -0
  226. package/src/lib/components/ui/trigger-button/trigger-button.jsx +63 -0
  227. package/src/logger/devLogger.js +238 -0
  228. package/src/logger/devLogger.test.js +193 -0
  229. package/src/modes.test.js +4 -4
  230. package/src/mountStoryboardCore.js +123 -27
  231. package/src/paletteProviders.js +3 -0
  232. package/src/paletteProviders.test.js +2 -2
  233. package/src/server/index.js +98 -36
  234. package/src/sidepanel.css +214 -0
  235. package/src/styles/tailwind.css +1 -1
  236. package/src/svelte-plugin-ui/__tests__/ModeSwitch.test.ts +8 -8
  237. package/src/svelte-plugin-ui/__tests__/ToolbarShell.test.ts +11 -10
  238. package/src/svelte-plugin-ui/components/Icon.css +11 -0
  239. package/src/svelte-plugin-ui/components/Icon.jsx +281 -0
  240. package/src/svelte-plugin-ui/components/ModeSwitch.css +90 -0
  241. package/src/svelte-plugin-ui/components/ModeSwitch.jsx +47 -0
  242. package/src/svelte-plugin-ui/components/ToolbarShell.css +80 -0
  243. package/src/svelte-plugin-ui/components/ToolbarShell.jsx +84 -0
  244. package/src/svelte-plugin-ui/components/Viewfinder.css +412 -0
  245. package/src/svelte-plugin-ui/components/Viewfinder.jsx +512 -0
  246. package/src/svelte-plugin-ui/mount.ts +12 -16
  247. package/src/toolRegistry.js +4 -4
  248. package/src/toolbarConfigStore.js +30 -0
  249. package/src/tools/handlers/autosync.js +1 -1
  250. package/src/tools/handlers/canvasAddWidget.js +1 -1
  251. package/src/tools/handlers/canvasAgents.js +19 -0
  252. package/src/tools/handlers/canvasToolbar.js +8 -8
  253. package/src/tools/handlers/commandPalette.js +9 -0
  254. package/src/tools/handlers/comments.js +1 -1
  255. package/src/tools/handlers/create.js +1 -1
  256. package/src/tools/handlers/devtools.js +16 -0
  257. package/src/tools/handlers/devtools.test.js +38 -0
  258. package/src/tools/handlers/flows.js +1 -1
  259. package/src/tools/handlers/hideChrome.js +9 -0
  260. package/src/tools/handlers/paletteTheme.js +35 -0
  261. package/src/tools/handlers/theme.js +1 -1
  262. package/src/tools/registry.js +4 -1
  263. package/src/tools/surfaces/commandList.js +3 -3
  264. package/src/tools/surfaces/mainToolbar.js +3 -3
  265. package/src/tools/surfaces/registry.js +4 -4
  266. package/src/ui/design-modes.ts +2 -2
  267. package/src/ui/viewfinder.ts +1 -1
  268. package/src/vite/server-plugin.js +242 -60
  269. package/src/workshop/features/createCanvas/CreateCanvasForm.jsx +260 -0
  270. package/src/workshop/features/createCanvas/index.js +1 -1
  271. package/src/workshop/features/createFlow/CreateFlowForm.jsx +334 -0
  272. package/src/workshop/features/createFlow/index.js +1 -1
  273. package/src/workshop/features/createPage/CreatePageForm.jsx +304 -0
  274. package/src/workshop/features/createPage/index.js +1 -1
  275. package/src/workshop/features/createPrototype/CreatePrototypeForm.jsx +289 -0
  276. package/src/workshop/features/createPrototype/index.js +1 -1
  277. package/src/workshop/features/createPrototype/server.js +98 -0
  278. package/src/workshop/features/createStory/CreateStoryForm.jsx +208 -0
  279. package/src/workshop/features/createStory/index.js +1 -1
  280. package/src/workshop/ui/WorkshopPanel.jsx +98 -0
  281. package/src/workshop/ui/mount.ts +1 -1
  282. package/src/worktree/port.js +48 -0
  283. package/src/worktree/serverRegistry.js +120 -0
  284. package/toolbar.config.json +93 -42
  285. package/widgets.config.json +580 -12
  286. package/src/ActionMenuButton.svelte +0 -119
  287. package/src/AutosyncMenuButton.svelte +0 -397
  288. package/src/CanvasCreateMenu.svelte +0 -295
  289. package/src/CanvasSnap.svelte +0 -87
  290. package/src/CanvasUndoRedo.svelte +0 -108
  291. package/src/CanvasZoomControl.svelte +0 -111
  292. package/src/CanvasZoomToFit.svelte +0 -52
  293. package/src/CommandMenu.svelte +0 -249
  294. package/src/CommandPalette.svelte +0 -33
  295. package/src/CommentsMenuButton.svelte +0 -53
  296. package/src/CoreUIBar.svelte +0 -847
  297. package/src/CreateMenuButton.svelte +0 -133
  298. package/src/DocPanel.svelte +0 -299
  299. package/src/InspectorPanel.svelte +0 -745
  300. package/src/PwaInstallBanner.svelte +0 -124
  301. package/src/SidePanel.svelte +0 -480
  302. package/src/ThemeMenuButton.svelte +0 -132
  303. package/src/comments/ui/AuthModal.svelte +0 -108
  304. package/src/comments/ui/CommentWindow.svelte +0 -333
  305. package/src/comments/ui/CommentsDrawer.svelte +0 -96
  306. package/src/comments/ui/Composer.svelte +0 -65
  307. package/src/lib/components/ui/alert/alert-action.svelte +0 -19
  308. package/src/lib/components/ui/alert/alert-description.svelte +0 -22
  309. package/src/lib/components/ui/alert/alert-title.svelte +0 -22
  310. package/src/lib/components/ui/alert/alert.svelte +0 -38
  311. package/src/lib/components/ui/avatar/avatar-badge.svelte +0 -25
  312. package/src/lib/components/ui/avatar/avatar-fallback.svelte +0 -20
  313. package/src/lib/components/ui/avatar/avatar-group-count.svelte +0 -22
  314. package/src/lib/components/ui/avatar/avatar-group.svelte +0 -22
  315. package/src/lib/components/ui/avatar/avatar-image.svelte +0 -17
  316. package/src/lib/components/ui/avatar/avatar.svelte +0 -24
  317. package/src/lib/components/ui/badge/badge.svelte +0 -44
  318. package/src/lib/components/ui/button/button.svelte +0 -108
  319. package/src/lib/components/ui/card/card-action.svelte +0 -21
  320. package/src/lib/components/ui/card/card-content.svelte +0 -19
  321. package/src/lib/components/ui/card/card-description.svelte +0 -19
  322. package/src/lib/components/ui/card/card-footer.svelte +0 -18
  323. package/src/lib/components/ui/card/card-header.svelte +0 -21
  324. package/src/lib/components/ui/card/card-title.svelte +0 -14
  325. package/src/lib/components/ui/card/card.svelte +0 -21
  326. package/src/lib/components/ui/checkbox/checkbox.svelte +0 -39
  327. package/src/lib/components/ui/collapsible/collapsible-content.svelte +0 -7
  328. package/src/lib/components/ui/collapsible/collapsible-trigger.svelte +0 -7
  329. package/src/lib/components/ui/collapsible/collapsible.svelte +0 -11
  330. package/src/lib/components/ui/dialog/dialog-close.svelte +0 -11
  331. package/src/lib/components/ui/dialog/dialog-content.svelte +0 -42
  332. package/src/lib/components/ui/dialog/dialog-description.svelte +0 -17
  333. package/src/lib/components/ui/dialog/dialog-footer.svelte +0 -29
  334. package/src/lib/components/ui/dialog/dialog-header.svelte +0 -19
  335. package/src/lib/components/ui/dialog/dialog-overlay.svelte +0 -17
  336. package/src/lib/components/ui/dialog/dialog-portal.svelte +0 -7
  337. package/src/lib/components/ui/dialog/dialog-title.svelte +0 -17
  338. package/src/lib/components/ui/dialog/dialog-trigger.svelte +0 -11
  339. package/src/lib/components/ui/dialog/dialog.svelte +0 -7
  340. package/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte +0 -16
  341. package/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +0 -40
  342. package/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte +0 -27
  343. package/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +0 -18
  344. package/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte +0 -7
  345. package/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte +0 -24
  346. package/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte +0 -20
  347. package/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte +0 -7
  348. package/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte +0 -16
  349. package/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +0 -34
  350. package/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte +0 -17
  351. package/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +0 -19
  352. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +0 -17
  353. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +0 -27
  354. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte +0 -7
  355. package/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +0 -7
  356. package/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte +0 -7
  357. package/src/lib/components/ui/input/input.svelte +0 -40
  358. package/src/lib/components/ui/label/label.svelte +0 -20
  359. package/src/lib/components/ui/panel/panel-body.svelte +0 -13
  360. package/src/lib/components/ui/panel/panel-close.svelte +0 -16
  361. package/src/lib/components/ui/panel/panel-content.svelte +0 -33
  362. package/src/lib/components/ui/panel/panel-footer.svelte +0 -13
  363. package/src/lib/components/ui/panel/panel-header.svelte +0 -16
  364. package/src/lib/components/ui/panel/panel-title.svelte +0 -14
  365. package/src/lib/components/ui/panel/panel.svelte +0 -15
  366. package/src/lib/components/ui/popover/popover-close.svelte +0 -7
  367. package/src/lib/components/ui/popover/popover-content.svelte +0 -27
  368. package/src/lib/components/ui/popover/popover-description.svelte +0 -19
  369. package/src/lib/components/ui/popover/popover-header.svelte +0 -19
  370. package/src/lib/components/ui/popover/popover-portal.svelte +0 -7
  371. package/src/lib/components/ui/popover/popover-title.svelte +0 -19
  372. package/src/lib/components/ui/popover/popover-trigger.svelte +0 -17
  373. package/src/lib/components/ui/popover/popover.svelte +0 -7
  374. package/src/lib/components/ui/select/select-content.svelte +0 -40
  375. package/src/lib/components/ui/select/select-group-heading.svelte +0 -19
  376. package/src/lib/components/ui/select/select-group.svelte +0 -17
  377. package/src/lib/components/ui/select/select-item.svelte +0 -38
  378. package/src/lib/components/ui/select/select-label.svelte +0 -18
  379. package/src/lib/components/ui/select/select-portal.svelte +0 -7
  380. package/src/lib/components/ui/select/select-scroll-down-button.svelte +0 -20
  381. package/src/lib/components/ui/select/select-scroll-up-button.svelte +0 -20
  382. package/src/lib/components/ui/select/select-separator.svelte +0 -17
  383. package/src/lib/components/ui/select/select-trigger.svelte +0 -27
  384. package/src/lib/components/ui/select/select.svelte +0 -11
  385. package/src/lib/components/ui/separator/separator.svelte +0 -23
  386. package/src/lib/components/ui/sheet/sheet-close.svelte +0 -7
  387. package/src/lib/components/ui/sheet/sheet-content.svelte +0 -43
  388. package/src/lib/components/ui/sheet/sheet-description.svelte +0 -17
  389. package/src/lib/components/ui/sheet/sheet-footer.svelte +0 -18
  390. package/src/lib/components/ui/sheet/sheet-header.svelte +0 -19
  391. package/src/lib/components/ui/sheet/sheet-overlay.svelte +0 -17
  392. package/src/lib/components/ui/sheet/sheet-portal.svelte +0 -7
  393. package/src/lib/components/ui/sheet/sheet-title.svelte +0 -17
  394. package/src/lib/components/ui/sheet/sheet-trigger.svelte +0 -7
  395. package/src/lib/components/ui/sheet/sheet.svelte +0 -7
  396. package/src/lib/components/ui/textarea/textarea.svelte +0 -21
  397. package/src/lib/components/ui/toggle/toggle.svelte +0 -45
  398. package/src/lib/components/ui/toggle-group/toggle-group-item.svelte +0 -35
  399. package/src/lib/components/ui/toggle-group/toggle-group.svelte +0 -63
  400. package/src/lib/components/ui/tooltip/tooltip-content.svelte +0 -24
  401. package/src/lib/components/ui/tooltip/tooltip-trigger.svelte +0 -27
  402. package/src/lib/components/ui/tooltip/tooltip.svelte +0 -9
  403. package/src/lib/components/ui/trigger-button/trigger-button.svelte +0 -106
  404. package/src/svelte-plugin-ui/components/Icon.svelte +0 -181
  405. package/src/svelte-plugin-ui/components/ModeSwitch.svelte +0 -121
  406. package/src/svelte-plugin-ui/components/ToolbarShell.svelte +0 -150
  407. package/src/svelte-plugin-ui/components/Viewfinder.svelte +0 -1001
  408. package/src/tools/handlers/docs.js +0 -11
  409. package/src/workshop/features/createCanvas/CreateCanvasForm.svelte +0 -139
  410. package/src/workshop/features/createFlow/CreateFlowForm.svelte +0 -314
  411. package/src/workshop/features/createPage/CreatePageForm.svelte +0 -249
  412. package/src/workshop/features/createPrototype/CreatePrototypeForm.svelte +0 -287
  413. package/src/workshop/features/createStory/CreateStoryForm.svelte +0 -161
  414. package/src/workshop/ui/WorkshopPanel.svelte +0 -97
@@ -1,745 +0,0 @@
1
- <!--
2
- InspectorPanel — Inspector tab for the side panel.
3
- Select DOM elements and view their React component information.
4
- Uses mouseMode for element selection and fiberWalker for component introspection.
5
- -->
6
-
7
- <script>
8
- import { onMount, onDestroy } from 'svelte'
9
- import Icon from './svelte-plugin-ui/components/Icon.svelte'
10
- import { inspectElement, inspectElementChain } from './inspector/fiberWalker.js'
11
- import { createMouseMode } from './inspector/mouseMode.js'
12
- import { getColors, createInspectorHighlighter } from './inspector/highlighter.js'
13
-
14
- /** @type {{ name: string, props: object, source: { fileName: string, lineNumber: number, columnNumber?: number } | null, owner: string | null } | null} */
15
- let componentInfo = $state(null)
16
-
17
- /** @type {Array<{ name: string, source: { fileName: string, lineNumber: number, columnNumber?: number } | null }>} */
18
- let componentChain = $state([])
19
-
20
- let inspecting = $state(false)
21
- let sourceCode = $state('')
22
- let sourceLoading = $state(false)
23
- let sourcePath = $state('')
24
- let matchedLine = $state(-1)
25
-
26
- /** @type {HTMLElement | null} */
27
- let sourceContainer = $state(null)
28
-
29
- /** @type {Element | null} — the currently selected DOM element */
30
- let selectedElement = $state(null)
31
-
32
- // ── URL state helpers ─────────────────────────────────────────────
33
-
34
- /**
35
- * Build a CSS selector that can re-find `el` later.
36
- * Prefers id, then data-testid, then an nth-child path from <body>.
37
- */
38
- function generateSelector(el) {
39
- if (!(el instanceof Element)) return null
40
- if (el.id) return `#${CSS.escape(el.id)}`
41
-
42
- const testId = el.getAttribute('data-testid')
43
- if (testId) return `[data-testid="${CSS.escape(testId)}"]`
44
-
45
- const parts = []
46
- let cur = el
47
- while (cur && cur !== document.body && cur !== document.documentElement) {
48
- let seg = cur.tagName.toLowerCase()
49
- if (cur.id) {
50
- parts.unshift(`#${CSS.escape(cur.id)}`)
51
- break
52
- }
53
- const parent = cur.parentElement
54
- if (parent) {
55
- const siblings = Array.from(parent.children)
56
- const idx = siblings.indexOf(cur) + 1
57
- seg += `:nth-child(${idx})`
58
- }
59
- parts.unshift(seg)
60
- cur = parent
61
- }
62
- return parts.length ? parts.join(' > ') : null
63
- }
64
-
65
- /** Read the `inspect` search param from the current URL. */
66
- function getInspectParam() {
67
- try {
68
- return new URL(window.location.href).searchParams.get('inspect')
69
- } catch { return null }
70
- }
71
-
72
- /** Set or clear the `inspect` search param without triggering navigation. */
73
- function setInspectParam(selector) {
74
- try {
75
- const url = new URL(window.location.href)
76
- if (selector) {
77
- url.searchParams.set('inspect', selector)
78
- } else {
79
- url.searchParams.delete('inspect')
80
- }
81
- history.replaceState(history.state, '', url.toString())
82
- } catch {}
83
- }
84
-
85
- /** @type {string[]} */
86
- let knownFiles = []
87
-
88
- /** @type {{ owner: string, name: string } | null} */
89
- let repoInfo = $state(null)
90
-
91
- /** @type {{ files: string[], sources: Record<string, string>, repo: { owner: string, name: string } | null } | null} */
92
- let staticInspectorData = null
93
-
94
- /**
95
- * Load the build-time static inspector JSON (production only).
96
- * Cached after the first successful fetch.
97
- */
98
- async function loadStaticData() {
99
- if (staticInspectorData) return staticInspectorData
100
- try {
101
- // Use window.location to derive base path at runtime, since
102
- // import.meta.env.BASE_URL is baked at compile time in the UI bundle
103
- const basePath = window.__STORYBOARD_BASE_PATH__ || '/'
104
- const res = await fetch(`${basePath}_storyboard/inspector.json`)
105
- if (res.ok) {
106
- staticInspectorData = await res.json()
107
- return staticInspectorData
108
- }
109
- } catch {}
110
- return null
111
- }
112
-
113
- const _isLocalDev = typeof window !== 'undefined' && window.__SB_LOCAL_DEV__ === true && !new URLSearchParams(window.location.search).has('prodMode')
114
- const _basePath = (typeof window !== 'undefined' && window.__STORYBOARD_BASE_PATH__) || '/'
115
-
116
- /**
117
- * Fetch source file content — uses dev middleware in dev, static JSON in prod.
118
- */
119
- async function fetchSourceContent(filePath) {
120
- // In local dev, use the live middleware (reads from disk)
121
- if (_isLocalDev) {
122
- try {
123
- const res = await fetch(`${_basePath.replace(/\/$/, '')}/_storyboard/docs/source?path=${encodeURIComponent(filePath)}`)
124
- if (res.ok) {
125
- const json = await res.json()
126
- return json?.content || ''
127
- }
128
- } catch {}
129
- }
130
- // In production (or if dev middleware failed), use static build-time JSON
131
- const data = await loadStaticData()
132
- return data?.sources?.[filePath] || ''
133
- }
134
-
135
- let mouseMode = null
136
-
137
- const hasSelection = $derived(componentInfo !== null)
138
-
139
- /**
140
- * Derive the git branch from the URL base path.
141
- * Branch deploys use /branch--{name}/ in the path.
142
- * Falls back to 'main'.
143
- */
144
- const gitBranch = $derived.by(() => {
145
- const m = window.location.pathname.match(/\/branch--([^/]+)/)
146
- if (m) return m[1].replace(/-/g, '/')
147
- return 'main'
148
- })
149
-
150
- const githubUrl = $derived.by(() => {
151
- if (!repoInfo || !sourcePath) return null
152
- const base = `https://github.com/${repoInfo.owner}/${repoInfo.name}/blob/${gitBranch}/${sourcePath}`
153
- const line = matchedLine > 0 ? matchedLine : componentInfo?.source?.lineNumber
154
- return line ? `${base}#L${line}` : base
155
- })
156
-
157
- const sourceLink = $derived.by(() => {
158
- if (!sourcePath) return null
159
- return {
160
- label: sourcePath.split('/').pop(),
161
- href: null,
162
- }
163
- })
164
-
165
- /**
166
- * Find the source file for a component by matching against known files.
167
- * Strategy:
168
- * 1. If _debugSource is available (React <19), use that directly
169
- * Resolve the source file for the current page from the URL.
170
- * Maps the route path to a file in src/prototypes/ by stripping the
171
- * base path and matching against known files (which have .folder/
172
- * segments stripped during route generation).
173
- *
174
- * Also tries matching a specific component name as a fallback.
175
- */
176
- function resolveSourceFile(info) {
177
- // Strategy 1: _debugSource (React <19)
178
- if (info?.source?.fileName) {
179
- // Strip Vite query params (e.g. ?v=12345)
180
- const cleanName = info.source.fileName.split('?')[0]
181
- const srcIndex = cleanName.indexOf('/src/')
182
- if (srcIndex !== -1) return cleanName.slice(srcIndex + 1)
183
- if (cleanName.startsWith('src/')) return cleanName
184
- }
185
-
186
- // Strategy 2: match current URL route to a page file
187
- const pageFile = resolvePageFile()
188
- if (pageFile) return pageFile
189
-
190
- // Strategy 3: match component name to a file basename
191
- const name = info?.name
192
- if (name && name !== 'Anonymous' && name !== 'Unknown') {
193
- const match = knownFiles.find(f => {
194
- const base = f.split('/').pop()?.replace(/\.(jsx|tsx|js|ts)$/, '')
195
- return base === name
196
- })
197
- if (match) return match
198
- }
199
-
200
- return null
201
- }
202
-
203
- /**
204
- * Derive the current page's source file from window.location.pathname.
205
- * Strips the Vite base path, then searches known files for a match.
206
- */
207
- function resolvePageFile() {
208
- if (knownFiles.length === 0) return null
209
-
210
- let pathname = window.location.pathname
211
-
212
- // Strip any base path prefix by progressively removing leading segments
213
- // until we find a match. This handles /storyboard-source/Example → Example
214
- // without needing to know the exact base path.
215
- if (pathname.startsWith('/')) pathname = pathname.slice(1)
216
- pathname = pathname.replace(/\/$/, '')
217
-
218
- // Normalize file paths once: strip src/prototypes/, .folder/ segments, extensions
219
- const normalizedFiles = knownFiles.map(f => ({
220
- original: f,
221
- normalized: f
222
- .replace(/^src\/prototypes\//, '')
223
- .replace(/[^/]*\.folder\//g, '')
224
- .replace(/\.(jsx|tsx|js|ts)$/, ''),
225
- }))
226
-
227
- // Try matching with progressively fewer leading segments
228
- const segments = pathname.split('/').filter(Boolean)
229
- for (let start = 0; start < segments.length; start++) {
230
- const routeEnd = segments.slice(start).join('/')
231
- if (!routeEnd) continue
232
-
233
- for (const { original, normalized } of normalizedFiles) {
234
- // Match: "Example" → "Example/index" or "Example"
235
- const withoutIndex = normalized.replace(/\/index$/, '')
236
- if (withoutIndex === routeEnd || normalized === routeEnd) return original
237
- }
238
- }
239
-
240
- // Root path fallback
241
- if (!pathname || segments.length === 0) {
242
- const idx = knownFiles.find(f => /^src\/prototypes\/index\.(jsx|tsx|js|ts)$/.test(f))
243
- if (idx) return idx
244
- }
245
-
246
- return null
247
- }
248
-
249
- let highlightedHtml = $state('')
250
-
251
- // Code theme colors — refreshed on theme change events
252
- let codeTheme = $state(getColors())
253
-
254
- /** @type {any} */
255
- let highlighter = null
256
-
257
- async function getHighlighter() {
258
- if (highlighter) return highlighter
259
- highlighter = await createInspectorHighlighter()
260
- return highlighter
261
- }
262
-
263
- /** Re-highlight source code with current theme (called on theme change). */
264
- async function rehighlight() {
265
- codeTheme = getColors()
266
- if (!sourceCode || !sourcePath) return
267
- try {
268
- const hl = await getHighlighter()
269
- highlightedHtml = hl.codeToHtml(sourceCode, {
270
- lang: getLang(sourcePath),
271
- theme: 'github-dark',
272
- lineNumbers: false,
273
- decorations: matchedLine > 0
274
- ? [{ start: { line: matchedLine - 1, character: 0 }, end: { line: matchedLine - 1, character: Infinity }, properties: { class: 'highlighted-line' } }]
275
- : [],
276
- })
277
- } catch { /* ignore */ }
278
- }
279
-
280
- /**
281
- * Find the line number of a JSX component in source code by matching
282
- * the component name and its props against the source lines.
283
- *
284
- * Searches for `<ComponentName` followed by prop values from the
285
- * component's props. Scores each `<ComponentName` occurrence by how
286
- * many prop values appear nearby, picks the best match.
287
- */
288
- function findComponentLine(code, info) {
289
- if (!code || !info?.name) return -1
290
-
291
- const lines = code.split('\n')
292
- const name = info.name
293
- const props = info.props || {}
294
-
295
- // Collect string representations of prop values for matching
296
- const propSignatures = []
297
- for (const [key, val] of Object.entries(props)) {
298
- if (key === 'children') continue
299
- if (typeof val === 'string') {
300
- propSignatures.push(`"${val}"`, `'${val}'`, `\`${val}\``, `="${val}"`, `='${val}'`)
301
- } else if (typeof val === 'number' || typeof val === 'boolean') {
302
- propSignatures.push(`{${val}}`, `=${val}`)
303
- }
304
- }
305
-
306
- // Find all lines with `<ComponentName` (opening JSX tag)
307
- const tagPattern = new RegExp(`<${name}[\\s/>]`)
308
- const candidates = []
309
- for (let i = 0; i < lines.length; i++) {
310
- if (tagPattern.test(lines[i])) {
311
- candidates.push(i)
312
- }
313
- }
314
-
315
- if (candidates.length === 0) return -1
316
- if (candidates.length === 1) return candidates[0] + 1
317
-
318
- // Score each candidate by how many prop values appear in nearby lines
319
- let bestLine = candidates[0]
320
- let bestScore = -1
321
-
322
- for (const lineIdx of candidates) {
323
- // Look at this line + the next 5 lines for prop values (JSX props are close)
324
- const window = lines.slice(lineIdx, lineIdx + 6).join(' ')
325
- let score = 0
326
- for (const sig of propSignatures) {
327
- if (window.includes(sig)) score++
328
- }
329
- if (score > bestScore) {
330
- bestScore = score
331
- bestLine = lineIdx
332
- }
333
- }
334
-
335
- return bestLine + 1 // 1-indexed
336
- }
337
-
338
- function getLang(filePath) {
339
- if (filePath.endsWith('.tsx')) return 'tsx'
340
- if (filePath.endsWith('.jsx')) return 'jsx'
341
- if (filePath.endsWith('.ts')) return 'typescript'
342
- return 'javascript'
343
- }
344
-
345
- $effect(() => {
346
- const path = resolveSourceFile(componentInfo)
347
- if (path) {
348
- sourceLoading = true
349
- sourcePath = path
350
- highlightedHtml = ''
351
- fetchSourceContent(path)
352
- .then(async (content) => {
353
- sourceCode = content
354
- // Try the selected component first, then walk up the chain
355
- matchedLine = findComponentLine(sourceCode, componentInfo)
356
- if (matchedLine < 0 && componentChain.length > 0) {
357
- for (const ancestor of componentChain) {
358
- matchedLine = findComponentLine(sourceCode, { name: ancestor.name, props: {} })
359
- if (matchedLine > 0) break
360
- }
361
- }
362
- if (sourceCode) {
363
- try {
364
- const hl = await getHighlighter()
365
- highlightedHtml = hl.codeToHtml(sourceCode, {
366
- lang: getLang(path),
367
- theme: 'github-dark',
368
- lineNumbers: false,
369
- decorations: matchedLine > 0
370
- ? [{ start: { line: matchedLine - 1, character: 0 }, end: { line: matchedLine - 1, character: Infinity }, properties: { class: 'highlighted-line' } }]
371
- : [],
372
- })
373
- } catch {
374
- highlightedHtml = ''
375
- }
376
- }
377
- sourceLoading = false
378
- })
379
- .catch(() => { sourceCode = ''; highlightedHtml = ''; matchedLine = -1; sourceLoading = false })
380
- } else {
381
- sourceCode = ''
382
- sourcePath = ''
383
- highlightedHtml = ''
384
- }
385
- })
386
-
387
- $effect(() => {
388
- if (sourceContainer && highlightedHtml) {
389
- requestAnimationFrame(() => {
390
- const el = sourceContainer.querySelector('.highlighted-line')
391
- if (el) {
392
- // Align the highlighted line to the top of the code viewport.
393
- const targetTop = Math.max(el.offsetTop - 24, 0)
394
- sourceContainer.scrollTo({ top: targetTop, behavior: 'smooth' })
395
- } else {
396
- sourceContainer.scrollTop = 0
397
- }
398
- })
399
- }
400
- })
401
-
402
- function handleSelect(el) {
403
- componentInfo = inspectElement(el)
404
- componentChain = inspectElementChain(el)
405
- selectedElement = el
406
- inspecting = false
407
- // Show persistent highlight on the selected element
408
- mouseMode?.showHighlight(el)
409
- // Persist selection to URL
410
- setInspectParam(generateSelector(el))
411
- }
412
-
413
- function handleDeactivate() {
414
- inspecting = false
415
- }
416
-
417
- function startInspecting() {
418
- // Hide any persistent highlight before entering mouse mode
419
- mouseMode?.hideHighlight()
420
- mouseMode?.activate()
421
- inspecting = true
422
- // Clear URL param while re-selecting
423
- setInspectParam(null)
424
- }
425
-
426
- function stopInspecting() {
427
- mouseMode?.deactivate()
428
- inspecting = false
429
- }
430
-
431
- function toggleInspecting() {
432
- if (inspecting) stopInspecting()
433
- else startInspecting()
434
- }
435
-
436
- function formatSourceLink(source) {
437
- if (!source) return null
438
- const { fileName, lineNumber, columnNumber } = source
439
- return {
440
- label: `${fileName.split('/').pop()}:${lineNumber}`,
441
- href: `vscode://file/${fileName}:${lineNumber}:${columnNumber || 1}`,
442
- }
443
- }
444
-
445
- onMount(async () => {
446
- mouseMode = createMouseMode({
447
- onSelect: handleSelect,
448
- onDeactivate: handleDeactivate,
449
- })
450
-
451
- // Re-highlight code when theme changes
452
- document.addEventListener('storyboard:theme:changed', rehighlight)
453
-
454
- // Pre-fetch file list and repo info
455
- // In local dev, try dev middleware; in production, go straight to static JSON
456
- let filesLoaded = false
457
- if (_isLocalDev) {
458
- try {
459
- const [filesRes, repoRes] = await Promise.all([
460
- fetch(`${_basePath.replace(/\/$/, '')}/_storyboard/docs/files`),
461
- fetch(`${_basePath.replace(/\/$/, '')}/_storyboard/docs/repo`),
462
- ])
463
- if (filesRes.ok) {
464
- const data = await filesRes.json()
465
- knownFiles = data.files || []
466
- filesLoaded = true
467
- }
468
- if (repoRes.ok) {
469
- repoInfo = await repoRes.json()
470
- }
471
- } catch {}
472
- }
473
-
474
- if (!filesLoaded) {
475
- // Use static build-time JSON
476
- const data = await loadStaticData()
477
- if (data) {
478
- knownFiles = data.files || []
479
- repoInfo = data.repo || null
480
- }
481
- }
482
-
483
- // Restore inspector selection from URL param (after files are loaded)
484
- const savedSelector = getInspectParam()
485
- let restored = false
486
- if (savedSelector) {
487
- // Retry with delay — the React page may still be rendering
488
- for (let attempt = 0; attempt < 5 && !restored; attempt++) {
489
- if (attempt > 0) await new Promise(r => setTimeout(r, 300))
490
- try {
491
- const el = document.querySelector(savedSelector)
492
- if (el) {
493
- handleSelect(el)
494
- restored = true
495
- }
496
- } catch {
497
- break // invalid selector, don't retry
498
- }
499
- }
500
- if (!restored) setInspectParam(null)
501
- }
502
-
503
- if (!restored) {
504
- startInspecting()
505
- }
506
- })
507
-
508
- onDestroy(() => {
509
- mouseMode?.deactivate()
510
- mouseMode?.hideHighlight()
511
- setInspectParam(null)
512
- document.removeEventListener('storyboard:theme:changed', rehighlight)
513
- })
514
- </script>
515
-
516
- <div class="flex flex-col h-full" data-inspector-panel>
517
- <!-- Content -->
518
- <div class="flex-1 overflow-y-auto min-h-0 flex flex-col">
519
- <!-- Empty state -->
520
- {#if !hasSelection && !inspecting}
521
- <div class="flex flex-col items-center justify-center h-full gap-3 px-6 py-12 text-center">
522
- <span style:color="var(--fgColor-muted)" class="opacity-40">
523
- <Icon name="iconoir/square-dashed" size={48} strokeWeight={2} scale={1.05} />
524
- </span>
525
- <p class="text-sm font-medium m-0" style:color="var(--fgColor-default)">
526
- Select an element to start
527
- </p>
528
- <p class="text-xs m-0" style:color="var(--fgColor-muted)">
529
- Click the inspect button to enter selection mode
530
- </p>
531
- <button
532
- class="mt-2 px-4 py-1.5 text-xs font-medium rounded-md border-none cursor-pointer transition-colors"
533
- style:background="var(--sb--color-purple, #7655a4)"
534
- style:color="#fff"
535
- onclick={startInspecting}
536
- >
537
- Start inspecting
538
- </button>
539
- </div>
540
-
541
- <!-- Inspecting state -->
542
- {:else if inspecting}
543
- <div class="flex flex-col items-center justify-center h-full gap-3 px-6 py-12 text-center">
544
- <div class="flex items-center gap-2">
545
- <span class="inspector-pulse-dot"></span>
546
- <p class="text-sm m-0" style:color="var(--fgColor-default)">
547
- Click any element on the page to inspect it
548
- </p>
549
- </div>
550
- <button
551
- class="mt-2 px-4 py-1.5 text-xs font-medium rounded-md border cursor-pointer transition-colors"
552
- style:background="transparent"
553
- style:color="var(--fgColor-muted)"
554
- style:border-color="var(--borderColor-default, var(--sb--color-border, #d1d9e0))"
555
- onclick={stopInspecting}
556
- >
557
- Cancel
558
- </button>
559
- </div>
560
-
561
- <!-- Selected state -->
562
- {:else}
563
- <div class="flex flex-col flex-1 min-h-0 p-3 pt-0 gap-3">
564
- <!-- Component name -->
565
- <div>
566
- <h3 class="text-base font-bold m-0 inspector-mono" style:color="var(--sb--color-purple, #7655a4)">
567
- {componentInfo.name}
568
- </h3>
569
- </div>
570
-
571
- <!-- Source code -->
572
- {#if sourcePath}
573
- <div class="border rounded-md overflow-hidden flex-1 min-h-0 flex flex-col" style:background={codeTheme.bg} style:border-color={codeTheme.border}>
574
- <div
575
- class="flex items-center justify-between w-full px-3 py-1.5 text-xs font-semibold shrink-0"
576
- style:background={codeTheme.headerBg}
577
- style:color={codeTheme.headerFg}
578
- style:border-bottom="1px solid {codeTheme.border}"
579
- >
580
- <span class="flex items-center gap-1.5 min-w-0">
581
- <Icon name="primer/file-code" size={12} />
582
- <span class="truncate">{sourcePath}</span>
583
- </span>
584
- {#if githubUrl}
585
- <a
586
- href={githubUrl}
587
- target="_blank"
588
- rel="noopener noreferrer"
589
- class="flex items-center gap-1 shrink-0 text-xs no-underline hover:underline inspector-mono inspector-code-link"
590
- style:color={codeTheme.headerFg}
591
- >
592
- <Icon name="primer/mark-github" size={14} />
593
- <span>GitHub</span>
594
- </a>
595
- {/if}
596
- </div>
597
-
598
- <div class="border-t flex-1 min-h-0 flex flex-col" style:border-color={codeTheme.border}>
599
- {#if sourceLoading}
600
- <div class="px-3 py-4 text-xs text-center" style:color={codeTheme.headerFg}>
601
- Loading source…
602
- </div>
603
- {:else if sourceCode}
604
- <div class="flex-1 min-h-0 overflow-y-auto source-scroll-container" bind:this={sourceContainer} style:--inspector-line-num-color={codeTheme.comment} style:--inspector-line-hover={codeTheme.lineHighlight}>
605
- {#if highlightedHtml}
606
- <div class="code-wrapper line-numbers">{@html highlightedHtml}</div>
607
- {:else}
608
- <pre class="m-0 text-xs leading-relaxed inspector-mono source-pre line-numbers" style:background={codeTheme.bg} style:color={codeTheme.fg}><code>{#each sourceCode.split('\n') as line, i}<span class="line{matchedLine > 0 && i + 1 === matchedLine ? ' highlighted-line' : ''}">{line}</span>{#if i < sourceCode.split('\n').length - 1}{'\n'}{/if}{/each}</code></pre>
609
- {/if}
610
- </div>
611
- {:else}
612
- <div class="px-3 py-4 text-xs text-center" style:color={codeTheme.headerFg}>
613
- Unable to load source
614
- </div>
615
- {/if}
616
- </div>
617
- </div>
618
- {/if}
619
-
620
- <!-- Re-select button -->
621
- <button
622
- class="flex items-center justify-center gap-1.5 w-full px-3 py-1.5 text-xs font-medium rounded-md border-none cursor-pointer transition-colors shrink-0"
623
- style:background="var(--sb--color-purple, #7655a4)"
624
- style:color="#fff"
625
- onclick={startInspecting}
626
- >
627
- <Icon name="primer/search" size={12} />
628
- Re-select
629
- </button>
630
- </div>
631
- {/if}
632
- </div>
633
- </div>
634
-
635
- <style>
636
- .inspector-mono {
637
- font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
638
- }
639
-
640
- .inspector-pulse-dot {
641
- width: 8px;
642
- height: 8px;
643
- border-radius: 50%;
644
- background: var(--sb--color-purple, #7655a4);
645
- animation: inspector-pulse 1.5s ease-in-out infinite;
646
- flex-shrink: 0;
647
- }
648
-
649
- @keyframes inspector-pulse {
650
- 0%, 100% { opacity: 1; transform: scale(1); }
651
- 50% { opacity: 0.4; transform: scale(0.85); }
652
- }
653
-
654
- pre {
655
- background: transparent;
656
- }
657
-
658
- .source-pre {
659
- background: transparent;
660
- tab-size: 2;
661
- padding: 12px 0;
662
- color: #c9d1d9;
663
- overflow-x: auto;
664
- }
665
-
666
- .source-pre code {
667
- font-family: inherit;
668
- display: block;
669
- }
670
-
671
- .source-pre .line {
672
- padding: 0 12px 0 0;
673
- display: inline-block;
674
- width: 100%;
675
- min-height: 1.5em;
676
- }
677
-
678
- .source-pre .line:hover {
679
- background: var(--inspector-line-hover, rgba(255, 255, 255, 0.04));
680
- }
681
-
682
- .source-pre :global(.highlighted-line) {
683
- background: color-mix(in srgb, var(--sb--color-purple, #7655a4) 20%, transparent);
684
- border-left: 2px solid var(--sb--color-purple, #7655a4);
685
- padding-left: 10px;
686
- }
687
-
688
- /* Line numbers via CSS counters — works for both highlight.js and plain-text */
689
- .line-numbers :global(code) {
690
- counter-reset: line;
691
- }
692
-
693
- .line-numbers :global(.line) {
694
- padding-left: 0 !important;
695
- }
696
-
697
- .line-numbers :global(.line::before) {
698
- counter-increment: line;
699
- content: counter(line);
700
- display: inline-block;
701
- width: 3.5ch;
702
- margin-right: 1.5ch;
703
- text-align: right;
704
- color: var(--inspector-line-num-color, #484f58);
705
- user-select: none;
706
- }
707
-
708
- .code-wrapper :global(pre) {
709
- margin: 0;
710
- padding: 12px 0;
711
- font-size: 12px;
712
- line-height: 1.6;
713
- font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
714
- tab-size: 2;
715
- background: transparent !important;
716
- overflow-x: auto;
717
- }
718
-
719
- .code-wrapper :global(code) {
720
- font-family: inherit;
721
- display: block;
722
- }
723
-
724
- .code-wrapper :global(.line) {
725
- padding: 0 12px 0 0;
726
- display: inline-block;
727
- width: 100%;
728
- min-height: 1.5em;
729
- }
730
-
731
- .code-wrapper :global(.line:hover) {
732
- background: var(--inspector-line-hover, rgba(255, 255, 255, 0.04));
733
- }
734
-
735
- .code-wrapper :global(.highlighted-line) {
736
- background: color-mix(in srgb, var(--sb--color-purple, #7655a4) 20%, transparent);
737
- border-left: 2px solid var(--sb--color-purple, #7655a4);
738
- padding-left: 10px;
739
- }
740
-
741
- /* Force dark chrome on the code block — independent of page theme */
742
- .inspector-code-link:hover {
743
- text-decoration: underline;
744
- }
745
- </style>