@jxsuite/studio 6.1.2 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
@@ -13,7 +13,7 @@ import { projectState } from "./store";
13
13
  import { getPlatform } from "./platform";
14
14
  import { commitProjectConfig } from "./tabs/project-config";
15
15
 
16
- import { resolveI18n } from "@jxsuite/schema/locale";
16
+ import { canonicalizeLocale, localeOfPath, resolveI18n } from "@jxsuite/schema/locale";
17
17
  import type { ResolvedI18n } from "@jxsuite/schema/locale";
18
18
  import type {
19
19
  JxElement,
@@ -22,6 +22,7 @@ import type {
22
22
  JxStyle,
23
23
  ProjectConfig,
24
24
  } from "@jxsuite/schema/types";
25
+ import type { ExtensionsInfo } from "./types";
25
26
 
26
27
  /**
27
28
  * Merge site $media with document $media. Document keys win on conflict.
@@ -71,15 +72,35 @@ export function getEffectiveStyle(docStyle?: JxStyle) {
71
72
  * undefined)
72
73
  * @returns {Record<string, string>}
73
74
  */
74
- export function getEffectiveImports(docImports?: Record<string, string>) {
75
- const siteImports = projectState?.projectConfig?.imports;
76
- if (!siteImports) {
77
- return docImports || {};
78
- }
79
- if (!docImports) {
80
- return { ...siteImports };
81
- }
82
- return { ...siteImports, ...docImports };
75
+ export function getEffectiveImports(
76
+ docImports?: Record<string, string>,
77
+ extensions: readonly ExtensionsInfo[] = [],
78
+ ) {
79
+ /* The enabled extensions' manifest classes come last in the order the build resolves a bare
80
+ `$prototype` in (spec.md §12.5: the document's `imports`, then the project's, then the
81
+ extension registry), so they are the base the other two are spread over. Without them a
82
+ layout's `{ "$prototype": "ContentEntry" }` named a class the build knows and the canvas did
83
+ not, and the canvas warned of an unknown prototype and drew the layout with no data. The
84
+ first extension to declare a name keeps it, as the registry's `byName` answers. */
85
+ return {
86
+ ...extensionClassPaths(extensions),
87
+ ...projectState?.projectConfig?.imports,
88
+ ...docImports,
89
+ };
90
+ }
91
+
92
+ /**
93
+ * The enabled extensions' manifest classes, by name, as descriptor paths: the last step of the
94
+ * build's bare-`$prototype` resolution (spec.md §12.5). The first extension to declare a name keeps
95
+ * it, as the registry's `byName` answers.
96
+ */
97
+ export function extensionClassPaths(extensions: readonly ExtensionsInfo[]) {
98
+ const classes = extensions.flatMap((extension) =>
99
+ (extension.classes ?? [])
100
+ .filter((cls) => cls.path.endsWith(".class.json"))
101
+ .map((cls): [string, string] => [cls.name, cls.path]),
102
+ );
103
+ return Object.fromEntries(classes.toReversed());
83
104
  }
84
105
 
85
106
  /**
@@ -159,6 +180,39 @@ export function getEffectiveLocales(): ResolvedI18n | null {
159
180
  return config ? resolveI18n(config).i18n : null;
160
181
  }
161
182
 
183
+ /**
184
+ * The language a pane renders in (studio.md §20.2), the one answer the context bar's Language
185
+ * segment, every artboard's `render` and the live push all read.
186
+ *
187
+ * The author's choice while the project declares it, else the document's own: the locale its path
188
+ * sits under (`site-architecture.md` §13.3 puts a translation in its own directory, so
189
+ * `pages/ar/about.json` and `content/exhibitions/ar/x.md` are Arabic), else the default locale,
190
+ * which is what an unprefixed page renders as. Null for a project that declares no locales.
191
+ *
192
+ * A stored choice the project no longer declares answers as if none were made, the counterpart of
193
+ * `i18n.switchLocale` refusing one on the way in; the stored value is left alone, so a locale that
194
+ * is declared again comes back. Answering with the document's own language when nothing is chosen
195
+ * is what makes an Arabic translation mirror as soon as it is opened: before, the artboard drew it
196
+ * left to right until the author picked Arabic from a control already showing Arabic.
197
+ *
198
+ * @param previewLocale - The pane's choice (`session.ui.previewLocale`), or null.
199
+ * @param documentPath - The project-relative path of the document being drawn.
200
+ */
201
+ export function getEffectiveRenderLocale(
202
+ previewLocale: string | null | undefined,
203
+ documentPath: string | null | undefined,
204
+ ): string | null {
205
+ const i18n = getEffectiveLocales();
206
+ if (i18n === null) {
207
+ return null;
208
+ }
209
+ const chosen = canonicalizeLocale(previewLocale);
210
+ if (chosen !== null && i18n.locales.includes(chosen)) {
211
+ return chosen;
212
+ }
213
+ return localeOfPath(documentPath ?? "", i18n) ?? i18n.defaultLocale;
214
+ }
215
+
162
216
  // ─── Layout resolution ──────────────────────────────────────────────────────
163
217
 
164
218
  const layoutCache = new Map<string, JxMutableNode>();
package/src/state.ts CHANGED
@@ -51,16 +51,22 @@ export function childList(node: JxMutableNode | null | undefined): (JxMutableNod
51
51
  * `$switch` cases. Runs once when a document is loaded into a tab so every in-studio doc — and its
52
52
  * history checkpoints — uses the member form before any mutation.
53
53
  *
54
+ * The rewrite is the editor's invariant, not the file's: `onBare` hears every repeater it moved,
55
+ * with the JSON Pointer of the node holding it (in the NORMALIZED document's coordinates), so a
56
+ * save can put the authored form back (`tabs/bare-repeaters.ts`).
57
+ *
54
58
  * @param {T} node
59
+ * @param {BareRepeaterVisitor} [onBare]
60
+ * @param {string} [pointer] - The node's JSON Pointer, `""` for the root.
55
61
  * @returns {T} The same node (mutated)
56
62
  */
57
- export function normalizeArrayChildren<T>(node: T): T {
63
+ export function normalizeArrayChildren<T>(node: T, onBare?: BareRepeaterVisitor, pointer = ""): T {
58
64
  if (!isNonNullObject(node)) {
59
65
  return node;
60
66
  }
61
67
  if (Array.isArray(node)) {
62
- for (const child of node) {
63
- normalizeArrayChildren(child);
68
+ for (const [i, child] of node.entries()) {
69
+ normalizeArrayChildren(child, onBare, `${pointer}/${i}`);
64
70
  }
65
71
  return node;
66
72
  }
@@ -70,24 +76,37 @@ export function normalizeArrayChildren<T>(node: T): T {
70
76
  const { children } = n;
71
77
  if (isMappedArray(children)) {
72
78
  // SAFETY: A legacy whole-children repeater is the same repeater node that becomes the member.
73
- n.children = [children as JxMutableNode];
79
+ const repeater = children as JxMutableNode;
80
+ onBare?.(pointer, repeater);
81
+ n.children = [repeater];
74
82
  }
75
83
  if (Array.isArray(n.children)) {
76
- for (const child of n.children) {
77
- normalizeArrayChildren(child);
84
+ for (const [i, child] of n.children.entries()) {
85
+ normalizeArrayChildren(child, onBare, `${pointer}/children/${i}`);
78
86
  }
79
87
  }
80
88
  if (n.$prototype === "Array" && isNonNullObject(n.map)) {
81
- normalizeArrayChildren(n.map);
89
+ normalizeArrayChildren(n.map, onBare, `${pointer}/map`);
82
90
  }
83
91
  if (isNonNullObject(n.cases)) {
84
- for (const caseDef of Object.values(n.cases)) {
85
- normalizeArrayChildren(caseDef);
92
+ for (const [key, caseDef] of Object.entries(n.cases)) {
93
+ normalizeArrayChildren(caseDef, onBare, `${pointer}/cases/${pointerToken(key)}`);
86
94
  }
87
95
  }
88
96
  return node;
89
97
  }
90
98
 
99
+ /**
100
+ * Hears each legacy whole-children repeater {@link normalizeArrayChildren} rewrites: the JSON
101
+ * Pointer of the node holding it, and the repeater.
102
+ */
103
+ export type BareRepeaterVisitor = (pointer: string, repeater: JxMutableNode) => void;
104
+
105
+ /** One JSON Pointer reference token (RFC 6901 §4). */
106
+ export function pointerToken(segment: string | number): string {
107
+ return String(segment).replaceAll("~", "~0").replaceAll("/", "~1");
108
+ }
109
+
91
110
  /**
92
111
  * Return the path to the parent element (strips trailing 'children' + index).
93
112
  *
package/src/studio.ts CHANGED
@@ -26,6 +26,7 @@ import {
26
26
  toolbarEl,
27
27
  updateSession,
28
28
  } from "./store";
29
+ import { getEffectiveRenderLocale } from "./site-context";
29
30
 
30
31
  import {
31
32
  PRIMARY_PANE,
@@ -58,6 +59,7 @@ import { isEditing } from "./editor/inline-edit";
58
59
  import { applyTransform, registerCanvasViewCommands } from "./canvas/canvas-utils";
59
60
  import { diffCommands, setDiffChromeRepaint } from "./canvas/diff-toolbar";
60
61
  import type { CanvasSurface } from "./canvas/canvas-surface";
62
+ import type { InspectorTabId } from "./shell";
61
63
  import {
62
64
  initCanvasRender,
63
65
  registerSelectionSetCommand,
@@ -126,6 +128,7 @@ import {
126
128
  openLastSessionOrHome,
127
129
  reloadCleanTab,
128
130
  reloadTabsIfChanged,
131
+ setSessionWorkspaceShow,
129
132
  } from "./files/files";
130
133
  import { resetIgnoreCache } from "./files/gitignore";
131
134
  import { resetAssetVersions } from "./files/asset-versions";
@@ -138,8 +141,19 @@ import {
138
141
  } from "./collab/collab-session";
139
142
  import { invalidateLayoutPickerCache } from "./panels/head-panel";
140
143
  import { installAutomationHook } from "./services/automation";
141
- import { invalidateLibrary } from "./browse/library-pane";
142
- import { invalidateMediaCache } from "./ui/media-picker";
144
+ import { invalidateLibrary, resetContentView } from "./browse/library-pane";
145
+ import { invalidateCollectionPages, resetCollectionPages } from "./content/collection-pages";
146
+ import { invalidatePageSummaries } from "./content/page-summaries";
147
+ import { invalidateEntrySummaries, noteSavedEntry } from "./content/entry-summaries";
148
+ import { invalidateRepeaterSources } from "./canvas/repeater-sources";
149
+ import { entryFields } from "./content/entry-fields";
150
+ import { contentCacheDrops } from "./content/content-collections";
151
+ import { resetWritingBanners } from "./content/writing-banner";
152
+ import { resetCollectionsPanel } from "./panels/collections-panel";
153
+ import { resetStylesPanel } from "./panels/styles-panel";
154
+ import { resetVariablesFocus } from "./style/variables-focus";
155
+ import { invalidateMediaCache, isMediaScanPath } from "./ui/media-picker";
156
+ import { invalidateSiteIndex, resetSitePanel } from "./panels/site-panel";
143
157
  import { setMediaChangedHandler } from "./files/media-upload";
144
158
  import { applyFileDrop } from "./editor/file-drop-action";
145
159
  import {
@@ -169,12 +183,13 @@ import { autoSyncProjectOnOpen } from "./packages/pull-package-sync";
169
183
  import webdata from "../data/webdata.json";
170
184
  import { registerDataExplorerCommands } from "./panels/data-explorer";
171
185
  import {
172
- cleanupGitPanel,
186
+ cleanupSourceControl,
173
187
  cloneRepository,
174
188
  loadDiffForLens,
175
189
  registerSourceControlCommands,
176
190
  noteFileSaved,
177
- } from "./panels/git-panel";
191
+ setSourceControlDeps,
192
+ } from "./publish/source-control";
178
193
 
179
194
  import { registerKit } from "./ui/kit";
180
195
  import "./ui/panel-resize.js";
@@ -185,13 +200,12 @@ import { initShortcuts, registerStudioCommands } from "./editor/shortcuts";
185
200
  import type { ProjectOpenOutcome, ProjectOpenTarget } from "./editor/shortcuts";
186
201
  import { createCommandRegistry } from "./commands/registry";
187
202
  import { chordsInScopes } from "./commands/keymap";
188
- import { FRAME_KEY_SCOPES } from "./canvas/iframe-keys";
203
+ import { FRAME_KEY_SCOPES, HOST_ONLY_COMMANDS } from "./canvas/iframe-keys";
189
204
  import { createLiveContext } from "./commands/live-context";
190
205
  import { hasAiCredentials } from "./services/ai-models";
191
206
  import { mount } from "./surfaces/rail";
192
207
  import * as toolbarPanel from "./surfaces/commandbar";
193
208
  import * as overlaysPanel from "./panels/overlays";
194
- import * as frontmatterPanelMod from "./panels/frontmatter-panel";
195
209
  import * as rightPanelMod from "./panels/right-panel";
196
210
  import * as chatPanelMod from "./panels/chat-panel";
197
211
  import { setProjectAdopter } from "./services/project-adoption";
@@ -251,19 +265,36 @@ import { registerPopoverCommands } from "./services/popover-report";
251
265
  import { registerStyleCommands } from "./panels/style-panel";
252
266
  import { registerGridCommands } from "./grid/grid-open";
253
267
  import { registerExtensionCommands } from "./settings/extension-commands";
254
- import { registerSettingsCommands } from "./settings/settings-document";
268
+ import {
269
+ registerSettingsCommands,
270
+ rememberStylesView,
271
+ showSettingsDocument,
272
+ } from "./settings/settings-document";
273
+ import {
274
+ installWorkspaceFollow,
275
+ revealInPane,
276
+ switchWorkspace,
277
+ } from "./workspace/workspace-switch";
278
+ import { workspaceBackCommands } from "./workspace/workspace-back";
279
+ import type { HomeWorkspaceId, WorkspaceId } from "./workspace/workspace-ids";
280
+ import { openWorkspaceHome, placeWorkspaceHome } from "./workspace/workspace-home";
255
281
  import { registerPreferencesCommands } from "./settings/preferences-dialog";
256
282
  import { registerAboutCommands } from "./about/about-modal";
257
283
  import { registerCollabCommands } from "./collab/collab-commands";
258
- import { registerLibraryCommands } from "./browse/library-commands";
284
+ import { registerContentViewCommands } from "./browse/library-commands";
259
285
  import { registerFileFormatCommands } from "./format/convert-file";
260
286
  import { registerPublishCommands } from "./publish/publish-commands";
261
287
  import { registerGridViewCommands } from "./grid/grid-panel";
262
288
  import { registerRedirectsCommands } from "./grid/redirects-grid";
263
289
  import { registerContentCommands } from "./content/entry-commands";
290
+ import { registerAddNewCommands } from "./create/add-new-commands";
291
+ import { registerMediaCommands } from "./media/media-commands";
292
+ import { focusMediaHome, resetMediaLibrary } from "./media/media-library";
293
+ import { focusPublishHome } from "./publish/publish-workspace";
264
294
  import { registerI18nCommands } from "./i18n/i18n-commands";
265
295
  import { convertToComponent } from "./editor/convert-to-component";
266
296
  import type { GitDiffState } from "./types";
297
+ import { PROJECT_CONFIG_PATH } from "./tabs/tab";
267
298
  import type { Tab } from "./tabs/tab";
268
299
  import type { JxDocument, ProjectConfig } from "@jxsuite/schema/types";
269
300
  import { setBundleBase } from "./services/bundle-base";
@@ -296,8 +327,8 @@ setBundleBase(import.meta.url);
296
327
  *
297
328
  * `loadDiff` is here rather than in `workspace/pane-derive.ts` because that module owns no I/O —
298
329
  * which is what lets its whole decision-making half be tested with no platform. It is the same pair
299
- * of reads `panels/git-panel.ts` makes for a row click; an added file has no `HEAD` copy, so its
300
- * "original" is the empty string rather than a `gitShow` that would throw.
330
+ * of reads `publish/source-control.ts` makes for a Before and after; an added file has no `HEAD`
331
+ * copy, so its "original" is the empty string rather than a `gitShow` that would throw.
301
332
  */
302
333
  const derivationDeps: DerivationDeps = {
303
334
  /*
@@ -370,6 +401,10 @@ function setCanvasMode(tab: Tab | null, mode: string) {
370
401
  shell.git.diffState = null;
371
402
  }
372
403
  tab.session.ui.canvasMode = mode;
404
+ // The Styles home view follows the author's own switches between Variables and Elements.
405
+ if (tab.documentPath === PROJECT_CONFIG_PATH) {
406
+ rememberStylesView(mode);
407
+ }
373
408
  }
374
409
 
375
410
  // ─── Component registry ───────────────────────────────────────────────────────
@@ -524,11 +559,26 @@ const primaryCell = cellForPane(PRIMARY_PANE);
524
559
 
525
560
  tabStrip.mount(primaryCell?.strip ?? document.createElement("div"));
526
561
 
562
+ /**
563
+ * Give the keyboard to the home a Back landed on (`workspace/workspace-back.ts`): the media tile
564
+ * that was opened, the change whose comparison it was. One function for the Back control and for
565
+ * Escape, so the two land in the same place.
566
+ */
567
+ function focusWorkspaceHome(paneId: string, id: WorkspaceId): void {
568
+ if (id === "media") {
569
+ focusMediaHome(paneId);
570
+ } else if (id === "publish") {
571
+ focusPublishHome(paneId);
572
+ }
573
+ }
574
+
527
575
  paneContext.mount(primaryCell?.chrome ?? document.createElement("div"), {
528
576
  exportFile,
529
577
  // No `getCanvasMode`: the bar is drawn once per pane and asks its own pane. See `PaneContextCtx`.
530
578
  parseMediaEntries,
531
579
  setCanvasMode,
580
+ closeTab: tabStrip.requestClose,
581
+ focusHome: focusWorkspaceHome,
532
582
  });
533
583
  /* The diff's Visual/Code switch decides whether the zoom pod is drawn, and the half it writes is
534
584
  not reactive — so the switch repaints the chrome as well as the stage. See `setDiffChromeRepaint`. */
@@ -558,6 +608,7 @@ setFileDropHandler(applyFileDrop);
558
608
  setMediaChangedHandler(async (dir) => {
559
609
  invalidateMediaCache();
560
610
  invalidateLibrary();
611
+ invalidateSiteIndex();
561
612
  await loadDirectory(dir);
562
613
  renderLeftPanel();
563
614
  });
@@ -582,7 +633,7 @@ setStylebookHitHandler((tag, media) => {
582
633
  1. Commit-on-parent-click: it ends the live inline-edit session, which the iframe cannot observe
583
634
  itself (layers panel, tab strip, right panel…).
584
635
  2. The block action bar goes with it. The bar is `position: fixed` and clamped into the window,
585
- so it can sit over the Document Header card, the pane context bar and the docks; an author
636
+ so it can sit over the pane context bar, the Inspector and the docks; an author
586
637
  working in the Inspector's Logic tab reported it "blocking a part of the interface that the
587
638
  user needs to utilize". It is SUPPRESSED, not dismissed — a plain dismiss flashes back on the
588
639
  next snapshot or overlay repaint — and it comes back the moment the canvas takes a pointer or
@@ -774,10 +825,8 @@ function installPaneRenderEffects(paneId: string): void {
774
825
  void tab.session.ui.previewProps;
775
826
  void tab.session.ui.showLayout;
776
827
  }
777
- // Project-level render inputs: the stylebook catalogue's filters and the settings section are
778
- // Shell state, so a change repaints the canvas with or without a document focused.
779
- void shell.settingsTab;
780
- void shell.stylebook.tab;
828
+ // Project-level render inputs: the stylebook catalogue's filters are shell state, so a change
829
+ // Repaints the canvas with or without a document focused.
781
830
  void shell.stylebook.filter;
782
831
  void shell.stylebook.customizedOnly;
783
832
  scheduleCanvasRender(paneId);
@@ -796,8 +845,11 @@ function installPaneRenderEffects(paneId: string): void {
796
845
  * The other half of `i18n.switchLocale`. Without this the control moves a chip and the artboard
797
846
  * goes on drawing the same document left-to-right, which makes the verb a label rather than a
798
847
  * rendering context. Scoped to THIS pane's stage for the reason the scheme effect above gives.
848
+ * The document's OWN language when nothing is chosen, so an Arabic file draws right to left
849
+ * without being asked (`getEffectiveRenderLocale`).
799
850
  */
800
- const locale = tabOfPane(paneId)?.session.ui.previewLocale ?? null;
851
+ const tab = tabOfPane(paneId);
852
+ const locale = getEffectiveRenderLocale(tab?.session.ui.previewLocale, tab?.documentPath);
801
853
  postLocaleToLiveHosts(locale, surfaceForPane(paneId).wrap);
802
854
  });
803
855
  }
@@ -842,10 +894,6 @@ rightPanelMod.mount({
842
894
  renderCanvas: () => renderCanvas(),
843
895
  });
844
896
 
845
- // The Document Header card — every document with frontmatter or `$head`. It has no host of its own:
846
- // The stage hands one over (`canvas-render.ts`), and this only starts the reactive subscription.
847
- frontmatterPanelMod.mount();
848
-
849
897
  // The assistant's create_project tool adopts freshly scaffolded projects through the same
850
898
  // Flow as the recent-projects list.
851
899
  setProjectAdopter(openRecentProject);
@@ -855,8 +903,20 @@ setImportHandoff(revealImportHandoff);
855
903
  one — see services/connection.ts for why only the chromium shell can. */
856
904
  watchConnection();
857
905
 
906
+ /* What source control needs from the bootstrap: the two writes a comparison makes outside
907
+ `shell.git` (the Publish workspace's Before and after puts the file's own tab into git-diff), and
908
+ the clone flow, which ends by opening the project it cloned. */
909
+ setSourceControlDeps({
910
+ cloneRepository: () => {
911
+ void cloneRepository({ openRecentProject });
912
+ },
913
+ setCanvasMode,
914
+ setGitDiffState: (state: GitDiffState | null) => {
915
+ shell.git.diffState = state;
916
+ },
917
+ });
918
+
858
919
  leftPanelMod.mount({
859
- cloneRepository: () => cloneRepository({ openRecentProject }),
860
920
  defBadgeLabel,
861
921
  defCategory,
862
922
  defaultDef,
@@ -888,9 +948,6 @@ leftPanelMod.mount({
888
948
  },
889
949
  mountSignalsPanel,
890
950
  setCanvasMode,
891
- setGitDiffState: (state: GitDiffState | null) => {
892
- shell.git.diffState = state;
893
- },
894
951
  webdata,
895
952
  });
896
953
 
@@ -899,7 +956,6 @@ leftPanelMod.mount({
899
956
  registerRenderer("leftPanel", () => leftPanelMod.render());
900
957
  registerRenderer("canvas", () => renderCanvas());
901
958
  registerRenderer("rightPanel", () => rightPanelMod.render());
902
- registerRenderer("frontmatterPanel", () => frontmatterPanelMod.render());
903
959
  registerRenderer("seoModal", renderSeoModal);
904
960
  registerRenderer("chatPanel", () => chatPanelMod.render());
905
961
  registerRenderer("overlays", () => overlaysPanel.render());
@@ -945,9 +1001,32 @@ function ensureFsSync() {
945
1001
  of them wrong, and it is the same event for all four. The bar's memo is separate from
946
1002
  `page-params`' because it is keyed per DOCUMENT rather than globally; leaving it behind kept
947
1003
  a stale candidate list in the picker after the collection changed. */
948
- invalidateDerivedCaches: () => {
1004
+ invalidateDerivedCaches: (paths, structural = true) => {
949
1005
  invalidatePageRouteCache();
950
1006
  invalidateLayoutPickerCache();
1007
+ invalidateSiteIndex(paths);
1008
+ /* The Content workspace's three: the scan its collections are filtered from, the pages that
1009
+ say where each collection is published, and the entry list the Collections panel draws.
1010
+ Each is dropped only by a batch that can make it wrong, so a save does not re-walk the
1011
+ project or blank the Collections panel (`contentCacheDrops`). */
1012
+ const drops = contentCacheDrops(paths, structural);
1013
+ if (drops.scan) {
1014
+ invalidateLibrary();
1015
+ }
1016
+ if (drops.pages) {
1017
+ invalidateCollectionPages();
1018
+ invalidatePageSummaries();
1019
+ }
1020
+ if (drops.entries) {
1021
+ invalidateEntrySummaries();
1022
+ invalidateRepeaterSources();
1023
+ }
1024
+ /* The media listing is a walk of `public/` and every collection's `images/`, so only a batch
1025
+ under one of them (or one that cannot say what changed) can make it wrong: a file added by
1026
+ git, the OS or a Files-panel delete. */
1027
+ if (paths === undefined || paths.some((path) => isMediaScanPath(path))) {
1028
+ invalidateMediaCache();
1029
+ }
951
1030
  invalidateParamValues();
952
1031
  paneContext.resetParamValues();
953
1032
  },
@@ -963,11 +1042,11 @@ const _urlParams = new URLSearchParams(location.search);
963
1042
  const _projectParam = _urlParams.get("project") || _urlParams.get("open");
964
1043
 
965
1044
  if (!_projectParam) {
966
- // Electrobun (and other non-?project= hosts) load their project over RPC, so the ?project= branch
1045
+ // The desktop app (and other non-?project= hosts) load their project over RPC, so the ?project= branch
967
1046
  // Below — which is the only place that calls platform.activate() — is skipped. Kick off activate()
968
- // Here UNCONDITIONALLY so this window's loopback canvasUrl is fetched on boot (the canvas iframe
969
- // Needs it); a render() once it resolves lets ensureHost swap an early default iframe for the
970
- // Loopback one (see iframe-host ensureHost's canvasUrl-changed rebuild).
1047
+ // Here UNCONDITIONALLY so this window's canvasUrl is fetched on boot (the canvas iframe
1048
+ // Needs it); a render() once it resolves lets ensureHost rebuild against it if it differs from
1049
+ // The default (see iframe-host ensureHost's canvasUrl-changed rebuild).
971
1050
  const _bootPlatform = getPlatform();
972
1051
  // oxlint-disable-next-line unicorn/prefer-top-level-await -- fire-and-forget: must not block the initial render
973
1052
  void _bootPlatform
@@ -1256,10 +1335,32 @@ async function openProject(target: ProjectOpenTarget = "thisWindow"): Promise<Pr
1256
1335
  if (!(await tabStrip.confirmCloseAll("Opening another project"))) {
1257
1336
  return "cancelled";
1258
1337
  }
1259
- const opened = await _openProject({ renderLeftPanel });
1338
+ const opened = await _openProject({ renderLeftPanel, resetProjectCaches });
1260
1339
  ensureFsSync();
1261
1340
  return opened ? "opened" : "cancelled";
1262
1341
  }
1342
+ /**
1343
+ * The one project-switch reset of the caches panels keep for the project being left: the Site
1344
+ * panel's index and filter, the media listing it and every image field read, and the Media
1345
+ * workspace's own filter, search and selection. Both open paths run it (this file's
1346
+ * `openRecentProject`, and `files.ts`'s `openProject` behind ⌘O, the toolbar and the welcome
1347
+ * screen), so neither can show the previous project's pages or media.
1348
+ */
1349
+ function resetProjectCaches(): void {
1350
+ resetSitePanel();
1351
+ resetContentView();
1352
+ resetCollectionPages();
1353
+ invalidatePageSummaries();
1354
+ invalidateEntrySummaries();
1355
+ invalidateRepeaterSources();
1356
+ resetCollectionsPanel();
1357
+ resetStylesPanel();
1358
+ resetVariablesFocus();
1359
+ resetWritingBanners();
1360
+ invalidateMediaCache();
1361
+ resetMediaLibrary();
1362
+ }
1363
+
1263
1364
  async function openRecentProject(root: string) {
1264
1365
  // One entry for the whole sequence, not three surfaces for its three phases. Opening a project
1265
1366
  // Used to chain a blocking spinner (dependencies), a transient status line (git sync) and a
@@ -1317,9 +1418,10 @@ async function openRecentProject(root: string) {
1317
1418
  platform.projectRoot = root;
1318
1419
  // Source control, the stylebook selection and the settings tab describe the project being
1319
1420
  // Left behind; carrying them over showed the previous repository's branch and file count
1320
- // Under the new project's name. The poll timer is re-armed by the panel's next render.
1321
- cleanupGitPanel();
1421
+ // Under the new project's name. The poll timer is re-armed by the Publish workspace's next mount.
1422
+ cleanupSourceControl();
1322
1423
  resetProjectShell();
1424
+ resetProjectCaches();
1323
1425
  // The format registry is cached per project — the previous root's registry (often empty on a
1324
1426
  // Fresh desktop launch) must not answer for this project, or non-JSON documents fail with
1325
1427
  // "No format class imported" until a reload. Mirrors openProject in files.ts.
@@ -1358,7 +1460,7 @@ async function openRecentProject(root: string) {
1358
1460
  await loadComponentRegistry();
1359
1461
 
1360
1462
  addRecentProject(requireProjectState().name, root);
1361
- setActivityTab("files");
1463
+ // The Navigator shows the panel the workspace frame chose as the project opened (§22.3).
1362
1464
  renderLeftPanel();
1363
1465
  // The project's name is now permanent state in the status bar's PROJECT field.
1364
1466
 
@@ -1459,7 +1561,16 @@ registerStudioCommands(
1459
1561
  );
1460
1562
 
1461
1563
  // Tab navigation (⌃Tab MRU cycling, ⌘⇧T reopen-closed) is defined beside the tab model it drives.
1462
- registerTabCommands(commandRegistry, { openFile: openFileInTab, openFileInPane });
1564
+ /* `pane.compareWith` opens into the other pane without moving the keyboard; a compared document of
1565
+ another workspace would land hidden by that pane's strip, so it is revealed, which enters its
1566
+ workspace (`workspace/workspace-switch.ts`). */
1567
+ registerTabCommands(commandRegistry, {
1568
+ openFile: openFileInTab,
1569
+ openFileInPane: async (paneId, path) => {
1570
+ await openFileInPane(paneId, path);
1571
+ revealInPane(paneId, path);
1572
+ },
1573
+ });
1463
1574
 
1464
1575
  /* The derivation's own two verbs (§18.4), beside the `PaneDerivation` they read and write rather
1465
1576
  than in `paneCommands()`. `tests/app-commands-composition.test.ts` is the guard that this line
@@ -1475,6 +1586,28 @@ commandRegistry.registerAll(derivationCommands(derivationDeps));
1475
1586
  * available or what it does — that would be the second definition site the design exists to prevent
1476
1587
  * (§13).
1477
1588
  */
1589
+ /* The workspace's two halves (`workspace/workspace-switch.ts`): the follow, which enters a tab's
1590
+ workspace whenever a tab is activated, and the switch `view.setWorkspace` runs, which puts a
1591
+ workspace's tabs (or its home) on screen. The homes are handed in, so the switch imports
1592
+ neither the homes' surfaces nor the settings document. */
1593
+ const workspaceDeps = {
1594
+ openHome: (id: HomeWorkspaceId) => {
1595
+ openWorkspaceHome(id);
1596
+ },
1597
+ // The Styles home: the view it was left in, Variables on a first visit (§7.1).
1598
+ openStyles: () => {
1599
+ showSettingsDocument();
1600
+ },
1601
+ placeHome: placeWorkspaceHome,
1602
+ setInspectorTab: (tab: InspectorTabId) => rightPanelMod.setInspectorTab(tab),
1603
+ };
1604
+ installWorkspaceFollow(workspaceDeps);
1605
+ /** Show a workspace with the bootstrap's homes: what `view.setWorkspace` and a reopen both run. */
1606
+ function showWorkspaceWithHomes(id: WorkspaceId): void {
1607
+ switchWorkspace(id, workspaceDeps);
1608
+ }
1609
+ // A project reopens in the workspace it was left in, once its documents are open (§22.1).
1610
+ setSessionWorkspaceShow(showWorkspaceWithHomes);
1478
1611
  registerShellViewCommands(commandRegistry, {
1479
1612
  // The registry's own answer, so a gated-off panel cannot be persisted as a showing tab.
1480
1613
  panelAvailable: (id) => {
@@ -1482,8 +1615,20 @@ registerShellViewCommands(commandRegistry, {
1482
1615
  return panel ? (panel.when?.(commandRegistry.context()) ?? true) : true;
1483
1616
  },
1484
1617
  inspectorTab: () => rightPanelMod.inspectorTab(),
1618
+ restingInspectorTab: () => rightPanelMod.restingInspectorTab(),
1485
1619
  setInspectorTab: (tab) => rightPanelMod.setInspectorTab(tab),
1620
+ showWorkspace: showWorkspaceWithHomes,
1486
1621
  });
1622
+ /* Back to a strip-less workspace's home (Media, Styles, Publish): the pane context bar's Back
1623
+ control and Escape. The close goes through the strip's guarded close, so a view with unsaved
1624
+ work still asks first. */
1625
+ commandRegistry.registerAll(
1626
+ workspaceBackCommands({
1627
+ closeTab: tabStrip.requestClose,
1628
+ focusHome: focusWorkspaceHome,
1629
+ setCanvasMode,
1630
+ }),
1631
+ );
1487
1632
  registerCanvasViewCommands(commandRegistry, {
1488
1633
  getCanvasMode,
1489
1634
  renderPane: renderCanvas,
@@ -1494,7 +1639,7 @@ registerCanvasViewCommands(commandRegistry, {
1494
1639
  });
1495
1640
  /* A save moves the working tree under any comparison of that file, and nothing about a
1496
1641
  comparison notices on its own — see `noteFileSaved`. Injected rather than imported: `file-ops`
1497
- must not pull the Source Control panel into its graph. */
1642
+ must not pull source control into its graph. */
1498
1643
  /* The second listener is the live chrome lane: a saved surface document or kit component re-mounts
1499
1644
  the roots it draws in THIS shell (studio-ui-guidelines.md §9.3). Inert for every project but the
1500
1645
  two the chrome comes from, by the saved path alone. */
@@ -1507,8 +1652,14 @@ const liveChrome = createLiveSurfaceSaver({
1507
1652
  Component Settings and the Library read the props the file has now rather than the ones the scan
1508
1653
  saw when the project opened. The Content tab and the Library are told, because neither reads the
1509
1654
  registry reactively. */
1510
- setDocumentSavedListener((path, doc) => {
1655
+ setDocumentSavedListener((path, doc, tab) => {
1511
1656
  void noteFileSaved(path);
1657
+ // Any saved file can be data a repeater on the canvas reads; the next render asks again.
1658
+ invalidateRepeaterSources();
1659
+ // An entry's new title or status reaches the Collections panel and the Content home at once.
1660
+ if (noteSavedEntry(path, entryFields(tab))) {
1661
+ renderLeftPanel();
1662
+ }
1512
1663
  /* SAFETY: The listener fires for a tab's saved ROOT document, and a root document is a
1513
1664
  JxDocument held in the editor's mutable node form; `liveChrome` only acts on surface paths. */
1514
1665
  void liveChrome(path, doc as JxDocument);
@@ -1525,8 +1676,8 @@ commandRegistry.registerAll(diffCommands());
1525
1676
  ensurePopoverRevealWatch();
1526
1677
  registerSelectionSetCommand(commandRegistry);
1527
1678
  registerInspectorCommands(commandRegistry);
1528
- /* Search appearance, behind one record with two buttons: the Document Header card's and the Page
1529
- panel's. A surface that IS the capability is one the palette cannot reach. */
1679
+ /* Search appearance, behind one record the Page tab's button runs: a surface that IS the capability
1680
+ is one the palette cannot reach. */
1530
1681
  registerSeoCommands(commandRegistry);
1531
1682
  registerA11yCommands(commandRegistry);
1532
1683
  registerPopoverCommands(commandRegistry);
@@ -1547,9 +1698,11 @@ registerGridCommands(commandRegistry);
1547
1698
  registerSettingsCommands(commandRegistry);
1548
1699
  registerExtensionCommands(commandRegistry);
1549
1700
  registerPreferencesCommands(commandRegistry);
1550
- registerLibraryCommands(commandRegistry);
1701
+ registerContentViewCommands(commandRegistry);
1551
1702
  registerFileFormatCommands(commandRegistry);
1552
1703
  registerContentCommands(commandRegistry);
1704
+ registerAddNewCommands(commandRegistry);
1705
+ registerMediaCommands(commandRegistry);
1553
1706
  /* The four translation verbs: open a sibling translation, create the missing one, show the
1554
1707
  Languages panel, declare a language. `i18n.switchLocale` is deliberately not among them — it sets
1555
1708
  a rendering context, so it lives with the other axis-3 verbs in `canvasViewCommands`. */
@@ -1593,7 +1746,7 @@ initShortcuts(commandRegistry, stageContext);
1593
1746
  which is what makes Preferences › Keyboard reach inside the page. */
1594
1747
  setKeymapSource(
1595
1748
  () => ({
1596
- chords: chordsInScopes(commandRegistry.keymap, FRAME_KEY_SCOPES),
1749
+ chords: chordsInScopes(commandRegistry.keymap, FRAME_KEY_SCOPES, HOST_ONLY_COMMANDS),
1597
1750
  mac: commandRegistry.keymap.mac,
1598
1751
  }),
1599
1752
  (listener) => commandRegistry.keymap.onChange(listener),