@jxsuite/studio 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (419) hide show
  1. package/canvas.html +21 -0
  2. package/dist/chunks/Overlay.dev-qfjzkms8.js +23 -0
  3. package/dist/chunks/{Overlay.dev-cszx7yn5.js.map → Overlay.dev-qfjzkms8.js.map} +1 -1
  4. package/dist/chunks/{adapter-z8fkmbmv.js → adapter-qfnesn5v.js} +2 -2
  5. package/dist/chunks/{cf-settings-mmyv436d.js → cf-settings-73sh5z4p.js} +3 -3
  6. package/dist/chunks/{components-0hzentwq.js → components-2bpqp4mq.js} +5 -7
  7. package/dist/chunks/{components-0hzentwq.js.map → components-2bpqp4mq.js.map} +1 -1
  8. package/dist/chunks/content-source-34gnkbnn.js +38 -0
  9. package/dist/chunks/content-source-34gnkbnn.js.map +9 -0
  10. package/dist/chunks/convert-to-repeater-t8kxre5s.js +258 -0
  11. package/dist/chunks/convert-to-repeater-t8kxre5s.js.map +10 -0
  12. package/dist/chunks/extension-sections-6mqydz35.js +301 -0
  13. package/dist/chunks/extension-sections-6mqydz35.js.map +11 -0
  14. package/dist/chunks/files-8kn321h1.js +70 -0
  15. package/dist/chunks/files-8kn321h1.js.map +9 -0
  16. package/dist/chunks/{format-host-2c188n41.js → format-host-mkwsmt8d.js} +3 -3
  17. package/dist/chunks/git-panel-tjbr191d.js +51 -0
  18. package/dist/chunks/git-panel-tjbr191d.js.map +9 -0
  19. package/dist/chunks/{index-baeg2x3y.js → index-7pxchcce.js} +4 -3
  20. package/dist/chunks/{index-baeg2x3y.js.map → index-7pxchcce.js.map} +3 -3
  21. package/dist/chunks/{jx-validate-qx8degj7.js → jx-validate-v6qgknrs.js} +3 -3
  22. package/dist/chunks/layers-panel-87pb25km.js +58 -0
  23. package/dist/chunks/layers-panel-87pb25km.js.map +9 -0
  24. package/dist/chunks/{monaco-setup-zjdp9zdw.js → monaco-setup-e0yh25j4.js} +4 -75
  25. package/dist/chunks/{monaco-setup-zjdp9zdw.js.map → monaco-setup-e0yh25j4.js.map} +3 -4
  26. package/dist/chunks/publish-panel-m0fcgdrt.js +21 -0
  27. package/dist/chunks/publish-panel-m0fcgdrt.js.map +9 -0
  28. package/dist/chunks/quick-search-rhs6cbsb.js +53 -0
  29. package/dist/chunks/quick-search-rhs6cbsb.js.map +9 -0
  30. package/dist/chunks/right-panel-zpdxd98t.js +37 -0
  31. package/dist/chunks/right-panel-zpdxd98t.js.map +9 -0
  32. package/dist/chunks/section-registry-zmckaxf4.js +30 -0
  33. package/dist/chunks/section-registry-zmckaxf4.js.map +9 -0
  34. package/dist/chunks/sp-overlay.dev-9ran0sfq.js +18 -0
  35. package/dist/chunks/sp-overlay.dev-9ran0sfq.js.map +9 -0
  36. package/dist/chunks/sp-popover.dev-rebmdncr.js +9 -0
  37. package/dist/chunks/sp-popover.dev-rebmdncr.js.map +9 -0
  38. package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js +15 -0
  39. package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js.map +9 -0
  40. package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js +15 -0
  41. package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js.map +9 -0
  42. package/dist/chunks/{sp-tray.dev-pb2fsd65.js → sp-tray.dev-ey59vfh7.js} +10 -8
  43. package/dist/chunks/{sp-tray.dev-pb2fsd65.js.map → sp-tray.dev-ey59vfh7.js.map} +2 -2
  44. package/dist/chunks/{studio-9qr6fq7p.js → studio-0rqqhrdy.js} +10 -378
  45. package/dist/chunks/{studio-9qr6fq7p.js.map → studio-0rqqhrdy.js.map} +4 -14
  46. package/dist/chunks/{studio-5x6tqqec.js → studio-2sj1jj3v.js} +10 -8
  47. package/dist/chunks/{studio-5x6tqqec.js.map → studio-2sj1jj3v.js.map} +2 -2
  48. package/dist/chunks/{studio-h3fw0wn8.js → studio-3fk1ac9z.js} +6 -4
  49. package/dist/chunks/{studio-h3fw0wn8.js.map → studio-3fk1ac9z.js.map} +2 -2
  50. package/dist/chunks/studio-41exgzhq.js +6690 -0
  51. package/dist/chunks/studio-41exgzhq.js.map +38 -0
  52. package/dist/chunks/{studio-7v2bpweq.js → studio-4mqb9a0j.js} +6 -4
  53. package/dist/chunks/{studio-7v2bpweq.js.map → studio-4mqb9a0j.js.map} +2 -2
  54. package/dist/chunks/studio-50k77cca.js +1787 -0
  55. package/dist/chunks/studio-50k77cca.js.map +18 -0
  56. package/dist/chunks/{studio-56v3zwk6.js → studio-6a0h7sne.js} +10 -8
  57. package/dist/chunks/{studio-56v3zwk6.js.map → studio-6a0h7sne.js.map} +2 -2
  58. package/dist/chunks/studio-6f0am8f2.js +53 -0
  59. package/dist/chunks/studio-6f0am8f2.js.map +10 -0
  60. package/dist/chunks/studio-6nmjc5qk.js +7002 -0
  61. package/dist/chunks/studio-6nmjc5qk.js.map +32 -0
  62. package/dist/chunks/studio-7afd21nw.js +67 -0
  63. package/dist/chunks/studio-7afd21nw.js.map +10 -0
  64. package/dist/chunks/{studio-xze4zrs1.js → studio-7bmdvzne.js} +2 -2
  65. package/dist/chunks/studio-7bmdvzne.js.map +10 -0
  66. package/dist/chunks/studio-8jpzqk5s.js +128 -0
  67. package/dist/chunks/studio-8jpzqk5s.js.map +10 -0
  68. package/dist/chunks/studio-94m77tgk.js +1482 -0
  69. package/dist/chunks/studio-94m77tgk.js.map +13 -0
  70. package/dist/chunks/studio-9je6w5sq.js +1000 -0
  71. package/dist/chunks/studio-9je6w5sq.js.map +16 -0
  72. package/dist/chunks/{studio-w7c6kvk7.js → studio-a7pzveq1.js} +2 -2
  73. package/dist/chunks/{studio-97qcgvdn.js → studio-adn0z1k3.js} +14 -8
  74. package/dist/chunks/{studio-97qcgvdn.js.map → studio-adn0z1k3.js.map} +3 -3
  75. package/dist/chunks/{studio-kr88ryr7.js → studio-bsxxx3x2.js} +17 -15
  76. package/dist/chunks/{studio-kr88ryr7.js.map → studio-bsxxx3x2.js.map} +7 -6
  77. package/dist/chunks/studio-bw5dz6km.js +608 -0
  78. package/dist/chunks/studio-bw5dz6km.js.map +21 -0
  79. package/dist/chunks/studio-c6s5getc.js +4232 -0
  80. package/dist/chunks/studio-c6s5getc.js.map +39 -0
  81. package/dist/chunks/studio-cjm7fdjf.js +451 -0
  82. package/dist/chunks/studio-cjm7fdjf.js.map +14 -0
  83. package/dist/chunks/{studio-cx91mnh8.js → studio-ckwz4d3x.js} +53 -53
  84. package/dist/chunks/{studio-cx91mnh8.js.map → studio-ckwz4d3x.js.map} +5 -5
  85. package/dist/chunks/studio-dg7zyt5x.js +28 -0
  86. package/dist/chunks/studio-dg7zyt5x.js.map +10 -0
  87. package/dist/chunks/studio-dzcyvvvz.js +166 -0
  88. package/dist/chunks/studio-dzcyvvvz.js.map +10 -0
  89. package/dist/chunks/{studio-7kqe41sa.js → studio-evkr5d3b.js} +15 -7
  90. package/dist/chunks/{studio-7kqe41sa.js.map → studio-evkr5d3b.js.map} +5 -4
  91. package/dist/chunks/studio-f12h6177.js +411 -0
  92. package/dist/chunks/studio-f12h6177.js.map +13 -0
  93. package/dist/chunks/studio-hbp1s8m9.js +1817 -0
  94. package/dist/chunks/studio-hbp1s8m9.js.map +14 -0
  95. package/dist/chunks/studio-k2sxjph5.js +15295 -0
  96. package/dist/chunks/studio-k2sxjph5.js.map +235 -0
  97. package/dist/chunks/studio-myje51t3.js +385 -0
  98. package/dist/chunks/studio-myje51t3.js.map +12 -0
  99. package/dist/chunks/studio-na6rwzhw.js +353 -0
  100. package/dist/chunks/studio-na6rwzhw.js.map +11 -0
  101. package/dist/chunks/{studio-4k0m4fmp.js → studio-p471gg5n.js} +126 -3
  102. package/dist/chunks/studio-p471gg5n.js.map +14 -0
  103. package/dist/chunks/{studio-9bjwf0d4.js → studio-rgwcpast.js} +5 -46
  104. package/dist/chunks/{studio-9bjwf0d4.js.map → studio-rgwcpast.js.map} +4 -5
  105. package/dist/chunks/{studio-hhj92gcr.js → studio-s519zc99.js} +3 -3
  106. package/dist/chunks/studio-sas7mt3k.js +75 -0
  107. package/dist/chunks/studio-sas7mt3k.js.map +10 -0
  108. package/dist/chunks/studio-t5wqwzdh.js +74 -0
  109. package/dist/chunks/studio-t5wqwzdh.js.map +10 -0
  110. package/dist/chunks/{studio-9qpspwfn.js → studio-temv5bw4.js} +5 -5
  111. package/dist/chunks/{studio-9qpspwfn.js.map → studio-temv5bw4.js.map} +1 -1
  112. package/dist/chunks/{studio-qkvt37c0.js → studio-tr20m8g8.js} +669 -18
  113. package/dist/chunks/studio-tr20m8g8.js.map +9 -0
  114. package/dist/chunks/{studio-ygzav7z5.js → studio-v96qfnww.js} +5514 -4291
  115. package/dist/chunks/studio-v96qfnww.js.map +54 -0
  116. package/dist/chunks/studio-vcetc91k.js +659 -0
  117. package/dist/chunks/studio-vcetc91k.js.map +10 -0
  118. package/dist/chunks/{studio-n9zmpxjg.js → studio-vmymjefp.js} +2972 -4937
  119. package/dist/chunks/studio-vmymjefp.js.map +98 -0
  120. package/dist/chunks/{studio-bghqfmea.js → studio-wwseqyw0.js} +2 -2
  121. package/dist/chunks/studio-x9hmy5kr.js +390 -0
  122. package/dist/chunks/studio-x9hmy5kr.js.map +10 -0
  123. package/dist/chunks/studio-xa0ce0n7.js +335 -0
  124. package/dist/chunks/studio-xa0ce0n7.js.map +10 -0
  125. package/dist/chunks/studio-xm3dbxvn.js +378 -0
  126. package/dist/chunks/studio-xm3dbxvn.js.map +19 -0
  127. package/dist/chunks/{studio-nqw433kv.js → studio-xmvbhg31.js} +2 -2
  128. package/dist/chunks/studio-zv37yrfa.js +1054 -0
  129. package/dist/chunks/studio-zv37yrfa.js.map +13 -0
  130. package/dist/chunks/{ws-client-q7hkz3j9.js → ws-client-654ts66j.js} +6 -4
  131. package/dist/chunks/ws-client-654ts66j.js.map +11 -0
  132. package/dist/iframe-entry.js +668 -230
  133. package/dist/studio.js +23711 -35185
  134. package/index.html +35 -4685
  135. package/package.json +17 -15
  136. package/src/about/about-modal.ts +42 -11
  137. package/src/browse/library-commands.ts +240 -0
  138. package/src/browse/library-layouts.ts +369 -0
  139. package/src/browse/library-model.ts +396 -0
  140. package/src/browse/library-pane.ts +1049 -0
  141. package/src/browse/library-preview.ts +252 -0
  142. package/src/browse/library-source.ts +150 -0
  143. package/src/canvas/canvas-helpers.ts +33 -9
  144. package/src/canvas/canvas-live-render.ts +45 -29
  145. package/src/canvas/canvas-patcher.ts +151 -31
  146. package/src/canvas/canvas-perf.ts +46 -7
  147. package/src/canvas/canvas-render.ts +1092 -220
  148. package/src/canvas/canvas-surface.ts +240 -0
  149. package/src/canvas/canvas-utils.ts +1166 -124
  150. package/src/canvas/iframe-drop.ts +2 -1
  151. package/src/canvas/iframe-entry.ts +241 -4
  152. package/src/canvas/iframe-host.ts +1226 -143
  153. package/src/canvas/iframe-inline-edit.ts +31 -0
  154. package/src/canvas/iframe-interaction.ts +76 -16
  155. package/src/canvas/iframe-keys.ts +107 -45
  156. package/src/canvas/iframe-overlay.ts +38 -1
  157. package/src/canvas/iframe-protocol.ts +137 -2
  158. package/src/canvas/iframe-render.ts +70 -2
  159. package/src/canvas/iframe-slash.ts +6 -0
  160. package/src/canvas/path-mapping.ts +56 -6
  161. package/src/canvas/surface-registry.ts +292 -0
  162. package/src/collab/collab-commands.ts +244 -0
  163. package/src/collab/collab-session.ts +198 -32
  164. package/src/collab/collab-state.ts +28 -2
  165. package/src/collab/presence-chips.ts +100 -9
  166. package/src/commands/active-registry.ts +42 -0
  167. package/src/commands/app-commands.ts +176 -0
  168. package/src/commands/budget.ts +158 -0
  169. package/src/commands/command-args.ts +253 -0
  170. package/src/commands/context.ts +387 -0
  171. package/src/commands/defaults.ts +580 -0
  172. package/src/commands/keymap.ts +571 -0
  173. package/src/commands/levels.ts +345 -0
  174. package/src/commands/live-context.ts +193 -0
  175. package/src/commands/reference.ts +227 -0
  176. package/src/commands/registry.ts +293 -0
  177. package/src/component-props.ts +3 -2
  178. package/src/content/draft-state.ts +106 -0
  179. package/src/content/entry-commands.ts +282 -0
  180. package/src/content/entry-editor.ts +327 -0
  181. package/src/content/entry-fields.ts +116 -0
  182. package/src/content/entry-model.ts +175 -0
  183. package/src/editor/canvas-context-menu.ts +17 -11
  184. package/src/editor/canvas-slash-bridge.ts +11 -4
  185. package/src/editor/context-menu.ts +804 -204
  186. package/src/editor/convert-to-component.ts +31 -10
  187. package/src/editor/convert-to-repeater.ts +3 -2
  188. package/src/editor/inline-edit-apply.ts +5 -5
  189. package/src/editor/inline-edit.ts +86 -50
  190. package/src/editor/insert-zone-action.ts +1 -1
  191. package/src/editor/shortcuts.ts +1043 -329
  192. package/src/editor/slash-menu.ts +1 -0
  193. package/src/files/elements.ts +166 -0
  194. package/src/files/file-ops.ts +178 -31
  195. package/src/files/files.ts +898 -268
  196. package/src/files/fs-events.ts +21 -0
  197. package/src/files/media-meta.ts +203 -0
  198. package/src/files/media-paths.ts +141 -0
  199. package/src/files/media-upload.ts +7 -3
  200. package/src/files/media-usage.ts +189 -0
  201. package/src/github/github-auth.ts +235 -33
  202. package/src/github/github-publish.ts +80 -21
  203. package/src/grid/grid-controller.ts +152 -12
  204. package/src/grid/grid-layout.ts +225 -20
  205. package/src/grid/grid-open.ts +120 -0
  206. package/src/grid/grid-panel.ts +554 -39
  207. package/src/grid/grid-source.ts +27 -1
  208. package/src/grid/redirects-grid.ts +599 -0
  209. package/src/grid/redirects.ts +398 -0
  210. package/src/grid/sources/content-source.ts +108 -2
  211. package/src/i18n/i18n-commands.ts +322 -0
  212. package/src/new-project/add-repo-modal.ts +8 -10
  213. package/src/new-project/import-tab.ts +34 -9
  214. package/src/new-project/location-fields.ts +9 -1
  215. package/src/new-project/new-project-modal.ts +270 -262
  216. package/src/packages/jxsuite-update.ts +97 -48
  217. package/src/packages/pull-package-sync.ts +18 -9
  218. package/src/page-params.ts +2 -1
  219. package/src/panels/activity-bar.ts +152 -91
  220. package/src/panels/activity-panel.ts +481 -0
  221. package/src/panels/ai-chat/chat-markdown.ts +8 -3
  222. package/src/panels/ai-chat/chat-view.ts +245 -18
  223. package/src/panels/ai-chat/composer.ts +31 -5
  224. package/src/panels/ai-chat/sessions-view.ts +17 -10
  225. package/src/panels/ai-panel.ts +279 -120
  226. package/src/panels/block-action-bar.ts +1115 -224
  227. package/src/panels/bottom-dock.ts +337 -0
  228. package/src/panels/canvas-dnd-bridge.ts +37 -8
  229. package/src/panels/chat-panel.ts +29 -12
  230. package/src/panels/data-explorer.ts +254 -112
  231. package/src/panels/data-grid.ts +10 -4
  232. package/src/panels/dnd.ts +28 -51
  233. package/src/panels/editors.ts +434 -107
  234. package/src/panels/elements-panel.ts +66 -2
  235. package/src/panels/empty-state.ts +112 -0
  236. package/src/panels/events-panel.ts +596 -82
  237. package/src/panels/formula-workspace.ts +408 -218
  238. package/src/panels/frontmatter-fields.ts +51 -10
  239. package/src/panels/frontmatter-panel.ts +357 -79
  240. package/src/panels/git-panel.ts +375 -164
  241. package/src/panels/head-panel.ts +791 -85
  242. package/src/panels/i18n-panel.ts +592 -0
  243. package/src/panels/imports-panel.ts +95 -85
  244. package/src/panels/jump-bar.ts +584 -0
  245. package/src/panels/layers-panel.ts +1106 -328
  246. package/src/panels/left-panel.ts +109 -204
  247. package/src/panels/navigator-panels.ts +131 -0
  248. package/src/panels/overlays.ts +7 -2
  249. package/src/panels/pane-context.ts +1477 -0
  250. package/src/panels/pane-grid.ts +406 -0
  251. package/src/panels/panel-registry.ts +340 -0
  252. package/src/panels/panel-scheduler.ts +75 -0
  253. package/src/panels/problems-panel.ts +234 -0
  254. package/src/panels/properties-panel.ts +946 -1139
  255. package/src/panels/provenance.ts +258 -0
  256. package/src/panels/quick-search.ts +791 -122
  257. package/src/panels/right-panel.ts +228 -102
  258. package/src/panels/seo-modal.ts +395 -0
  259. package/src/panels/settings-pane.ts +203 -0
  260. package/src/panels/signals-panel.ts +354 -137
  261. package/src/panels/statement-editor.ts +41 -25
  262. package/src/panels/statusbar.ts +342 -106
  263. package/src/panels/style-panel.ts +974 -463
  264. package/src/panels/style-utils.ts +3 -3
  265. package/src/panels/stylebook-doc.ts +4 -2
  266. package/src/panels/stylebook-layers-panel.ts +3 -2
  267. package/src/panels/stylebook-panel.ts +51 -26
  268. package/src/panels/tab-strip.ts +1058 -78
  269. package/src/panels/target-line.ts +274 -0
  270. package/src/panels/toolbar.ts +631 -484
  271. package/src/panels/welcome-screen.ts +301 -198
  272. package/src/platform-errors.ts +26 -3
  273. package/src/platform.ts +96 -2
  274. package/src/platforms/cloud.ts +71 -8
  275. package/src/platforms/devserver.ts +92 -29
  276. package/src/publish/deploy-checklist.ts +383 -0
  277. package/src/publish/pages-service.ts +10 -1
  278. package/src/publish/publish-commands.ts +218 -0
  279. package/src/publish/publish-panel.ts +110 -16
  280. package/src/recent-projects.ts +3 -2
  281. package/src/services/a11y-report.ts +505 -0
  282. package/src/services/ai-models.ts +75 -2
  283. package/src/services/ai-project-tools.ts +29 -10
  284. package/src/services/ai-system-prompt.ts +53 -14
  285. package/src/services/ai-tools.ts +39 -3
  286. package/src/services/ai-writes.ts +154 -0
  287. package/src/services/announce.ts +97 -0
  288. package/src/services/automation.ts +424 -175
  289. package/src/services/cem-export.ts +9 -4
  290. package/src/services/clock.ts +61 -0
  291. package/src/services/document-assistant.ts +36 -8
  292. package/src/services/idle.ts +179 -0
  293. package/src/services/import-client.ts +26 -0
  294. package/src/services/monaco-buffer.ts +627 -0
  295. package/src/services/monaco-lazy.ts +36 -0
  296. package/src/services/notify.ts +271 -0
  297. package/src/services/profile.ts +155 -0
  298. package/src/services/references.ts +0 -0
  299. package/src/services/token-lint.ts +3 -2
  300. package/src/services/tool-executor.ts +53 -7
  301. package/src/services/trusted-types.ts +123 -0
  302. package/src/settings/contexts-section.ts +427 -0
  303. package/src/settings/contributed-section.ts +149 -11
  304. package/src/settings/css-vars-editor.ts +306 -349
  305. package/src/settings/defs-editor.ts +93 -34
  306. package/src/settings/dependencies-editor.ts +7 -7
  307. package/src/settings/extension-sections.ts +37 -5
  308. package/src/settings/general-settings.ts +204 -121
  309. package/src/settings/locales-section.ts +347 -0
  310. package/src/settings/preferences-accounts.ts +140 -0
  311. package/src/settings/preferences-dialog.ts +620 -0
  312. package/src/settings/preferences-keymap.ts +270 -0
  313. package/src/settings/project-sections.ts +260 -0
  314. package/src/settings/section-registry.ts +169 -0
  315. package/src/settings/settings-document.ts +385 -0
  316. package/src/shell.ts +1549 -0
  317. package/src/site-context.ts +45 -20
  318. package/src/state.ts +14 -275
  319. package/src/store.ts +88 -43
  320. package/src/studio.ts +790 -346
  321. package/src/style/live-preview.ts +36 -0
  322. package/src/style/project-styles.ts +349 -0
  323. package/src/style/token-ref.ts +123 -0
  324. package/src/tabs/patch-ops.ts +16 -4
  325. package/src/tabs/project-config.ts +416 -0
  326. package/src/tabs/selection.ts +323 -0
  327. package/src/tabs/tab.ts +182 -47
  328. package/src/tabs/transact.ts +209 -28
  329. package/src/types.ts +68 -13
  330. package/src/ui/ai-credentials-form.ts +39 -35
  331. package/src/ui/ai-managed-connect.ts +113 -0
  332. package/src/ui/dynamic-slot.ts +224 -81
  333. package/src/ui/expression-editor.ts +71 -63
  334. package/src/ui/field-input.ts +4 -6
  335. package/src/ui/field-row.ts +215 -38
  336. package/src/ui/form-controls.ts +194 -7
  337. package/src/ui/layers.ts +492 -69
  338. package/src/ui/media-picker.ts +115 -25
  339. package/src/ui/panel-resize.ts +109 -91
  340. package/src/ui/progress-modal.ts +131 -50
  341. package/src/ui/regions.ts +462 -0
  342. package/src/ui/schema-form.ts +229 -45
  343. package/src/ui/spectrum.ts +24 -8
  344. package/src/ui/timing.ts +49 -0
  345. package/src/ui/value-selector.ts +20 -0
  346. package/src/ui/value-source.ts +348 -0
  347. package/src/ui/virtual-window.ts +400 -0
  348. package/src/utils/edit-display.ts +3 -2
  349. package/src/utils/inherited-style.ts +67 -37
  350. package/src/view.ts +64 -78
  351. package/src/workspace/pane-derive.ts +1258 -0
  352. package/src/workspace/session.ts +317 -0
  353. package/src/workspace/workspace.ts +1345 -23
  354. package/styles/canvas.css +653 -0
  355. package/styles/forced-colors.css +106 -0
  356. package/styles/inspector.css +1454 -0
  357. package/styles/overlays.css +2704 -0
  358. package/styles/panels.css +1701 -0
  359. package/styles/shell.css +1423 -0
  360. package/styles/tokens.css +151 -0
  361. package/dist/chunks/Overlay.dev-cszx7yn5.js +0 -22
  362. package/dist/chunks/extension-sections-qct0gt8f.js +0 -531
  363. package/dist/chunks/extension-sections-qct0gt8f.js.map +0 -12
  364. package/dist/chunks/files-02zn5y24.js +0 -50
  365. package/dist/chunks/files-02zn5y24.js.map +0 -9
  366. package/dist/chunks/git-panel-mbb0y0hz.js +0 -28
  367. package/dist/chunks/git-panel-mbb0y0hz.js.map +0 -9
  368. package/dist/chunks/layers-panel-9qekmqk1.js +0 -26
  369. package/dist/chunks/layers-panel-9qekmqk1.js.map +0 -9
  370. package/dist/chunks/settings-modal-gj0hrah4.js +0 -29
  371. package/dist/chunks/settings-modal-gj0hrah4.js.map +0 -9
  372. package/dist/chunks/sp-overlay.dev-earn5as8.js +0 -17
  373. package/dist/chunks/sp-overlay.dev-earn5as8.js.map +0 -9
  374. package/dist/chunks/sp-popover.dev-frxtfejn.js +0 -8
  375. package/dist/chunks/sp-popover.dev-frxtfejn.js.map +0 -9
  376. package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js +0 -14
  377. package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js.map +0 -9
  378. package/dist/chunks/sp-tooltip.dev-a9fywesm.js +0 -21
  379. package/dist/chunks/sp-tooltip.dev-a9fywesm.js.map +0 -10
  380. package/dist/chunks/studio-4k0m4fmp.js.map +0 -13
  381. package/dist/chunks/studio-568nx4t5.js +0 -469
  382. package/dist/chunks/studio-568nx4t5.js.map +0 -14
  383. package/dist/chunks/studio-9smfzqhc.js +0 -19
  384. package/dist/chunks/studio-9smfzqhc.js.map +0 -10
  385. package/dist/chunks/studio-asvf0j9e.js +0 -429
  386. package/dist/chunks/studio-asvf0j9e.js.map +0 -13
  387. package/dist/chunks/studio-d77qm3pk.js +0 -3427
  388. package/dist/chunks/studio-d77qm3pk.js.map +0 -26
  389. package/dist/chunks/studio-j6gqyjf4.js +0 -1854
  390. package/dist/chunks/studio-j6gqyjf4.js.map +0 -18
  391. package/dist/chunks/studio-n9zmpxjg.js.map +0 -115
  392. package/dist/chunks/studio-qkvt37c0.js.map +0 -9
  393. package/dist/chunks/studio-rq0vxb19.js +0 -3744
  394. package/dist/chunks/studio-rq0vxb19.js.map +0 -22
  395. package/dist/chunks/studio-wd6ewdvd.js +0 -853
  396. package/dist/chunks/studio-wd6ewdvd.js.map +0 -12
  397. package/dist/chunks/studio-xq0t7n5t.js +0 -140
  398. package/dist/chunks/studio-xq0t7n5t.js.map +0 -10
  399. package/dist/chunks/studio-xze4zrs1.js.map +0 -10
  400. package/dist/chunks/studio-ygzav7z5.js.map +0 -46
  401. package/dist/chunks/studio-zmy7241e.js +0 -399
  402. package/dist/chunks/studio-zmy7241e.js.map +0 -12
  403. package/dist/chunks/ws-client-q7hkz3j9.js.map +0 -11
  404. package/src/browse/browse-modal.ts +0 -69
  405. package/src/browse/browse.ts +0 -904
  406. package/src/canvas/canvas-diff.ts +0 -216
  407. package/src/canvas/nested-site-style.ts +0 -58
  408. package/src/new-project/design-fields.ts +0 -264
  409. package/src/new-project/templates.ts +0 -61
  410. package/src/panels/tab-bar.ts +0 -548
  411. package/src/settings/settings-modal.ts +0 -203
  412. /package/dist/chunks/{adapter-z8fkmbmv.js.map → adapter-qfnesn5v.js.map} +0 -0
  413. /package/dist/chunks/{cf-settings-mmyv436d.js.map → cf-settings-73sh5z4p.js.map} +0 -0
  414. /package/dist/chunks/{format-host-2c188n41.js.map → format-host-mkwsmt8d.js.map} +0 -0
  415. /package/dist/chunks/{jx-validate-qx8degj7.js.map → jx-validate-v6qgknrs.js.map} +0 -0
  416. /package/dist/chunks/{studio-w7c6kvk7.js.map → studio-a7pzveq1.js.map} +0 -0
  417. /package/dist/chunks/{studio-hhj92gcr.js.map → studio-s519zc99.js.map} +0 -0
  418. /package/dist/chunks/{studio-bghqfmea.js.map → studio-wwseqyw0.js.map} +0 -0
  419. /package/dist/chunks/{studio-nqw433kv.js.map → studio-xmvbhg31.js.map} +0 -0
@@ -1,91 +1,74 @@
1
1
  /// <reference lib="dom" />
2
2
  /**
3
- * Left panel — orchestrator that delegates to per-tab render functions.
3
+ * Left panel — the Navigator dock's host.
4
4
  *
5
- * Each sub-panel exports a render function that takes its dependencies as arguments and returns a
6
- * TemplateResult — the same pattern as imports-panel, signals-panel, etc. Only this orchestrator
7
- * uses mount/render/unmount because it owns the DOM root and error boundary.
5
+ * It no longer knows what a panel is. The eight-branch `if (tab === …)` chain, the eight-key
6
+ * no-document copy table and the two post-render special cases are gone: this file resolves ONE
7
+ * record from the panel registry, draws its header, calls its `render`, and calls its
8
+ * `afterRender`. Everything a panel is — its name, its level, its empty state, its drag
9
+ * registrations — is declared beside the state it writes (plan §2 principle 1).
10
+ *
11
+ * What stays here is what genuinely belongs to the host: the DOM root, the focus-aware scheduler,
12
+ * the error boundary with its Lit-marker recovery, and the region stamp.
8
13
  */
9
14
 
10
- import { html, render as litRender, nothing } from "lit-html";
15
+ import { html, render as litRender } from "lit-html";
11
16
  import type { TemplateResult } from "lit-html";
12
- import { leftPanel, updateSession } from "../store";
17
+ import { leftPanel } from "../store";
13
18
  import { effect, effectScope } from "../reactivity";
14
19
  import { createPanelScheduler } from "./panel-scheduler";
15
20
  import type { PanelScheduler } from "./panel-scheduler";
16
21
  import { activeTab } from "../workspace/workspace";
17
- import { view } from "../view";
18
- import { mutateUpdateFrontmatter, transact } from "../tabs/transact";
19
- import type { GitDiffState, JsonValue } from "../types";
20
- import type { JxHeadEntry, JxMutableNode } from "@jxsuite/schema/types";
21
-
22
- import { renderLayersTemplate } from "./layers-panel";
23
- import { renderStylebookLayersTemplate } from "./stylebook-layers-panel";
24
- import { renderElementsTemplate } from "./elements-panel";
25
- import { selectStylebookTag, stylebookMeta } from "./stylebook-panel";
26
- import type { renderImportsTemplate } from "./imports-panel";
27
- import type { renderSignalsTemplate } from "./signals-panel";
28
- import type { renderDataExplorerTemplate } from "./data-explorer";
29
- import type { renderHeadTemplate } from "./head-panel";
30
- import type { renderGitPanel } from "./git-panel";
22
+ import { shell } from "../shell";
23
+
24
+ import { navigatorPanelRegion } from "../ui/regions";
25
+ import { openPageAction, renderEmptyState } from "./empty-state";
26
+ import { getPanel, isPanelVisible, panelContext } from "./panel-registry";
27
+ import { registerNavigatorPanels } from "./navigator-panels";
28
+ import type {
29
+ NavigatorDocument,
30
+ NavigatorPanelContext,
31
+ NavigatorPanelDeps,
32
+ PanelRecord,
33
+ } from "./panel-registry";
31
34
  import type { EffectScope } from "@vue/reactivity";
32
35
 
33
- interface LeftPanelCtx {
34
- getCanvasMode: () => string;
35
- setCanvasMode: (mode: string) => void;
36
- // Renderers injected from studio.ts (dependency inversion avoids circular imports);
37
- // Typed against their implementations so call sites stay checked.
38
- renderImportsTemplate: typeof renderImportsTemplate;
39
- renderFilesTemplate: () => TemplateResult;
40
- renderSignalsTemplate: typeof renderSignalsTemplate;
41
- renderDataExplorerTemplate: typeof renderDataExplorerTemplate;
42
- renderHeadTemplate: typeof renderHeadTemplate;
43
- renderGitPanel: typeof renderGitPanel;
44
- renderCanvas: () => void;
45
- /** Canvas re-render that also lets automatic `Request` entries fetch (Data panel Refresh). */
46
- refreshData: () => void;
47
- defCategory: (def: unknown) => string;
48
- defBadgeLabel: (def: unknown) => string;
49
- navigateToComponent: (path: string) => void;
50
- webdata: Record<string, unknown>;
51
- defaultDef: (tag: string) => Record<string, unknown>;
52
- registerLayersDnD: () => void;
53
- registerElementsDnD: () => void;
54
- registerComponentsDnD: () => void;
55
- setupTreeKeyboard: (tree: HTMLElement) => void;
56
- registerFileTreeDnD: (ctx: { renderLeftPanel: () => void }) => void;
57
- setGitDiffState: (state: GitDiffState | null) => void;
58
- cloneRepository?: () => void;
59
- }
60
-
61
- let _ctx: LeftPanelCtx | null = null;
36
+ let _deps: NavigatorPanelDeps | null = null;
62
37
 
63
38
  let _scope: EffectScope | null = null;
64
39
 
65
40
  let _scheduler: PanelScheduler | null = null;
66
41
 
67
42
  /**
68
- * Mount the left panel orchestrator.
43
+ * Mount the Navigator dock.
69
44
  *
70
- * @param {LeftPanelCtx} ctx
45
+ * @param {NavigatorPanelDeps} deps
71
46
  */
72
- export function mount(ctx: LeftPanelCtx) {
73
- _ctx = ctx;
47
+ export function mount(deps: NavigatorPanelDeps) {
48
+ _deps = deps;
49
+ registerNavigatorPanels();
74
50
  _scheduler = createPanelScheduler({ render: _doRender, root: leftPanel });
75
51
  _scheduler.bindFocus();
76
52
  _scope = effectScope();
77
53
  _scope.run(() => {
78
54
  effect(() => {
55
+ // Shell state is tracked with no tab open — which panel is showing, and the project-level
56
+ // State the project-level panels draw from. A document-less rail tab still repaints.
57
+ void shell.leftTab;
58
+ void shell.settingsTab;
59
+ void shell.git.status;
60
+ void shell.git.loading;
61
+ void shell.git.error;
62
+ void shell.git.subTab;
63
+ void shell.git.logEntries;
79
64
  const tab = activeTab.value;
80
65
  if (tab) {
81
- // Track properties the left panel reads
66
+ // Track properties the Navigator's panels read
82
67
  void tab.doc.document;
83
68
  void tab.doc.mode;
84
- void tab.session.selection;
85
- void tab.session.ui.settingsTab;
86
- void tab.session.ui.gitStatus;
87
- void tab.session.ui.gitLoading;
88
- void tab.session.ui.gitError;
69
+ // The whole SET, joined — a bare property read would not re-trigger when the selection
70
+ // Changes WITHIN the array, and §6.5's helpers always replace it but nothing enforces that.
71
+ void tab.session.selection.map((path) => path.join("/")).join("|");
89
72
  }
90
73
  render();
91
74
  });
@@ -95,7 +78,7 @@ export function mount(ctx: LeftPanelCtx) {
95
78
  export function unmount() {
96
79
  _scope?.stop();
97
80
  _scope = null;
98
- _ctx = null;
81
+ _deps = null;
99
82
  _scheduler?.unbind();
100
83
  _scheduler = null;
101
84
  }
@@ -110,7 +93,7 @@ export function render() {
110
93
 
111
94
  /** Actual DOM paint, invoked by the scheduler. Includes a Lit-marker-corruption recovery retry. */
112
95
  function _doRender() {
113
- if (!_ctx) {
96
+ if (!_deps) {
114
97
  return;
115
98
  }
116
99
  try {
@@ -126,162 +109,84 @@ function _doRender() {
126
109
  console.error("left-panel retry failed:", retryError);
127
110
  }
128
111
  }
129
-
130
- if (view.leftTab === "layers") {
131
- const sel = leftPanel.querySelector(".layer-row.selected");
132
- if (sel) {
133
- sel.scrollIntoView({ behavior: "smooth", block: "nearest" });
134
- }
135
- }
136
112
  }
137
113
 
138
- /** Overlay content-mode frontmatter title/$head onto the document for the head panel. */
139
- function buildHeadDoc(doc: JxMutableNode, fm: Record<string, unknown>): JxMutableNode {
140
- const title = fm.title as string | undefined;
141
- const $head = fm.$head as JxHeadEntry[] | undefined;
142
- return {
143
- ...doc,
144
- ...(title !== undefined ? { title } : {}),
145
- ...($head !== undefined ? { $head } : {}),
146
- };
114
+ /**
115
+ * The panel header — the fix for "which panel am I in?".
116
+ *
117
+ * Six of eight panels had no header at all, and the Imports panel silently changed meaning based on
118
+ * whether the focused document was `project.json`. Every panel now renders under its title AND its
119
+ * level ("FILES · project"), so the containment model is legible from the screen rather than only
120
+ * from the matrix: a badge on a `project` panel does not go away when the last tab closes, and a
121
+ * `document` panel says out loud that it is about the file in front of you.
122
+ */
123
+ function panelHeader(panel: PanelRecord): TemplateResult {
124
+ return html`
125
+ <header class="panel-header">
126
+ <span class="panel-header-title">${panel.title}</span>
127
+ <span class="panel-header-level">${panel.level}</span>
128
+ </header>
129
+ `;
147
130
  }
148
131
 
149
- function _render() {
150
- const ctx = _ctx as LeftPanelCtx;
151
- const tab = view.leftTab;
152
-
153
- // ── Project-level panels: render based on projectState, independent of active tab ──
154
-
155
- if (tab === "files") {
156
- litRender(html`<div class="panel-body">${ctx.renderFilesTemplate()}</div>`, leftPanel);
157
- const tree = leftPanel.querySelector(".file-tree") as HTMLElement | null;
158
- if (tree) {
159
- ctx.setupTreeKeyboard(tree);
160
- }
161
- ctx.registerFileTreeDnD({ renderLeftPanel: render });
162
- return;
163
- }
132
+ /**
133
+ * The Navigator's one panel host.
134
+ *
135
+ * Every panel renders through this, which is what makes `navigator/panel:<id>` **derived**: the
136
+ * region is stamped once, from the same id the rail routes by, so every panel is addressable
137
+ * without anyone authoring an id — and renaming a panel renames its region in the same edit,
138
+ * instead of leaving a stale selector that photographs the wrong box.
139
+ */
140
+ function panelBody(panel: PanelRecord, content: unknown): TemplateResult {
141
+ return html`<div class="panel-body" data-jx-region=${navigatorPanelRegion(panel.id)}>
142
+ ${panelHeader(panel)}
143
+ <div class="panel-content">${content}</div>
144
+ </div>`;
145
+ }
164
146
 
165
- if (tab === "git") {
166
- const aTab = activeTab.value;
167
- const ui: Parameters<LeftPanelCtx["renderGitPanel"]>[0]["ui"] = aTab ? aTab.session.ui : {};
168
- litRender(html`<div class="panel-body">${ctx.renderGitPanel({ ui }, ctx)}</div>`, leftPanel);
169
- return;
170
- }
147
+ /** The whole Navigator when `shell.leftTab` names nothing the registry declares. */
148
+ function unknownPanel(id: string): void {
149
+ litRender(
150
+ html`<div class="panel-body">
151
+ ${renderEmptyState({ message: `No Navigator panel is registered as "${id}".` })}
152
+ </div>`,
153
+ leftPanel,
154
+ );
155
+ }
171
156
 
172
- if (tab === "blocks") {
173
- const content = renderElementsTemplate({
174
- defaultDef: ctx.defaultDef,
175
- rerender: render,
176
- webdata: ctx.webdata,
177
- } as Parameters<typeof renderElementsTemplate>[0]);
178
- litRender(html`<div class="panel-body">${content}</div>`, leftPanel);
179
- ctx.registerElementsDnD();
180
- ctx.registerComponentsDnD();
157
+ function _render() {
158
+ const deps = _deps as NavigatorPanelDeps;
159
+ const panel = getPanel(shell.leftTab);
160
+ if (!panel || !isPanelVisible(panel, panelContext())) {
161
+ unknownPanel(shell.leftTab);
181
162
  return;
182
163
  }
183
164
 
184
- // ── Document-level panels: require an active tab ──
185
-
186
165
  const aTab = activeTab.value;
187
- if (!aTab) {
188
- litRender(html`<div class="panel-body"></div>`, leftPanel);
189
- return;
190
- }
166
+ const doc: NavigatorDocument | null = aTab
167
+ ? {
168
+ canvas: aTab.session.canvas as Record<string, unknown> | null,
169
+ content: aTab.doc.content,
170
+ document: aTab.doc.document,
171
+ documentPath: aTab.documentPath,
172
+ mode: aTab.doc.mode,
173
+ selection: aTab.session.selection,
174
+ ui: aTab.session.ui,
175
+ }
176
+ : null;
191
177
 
192
- const S = /**
193
- * @type {{
194
- * ui: unknown;
195
- * document: JxMutableNode;
196
- * mode: string;
197
- * selection: JxPath | null;
198
- * canvas: { scope?: object } | null;
199
- * content?: { frontmatter?: Record<string, unknown> };
200
- * documentPath?: string;
201
- * }}
202
- */ {
203
- canvas: aTab.session.canvas,
204
- content: aTab.doc.content,
205
- document: aTab.doc.document,
206
- documentPath: aTab.documentPath,
207
- mode: aTab.doc.mode,
208
- selection: aTab.session.selection,
209
- ui: aTab.session.ui,
210
- };
178
+ const ctx: NavigatorPanelContext = { deps, doc, rerender: render };
211
179
 
212
- /** @type {TemplateResult | typeof nothing} */
213
- let content;
214
- if (tab === "layers") {
215
- content =
216
- ctx.getCanvasMode() === "stylebook"
217
- ? renderStylebookLayersTemplate({
218
- selectStylebookTag,
219
- stylebookMeta,
220
- } as Parameters<typeof renderStylebookLayersTemplate>[0])
221
- : renderLayersTemplate({
222
- navigateToComponent: ctx.navigateToComponent,
223
- rerender: render,
224
- });
225
- } else if (tab === "imports") {
226
- content = ctx.renderImportsTemplate({
227
- applyMutation: (fn: (doc: JxMutableNode) => void) => {
228
- transact(activeTab.value, fn);
229
- },
230
- documentElements: S.document.$elements || [],
231
- documentPath: S.documentPath,
232
- renderLeftPanel: render,
233
- });
234
- } else if (tab === "state") {
235
- content = ctx.renderSignalsTemplate(S, {
236
- renderCanvas: ctx.renderCanvas,
237
- renderLeftPanel: render,
238
- updateSession,
239
- });
240
- } else if (tab === "data") {
241
- content = ctx.renderDataExplorerTemplate(S.document.state ?? {}, S.canvas?.scope ?? null, {
242
- defBadgeLabel: ctx.defBadgeLabel,
243
- defCategory: ctx.defCategory,
244
- refreshData: ctx.refreshData,
245
- renderCanvas: ctx.renderCanvas,
246
- renderLeftPanel: render,
247
- });
248
- } else if (tab === "head") {
249
- const isContent = S.mode === "content";
250
- const fm = S.content?.frontmatter ?? {};
251
- const headDoc = isContent ? buildHeadDoc(S.document, fm) : S.document;
252
- content = ctx.renderHeadTemplate({
253
- applyMutation: isContent
254
- ? (fn: (doc: JxMutableNode) => void) => {
255
- const tabNow = activeTab.value!;
256
- const fmNow = (tabNow.doc.content?.frontmatter ?? {}) as Record<string, unknown>;
257
- const fmHead = fmNow.$head as JxHeadEntry[] | undefined;
258
- const tmp: JxMutableNode = {
259
- ...(typeof fmNow.title === "string" ? { title: fmNow.title } : {}),
260
- ...(fmHead ? { $head: [...fmHead] } : {}),
261
- };
262
- fn(tmp);
263
- if (tmp.title !== fmNow.title) {
264
- mutateUpdateFrontmatter(tabNow, "title", tmp.title as JsonValue);
265
- }
266
- const newHead = tmp.$head && tmp.$head.length > 0 ? tmp.$head : undefined;
267
- // JxHeadEntry[] is JSON document content by construction.
268
- mutateUpdateFrontmatter(tabNow, "$head", newHead as JsonValue);
269
- render();
270
- }
271
- : (fn: (doc: JxMutableNode) => void) => {
272
- transact(activeTab.value, fn);
273
- },
274
- document: headDoc,
275
- renderLeftPanel: render,
276
- });
277
- } else {
278
- content = nothing;
279
- }
180
+ // A panel that declares what it needs renders the sentence instead of an empty box.
181
+ const content =
182
+ doc === null && panel.requiresDocument
183
+ ? renderEmptyState({ actions: [openPageAction()], message: panel.requiresDocument })
184
+ : panel.render(ctx);
280
185
 
281
- litRender(html`<div class="panel-body">${content}</div>`, leftPanel);
186
+ litRender(panelBody(panel, content), leftPanel);
282
187
 
283
- // Post-render side effects
284
- if (tab === "layers" && ctx.getCanvasMode() !== "stylebook") {
285
- ctx.registerLayersDnD();
188
+ const host = leftPanel.querySelector(".panel-body") as HTMLElement | null;
189
+ if (host && (doc !== null || !panel.requiresDocument)) {
190
+ panel.afterRender?.(ctx, host);
286
191
  }
287
192
  }
@@ -0,0 +1,131 @@
1
+ /// <reference lib="dom" />
2
+ /**
3
+ * Navigator-panels.ts — the Navigator's panel set, composed once.
4
+ *
5
+ * The counterpart to `commands/app-commands.ts`: every record is DEFINED beside the state it
6
+ * writes, in the module that owns the surface, and this file is the ONE place that composes them.
7
+ * Nothing here decides what a panel is called, what level it is, or what it draws — that would be
8
+ * the second definition site the registry exists to prevent.
9
+ *
10
+ * **Registration order is rail order** within a level group: PROJECT (Files ⌘1 · Search ⌘2 · Source
11
+ * Control ⌘3) above the divider, DOCUMENT (Outline ⌘4 · Page ⌘5 · Data ⌘6 · Packages ⌘7) below it.
12
+ *
13
+ * **Every rail button opens the Navigator.** Problems used to hold the fourth PROJECT slot while
14
+ * its body was drawn in the Bottom dock, and paying for that took a per-dock branch in three
15
+ * separate places. A permanent button that opens something somewhere else is also a standing
16
+ * advertisement, in the shell's own furniture, for a place to find things wrong with the product.
17
+ * The count reaches the user from the status bar the moment there is one.
18
+ *
19
+ * **Search is declared and hidden.** It is a surface a later phase builds (P3.3's palette index),
20
+ * and it holds a rail slot §3.2 has already spent. A `when: () => false` record is the honest way
21
+ * to say "this exists in the design and not yet in the app": the id is reserved, the budget already
22
+ * counts it, and the day it ships the only edit is deleting one predicate — as opposed to a stub
23
+ * button that lies to whoever clicks it.
24
+ */
25
+
26
+ import { registerFilesPanel } from "../files/files";
27
+ import { registerDataPanel } from "./data-explorer";
28
+ import { registerInsertPanel } from "./elements-panel";
29
+ import { registerGitPanel } from "./git-panel";
30
+ import { registerI18nPanel } from "./i18n-panel";
31
+ import { registerPagePanel } from "./head-panel";
32
+ import { registerPackagesPanel } from "./imports-panel";
33
+ import { registerBottomPanels } from "./bottom-dock";
34
+ import { registerLayersPanel } from "./layers-panel";
35
+ import { getPanel, listPanels, railPanelSet, registerPanel, resetPanels } from "./panel-registry";
36
+ import type { PanelRecord } from "./panel-registry";
37
+
38
+ /** Surfaces the design has declared and the app has not built. Registered, hidden, budgeted. */
39
+ const NOT_YET_BUILT = () => false;
40
+
41
+ /**
42
+ * Register every Navigator panel, in rail order. Idempotent — a second call is a no-op.
43
+ *
44
+ * Idempotence matters because `registerPanel` throws on a duplicate id: the Navigator mounts once
45
+ * per window in the app, but a test suite mounts it per case.
46
+ */
47
+ export function registerNavigatorPanels(): void {
48
+ // Keyed on Files rather than on `listPanels("navigator")`, because the Bottom dock composes
49
+ // Itself independently (`bottomPanelSet()` calls `registerBottomPanels()` directly) and either
50
+ // Order has to leave this function still registering the Navigator's own eight.
51
+ if (getPanel("files")) {
52
+ return;
53
+ }
54
+
55
+ // ── PROJECT group ───────────────────────────────────────────────────────────
56
+ registerFilesPanel();
57
+ registerPanel({
58
+ id: "search",
59
+ title: "Search",
60
+ level: "project",
61
+ dock: "navigator",
62
+ icon: "sp-icon-search",
63
+ when: NOT_YET_BUILT,
64
+ render: () => nothingYet(),
65
+ });
66
+ registerGitPanel();
67
+ /* Off the rail, and registered in the PROJECT group anyway: registration order is roster order,
68
+ so this is what puts Languages beside the panels it belongs with in the palette and in
69
+ `panel.focus.*`. Its `when` is `project.isMultilingual` — a project written in one language
70
+ never sees it. */
71
+ registerI18nPanel();
72
+
73
+ // ── DOCUMENT group ──────────────────────────────────────────────────────────
74
+ registerLayersPanel();
75
+ registerPagePanel();
76
+ registerDataPanel();
77
+ registerPackagesPanel();
78
+
79
+ // ── Off-rail: reachable by command and palette, no rail button ──────────────
80
+ registerInsertPanel();
81
+
82
+ // ── The Bottom dock's tabs (§3.2 ⑪): Problems · Diff · Logic · Activity ──────
83
+ // Composed here, in the one place panel records are gathered, so the shell has ONE composition
84
+ // Site rather than one per dock. Importing the module is also what attaches the dock to the
85
+ // Shell's mount lifecycle — see its `registerShellSurface` call. Problems arrives with them and
86
+ // Still takes the rail's fourth PROJECT slot, because the rail groups by level, not by dock.
87
+ registerBottomPanels();
88
+ }
89
+
90
+ /**
91
+ * The body a declared-but-unbuilt panel would draw.
92
+ *
93
+ * Unreachable while `when` is false — it exists so the record is complete rather than carrying an
94
+ * `undefined` render that would throw the first time someone deleted the predicate without reading
95
+ * this file.
96
+ */
97
+ function nothingYet(): never {
98
+ throw new Error(
99
+ "This Navigator panel is declared but not built — its `when` predicate should have hidden it.",
100
+ );
101
+ }
102
+
103
+ /** Every panel the Navigator dock DRAWS, in registration order. */
104
+ export function navigatorPanelSet(): readonly PanelRecord[] {
105
+ registerNavigatorPanels();
106
+ return listPanels("navigator");
107
+ }
108
+
109
+ /**
110
+ * The roster `panel.focus.*` is generated from: rail order first, then the rail-less Navigator
111
+ * panels.
112
+ *
113
+ * Not `railPanelSet()`: Insert and State have no rail button and no chord, and they still need a
114
+ * `Show …` command and a palette row, which is the whole point of `rail: false` (a surface
115
+ * reachable by name, not by number).
116
+ *
117
+ * The Bottom dock's four tabs are deliberately absent — Problems as of this change, and Diff, Logic
118
+ * and Activity all along. Each is `rail: false` AND hosted there, so each is addressed by
119
+ * `view.setBottomTab`: one verb per surface, and the dock's own strip is how a human picks between
120
+ * them. That is also why the filter here is by DOCK and not merely by `rail`, and why Problems
121
+ * leaving the rail removed `panel.focus.problems` rather than demoting it to a chordless row.
122
+ */
123
+ export function panelFocusRoster(): readonly PanelRecord[] {
124
+ registerNavigatorPanels();
125
+ return [...railPanelSet(), ...listPanels("navigator").filter((panel) => panel.rail === false)];
126
+ }
127
+
128
+ /** Drop every registration — tests only, so each case composes the set from scratch. */
129
+ export function resetNavigatorPanels(): void {
130
+ resetPanels();
131
+ }
@@ -11,7 +11,10 @@ import { updateActivePanelHeaders } from "../canvas/canvas-utils";
11
11
  import type { EffectScope } from "@vue/reactivity";
12
12
 
13
13
  interface OverlaysCtx {
14
- getCanvasMode: () => string;
14
+ // No `getCanvasMode`. It was declared here and supplied by the bootstrap for as long as this
15
+ // Interface has existed, and this module never called it — a focus reader wired into a surface
16
+ // With no use for it, which is one more edge for the pane rule to walk and one more thing a
17
+ // Reader has to rule out.
15
18
  isEditing: () => boolean;
16
19
  renderBlockActionBar: () => void;
17
20
  }
@@ -38,7 +41,9 @@ export function mount(ctx: OverlaysCtx) {
38
41
  }
39
42
  // Track selection, hover, mode, and the active panel (a hit in another breakpoint panel — or
40
43
  // A header click — re-anchors the block action bar even when the selection path is unchanged).
41
- void tab.session.selection;
44
+ // The whole SET, joined — a bare property read would not re-trigger when the selection
45
+ // Changes WITHIN the array, and §6.5's helpers always replace it but nothing enforces that.
46
+ void tab.session.selection.map((path) => path.join("/")).join("|");
42
47
  void tab.session.hover;
43
48
  void tab.doc.mode;
44
49
  void tab.session.ui.activeMedia;