@jxsuite/studio 6.1.2 → 8.0.1

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 (522) hide show
  1. package/README.md +5 -5
  2. package/dist/chunks/2020-5wtzce5g.js +4 -0
  3. package/dist/chunks/adapter-5tphg7xe.js +4 -0
  4. package/dist/chunks/add-new-flow-psym14sn.js +4 -0
  5. package/dist/chunks/cf-account-picker-haqazq5r.js +4 -0
  6. package/dist/chunks/cf-settings-h2wrh6hq.js +4 -0
  7. package/dist/chunks/{color-area-0fj8a4ga.js → color-area-6rbra5dy.js} +2 -2
  8. package/dist/chunks/{color-field-xch8kx2g.js → color-field-gy56c94g.js} +3 -3
  9. package/dist/chunks/color-m7r1vk54.js +4 -0
  10. package/dist/chunks/{color-slider-jxd8v350.js → color-slider-sqqdyf6c.js} +2 -2
  11. package/dist/chunks/{combobox-p0efwjke.js → combobox-72h32ejk.js} +3 -3
  12. package/dist/chunks/components-r22xca09.js +4 -0
  13. package/dist/chunks/content-source-mmppmcyg.js +4 -0
  14. package/dist/chunks/convert-to-repeater-he70fc2b.js +4 -0
  15. package/dist/chunks/editor-ccd9jwsa.js +4 -0
  16. package/dist/chunks/entry-commands-6qxz9e8p.js +4 -0
  17. package/dist/chunks/extension-sections-0egb88dm.js +4 -0
  18. package/dist/chunks/file-ops-qnab36ek.js +4 -0
  19. package/dist/chunks/files-rcn56qvm.js +4 -0
  20. package/dist/chunks/format-host-yxz0kjjs.js +4 -0
  21. package/dist/chunks/fs-events-d1qxq4z4.js +4 -0
  22. package/dist/chunks/grid-open-4z1g062t.js +4 -0
  23. package/dist/chunks/{grid-view-d2wq9ezg.js → grid-view-qg1b5eqx.js} +25 -25
  24. package/dist/chunks/{icons-pnfz478q.js → icons-63bjtbs7.js} +2 -2
  25. package/dist/chunks/{iframe-entry-jdcktez8.js → iframe-entry-2zggzajv.js} +4 -4
  26. package/dist/chunks/{iframe-entry-zap785cw.js → iframe-entry-76j8vwwx.js} +4 -4
  27. package/dist/chunks/iframe-entry-99nr5zfb.js +5 -0
  28. package/dist/chunks/{iframe-entry-x0ygf2yr.js → iframe-entry-pkgmcgp0.js} +4 -4
  29. package/dist/chunks/iframe-host-ssv7kyj0.js +4 -0
  30. package/dist/chunks/{index-zpjmzqfk.js → index-32eqzv1k.js} +3 -3
  31. package/dist/chunks/index-f0jn7nnp.js +4 -0
  32. package/dist/chunks/{javascript-m54mnwp6.js → javascript-pjp734q4.js} +3 -3
  33. package/dist/chunks/jsonMode-njkvsa02.js +13 -0
  34. package/dist/chunks/jx-validate-ttasrbh7.js +4 -0
  35. package/dist/chunks/layers-bgyr11tr.js +4 -0
  36. package/dist/chunks/layers-panel-7ez66zeq.js +4 -0
  37. package/dist/chunks/{listbox-e74qjyq6.js → listbox-c421cf8c.js} +2 -2
  38. package/dist/chunks/lit-html-v9gh687x.js +4 -0
  39. package/dist/chunks/media-library-sq468wts.js +4 -0
  40. package/dist/chunks/media-picker-shfe59pt.js +4 -0
  41. package/dist/chunks/{menu-n6yzswmy.js → menu-bdpzbfvs.js} +2 -2
  42. package/dist/chunks/{monaco-binding-7gx83x3r.js → monaco-binding-vq1hgnn0.js} +3 -3
  43. package/dist/chunks/monaco-buffer-3afgwvbp.js +4 -0
  44. package/dist/chunks/monaco-setup-xrd2cbkp.js +4 -0
  45. package/dist/chunks/notify-kzrjr3fv.js +4 -0
  46. package/dist/chunks/parse-v77xtwv7.js +4 -0
  47. package/dist/chunks/platform-7v4rtd7m.js +4 -0
  48. package/dist/chunks/popover-b89sfej7.js +4 -0
  49. package/dist/chunks/publish-panel-2z9gw8ee.js +4 -0
  50. package/dist/chunks/publish-quick-qx2455cj.js +4 -0
  51. package/dist/chunks/publish-workspace-wrc1dgwx.js +4 -0
  52. package/dist/chunks/quick-search-n0t0eqxb.js +4 -0
  53. package/dist/chunks/references-9547rg5s.js +4 -0
  54. package/dist/chunks/right-panel-wsgnr9pn.js +4 -0
  55. package/dist/chunks/source-control-kwktr9y6.js +4 -0
  56. package/dist/chunks/{split-n2gfpm5m.js → split-c9zfdgxf.js} +2 -2
  57. package/dist/chunks/studio-03ct6yfv.js +9 -0
  58. package/dist/chunks/studio-07rcfje3.js +5 -0
  59. package/dist/chunks/studio-3e54qh39.js +7 -0
  60. package/dist/chunks/studio-3exxhz5g.js +5 -0
  61. package/dist/chunks/studio-3q40e3rj.js +5 -0
  62. package/dist/chunks/studio-3qeh9t0h.js +6 -0
  63. package/dist/chunks/studio-3qqjeep5.js +6 -0
  64. package/dist/chunks/studio-43sd2mam.js +4 -0
  65. package/dist/chunks/studio-4hp8pkyt.js +5 -0
  66. package/dist/chunks/studio-58xg6j2q.js +9 -0
  67. package/dist/chunks/studio-5g0rprdt.js +7 -0
  68. package/dist/chunks/{studio-2j1cb95x.js → studio-6m380wp7.js} +4 -4
  69. package/dist/chunks/studio-80jyh1xh.js +4 -0
  70. package/dist/chunks/studio-83mk4bgg.js +9 -0
  71. package/dist/chunks/{studio-v0jzqdjm.js → studio-881z1xrx.js} +4 -4
  72. package/dist/chunks/studio-8m0y2qe7.js +5 -0
  73. package/dist/chunks/{studio-d81xfh1g.js → studio-8tr6cfrc.js} +4 -4
  74. package/dist/chunks/studio-8vcvfs7r.js +6 -0
  75. package/dist/chunks/studio-9tmebf0s.js +5 -0
  76. package/dist/chunks/studio-a2bvaptz.js +5 -0
  77. package/dist/chunks/studio-b7y5mr30.js +5 -0
  78. package/dist/chunks/studio-bavb31r0.js +5 -0
  79. package/dist/chunks/{studio-dgz8d0c1.js → studio-bbe4c90a.js} +4 -4
  80. package/dist/chunks/studio-c05wdnt3.js +5 -0
  81. package/dist/chunks/studio-ccv2svc6.js +5 -0
  82. package/dist/chunks/studio-d5grtb9e.js +16 -0
  83. package/dist/chunks/studio-df0baea9.js +5 -0
  84. package/dist/chunks/studio-dgk4dqtx.js +7 -0
  85. package/dist/chunks/studio-e1g64q43.js +5 -0
  86. package/dist/chunks/studio-ed1hp6zf.js +6 -0
  87. package/dist/chunks/studio-ed3xx40h.js +7 -0
  88. package/dist/chunks/studio-f14e1zdj.js +5 -0
  89. package/dist/chunks/studio-fbhxxc5f.js +5 -0
  90. package/dist/chunks/studio-fyh0jc96.js +5 -0
  91. package/dist/chunks/studio-gcxk20n7.js +5 -0
  92. package/dist/chunks/studio-jaaz8ce9.js +5 -0
  93. package/dist/chunks/{studio-90pq9km1.js → studio-jcnsdaep.js} +4 -4
  94. package/dist/chunks/studio-jsgf2q5k.js +7 -0
  95. package/dist/chunks/{studio-0q988f9w.js → studio-k3xxbagr.js} +3 -3
  96. package/dist/chunks/{studio-5ve6bbep.js → studio-k7evxqh4.js} +4 -4
  97. package/dist/chunks/studio-kt3pjkwd.js +5 -0
  98. package/dist/chunks/studio-m8g16bgz.js +5 -0
  99. package/dist/chunks/studio-mn0476ag.js +5 -0
  100. package/dist/chunks/studio-mx1smyq0.js +5 -0
  101. package/dist/chunks/studio-n0c5h6mf.js +5 -0
  102. package/dist/chunks/{studio-485046te.js → studio-nh6d342n.js} +7 -7
  103. package/dist/chunks/studio-nqxqf8p2.js +4 -0
  104. package/dist/chunks/studio-p4nrkvqr.js +5 -0
  105. package/dist/chunks/{studio-1fxkaaea.js → studio-pbxa5fpc.js} +4 -4
  106. package/dist/chunks/studio-pgmvdv7z.js +7 -0
  107. package/dist/chunks/studio-ph84avkf.js +5 -0
  108. package/dist/chunks/{studio-tq0rtfwj.js → studio-q0mvbaq6.js} +4 -4
  109. package/dist/chunks/studio-q0tccd43.js +5 -0
  110. package/dist/chunks/studio-q7rtx6zq.js +14 -0
  111. package/dist/chunks/{studio-a3g98wjr.js → studio-qgh13jtz.js} +4 -4
  112. package/dist/chunks/studio-qmn1xc24.js +5 -0
  113. package/dist/chunks/studio-qwdqwkj0.js +5 -0
  114. package/dist/chunks/studio-r5qy30vx.js +5 -0
  115. package/dist/chunks/studio-rj9eamf8.js +5 -0
  116. package/dist/chunks/studio-rptgsk96.js +5 -0
  117. package/dist/chunks/studio-rthyg42z.js +928 -0
  118. package/dist/chunks/studio-s19tp1xr.js +5 -0
  119. package/dist/chunks/studio-s32578pn.js +5 -0
  120. package/dist/chunks/studio-svb7yyve.js +5 -0
  121. package/dist/chunks/studio-syreb644.js +5 -0
  122. package/dist/chunks/studio-tf9jryb1.js +10 -0
  123. package/dist/chunks/studio-tfkznv39.js +5 -0
  124. package/dist/chunks/studio-tft6r105.js +5 -0
  125. package/dist/chunks/studio-txf2kysx.js +5 -0
  126. package/dist/chunks/studio-v8867ddv.js +12 -0
  127. package/dist/chunks/studio-vxq7fcvv.js +5 -0
  128. package/dist/chunks/studio-w4rz9hdk.js +5 -0
  129. package/dist/chunks/studio-wbcjbhy1.js +9 -0
  130. package/dist/chunks/studio-wc649wss.js +5 -0
  131. package/dist/chunks/studio-wys23mxz.js +5 -0
  132. package/dist/chunks/studio-x1x167jh.js +5 -0
  133. package/dist/chunks/studio-x9hsze61.js +5 -0
  134. package/dist/chunks/studio-y0n7yxea.js +9 -0
  135. package/dist/chunks/studio-y3ahhdpx.js +5 -0
  136. package/dist/chunks/studio-z97c48fk.js +5 -0
  137. package/dist/chunks/studio-zat62m0c.js +5 -0
  138. package/dist/chunks/studio-zcd2e7yz.js +5 -0
  139. package/dist/chunks/studio-zz9qe3rw.js +64 -0
  140. package/dist/chunks/toast-1gv0h53h.js +4 -0
  141. package/dist/chunks/{toast-host-ke5z4ng7.js → toast-host-1yg5ar8d.js} +3 -3
  142. package/dist/chunks/{tooltip-5v8ngwj2.js → tooltip-yypz28gq.js} +3 -3
  143. package/dist/chunks/{tree-mdq3v5cw.js → tree-9xa4hm7n.js} +2 -2
  144. package/dist/chunks/tsMode-epyfz1hv.js +14 -0
  145. package/dist/chunks/workspace-dz7nxfhv.js +4 -0
  146. package/dist/chunks/workspace-home-xsd7hkjw.js +4 -0
  147. package/dist/chunks/{ws-client-nze0k6mv.js → ws-client-bv552sfx.js} +3 -3
  148. package/dist/iframe-entry.js +20 -16
  149. package/dist/manifest.json +77 -63
  150. package/dist/studio.js +103 -104
  151. package/dist/workers/ts.worker.js +3 -3
  152. package/package.json +12 -11
  153. package/src/browse/component-examples.ts +272 -0
  154. package/src/browse/library-commands.ts +64 -104
  155. package/src/browse/library-layouts.ts +263 -49
  156. package/src/browse/library-model.ts +181 -133
  157. package/src/browse/library-pane.ts +738 -446
  158. package/src/browse/library-preview.ts +149 -19
  159. package/src/browse/library-source.ts +308 -41
  160. package/src/browse/preview-root.ts +78 -0
  161. package/src/browse/preview-style.ts +155 -0
  162. package/src/canvas/asset-refs.ts +16 -1
  163. package/src/canvas/canvas-live-render.ts +222 -30
  164. package/src/canvas/canvas-origin.ts +37 -12
  165. package/src/canvas/canvas-page-context.ts +112 -0
  166. package/src/canvas/canvas-render.ts +113 -107
  167. package/src/canvas/canvas-utils.ts +57 -12
  168. package/src/canvas/iframe-drop.ts +107 -0
  169. package/src/canvas/iframe-entry.ts +24 -12
  170. package/src/canvas/iframe-host.ts +134 -62
  171. package/src/canvas/iframe-keys.ts +11 -0
  172. package/src/canvas/iframe-patch.ts +8 -7
  173. package/src/canvas/iframe-protocol.ts +24 -5
  174. package/src/canvas/iframe-render.ts +48 -1
  175. package/src/canvas/iframe-subtree.ts +5 -2
  176. package/src/canvas/npm-modules.ts +22 -0
  177. package/src/canvas/preview-navigate.ts +16 -0
  178. package/src/canvas/repeater-sources.ts +200 -0
  179. package/src/canvas/stage-scrollbar.ts +5 -1
  180. package/src/canvas/surface-registry.ts +6 -0
  181. package/src/commands/app-commands.ts +16 -6
  182. package/src/commands/budget.ts +10 -8
  183. package/src/commands/context.ts +35 -10
  184. package/src/commands/defaults.ts +69 -45
  185. package/src/commands/keymap.ts +9 -0
  186. package/src/commands/levels.ts +11 -5
  187. package/src/commands/live-context.ts +2 -0
  188. package/src/commands/registry.ts +10 -1
  189. package/src/content/collection-match.ts +6 -5
  190. package/src/content/collection-pages.ts +412 -0
  191. package/src/content/content-collections.ts +270 -0
  192. package/src/content/entry-commands.ts +51 -60
  193. package/src/content/entry-editor.ts +111 -18
  194. package/src/content/entry-fields.ts +13 -1
  195. package/src/content/entry-inspector.ts +225 -0
  196. package/src/content/entry-model.ts +17 -3
  197. package/src/content/entry-open.ts +80 -0
  198. package/src/content/entry-summaries.ts +440 -0
  199. package/src/content/file-record-ids.ts +80 -0
  200. package/src/content/file-records.ts +125 -0
  201. package/src/content/page-summaries.ts +129 -0
  202. package/src/content/record-entry.ts +201 -0
  203. package/src/content/writing-banner.ts +177 -0
  204. package/src/create/add-new-commands.ts +185 -0
  205. package/src/create/add-new-flow.ts +1116 -0
  206. package/src/create/add-new.ts +1014 -0
  207. package/src/create/element-name.ts +121 -0
  208. package/src/editor/convert-to-component.ts +67 -43
  209. package/src/editor/file-drop-action.ts +9 -1
  210. package/src/editor/inline-edit-apply.ts +44 -0
  211. package/src/editor/inline-edit.ts +10 -0
  212. package/src/editor/insert-component.ts +91 -0
  213. package/src/editor/insert-zone-action.ts +13 -4
  214. package/src/editor/shortcuts.ts +44 -22
  215. package/src/editor/slash-menu.ts +51 -8
  216. package/src/files/components.ts +74 -10
  217. package/src/files/file-ops.ts +15 -5
  218. package/src/files/files.ts +164 -150
  219. package/src/files/fs-events.ts +18 -7
  220. package/src/files/media-meta.ts +95 -1
  221. package/src/files/media-types.ts +55 -0
  222. package/src/files/media-upload.ts +209 -52
  223. package/src/files/new-file-name.ts +156 -0
  224. package/src/files/serialize-document.ts +13 -3
  225. package/src/format/format-host.ts +15 -0
  226. package/src/github/github-auth.ts +2 -2
  227. package/src/github/github-publish.ts +4 -3
  228. package/src/grid/grid-controller.ts +5 -1
  229. package/src/grid/grid-open.ts +0 -27
  230. package/src/grid/grid-panel.ts +54 -2
  231. package/src/grid/grid-reveal.ts +34 -0
  232. package/src/grid/grid-source.ts +3 -25
  233. package/src/grid/grid-view.ts +31 -6
  234. package/src/grid/sources/content-source.ts +75 -7
  235. package/src/grid/tabulator-tables.d.ts +6 -0
  236. package/src/hosting/document.ts +2 -2
  237. package/src/i18n/i18n-commands.ts +2 -1
  238. package/src/media/media-commands.ts +181 -0
  239. package/src/media/media-library-model.ts +232 -0
  240. package/src/media/media-library.ts +1283 -0
  241. package/src/media/media-pane.ts +47 -19
  242. package/src/packages/pull-package-sync.ts +1 -1
  243. package/src/panels/activity-panel.ts +21 -5
  244. package/src/panels/ai-chat/chat-markdown.ts +8 -8
  245. package/src/panels/block-action-bar.ts +11 -11
  246. package/src/panels/canvas-dnd-bridge.ts +5 -2
  247. package/src/panels/chat-panel.ts +6 -6
  248. package/src/panels/collections-panel.ts +306 -0
  249. package/src/panels/component-preview.ts +35 -13
  250. package/src/panels/data-explorer.ts +1 -1
  251. package/src/panels/data-grid.ts +4 -0
  252. package/src/panels/dnd.ts +17 -30
  253. package/src/panels/elements-panel.ts +9 -2
  254. package/src/panels/empty-state.ts +2 -2
  255. package/src/panels/formula-workspace.ts +2 -3
  256. package/src/panels/frontmatter-fields.ts +9 -9
  257. package/src/panels/git-diff-open.ts +9 -5
  258. package/src/panels/head-panel.ts +369 -103
  259. package/src/panels/i18n-panel.ts +11 -10
  260. package/src/panels/imports-panel.ts +2 -0
  261. package/src/panels/jump-bar.ts +27 -2
  262. package/src/panels/layers-panel.ts +36 -30
  263. package/src/panels/left-panel.ts +22 -8
  264. package/src/panels/navigator-panels.ts +23 -11
  265. package/src/panels/pane-context.ts +111 -29
  266. package/src/panels/pane-grid.ts +6 -6
  267. package/src/panels/panel-registry.ts +14 -9
  268. package/src/panels/properties-panel.ts +7 -3
  269. package/src/panels/right-panel.ts +199 -43
  270. package/src/panels/seo-modal.ts +41 -108
  271. package/src/panels/settings-menu.ts +52 -50
  272. package/src/panels/settings-pane.ts +268 -162
  273. package/src/panels/signals-panel.ts +3 -4
  274. package/src/panels/site-model.ts +367 -0
  275. package/src/panels/site-panel.ts +638 -0
  276. package/src/panels/style-panel.ts +37 -3
  277. package/src/panels/stylebook-doc.ts +142 -10
  278. package/src/panels/stylebook-layers-panel.ts +39 -80
  279. package/src/panels/stylebook-panel.ts +47 -10
  280. package/src/panels/styles-panel.ts +327 -0
  281. package/src/panels/tab-strip.ts +109 -25
  282. package/src/platform.ts +1 -1
  283. package/src/platforms/cloud.ts +28 -1
  284. package/src/platforms/default-platform.ts +4 -4
  285. package/src/platforms/devserver.ts +51 -25
  286. package/src/publish/deploy-checklist.ts +12 -7
  287. package/src/publish/pages-service.ts +38 -14
  288. package/src/publish/publish-changes.ts +491 -0
  289. package/src/publish/publish-commands.ts +83 -18
  290. package/src/publish/publish-ids.ts +49 -0
  291. package/src/publish/publish-quick.ts +148 -0
  292. package/src/publish/publish-workspace.ts +926 -0
  293. package/src/publish/source-control.ts +907 -0
  294. package/src/services/automation.ts +16 -20
  295. package/src/services/cf-settings.ts +4 -4
  296. package/src/services/connection.ts +2 -2
  297. package/src/services/directory-picker.ts +2 -2
  298. package/src/services/references.ts +0 -0
  299. package/src/services/render-critic.ts +21 -2
  300. package/src/services/settings/definitions.ts +25 -14
  301. package/src/settings/contributed-section.ts +49 -10
  302. package/src/settings/css-vars-editor.ts +93 -27
  303. package/src/settings/developer-panels.ts +43 -0
  304. package/src/settings/extension-sections.ts +20 -2
  305. package/src/settings/general-settings.ts +91 -21
  306. package/src/settings/preferences-dialog.ts +8 -1
  307. package/src/settings/project-sections.ts +27 -10
  308. package/src/settings/schema-field-ui.ts +3 -1
  309. package/src/settings/section-registry.ts +116 -11
  310. package/src/settings/settings-dialog.ts +192 -0
  311. package/src/settings/settings-document.ts +182 -162
  312. package/src/shell.ts +467 -431
  313. package/src/site-context.ts +64 -10
  314. package/src/state.ts +28 -9
  315. package/src/studio.ts +194 -41
  316. package/src/style/project-styles.ts +34 -0
  317. package/src/style/stylebook-specimens.ts +89 -0
  318. package/src/style/stylebook-target.ts +26 -0
  319. package/src/style/tag-inheritance.ts +105 -0
  320. package/src/style/variables-focus.ts +61 -0
  321. package/src/style/variables-view.ts +235 -0
  322. package/src/surfaces/add-new.json +1482 -0
  323. package/src/surfaces/add-new.ts +325 -0
  324. package/src/surfaces/ai-chat.ts +2 -2
  325. package/src/surfaces/boot-failure.json +4 -3
  326. package/src/surfaces/bottom-dock.json +1 -1
  327. package/src/surfaces/canvas-stage.json +30 -19
  328. package/src/surfaces/canvas-stage.ts +5 -5
  329. package/src/surfaces/collections-panel.json +615 -0
  330. package/src/surfaces/collections-panel.ts +168 -0
  331. package/src/surfaces/commandbar.json +241 -96
  332. package/src/surfaces/commandbar.ts +134 -99
  333. package/src/surfaces/empty-state.json +1 -1
  334. package/src/surfaces/entry-editor.json +136 -0
  335. package/src/surfaces/entry-editor.ts +21 -0
  336. package/src/surfaces/entry-inspector.json +371 -0
  337. package/src/surfaces/entry-inspector.ts +143 -0
  338. package/src/surfaces/inspector-dock.json +162 -14
  339. package/src/surfaces/inspector-dock.ts +46 -19
  340. package/src/surfaces/library-pane.json +670 -437
  341. package/src/surfaces/library-pane.ts +94 -59
  342. package/src/surfaces/media-browser.json +62 -6
  343. package/src/surfaces/media-browser.ts +15 -1
  344. package/src/surfaces/media-field.json +1 -1
  345. package/src/surfaces/media-library.json +1586 -0
  346. package/src/surfaces/media-library.ts +282 -0
  347. package/src/surfaces/media-pick-dialog.json +71 -0
  348. package/src/surfaces/media-pick-dialog.ts +132 -0
  349. package/src/surfaces/menu.ts +18 -0
  350. package/src/surfaces/pane-context.json +144 -77
  351. package/src/surfaces/pane-context.ts +24 -0
  352. package/src/surfaces/panel-deploy-checklist.json +12 -6
  353. package/src/surfaces/panel-deploy-checklist.ts +3 -1
  354. package/src/surfaces/panel-page.json +72 -2
  355. package/src/surfaces/panel-page.ts +38 -7
  356. package/src/surfaces/panel-signals.json +1 -1
  357. package/src/surfaces/panel-signals.ts +5 -5
  358. package/src/surfaces/panel-stylebook-layers.json +71 -204
  359. package/src/surfaces/panel-stylebook-layers.ts +0 -21
  360. package/src/surfaces/preferences.json +120 -48
  361. package/src/surfaces/preferences.ts +8 -0
  362. package/src/surfaces/publish-quick.json +428 -0
  363. package/src/surfaces/publish-quick.ts +165 -0
  364. package/src/surfaces/publish-workspace.json +2892 -0
  365. package/src/surfaces/publish-workspace.ts +391 -0
  366. package/src/surfaces/rail.json +1 -159
  367. package/src/surfaces/rail.ts +18 -75
  368. package/src/surfaces/schema-form.json +10 -2
  369. package/src/surfaces/schema-form.ts +2 -0
  370. package/src/surfaces/seo.json +1 -1
  371. package/src/surfaces/settings-contributed.json +5 -5
  372. package/src/surfaces/settings-contributed.ts +18 -2
  373. package/src/surfaces/settings-css-vars.json +44 -36
  374. package/src/surfaces/settings-css-vars.ts +77 -4
  375. package/src/surfaces/settings-deploy.json +2 -15
  376. package/src/surfaces/settings-deploy.ts +1 -1
  377. package/src/surfaces/settings-dialog.json +51 -0
  378. package/src/surfaces/settings-dialog.ts +169 -0
  379. package/src/surfaces/settings-overview.json +3 -3
  380. package/src/surfaces/settings-overview.ts +9 -2
  381. package/src/surfaces/settings-pane.json +269 -46
  382. package/src/surfaces/settings-pane.ts +85 -24
  383. package/src/surfaces/shell.json +2 -1
  384. package/src/surfaces/site-panel.json +1029 -0
  385. package/src/surfaces/site-panel.ts +233 -0
  386. package/src/surfaces/slash-menu.json +63 -21
  387. package/src/surfaces/slash-menu.ts +23 -0
  388. package/src/surfaces/statusbar.ts +39 -15
  389. package/src/surfaces/styles-panel.json +735 -0
  390. package/src/surfaces/styles-panel.ts +195 -0
  391. package/src/surfaces/styles-variables.json +149 -0
  392. package/src/surfaces/styles-variables.ts +145 -0
  393. package/src/surfaces/tab-strip.json +4 -4
  394. package/src/surfaces/welcome.ts +1 -1
  395. package/src/surfaces/writing-banner.json +94 -0
  396. package/src/surfaces/writing-banner.ts +80 -0
  397. package/src/tabs/bare-repeaters.ts +101 -0
  398. package/src/tabs/tab.ts +47 -7
  399. package/src/types.ts +21 -26
  400. package/src/ui/form-controls.ts +47 -8
  401. package/src/ui/layers.ts +13 -0
  402. package/src/ui/media-picker.ts +284 -40
  403. package/src/ui/regions.ts +7 -6
  404. package/src/ui/schema-form.ts +259 -27
  405. package/src/ui/virtual-window.ts +26 -1
  406. package/src/utils/base64.ts +3 -3
  407. package/src/utils/edit-display.ts +322 -67
  408. package/src/utils/local-day.ts +18 -0
  409. package/src/workspace/pane-derive.ts +4 -4
  410. package/src/workspace/session.ts +28 -7
  411. package/src/workspace/tab-workspace.ts +137 -0
  412. package/src/workspace/workspace-back.ts +189 -0
  413. package/src/workspace/workspace-home.ts +133 -0
  414. package/src/workspace/workspace-ids.ts +129 -0
  415. package/src/workspace/workspace-switch.ts +372 -0
  416. package/src/workspace/workspace.ts +125 -11
  417. package/styles/shell-frame.css +30 -7
  418. package/styles/shell-frame.json +15 -3
  419. package/dist/chunks/2020-f2gkpy8d.js +0 -4
  420. package/dist/chunks/adapter-4912g339.js +0 -4
  421. package/dist/chunks/cf-account-picker-wccaenh6.js +0 -4
  422. package/dist/chunks/cf-settings-br6105tr.js +0 -4
  423. package/dist/chunks/color-28ksk2qm.js +0 -4
  424. package/dist/chunks/components-db68vsn7.js +0 -4
  425. package/dist/chunks/content-source-1449qesq.js +0 -4
  426. package/dist/chunks/convert-to-repeater-5h457egj.js +0 -4
  427. package/dist/chunks/editor-x9jn86a7.js +0 -4
  428. package/dist/chunks/entry-commands-may24cpt.js +0 -4
  429. package/dist/chunks/extension-sections-pvr14vxr.js +0 -4
  430. package/dist/chunks/file-ops-x9v54pcj.js +0 -4
  431. package/dist/chunks/files-j3knqf0s.js +0 -4
  432. package/dist/chunks/format-host-tyre2trb.js +0 -4
  433. package/dist/chunks/fs-events-64ma9htc.js +0 -4
  434. package/dist/chunks/git-panel-84ps5dex.js +0 -4
  435. package/dist/chunks/iframe-entry-fvbk89gm.js +0 -5
  436. package/dist/chunks/iframe-host-ck6vejt5.js +0 -4
  437. package/dist/chunks/index-b8xw3vy9.js +0 -4
  438. package/dist/chunks/jsonMode-w15cmrcm.js +0 -13
  439. package/dist/chunks/jx-validate-at3zn8wa.js +0 -4
  440. package/dist/chunks/layers-h4xp1pss.js +0 -4
  441. package/dist/chunks/layers-panel-m5hw1d7g.js +0 -4
  442. package/dist/chunks/lit-html-8t8t3dnr.js +0 -4
  443. package/dist/chunks/media-picker-2cweexc5.js +0 -4
  444. package/dist/chunks/menu-ynw13y0s.js +0 -4
  445. package/dist/chunks/monaco-buffer-qzxn567r.js +0 -4
  446. package/dist/chunks/monaco-setup-gxf6656g.js +0 -4
  447. package/dist/chunks/notify-cj5zbrs2.js +0 -4
  448. package/dist/chunks/parse-b7ddhr8m.js +0 -4
  449. package/dist/chunks/platform-3dfws9js.js +0 -4
  450. package/dist/chunks/popover-jt2gxmzs.js +0 -4
  451. package/dist/chunks/publish-panel-1gvxbj21.js +0 -4
  452. package/dist/chunks/quick-search-0dajrwqg.js +0 -4
  453. package/dist/chunks/references-49qgt404.js +0 -4
  454. package/dist/chunks/right-panel-jm1bwe53.js +0 -4
  455. package/dist/chunks/section-registry-6kwc4fky.js +0 -4
  456. package/dist/chunks/studio-0rt52vpq.js +0 -5
  457. package/dist/chunks/studio-18vgbhs5.js +0 -5
  458. package/dist/chunks/studio-24mccdrj.js +0 -5
  459. package/dist/chunks/studio-2eh507zk.js +0 -9
  460. package/dist/chunks/studio-2hcbccfv.js +0 -5
  461. package/dist/chunks/studio-2jbs3rxv.js +0 -5
  462. package/dist/chunks/studio-4h8k4dw9.js +0 -5
  463. package/dist/chunks/studio-5f6n18kx.js +0 -5
  464. package/dist/chunks/studio-5gthpky6.js +0 -5
  465. package/dist/chunks/studio-6ep3js6b.js +0 -9
  466. package/dist/chunks/studio-6wkmf3wz.js +0 -9
  467. package/dist/chunks/studio-841rf3cg.js +0 -5
  468. package/dist/chunks/studio-8gmwgheg.js +0 -5
  469. package/dist/chunks/studio-8qm0ep50.js +0 -5
  470. package/dist/chunks/studio-924p1tm1.js +0 -6
  471. package/dist/chunks/studio-a3shpz9y.js +0 -5
  472. package/dist/chunks/studio-amsbaaar.js +0 -6
  473. package/dist/chunks/studio-at5spjbc.js +0 -7
  474. package/dist/chunks/studio-b2xv945e.js +0 -5
  475. package/dist/chunks/studio-bn5nkafw.js +0 -5
  476. package/dist/chunks/studio-bw6q5xjf.js +0 -9
  477. package/dist/chunks/studio-c7q0t9x1.js +0 -5
  478. package/dist/chunks/studio-camnhc96.js +0 -6
  479. package/dist/chunks/studio-cffqvnzd.js +0 -5
  480. package/dist/chunks/studio-efvfrsf8.js +0 -5
  481. package/dist/chunks/studio-er30bpcx.js +0 -5
  482. package/dist/chunks/studio-ezscgr64.js +0 -5
  483. package/dist/chunks/studio-ffrrncvz.js +0 -5
  484. package/dist/chunks/studio-fpphgn8y.js +0 -10
  485. package/dist/chunks/studio-j1kvhdjk.js +0 -4
  486. package/dist/chunks/studio-j430n16g.js +0 -7
  487. package/dist/chunks/studio-jjkg84nj.js +0 -5
  488. package/dist/chunks/studio-m0q32ars.js +0 -4
  489. package/dist/chunks/studio-m6bdst11.js +0 -5
  490. package/dist/chunks/studio-nv2cptd4.js +0 -64
  491. package/dist/chunks/studio-nwfrc98n.js +0 -5
  492. package/dist/chunks/studio-p1wgvp7r.js +0 -5
  493. package/dist/chunks/studio-pag2wncm.js +0 -5
  494. package/dist/chunks/studio-qvanvzfd.js +0 -5
  495. package/dist/chunks/studio-qwa64kt7.js +0 -5
  496. package/dist/chunks/studio-rk1zc4x3.js +0 -928
  497. package/dist/chunks/studio-se2r3ptc.js +0 -5
  498. package/dist/chunks/studio-sg2a0dh0.js +0 -5
  499. package/dist/chunks/studio-tjzjhe68.js +0 -5
  500. package/dist/chunks/studio-v2w7q8r1.js +0 -7
  501. package/dist/chunks/studio-v5vjq1h0.js +0 -4
  502. package/dist/chunks/studio-v8aga3vp.js +0 -14
  503. package/dist/chunks/studio-vfcdrfmv.js +0 -5
  504. package/dist/chunks/studio-vmfkgdjf.js +0 -5
  505. package/dist/chunks/studio-wt1816jj.js +0 -5
  506. package/dist/chunks/studio-wz73q5kq.js +0 -4
  507. package/dist/chunks/studio-y04qtxvp.js +0 -7
  508. package/dist/chunks/studio-y21g8zzg.js +0 -5
  509. package/dist/chunks/studio-y64hrt8p.js +0 -12
  510. package/dist/chunks/studio-ynn90f58.js +0 -16
  511. package/dist/chunks/studio-yxz682sx.js +0 -5
  512. package/dist/chunks/studio-zp7snvkq.js +0 -5
  513. package/dist/chunks/studio-zq4z6tm6.js +0 -5
  514. package/dist/chunks/toast-c9fn075p.js +0 -4
  515. package/dist/chunks/tsMode-sf49ee9x.js +0 -14
  516. package/dist/chunks/workspace-jtfahpee.js +0 -4
  517. package/src/panels/frontmatter-panel.ts +0 -711
  518. package/src/panels/git-panel.ts +0 -1108
  519. package/src/surfaces/doc-header.json +0 -776
  520. package/src/surfaces/doc-header.ts +0 -222
  521. package/src/surfaces/git-panel.json +0 -1880
  522. package/src/surfaces/git-panel.ts +0 -264
@@ -7,7 +7,8 @@
7
7
  * a command, so what the document is handed is a PROJECTION of the registry rather than a list of
8
8
  * buttons: `primary` is `forPlacement("commandbar/primary")` (capped at five by
9
9
  * `scripts/check-chrome-budget.ts`), `docks` is the three dock records with the shell's state
10
- * beside them, `layouts` is the project's own layout record, and the ⬢ Studio menu is
10
+ * beside them, `workspaces` is the five-workspace switcher with `shell.workspace` selected, the ⚙
11
+ * gear is the `settings/menu` placement, and the ⬢ Studio menu is
11
12
  * `forPlacement("commandbar/overflow")` opened on the `menu` surface. With no project open the same
12
13
  * document renders; the records' own `when` clauses empty it (§13.1: enablement is a predicate with
13
14
  * a sentence, never a second template).
@@ -24,22 +25,23 @@
24
25
  * is the platform's.
25
26
  *
26
27
  * **Retired, with a name, a chord and a residue** (`studio-ui-guidelines.md` §12.2): Open Project +
27
- * New Project + recents → the pill and `Project: Open Recent…`; `Manage` → `File: Browse Library`;
28
- * `Publish` → the `Publish:` family; `Sync Project` → Source Control. The five-mode switcher lives
29
- * in the pane context bar and is reachable as `View: Set Canvas Mode` in the palette.
28
+ * New Project + recents → the pill and `Project: Open Recent…`; `Manage` → the Content workspace
29
+ * (`view.setWorkspace { workspace: "content" }`, ⌘2); `Publish` → the `Publish:` family; `Sync
30
+ * Project` → Source Control. The five-mode switcher lives in the pane context bar and is reachable
31
+ * as `View: Set Canvas Mode` in the palette.
30
32
  *
31
33
  * @docs studio/interface
32
34
  */
33
35
 
34
36
  import { presenceProjection } from "../collab/presence-chips";
35
37
  import { effect, effectScope, reactive } from "../reactivity";
36
- import { activeTab } from "../workspace/workspace";
38
+ import { activeTab, workspace } from "../workspace/workspace";
37
39
  import { primarySelection } from "../tabs/selection";
40
+ import { stylebookTarget } from "../style/stylebook-target";
38
41
  import { shell } from "../shell";
39
42
  import { openQuickSearch } from "../panels/quick-search";
40
- import { showPromptDialog } from "../ui/layers";
41
43
  import { getPlatform, hasPlatform } from "../platform";
42
- import { getPreviewNavigateHandler } from "../canvas/preview-navigate";
44
+ import { openUrlExternally } from "../canvas/preview-navigate";
43
45
  import { armPreviewOverlay, flushPreviewOverlay } from "../preview/preview-overlay";
44
46
  import { documentUrlPattern, dynamicRouteParams } from "../page-params";
45
47
  import { getNodeAtPath, nodeLabel, projectState } from "../store";
@@ -49,6 +51,14 @@ import { notify } from "../services/notify";
49
51
  import { mountSurface, registerSurface } from "../ui/surface";
50
52
  import { rectOf } from "../utils/geometry";
51
53
  import { openMenu } from "./menu";
54
+ import {
55
+ dismissSettingsMenu,
56
+ isSettingsMenuOpen,
57
+ openSettingsMenu,
58
+ SETTINGS_MENU_PLACEMENT,
59
+ } from "../panels/settings-menu";
60
+ import { WORKSPACES } from "../workspace/workspace-ids";
61
+ import type { WorkspaceId } from "../workspace/workspace-ids";
52
62
  import commandbarDoc from "./commandbar.json";
53
63
  import type { PresenceProjection } from "../collab/presence-chips";
54
64
  import type { MenuHandle, MenuRowProjection } from "./menu";
@@ -121,12 +131,22 @@ export interface DockProjection {
121
131
  disabled: boolean;
122
132
  }
123
133
 
124
- /** One layout tab. */
125
- export interface LayoutTabProjection {
126
- id: string;
127
- name: string;
128
- active: boolean;
134
+ /** One workspace tab. */
135
+ export interface WorkspaceTabProjection {
136
+ id: WorkspaceId;
129
137
  title: string;
138
+ icon: string;
139
+ /** The tab's tooltip: its title and chord, plus what its badge counts. */
140
+ tooltip: string;
141
+ /** The count drawn beside the title; empty for none, which hides the badge. */
142
+ badge: string;
143
+ /**
144
+ * What the badge counts, in words, as the tab's `aria-description`; empty for none. The badge is
145
+ * decorative, so this is how the count reaches a screen reader: the tab's NAME stays its title,
146
+ * which is what the label draws.
147
+ */
148
+ description: string;
149
+ hasBadge: boolean;
130
150
  }
131
151
 
132
152
  /** One segment of the address bar. */
@@ -149,8 +169,16 @@ interface CommandBarScope {
149
169
  csd: WindowControlLayout;
150
170
  menuVisible: boolean;
151
171
  menuOpen: boolean;
152
- layoutsVisible: boolean;
153
- layouts: LayoutTabProjection[];
172
+ workspacesVisible: boolean;
173
+ workspaces: WorkspaceTabProjection[];
174
+ /** The selected workspace tab's value: `shell.workspace`. */
175
+ workspace: string;
176
+ /** The quick-publish chevron beside the Publish tab: `publish.quick`, drawn when registered. */
177
+ quickVisible: boolean;
178
+ quickDisabled: boolean;
179
+ quickTooltip: string;
180
+ settingsVisible: boolean;
181
+ settingsOpen: boolean;
154
182
  segments: SegmentProjection[];
155
183
  chord: string;
156
184
  hasChord: boolean;
@@ -161,9 +189,8 @@ interface CommandBarScope {
161
189
  run: (id: string) => void;
162
190
  openSegment: (key: SegmentProjection["key"]) => void;
163
191
  openPicker: () => void;
164
- setLayout: (id: string) => void;
165
- renameLayout: (id: string) => void;
166
- saveLayout: () => void;
192
+ setWorkspace: (id: string) => void;
193
+ openSettings: (anchor: EventTarget | null) => void;
167
194
  openStudioMenu: (opener: HTMLElement) => void;
168
195
  windowControl: (action: keyof WindowControls) => void;
169
196
  }
@@ -193,6 +220,9 @@ const DOCKS = [
193
220
  { dock: "bottom", icon: "rows", id: "view.toggleBottomDock", mirror: false },
194
221
  ] as const;
195
222
 
223
+ /** The record the chevron beside the Publish tab renders. */
224
+ const QUICK_PUBLISH = "publish.quick";
225
+
196
226
  /** The palette mode each segment of the address opens. */
197
227
  const SEGMENT_MODES = { document: "files", project: "projects", selection: "nodes" } as const;
198
228
 
@@ -279,22 +309,6 @@ export function openInBrowserTarget(tab: Tab | null): BrowserTarget {
279
309
  return { path: route === "/" ? "/" : trailingSlash === "always" ? `${route}/` : route };
280
310
  }
281
311
 
282
- /**
283
- * Hand a URL to the user's real browser.
284
- *
285
- * Reuses the seam the desktop launchers already register for Preview link clicks
286
- * (`canvas/preview-navigate.ts`), which routes through the OS rather than navigating a webview with
287
- * no address bar; the browser build falls back to a new tab.
288
- */
289
- function openUrlExternally(url: string) {
290
- const override = getPreviewNavigateHandler();
291
- if (override) {
292
- override(url);
293
- return;
294
- }
295
- window.open(url, "_blank", "noopener,noreferrer");
296
- }
297
-
298
312
  /**
299
313
  * Run `View: Open in Browser`, reporting the blocking reason when there is one.
300
314
  *
@@ -496,11 +510,21 @@ export function documentSegmentLabel(tab: Tab | null): string {
496
510
  return root && trimmed.startsWith(`${root}/`) ? trimmed.slice(root.length + 1) : trimmed;
497
511
  }
498
512
 
499
- /** The selection's label — the Outline's own `nodeLabel`, so the two never disagree. */
513
+ /**
514
+ * The selection's label — the Outline's own `nodeLabel`, so the two never disagree.
515
+ *
516
+ * In the Styles workspace's Elements view the selection is a TAG (`stylebookTarget`), and the
517
+ * segment names it the way the status bar and the Style body do: `project.json › h1`, not the root
518
+ * node of the catalogue's document.
519
+ */
500
520
  export function selectionSegmentLabel(tab: Tab | null): string {
501
521
  if (shell.layoutSelection) {
502
522
  return "layout";
503
523
  }
524
+ const tag = stylebookTarget(tab);
525
+ if (tag) {
526
+ return tag.replaceAll(" ", " › ");
527
+ }
504
528
  const paths = tab?.session.selection ?? [];
505
529
  const selection = primarySelection(paths);
506
530
  if (!tab || !selection) {
@@ -514,30 +538,6 @@ export function selectionSegmentLabel(tab: Tab | null): string {
514
538
  return nodeLabel(getNodeAtPath(tab.doc.document, selection));
515
539
  }
516
540
 
517
- /** Ask for a name, then run the command. Exported for the same reason `runOpenInBrowser` is. */
518
- export async function saveLayoutPrompt(registry: CommandRegistry): Promise<void> {
519
- const name = await showPromptDialog("Save layout", {
520
- confirmLabel: "Save",
521
- message: "Remembers this project's Navigator panel, dock widths and Inspector tab.",
522
- placeholder: "Layout name",
523
- });
524
- if (name) {
525
- await runReported(registry, "view.saveLayout", { name }, "Command Bar");
526
- }
527
- }
528
-
529
- /** The double-click gesture, routed through the command so the rename has one implementation. */
530
- export async function renameLayoutPrompt(
531
- registry: CommandRegistry,
532
- layout: string,
533
- current: string,
534
- ): Promise<void> {
535
- const name = await showPromptDialog("Rename layout", { confirmLabel: "Rename", value: current });
536
- if (name) {
537
- await runReported(registry, "view.renameLayout", { layout, name }, "Command Bar");
538
- }
539
- }
540
-
541
541
  interface WindowControls {
542
542
  minimize: () => void;
543
543
  maximize: () => void;
@@ -549,13 +549,13 @@ function windowControls(): WindowControls | undefined {
549
549
  if (platform == null || !("windowControls" in platform)) {
550
550
  return undefined;
551
551
  }
552
- /* SAFETY: the PAL interface deliberately leaves `windowControls` undeclared; the one adapter that
553
- adds it is the desktop launcher's (`packages/desktop/src/platform.ts`), whose object carries the
554
- `close`, `maximize` and `minimize` functions this bar calls. */
552
+ /* SAFETY: the PAL interface deliberately leaves `windowControls` undeclared; the adapters that add
553
+ it is the desktop launcher's (`chromium/platform.ts` under the Electron shell), whose objects carry the `close`,
554
+ `maximize` and `minimize` functions this bar calls. */
555
555
  return platform.windowControls as WindowControls | undefined;
556
556
  }
557
557
 
558
- // ─── The Command Center pill, the layout tabs and the docks, projected ───────
558
+ // ─── The Command Center pill, the workspace tabs and the docks, projected ────
559
559
 
560
560
  /**
561
561
  * `◈ project › document › selection`: four facts about where you are, in non-collapsible chrome
@@ -584,25 +584,35 @@ function projectSegments(tab: Tab | null): SegmentProjection[] {
584
584
  }
585
585
 
586
586
  /**
587
- * `Write · Design · Build · Ship · +` — named arrangements, as plain-text tabs.
587
+ * `Design · Content · Media · Styles · Publish`: the five workspaces, as a tablist.
588
588
  *
589
- * Each tab RUNS `view.setLayout`, so the click, the palette row and an agent all take the same
590
- * path; double-clicking one renames it, and `+` saves whatever is on screen now. **A layout
591
- * reconfigures; it never removes**: every panel stays on the rail, on its chord and in the palette
592
- * after any layout is applied.
589
+ * Each tab RUNS `view.setWorkspace`, so the click, ⌘1–5, the palette row and a script all take the
590
+ * same path, and the selected tab is `shell.workspace` rather than a second record of it. Publish
591
+ * carries the count of uncommitted changes, which is what the workspace is there to deal with; at
592
+ * zero the badge is not drawn, because "0" is a number a reader has to read to learn nothing.
593
593
  */
594
- function projectLayouts(registry: CommandRegistry | null): LayoutTabProjection[] {
594
+ function projectWorkspaces(registry: CommandRegistry | null): WorkspaceTabProjection[] {
595
595
  // `get` first: a registry that has not been handed the shell's records yet (the skeleton the bar
596
596
  // Paints before the bootstrap composes them) has no verb to ask about.
597
- if (!registry?.get("view.setLayout") || !registry.isEnabled("view.setLayout")) {
597
+ if (!registry?.get("view.setWorkspace") || !registry.isEnabled("view.setWorkspace")) {
598
598
  return [];
599
599
  }
600
- return shell.layouts.map((preset) => ({
601
- active: preset.id === shell.layout,
602
- id: preset.id,
603
- name: preset.name,
604
- title: `${preset.name} layout — double-click to rename`,
605
- }));
600
+ const dirty = shell.git.status?.files.length ?? 0;
601
+ return WORKSPACES.map((entry) => {
602
+ const badge = entry.id === "publish" && dirty > 0 ? String(dirty) : "";
603
+ const chord = registry.keymap.formatBinding(`workspace.focus.${entry.id}`);
604
+ const named = chord ? `${entry.title} (${chord})` : entry.title;
605
+ const description = badge ? `${badge} unpublished ${dirty === 1 ? "change" : "changes"}` : "";
606
+ return {
607
+ badge,
608
+ description,
609
+ hasBadge: badge !== "",
610
+ icon: entry.icon,
611
+ id: entry.id,
612
+ title: entry.title,
613
+ tooltip: description ? `${named}, ${description}` : named,
614
+ };
615
+ });
606
616
  }
607
617
 
608
618
  /** The primary verb cluster: exactly what declared `commandbar/primary`, in the registry's order. */
@@ -734,8 +744,6 @@ function state(): CommandBarScope {
734
744
  csd: "none",
735
745
  docks: [],
736
746
  hasChord: false,
737
- layouts: [],
738
- layoutsVisible: false,
739
747
  menuOpen: false,
740
748
  menuVisible: false,
741
749
  openPicker: () => {
@@ -744,36 +752,46 @@ function state(): CommandBarScope {
744
752
  openSegment: (key) => {
745
753
  openQuickSearch(SEGMENT_MODES[key]);
746
754
  },
755
+ openSettings: (anchor: EventTarget | null) => {
756
+ if (!(anchor instanceof HTMLElement)) {
757
+ return;
758
+ }
759
+ openSettingsMenu(anchor, {
760
+ rerender: () => {
761
+ if (_state) {
762
+ _state.settingsOpen = isSettingsMenuOpen();
763
+ }
764
+ },
765
+ });
766
+ },
747
767
  openStudioMenu,
748
768
  presence: NO_PRESENCE,
749
769
  presenceVisible: false,
750
770
  primary: [],
751
- renameLayout: (id) => {
752
- const registry = activeRegistry();
753
- const preset = shell.layouts.find((layout) => layout.id === id);
754
- if (registry && preset) {
755
- void renameLayoutPrompt(registry, id, preset.name);
756
- }
757
- },
758
771
  run: (id) => {
759
772
  const registry = activeRegistry();
760
773
  if (registry?.isEnabled(id)) {
761
774
  void runReported(registry, id, undefined, "Command Bar");
762
775
  }
763
776
  },
764
- saveLayout: () => {
765
- const registry = activeRegistry();
766
- if (registry) {
767
- void saveLayoutPrompt(registry);
768
- }
769
- },
770
777
  segments: [],
771
- setLayout: (id) => {
772
- void runActiveReported("view.setLayout", { layout: id }, "Command Bar");
778
+ /* Run from each tab's CLICK, not from the strip's `change`: `jx-tabs` dispatches no change for
779
+ the tab already selected, and activating the selected workspace again is how an author gets
780
+ its home back after closing it. Enter and Space click the tab too (manual activation). */
781
+ setWorkspace: (id) => {
782
+ void runActiveReported("view.setWorkspace", { workspace: id }, "Command Bar");
773
783
  },
784
+ settingsOpen: false,
785
+ settingsVisible: false,
774
786
  windowControl: (action) => {
775
787
  windowControls()?.[action]();
776
788
  },
789
+ quickDisabled: true,
790
+ quickTooltip: "",
791
+ quickVisible: false,
792
+ workspace: "",
793
+ workspaces: [],
794
+ workspacesVisible: false,
777
795
  });
778
796
  return _state;
779
797
  }
@@ -789,8 +807,20 @@ function project(): void {
789
807
  const controls = windowControls();
790
808
  scope.csd = controls ? (isMacPlatform() ? "mac" : "other") : "none";
791
809
  scope.menuVisible = registry !== null;
792
- scope.layouts = projectLayouts(registry);
793
- scope.layoutsVisible = scope.layouts.length > 0;
810
+ scope.workspaces = projectWorkspaces(registry);
811
+ scope.workspacesVisible = scope.workspaces.length > 0;
812
+ scope.workspace = shell.workspace;
813
+ /* The chevron is a rendering of `publish.quick`, beside the tablist that ends on Publish
814
+ (studio.md §22.2): drawn only with the tabs and only while the registry shows the record, and
815
+ disabled with its own reason rather than hidden when the project is not a repository. */
816
+ const quick = QUICK_PUBLISH;
817
+ scope.quickVisible =
818
+ scope.workspacesVisible && registry?.get(quick) !== undefined && registry.isVisible(quick);
819
+ scope.quickDisabled = !scope.quickVisible || !registry?.isEnabled(quick);
820
+ scope.quickTooltip = registry && scope.quickVisible ? commandTooltip(registry, quick) : "";
821
+ scope.settingsVisible =
822
+ registry !== null && registry.forPlacement(SETTINGS_MENU_PLACEMENT).length > 0;
823
+ scope.settingsOpen = isSettingsMenuOpen();
794
824
  scope.segments = projectSegments(tab);
795
825
  scope.chord = registry?.keymap.formatBinding("palette.open") ?? "";
796
826
  scope.hasChord = scope.chord !== "";
@@ -817,7 +847,7 @@ export function mount(rootEl: HTMLElement, _ctx: ToolbarCtx = {}): void {
817
847
  unmount();
818
848
  _rootEl = rootEl;
819
849
  if (windowControls()) {
820
- rootEl.classList.add("electrobun-webkit-app-region-drag");
850
+ rootEl.classList.add("app-region-drag");
821
851
  }
822
852
  _scope = effectScope();
823
853
  _scope.run(() => {
@@ -830,10 +860,14 @@ export function mount(rootEl: HTMLElement, _ctx: ToolbarCtx = {}): void {
830
860
  void shell.docks.bottom.collapsed;
831
861
  void shell.git.status;
832
862
  void shell.layoutSelection;
833
- // The layout tabs are a rendering of the project's own record, so the band repaints when a
834
- // Layout is saved, renamed or deleted from anywhere.
835
- void shell.layout;
836
- void shell.layouts;
863
+ // The pill's selection segment names a Styles specimen's tag (`selectionSegmentLabel`).
864
+ void shell.stylebook.selection;
865
+ // The workspace tabs follow the shell, so a switch made by a chord, a script or a tab's
866
+ // Activation repaints the selected tab.
867
+ void shell.workspace;
868
+ // The project opening is what makes the workspace tabs (and the pill's project name) live:
869
+ // `projectState` is not reactive, and the reactive root it is opened beside is.
870
+ void workspace.projectRoot;
837
871
  // The registry itself is reactive state: it is composed AFTER this mount runs, and reading it
838
872
  // Here is what repaints the band from a skeleton into the real bar.
839
873
  void activeRegistry();
@@ -866,6 +900,7 @@ export function mount(rootEl: HTMLElement, _ctx: ToolbarCtx = {}): void {
866
900
 
867
901
  export function unmount(): void {
868
902
  _menu?.close();
903
+ dismissSettingsMenu();
869
904
  _scope?.stop();
870
905
  _scope = null;
871
906
  const pending = _mount;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://jxsuite.com/schema/v1",
3
3
  "$id": "StudioEmptyState",
4
- "$description": "The one empty-state pattern (studio-ui-guidelines.md §11), as the document every region draws it from. Nine surfaces had already copied it into their own JSON — `git-panel.json`, `logic-panel.json`, `panel-outline.json` and the rest each carry a `[part=\"empty\"]` block written from the same rules — because `panels/empty-state.ts` is a lit template a document cannot call. This is the copy those were waiting for: the region that has NO document of its own hands its box to this one instead of rendering the helper, so a shell with three surfaces still lit and eight converted has one empty state rather than two. The copy rules stay where they are stated, in `panels/empty-state.ts`'s header: one sentence saying what the region is FOR, the action that fills it, and one shared verb across equivalent surfaces. Nothing here decides any of them — the adapter is handed a message, an optional second sentence and a list of buttons, and this draws exactly that.",
4
+ "$description": "The one empty-state pattern (studio-ui-guidelines.md §11), as the document every region draws it from. Nine surfaces had already copied it into their own JSON — the Source Control panel's (since folded into `publish-workspace.json`), `logic-panel.json`, `panel-outline.json` and the rest each carry a `[part=\"empty\"]` block written from the same rules — because `panels/empty-state.ts` is a lit template a document cannot call. This is the copy those were waiting for: the region that has NO document of its own hands its box to this one instead of rendering the helper, so a shell with three surfaces still lit and eight converted has one empty state rather than two. The copy rules stay where they are stated, in `panels/empty-state.ts`'s header: one sentence saying what the region is FOR, the action that fills it, and one shared verb across equivalent surfaces. Nothing here decides any of them — the adapter is handed a message, an optional second sentence and a list of buttons, and this draws exactly that.",
5
5
  "tagName": "div",
6
6
  "attributes": {
7
7
  "part": "empty",
@@ -56,6 +56,13 @@
56
56
  "color": "var(--fg-dim)",
57
57
  "fontSize": "var(--jx-text-md)",
58
58
  "lineHeight": "1.5"
59
+ },
60
+ "& [part=\"record-nav\"]": {
61
+ "display": "flex",
62
+ "alignItems": "center",
63
+ "gap": "var(--jx-space-2)",
64
+ "color": "var(--fg-dim)",
65
+ "fontSize": "var(--jx-text-sm)"
59
66
  }
60
67
  },
61
68
  "children": [
@@ -102,6 +109,135 @@
102
109
  },
103
110
  "textContent": "${state.collection}"
104
111
  },
112
+ {
113
+ "tagName": "div",
114
+ "attributes": {
115
+ "part": "record-slot",
116
+ "role": "none"
117
+ },
118
+ "style": {
119
+ "display": "contents"
120
+ },
121
+ "$switch": {
122
+ "$ref": "#/state/recordNav"
123
+ },
124
+ "cases": {
125
+ "shown": {
126
+ "$description": "A record of a file-backed collection (a CSV row): which row of the file this is, the rows either side of it, and the grid that shows them all. A file entry has no neighbours to step to, so it draws none of this.",
127
+ "tagName": "div",
128
+ "attributes": {
129
+ "part": "record-nav",
130
+ "role": "group",
131
+ "aria-label": "Records"
132
+ },
133
+ "children": [
134
+ {
135
+ "tagName": "jx-action-button",
136
+ "attributes": {
137
+ "part": "previous"
138
+ },
139
+ "$props": {
140
+ "size": "sm",
141
+ "quiet": true,
142
+ "label": "Previous record",
143
+ "hint": "Previous record",
144
+ "disabled": {
145
+ "$ref": "#/state/previousDisabled"
146
+ }
147
+ },
148
+ "onclick": {
149
+ "$prototype": "Function",
150
+ "body": [
151
+ {
152
+ "operator": "call",
153
+ "target": {
154
+ "$ref": "#/state/showPrevious"
155
+ },
156
+ "value": []
157
+ }
158
+ ]
159
+ },
160
+ "children": [
161
+ {
162
+ "tagName": "span",
163
+ "textContent": "‹ Previous"
164
+ }
165
+ ]
166
+ },
167
+ {
168
+ "tagName": "span",
169
+ "attributes": {
170
+ "part": "place"
171
+ },
172
+ "textContent": "${state.place}"
173
+ },
174
+ {
175
+ "tagName": "jx-action-button",
176
+ "attributes": {
177
+ "part": "next"
178
+ },
179
+ "$props": {
180
+ "size": "sm",
181
+ "quiet": true,
182
+ "label": "Next record",
183
+ "hint": "Next record",
184
+ "disabled": {
185
+ "$ref": "#/state/nextDisabled"
186
+ }
187
+ },
188
+ "onclick": {
189
+ "$prototype": "Function",
190
+ "body": [
191
+ {
192
+ "operator": "call",
193
+ "target": {
194
+ "$ref": "#/state/showNext"
195
+ },
196
+ "value": []
197
+ }
198
+ ]
199
+ },
200
+ "children": [
201
+ {
202
+ "tagName": "span",
203
+ "textContent": "Next ›"
204
+ }
205
+ ]
206
+ },
207
+ {
208
+ "tagName": "jx-action-button",
209
+ "attributes": {
210
+ "part": "grid"
211
+ },
212
+ "$props": {
213
+ "size": "sm",
214
+ "quiet": true,
215
+ "label": "Edit in grid",
216
+ "hint": "Every record of the file, as a table"
217
+ },
218
+ "onclick": {
219
+ "$prototype": "Function",
220
+ "body": [
221
+ {
222
+ "operator": "call",
223
+ "target": {
224
+ "$ref": "#/state/openGrid"
225
+ },
226
+ "value": []
227
+ }
228
+ ]
229
+ },
230
+ "children": [
231
+ {
232
+ "tagName": "span",
233
+ "textContent": "Edit in grid"
234
+ }
235
+ ]
236
+ }
237
+ ]
238
+ }
239
+ }
240
+ },
105
241
  {
106
242
  "tagName": "div",
107
243
  "attributes": {
@@ -64,6 +64,12 @@ export interface EntryEditorView {
64
64
  note: string;
65
65
  /** The `empty` stage's first sentence, naming the document it is about. */
66
66
  emptyLine: string;
67
+ /** Whether the entry is a record of a file (a CSV row), which draws its place and its neighbours. */
68
+ recordNav: "hidden" | "shown";
69
+ /** Its place among the file's records: "3 of 11". */
70
+ place: string;
71
+ previousDisabled: boolean;
72
+ nextDisabled: boolean;
67
73
  }
68
74
 
69
75
  /** What the reader can do here. Both are decisions the editor owns. */
@@ -72,6 +78,10 @@ export interface EntryEditorActions {
72
78
  setDraft: (draft: boolean) => void;
73
79
  /** Open Project Settings › Content types — the door out of the `empty` stage. */
74
80
  openContentTypes: () => void;
81
+ /** A record: show the file's previous record, its next one, or the whole file in its grid. */
82
+ showPrevious: () => void;
83
+ showNext: () => void;
84
+ openGrid: () => void;
75
85
  }
76
86
 
77
87
  /** The node the document renders empty for somebody else to fill. */
@@ -105,6 +115,10 @@ function project(scope: EntryEditorScope, view: EntryEditorView): void {
105
115
  scope.noteState = view.noteState;
106
116
  scope.note = view.note;
107
117
  scope.emptyLine = view.emptyLine;
118
+ scope.recordNav = view.recordNav;
119
+ scope.place = view.place;
120
+ scope.previousDisabled = view.previousDisabled;
121
+ scope.nextDisabled = view.nextDisabled;
108
122
  }
109
123
 
110
124
  /** The `part` a node was authored with, or `""` — the only thing this adapter asks about a node. */
@@ -141,11 +155,18 @@ export function mountEntryEditorSurface(
141
155
  emptyLine: "",
142
156
  fieldsRegion: "",
143
157
  name: "",
158
+ nextDisabled: true,
144
159
  note: "",
145
160
  noteState: "hidden",
146
161
  openContentTypes: actions.openContentTypes,
162
+ openGrid: actions.openGrid,
163
+ place: "",
164
+ previousDisabled: true,
165
+ recordNav: "hidden",
147
166
  region: "",
148
167
  setDraft: actions.setDraft,
168
+ showNext: actions.showNext,
169
+ showPrevious: actions.showPrevious,
149
170
  stage: "empty",
150
171
  });
151
172
  project(scope, view);