@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
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Which workspace a tab belongs to, and which of a pane's tabs its strip draws.
3
+ *
4
+ * Every tab belongs to exactly one workspace, and the answer is DERIVED from the tab rather than
5
+ * stored on it: what a tab is (a home, a media file, a comparison) and how it is being edited (the
6
+ * configuration document's stylebook editor) are already on the tab, so a stored field would be a
7
+ * second record of the same fact, free to disagree with it.
8
+ *
9
+ * - **Content**: the Content home and the collection and page grids; an entry's form editor; and any
10
+ * file a content collection owns (collection-match.ts is the one matcher), because an entry is
11
+ * written in Content even when it is opened from somewhere else.
12
+ * - **Media**: the media home and every media file's viewer.
13
+ * - **Styles**: `project.json`, in any of its three views: Elements (`stylebook`), Variables
14
+ * (`tokens`) and Code (`source`). Project Settings is a dialog over every workspace (§17.1), not
15
+ * a tab, so it belongs to none.
16
+ * - **Publish**: the publish home and every comparison (`git-diff`).
17
+ * - **Design**: everything else: pages, templates, components and every other file.
18
+ *
19
+ * The rules read the tab's CURRENT editor, so switching an entry from its form to the canvas keeps
20
+ * it in Content while a grid's kind decides between Content and Design, and
21
+ * `workspace/workspace-switch.ts` follows the tab wherever that puts it.
22
+ *
23
+ * @docs studio/interface
24
+ */
25
+
26
+ import { shell } from "../shell";
27
+ import { workspace } from "./workspace";
28
+ import { homeWorkspaceOfTabId } from "./workspace-ids";
29
+ import { parseGridTabId } from "../grid/grid-source";
30
+ import { collectionForFile } from "../content/collection-match";
31
+ import { PROJECT_CONFIG_PATH } from "../tabs/tab";
32
+ import type { Pane } from "./workspace";
33
+ import type { WorkspaceId } from "./workspace-ids";
34
+ import type { Tab } from "../tabs/tab";
35
+
36
+ /** The editors that are Content's whatever document they are over. */
37
+ const CONTENT_MODES: ReadonlySet<string> = new Set(["entry"]);
38
+
39
+ /** The workspace `tab` belongs to. Pure over the tab and the open project's configuration. */
40
+ export function workspaceOfTab(tab: Tab): WorkspaceId {
41
+ const home = homeWorkspaceOfTabId(tab.id);
42
+ if (home) {
43
+ return home;
44
+ }
45
+ const mode = tab.session.ui.canvasMode;
46
+ if (mode === "git-diff") {
47
+ return "publish";
48
+ }
49
+ if (mode === "media") {
50
+ return "media";
51
+ }
52
+ if (CONTENT_MODES.has(mode)) {
53
+ return "content";
54
+ }
55
+ const grid = parseGridTabId(tab.id);
56
+ if (grid) {
57
+ // A data-table grid is the Data panel's, which is Design's; every other grid is content.
58
+ return grid.kind === "data" ? "design" : "content";
59
+ }
60
+ if (tab.documentPath === PROJECT_CONFIG_PATH) {
61
+ return "styles";
62
+ }
63
+ /* A file-backed collection's file too: its grid is where its records are written, and the
64
+ Content home opens it for any of them, so it must not carry the author off to Design. */
65
+ return collectionForFile(tab.documentPath) ? "content" : "design";
66
+ }
67
+
68
+ /**
69
+ * The editors in which a document is written on the canvas, where the Inspector applies: a page's
70
+ * canvas, and the Elements view (`stylebook`), whose canvas selects the element default the
71
+ * Inspector's Style tab edits.
72
+ */
73
+ const CANVAS_WRITING_MODES: ReadonlySet<string> = new Set(["edit", "design", "stylebook"]);
74
+
75
+ /**
76
+ * Whether a tab is a document being written on the canvas: a file-backed tab in an editing canvas
77
+ * mode. A grid, an entry's form, a home, the Variables view and a code view are not. Content's and
78
+ * Styles' presets read it to draw the Inspector while the canvas is being written (`shell.ts`'s
79
+ * `WORKSPACE_PRESETS`).
80
+ */
81
+ export function writesOnCanvas(tab: Tab): boolean {
82
+ return (
83
+ tab.documentPath !== null &&
84
+ parseGridTabId(tab.id) === null &&
85
+ CANVAS_WRITING_MODES.has(tab.session.ui.canvasMode)
86
+ );
87
+ }
88
+
89
+ /** Whether a tab id names an open tab of the workspace on screen. */
90
+ export function isTabInWorkspace(tabId: string, id: WorkspaceId = shell.workspace): boolean {
91
+ const tab = workspace.tabs.get(tabId);
92
+ return tab !== undefined && workspaceOfTab(tab) === id;
93
+ }
94
+
95
+ /**
96
+ * The tabs a pane's strip draws: its own, in strip order, less every tab of another workspace.
97
+ *
98
+ * The order is the pane's, so a drop index computed against {@link Pane.tabOrder} still lands
99
+ * between the two chips it was dropped between: the hidden tabs keep their slots, they are only not
100
+ * drawn.
101
+ */
102
+ export function workspaceTabOrder(pane: Pane, id: WorkspaceId = shell.workspace): string[] {
103
+ return pane.tabOrder.filter((tabId) => isTabInWorkspace(tabId, id));
104
+ }
105
+
106
+ /**
107
+ * The tab a workspace was last in: the most recently used of its open tabs, in any pane, or the
108
+ * first of them in strip order when none has been used yet (a restored session's tabs are opened
109
+ * without being focused). `null` when the workspace has no tab open.
110
+ */
111
+ export function lastTabOfWorkspace(id: WorkspaceId): string | null {
112
+ const recent = workspace.mruOrder.find((tabId) => isTabInWorkspace(tabId, id));
113
+ if (recent) {
114
+ return recent;
115
+ }
116
+ for (const pane of workspace.panes) {
117
+ const first = pane.tabOrder.find((tabId) => isTabInWorkspace(tabId, id));
118
+ if (first) {
119
+ return first;
120
+ }
121
+ }
122
+ return null;
123
+ }
124
+
125
+ /** The tab `pane` should show for a workspace: its most recent one there, or `null`. */
126
+ export function paneTabOfWorkspace(pane: Pane, id: WorkspaceId): string | null {
127
+ if (pane.activeTabId && isTabInWorkspace(pane.activeTabId, id)) {
128
+ return pane.activeTabId;
129
+ }
130
+ return (
131
+ workspace.mruOrder.find(
132
+ (tabId) => pane.tabOrder.includes(tabId) && isTabInWorkspace(tabId, id),
133
+ ) ??
134
+ pane.tabOrder.find((tabId) => isTabInWorkspace(tabId, id)) ??
135
+ null
136
+ );
137
+ }
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Back to the workspace home — the way out of a view in a workspace that draws no tab strip.
3
+ *
4
+ * Media, Styles and Publish draw their home surface without a strip (`shell.ts`'s
5
+ * `WorkspacePreset.tabStrip`, `specs/studio.md` §22.3). What they open beside their home has to be
6
+ * leave-able anyway, and without a strip there is no chip to click and no × to press:
7
+ *
8
+ * - **Media**: a media file opened in its viewer leads back to the media library.
9
+ * - **Publish**: a comparison (`git-diff`) leads back to the Publish home.
10
+ * - **Styles**: `project.json` in its Code view leads back to the view the Styles home was left in,
11
+ * Variables or Elements. Code is a view of the same tab, so going back switches the view and
12
+ * closes nothing.
13
+ *
14
+ * {@link backTargetOf} is the one rule, read by the pane context bar (which draws the Back control,
15
+ * naming the destination) and by `pane.backToHome` (the control's command, and Escape's). A media
16
+ * viewer or a comparison is CLOSED on the way back, so the home is what is left: a strip-less pane
17
+ * holds its home and one view beside it rather than a pile of views nobody can see, and the close
18
+ * lands on the home (`workspace/workspace-switch.ts`'s close landing). Closing such a view any
19
+ * other way (⌘W) lands there too.
20
+ *
21
+ * @docs studio/interface/tabs
22
+ */
23
+
24
+ import { shell, workspaceDrawsTabStrip } from "../shell";
25
+ import { PROJECT_CONFIG_PATH } from "../tabs/tab";
26
+ import { tabOfPane } from "../canvas/canvas-surface";
27
+ import { workspace } from "./workspace";
28
+ import { workspaceOfTab } from "./tab-workspace";
29
+ import { homeWorkspaceOfTabId, isHomeWorkspace, workspaceInfo } from "./workspace-ids";
30
+ import { argsSchema, optionalStringArg, stringProperty } from "../commands/command-args";
31
+ import { EDITOR_KIND_LABELS, editorKindForMode } from "../commands/context";
32
+ import { isPopoverOpen } from "../ui/layers";
33
+ import type { WorkspaceId } from "./workspace-ids";
34
+ import type { Tab } from "../tabs/tab";
35
+ import type { AnyCommand } from "../commands/registry";
36
+
37
+ /** Where the Back control leads, and how it gets there. */
38
+ export type BackTarget =
39
+ | {
40
+ /** Close the view: the home beside it is what the pane shows next. */
41
+ kind: "close";
42
+ /** The control's text, naming the destination: "Back to Media". */
43
+ label: string;
44
+ /** Its tooltip: what happens to the view. */
45
+ hint: string;
46
+ }
47
+ | {
48
+ /** Switch the tab to another of its views (Styles' Code view back to the home view). */
49
+ kind: "view";
50
+ label: string;
51
+ hint: string;
52
+ /** The canvas mode to switch to: `tokens` or `stylebook`. */
53
+ mode: string;
54
+ };
55
+
56
+ /** The Code view's mode over `project.json`. */
57
+ const SOURCE_MODE = "source";
58
+
59
+ /**
60
+ * Where a tab's Back control leads in workspace `id`, or `null` when there is nowhere to go back
61
+ * to: a workspace that draws a strip (its strip is the way between documents), a tab of another
62
+ * workspace, and a workspace's home itself.
63
+ *
64
+ * @param tab The tab a pane is showing
65
+ * @param id The workspace on screen
66
+ */
67
+ export function backTargetOf(
68
+ tab: Tab | null,
69
+ id: WorkspaceId = shell.workspace,
70
+ ): BackTarget | null {
71
+ if (!tab || workspaceDrawsTabStrip(id) || workspaceOfTab(tab) !== id) {
72
+ return null;
73
+ }
74
+ if (id === "styles") {
75
+ if (tab.documentPath !== PROJECT_CONFIG_PATH || tab.session.ui.canvasMode !== SOURCE_MODE) {
76
+ return null;
77
+ }
78
+ const mode = shell.stylebook.view;
79
+ const name = EDITOR_KIND_LABELS[editorKindForMode(mode)];
80
+ return {
81
+ hint: `Leave the Code view for the ${name} view of your styles`,
82
+ kind: "view",
83
+ label: `Back to ${name}`,
84
+ mode,
85
+ };
86
+ }
87
+ if (!isHomeWorkspace(id) || homeWorkspaceOfTabId(tab.id) === id) {
88
+ return null;
89
+ }
90
+ const home = workspaceInfo(id).title;
91
+ return {
92
+ hint: `Close this view and return to ${home}`,
93
+ kind: "close",
94
+ label: `Back to ${home}`,
95
+ };
96
+ }
97
+
98
+ /** {@link backTargetOf} for the tab a pane is showing. */
99
+ export function backTargetOfPane(paneId: string): BackTarget | null {
100
+ return backTargetOf(tabOfPane(paneId));
101
+ }
102
+
103
+ /** What going back needs that this module may not import. */
104
+ export interface WorkspaceBackDeps {
105
+ /** Close a tab through the strip's guarded close (`panels/tab-strip.ts` `requestClose`). */
106
+ closeTab: (tabId: string) => void | Promise<void>;
107
+ /** Switch a tab's editor (`studio.ts` `setCanvasMode`). */
108
+ setCanvasMode: (tab: Tab, mode: string) => void;
109
+ /**
110
+ * Give the keyboard to the home a close landed on: the Media home's tile, the Publish change the
111
+ * comparison was opened from. Without it the focus falls to the page body with the view.
112
+ */
113
+ focusHome?: (paneId: string, id: WorkspaceId) => void;
114
+ }
115
+
116
+ /**
117
+ * Go back from what `paneId` shows to its workspace's home. `false` when there is nowhere to go.
118
+ *
119
+ * @param paneId The pane whose Back control was pressed
120
+ * @param deps The close and the view switch
121
+ */
122
+ export async function goBack(paneId: string, deps: WorkspaceBackDeps): Promise<boolean> {
123
+ const tab = tabOfPane(paneId);
124
+ const target = backTargetOf(tab);
125
+ if (!tab || !target) {
126
+ return false;
127
+ }
128
+ if (target.kind === "view") {
129
+ tab.session.ui.preview = false;
130
+ deps.setCanvasMode(tab, target.mode);
131
+ return true;
132
+ }
133
+ const id = shell.workspace;
134
+ await deps.closeTab(tab.id);
135
+ // Only when the close went through: a refused close (unsaved work kept) leaves the view standing.
136
+ if (!workspace.tabs.has(tab.id)) {
137
+ deps.focusHome?.(paneId, id);
138
+ }
139
+ return true;
140
+ }
141
+
142
+ /**
143
+ * `pane.backToHome`: the Back control's command, and Escape's.
144
+ *
145
+ * Gated with `when`, not `enablement`, because Escape is the chord: a disabled record still claims
146
+ * its chord, and every other Escape in the global scope would be swallowed by a Back that is not
147
+ * there. Three places keep their own Escape: a text field (the caret is a field's, and Escape there
148
+ * is the field's own); the Code view, where Escape belongs to the code editor's widgets, so the
149
+ * Back control is how Code is left; and an open popover (the pane context bar's Context menu, for
150
+ * one), which the platform closes on Escape, and which a cancelled Escape would leave standing over
151
+ * a view that had gone.
152
+ *
153
+ * @param deps The close and the view switch
154
+ */
155
+ export function workspaceBackCommands(deps: WorkspaceBackDeps): AnyCommand[] {
156
+ return [
157
+ {
158
+ args: argsSchema(
159
+ {
160
+ pane: stringProperty("Which pane to go back in. Defaults to the focused one."),
161
+ },
162
+ [],
163
+ ),
164
+ id: "pane.backToHome",
165
+ title: "Back to Workspace Home",
166
+ category: "View",
167
+ level: "document",
168
+ keybinding: "escape",
169
+ menus: ["palette"],
170
+ group: "5_pane",
171
+ when: (ctx) =>
172
+ !ctx.caret.active &&
173
+ ctx.editor.kind !== "code" &&
174
+ !isPopoverOpen() &&
175
+ backTargetOfPane(workspace.activePaneId) !== null,
176
+ requires: "a view opened beside a workspace home",
177
+ undo: "none",
178
+ run: async (_ctx, args) => {
179
+ const paneId = optionalStringArg("pane.backToHome", args, "pane") ?? workspace.activePaneId;
180
+ if (!(await goBack(paneId, deps))) {
181
+ throw new RangeError(
182
+ `command "pane.backToHome": pane "${paneId}" shows no view opened beside a ` +
183
+ "workspace home, so there is nothing to go back from",
184
+ );
185
+ }
186
+ },
187
+ },
188
+ ];
189
+ }
@@ -0,0 +1,133 @@
1
+ /// <reference lib="dom" />
2
+ /**
3
+ * Workspace homes — the virtual tab a workspace opens on when none of its own tabs is open.
4
+ *
5
+ * A home is a tab like a grid is a tab: it sits in a pane's strip, it can be closed, and it has a
6
+ * canvas mode of its own (`content-home`, `media-home`, `publish-home`) that
7
+ * `canvas/canvas-render.ts` routes here. It has no document — the tab carries a stub, exactly as
8
+ * the grid tabs do — and its id is in the `workspace://` space `workspace/workspace-ids.ts`
9
+ * declares, so it can never collide with a file.
10
+ *
11
+ * What a home DRAWS is its workspace's own surface: the Content home is the collection it shows
12
+ * (`browse/library-pane.ts`, studio.md §22.5), the Media home is the media library
13
+ * (`media/media-library.ts`, §22.6) and the Publish home is the Publish workspace
14
+ * (`publish/publish-workspace.ts`, §22.8). The mechanism (the tab, the mode, the routing and the
15
+ * per-pane mount) is the same for all three, and this module only routes.
16
+ *
17
+ * @docs studio/interface
18
+ */
19
+
20
+ import { activateTab, openTab, workspace } from "./workspace";
21
+ import { WORKSPACE_HOME_MODES, homeWorkspaceOfTabId, workspaceHomeTabId } from "./workspace-ids";
22
+ import {
23
+ detachMediaLibrary,
24
+ mediaLibraryMounted,
25
+ renderMediaLibrary,
26
+ } from "../media/media-library";
27
+ import { detachLibraryPane, libraryPaneMounted, renderLibraryMode } from "../browse/library-pane";
28
+ import {
29
+ detachPublishWorkspace,
30
+ publishWorkspaceMounted,
31
+ renderPublishWorkspace,
32
+ } from "../publish/publish-workspace";
33
+ import type { HomeWorkspaceId } from "./workspace-ids";
34
+ import type { Tab } from "../tabs/tab";
35
+ import type { CanvasSurface } from "../canvas/canvas-surface";
36
+
37
+ /** The stub a home tab carries: it is never read, and nothing is ever saved from it. */
38
+ const HOME_STUB_DOCUMENT = { children: [], tagName: "div" };
39
+
40
+ /** The canvas modes a home draws under. */
41
+ export const WORKSPACE_HOME_MODE_SET: ReadonlySet<string> = new Set(
42
+ Object.values(WORKSPACE_HOME_MODES),
43
+ );
44
+
45
+ /** Whether a canvas mode is a workspace home's. */
46
+ export function isWorkspaceHomeMode(mode: string): boolean {
47
+ return WORKSPACE_HOME_MODE_SET.has(mode);
48
+ }
49
+
50
+ /**
51
+ * Open (or activate) a workspace's home.
52
+ *
53
+ * Idempotent by construction, which is what lets `view.setWorkspace` say "show me Media" without
54
+ * caring whether an earlier switch opened its home already.
55
+ */
56
+ export function openWorkspaceHome(id: HomeWorkspaceId): Tab {
57
+ const tabId = workspaceHomeTabId(id);
58
+ const existing = workspace.tabs.get(tabId);
59
+ if (existing) {
60
+ activateTab(tabId);
61
+ return existing;
62
+ }
63
+ return openTab({
64
+ capabilities: { modes: [WORKSPACE_HOME_MODES[id]] },
65
+ document: structuredClone(HOME_STUB_DOCUMENT),
66
+ documentPath: null,
67
+ id: tabId,
68
+ });
69
+ }
70
+
71
+ /**
72
+ * Put a workspace's home in `paneId`'s strip without showing it, unless it is open already.
73
+ *
74
+ * A workspace with no Navigator (Media, Publish) has no other way back to its home than its tab: a
75
+ * media file opened from the Site panel lands in Media on its viewer, and with the home absent the
76
+ * strip offered that viewer alone and closing it left an empty stage. Keeping the home beside it is
77
+ * what makes the grid one click away, and what closing the viewer falls back to.
78
+ */
79
+ export function placeWorkspaceHome(id: HomeWorkspaceId, paneId: string): void {
80
+ openTab({
81
+ background: true,
82
+ capabilities: { modes: [WORKSPACE_HOME_MODES[id]] },
83
+ document: structuredClone(HOME_STUB_DOCUMENT),
84
+ documentPath: null,
85
+ id: workspaceHomeTabId(id),
86
+ paneId,
87
+ });
88
+ }
89
+
90
+ // ─── Mounting ────────────────────────────────────────────────────────────────
91
+
92
+ /** Whether this tab's home is already mounted in this pane and still in the document. */
93
+ export function workspaceHomeMounted(paneId: string, tab: Tab): boolean {
94
+ const id = homeWorkspaceOfTabId(tab.id);
95
+ if (id === "media") {
96
+ return mediaLibraryMounted(paneId, tab);
97
+ }
98
+ if (id === "content") {
99
+ return libraryPaneMounted(paneId, tab);
100
+ }
101
+ return publishWorkspaceMounted(paneId, tab);
102
+ }
103
+
104
+ /** Tear one pane's home down (mode change, tab switch, project close). Idempotent. */
105
+ export function detachWorkspaceHome(paneId: string): void {
106
+ detachMediaLibrary(paneId);
107
+ detachLibraryPane(paneId);
108
+ detachPublishWorkspace(paneId);
109
+ }
110
+
111
+ /**
112
+ * Draw a home tab into its pane's stage.
113
+ *
114
+ * @param {CanvasSurface} surface
115
+ * @param {Tab} tab
116
+ */
117
+ export function renderWorkspaceHome(surface: CanvasSurface, tab: Tab): void {
118
+ const { paneId } = surface;
119
+ if (workspaceHomeMounted(paneId, tab)) {
120
+ return;
121
+ }
122
+ detachWorkspaceHome(paneId);
123
+ const id = homeWorkspaceOfTabId(tab.id);
124
+ if (id === "media") {
125
+ renderMediaLibrary(surface, tab);
126
+ return;
127
+ }
128
+ if (id === "content") {
129
+ renderLibraryMode(surface, tab);
130
+ return;
131
+ }
132
+ renderPublishWorkspace(surface, tab);
133
+ }
@@ -0,0 +1,129 @@
1
+ /**
2
+ * The five workspaces, declared where a bare Bun process can read them.
3
+ *
4
+ * A workspace is the answer to "what am I doing right now": designing pages, writing content,
5
+ * managing media, editing the project's styles, or publishing. Studio's top bar switches between
6
+ * them, and every open tab belongs to exactly one (`workspace/tab-workspace.ts` derives which).
7
+ *
8
+ * The ids live in a module with no DOM and no state for the reason `NAVIGATOR_PANEL_IDS` does:
9
+ * `view.setWorkspace`'s `args` enum is built from {@link WORKSPACE_IDS}, and
10
+ * `commands/app-commands.ts` must load that enum in the bare Bun process the CI checks run in. A
11
+ * manifest step naming a workspace this list does not declare is then a red check in the PR that
12
+ * renamed it, rather than a screenshot of the wrong screen.
13
+ *
14
+ * The workspace HOME tab ids are declared here too. A home is a virtual tab (a document the pane
15
+ * draws that no file backs), and both the derivation that says which workspace a tab belongs to and
16
+ * the module that opens one must agree on its id, so the id has one definition site that imports
17
+ * nothing.
18
+ *
19
+ * @docs studio/interface
20
+ */
21
+
22
+ /** The workspaces, in top-bar order. ⌘1 to ⌘5 follow this order. */
23
+ export const WORKSPACE_IDS = ["design", "content", "media", "styles", "publish"] as const;
24
+
25
+ export type WorkspaceId = (typeof WORKSPACE_IDS)[number];
26
+
27
+ /** The workspace a project wakes up in when nothing usable is stored. */
28
+ export const DEFAULT_WORKSPACE: WorkspaceId = "design";
29
+
30
+ /** One workspace, as the top bar and the palette name it. */
31
+ export interface WorkspaceInfo {
32
+ id: WorkspaceId;
33
+ /** What the top-bar tab reads, and what the palette row says after "Show". */
34
+ title: string;
35
+ /** A key into the kit's glyph manifest (`@jxsuite/ui/icons`), checked by this module's test. */
36
+ icon: string;
37
+ }
38
+
39
+ /** Every workspace, in {@link WORKSPACE_IDS} order. */
40
+ export const WORKSPACES: readonly WorkspaceInfo[] = [
41
+ {
42
+ icon: "frame-corners",
43
+ id: "design",
44
+ title: "Design",
45
+ },
46
+ {
47
+ icon: "file-text",
48
+ id: "content",
49
+ title: "Content",
50
+ },
51
+ {
52
+ icon: "image",
53
+ id: "media",
54
+ title: "Media",
55
+ },
56
+ {
57
+ icon: "paint-brush",
58
+ id: "styles",
59
+ title: "Styles",
60
+ },
61
+ {
62
+ icon: "paper-plane-tilt",
63
+ id: "publish",
64
+ title: "Publish",
65
+ },
66
+ ];
67
+
68
+ /** Whether a value is a declared workspace id. A stored value is untrusted input. */
69
+ export function isWorkspaceId(value: unknown): value is WorkspaceId {
70
+ return typeof value === "string" && WORKSPACE_IDS.some((id) => id === value);
71
+ }
72
+
73
+ /** The record for a workspace id. Total over {@link WorkspaceId}. */
74
+ export function workspaceInfo(id: WorkspaceId): WorkspaceInfo {
75
+ /* SAFETY of the `!`: WORKSPACES holds one entry per WORKSPACE_IDS member, which this module's
76
+ test asserts in both directions. */
77
+ return WORKSPACES.find((entry) => entry.id === id)!;
78
+ }
79
+
80
+ // ─── Workspace homes ─────────────────────────────────────────────────────────
81
+
82
+ /**
83
+ * The scheme a workspace home's tab id carries. Not a path, so it can never collide with a file,
84
+ * and not `grid://`, which is the grid's id space.
85
+ */
86
+ const HOME_SCHEME = "workspace://";
87
+
88
+ /**
89
+ * The workspaces whose home is a virtual tab of the generic home mechanism, and the canvas mode
90
+ * that tab draws under.
91
+ *
92
+ * Design has no home (an empty stage is its home), and Styles' is `project.json` in its stylebook
93
+ * editor, opened by the module that owns that document. These three are the generic mechanism's:
94
+ * Content's home is the collection it shows (`browse/library-pane.ts`), Media's the media library,
95
+ * and Publish's its own surface.
96
+ */
97
+ export const WORKSPACE_HOME_MODES = {
98
+ content: "content-home",
99
+ media: "media-home",
100
+ publish: "publish-home",
101
+ } as const satisfies Partial<Record<WorkspaceId, string>>;
102
+
103
+ /** A workspace whose home is a generic home tab. */
104
+ export type HomeWorkspaceId = keyof typeof WORKSPACE_HOME_MODES;
105
+
106
+ /** Whether a workspace's home is a generic home tab. */
107
+ export function isHomeWorkspace(id: WorkspaceId): id is HomeWorkspaceId {
108
+ return Object.hasOwn(WORKSPACE_HOME_MODES, id);
109
+ }
110
+
111
+ /** The tab id of a workspace's home. */
112
+ export function workspaceHomeTabId(id: HomeWorkspaceId): string {
113
+ return `${HOME_SCHEME}${id}`;
114
+ }
115
+
116
+ /** The workspace a home tab id names, or `null` for any other id. */
117
+ export function homeWorkspaceOfTabId(tabId: string): HomeWorkspaceId | null {
118
+ if (!tabId.startsWith(HOME_SCHEME)) {
119
+ return null;
120
+ }
121
+ const rest = tabId.slice(HOME_SCHEME.length);
122
+ return isWorkspaceId(rest) && isHomeWorkspace(rest) ? rest : null;
123
+ }
124
+
125
+ /** The label a home tab's chip reads: the workspace's own title. `null` for any other id. */
126
+ export function workspaceHomeLabel(tabId: string): string | null {
127
+ const id = homeWorkspaceOfTabId(tabId);
128
+ return id ? workspaceInfo(id).title : null;
129
+ }