@jxsuite/studio 6.1.1 → 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 (785) hide show
  1. package/README.md +5 -5
  2. package/dist/chunks/2020-5wtzce5g.js +4 -0
  3. package/dist/chunks/{action-group-2mqby73c.js → action-group-4aan7g6g.js} +3 -3
  4. package/dist/chunks/adapter-5tphg7xe.js +4 -0
  5. package/dist/chunks/add-new-flow-psym14sn.js +4 -0
  6. package/dist/chunks/cf-account-picker-haqazq5r.js +4 -0
  7. package/dist/chunks/cf-settings-h2wrh6hq.js +4 -0
  8. package/dist/chunks/color-area-6rbra5dy.js +4 -0
  9. package/dist/chunks/color-field-gy56c94g.js +4 -0
  10. package/dist/chunks/color-m7r1vk54.js +4 -0
  11. package/dist/chunks/color-slider-sqqdyf6c.js +4 -0
  12. package/dist/chunks/combobox-72h32ejk.js +4 -0
  13. package/dist/chunks/components-r22xca09.js +4 -0
  14. package/dist/chunks/content-source-mmppmcyg.js +4 -0
  15. package/dist/chunks/convert-to-repeater-he70fc2b.js +4 -0
  16. package/dist/chunks/dialog-c4x05vyx.js +4 -0
  17. package/dist/chunks/editor-ccd9jwsa.js +4 -0
  18. package/dist/chunks/entry-commands-6qxz9e8p.js +4 -0
  19. package/dist/chunks/extension-sections-0egb88dm.js +4 -0
  20. package/dist/chunks/file-ops-qnab36ek.js +4 -0
  21. package/dist/chunks/files-rcn56qvm.js +4 -0
  22. package/dist/chunks/format-host-yxz0kjjs.js +4 -0
  23. package/dist/chunks/fs-events-d1qxq4z4.js +4 -0
  24. package/dist/chunks/grid-open-4z1g062t.js +4 -0
  25. package/dist/chunks/grid-view-qg1b5eqx.js +51 -0
  26. package/dist/chunks/icons-63bjtbs7.js +4 -0
  27. package/dist/chunks/iframe-entry-2zggzajv.js +5 -0
  28. package/dist/chunks/iframe-entry-76j8vwwx.js +5 -0
  29. package/dist/chunks/iframe-entry-99nr5zfb.js +5 -0
  30. package/dist/chunks/iframe-entry-pkgmcgp0.js +5 -0
  31. package/dist/chunks/iframe-host-ssv7kyj0.js +4 -0
  32. package/dist/chunks/{index-2veqmnhr.js → index-32eqzv1k.js} +3 -3
  33. package/dist/chunks/index-f0jn7nnp.js +4 -0
  34. package/dist/chunks/{javascript-8nbvs12s.js → javascript-pjp734q4.js} +3 -3
  35. package/dist/chunks/jsonMode-njkvsa02.js +13 -0
  36. package/dist/chunks/jx-validate-ttasrbh7.js +4 -0
  37. package/dist/chunks/layers-bgyr11tr.js +4 -0
  38. package/dist/chunks/layers-panel-7ez66zeq.js +4 -0
  39. package/dist/chunks/listbox-c421cf8c.js +4 -0
  40. package/dist/chunks/lit-html-v9gh687x.js +4 -0
  41. package/dist/chunks/media-library-sq468wts.js +4 -0
  42. package/dist/chunks/media-picker-shfe59pt.js +4 -0
  43. package/dist/chunks/menu-bdpzbfvs.js +4 -0
  44. package/dist/chunks/monaco-binding-vq1hgnn0.js +4 -0
  45. package/dist/chunks/monaco-buffer-3afgwvbp.js +4 -0
  46. package/dist/chunks/monaco-setup-xrd2cbkp.js +4 -0
  47. package/dist/chunks/notify-kzrjr3fv.js +4 -0
  48. package/dist/chunks/number-field-y62xq0ty.js +4 -0
  49. package/dist/chunks/parse-v77xtwv7.js +4 -0
  50. package/dist/chunks/platform-7v4rtd7m.js +4 -0
  51. package/dist/chunks/popover-b89sfej7.js +4 -0
  52. package/dist/chunks/publish-panel-2z9gw8ee.js +4 -0
  53. package/dist/chunks/publish-quick-qx2455cj.js +4 -0
  54. package/dist/chunks/publish-workspace-wrc1dgwx.js +4 -0
  55. package/dist/chunks/quick-search-n0t0eqxb.js +4 -0
  56. package/dist/chunks/references-9547rg5s.js +4 -0
  57. package/dist/chunks/right-panel-wsgnr9pn.js +4 -0
  58. package/dist/chunks/select-rzds841e.js +4 -0
  59. package/dist/chunks/source-control-kwktr9y6.js +4 -0
  60. package/dist/chunks/split-c9zfdgxf.js +4 -0
  61. package/dist/chunks/studio-03ct6yfv.js +9 -0
  62. package/dist/chunks/studio-07rcfje3.js +5 -0
  63. package/dist/chunks/studio-3e54qh39.js +7 -0
  64. package/dist/chunks/studio-3exxhz5g.js +5 -0
  65. package/dist/chunks/studio-3q40e3rj.js +5 -0
  66. package/dist/chunks/studio-3qeh9t0h.js +6 -0
  67. package/dist/chunks/studio-3qqjeep5.js +6 -0
  68. package/dist/chunks/studio-43sd2mam.js +4 -0
  69. package/dist/chunks/studio-4hp8pkyt.js +5 -0
  70. package/dist/chunks/studio-58xg6j2q.js +9 -0
  71. package/dist/chunks/studio-5g0rprdt.js +7 -0
  72. package/dist/chunks/studio-6m380wp7.js +5 -0
  73. package/dist/chunks/studio-80jyh1xh.js +4 -0
  74. package/dist/chunks/studio-83mk4bgg.js +9 -0
  75. package/dist/chunks/{studio-kggey1jt.js → studio-881z1xrx.js} +4 -4
  76. package/dist/chunks/studio-8m0y2qe7.js +5 -0
  77. package/dist/chunks/studio-8tr6cfrc.js +5 -0
  78. package/dist/chunks/studio-8vcvfs7r.js +6 -0
  79. package/dist/chunks/studio-9tmebf0s.js +5 -0
  80. package/dist/chunks/studio-a2bvaptz.js +5 -0
  81. package/dist/chunks/studio-b7y5mr30.js +5 -0
  82. package/dist/chunks/studio-bavb31r0.js +5 -0
  83. package/dist/chunks/studio-bbe4c90a.js +5 -0
  84. package/dist/chunks/studio-c05wdnt3.js +5 -0
  85. package/dist/chunks/studio-ccv2svc6.js +5 -0
  86. package/dist/chunks/studio-d5grtb9e.js +16 -0
  87. package/dist/chunks/studio-df0baea9.js +5 -0
  88. package/dist/chunks/studio-dgk4dqtx.js +7 -0
  89. package/dist/chunks/studio-e1g64q43.js +5 -0
  90. package/dist/chunks/studio-ed1hp6zf.js +6 -0
  91. package/dist/chunks/studio-ed3xx40h.js +7 -0
  92. package/dist/chunks/studio-f14e1zdj.js +5 -0
  93. package/dist/chunks/studio-fbhxxc5f.js +5 -0
  94. package/dist/chunks/studio-fyh0jc96.js +5 -0
  95. package/dist/chunks/studio-gcxk20n7.js +5 -0
  96. package/dist/chunks/studio-jaaz8ce9.js +5 -0
  97. package/dist/chunks/{studio-8grwxtqk.js → studio-jcnsdaep.js} +4 -4
  98. package/dist/chunks/studio-jsgf2q5k.js +7 -0
  99. package/dist/chunks/{studio-1q1sh2ax.js → studio-k3xxbagr.js} +3 -3
  100. package/dist/chunks/studio-k7evxqh4.js +5 -0
  101. package/dist/chunks/studio-kt3pjkwd.js +5 -0
  102. package/dist/chunks/studio-m8g16bgz.js +5 -0
  103. package/dist/chunks/studio-mn0476ag.js +5 -0
  104. package/dist/chunks/studio-mx1smyq0.js +5 -0
  105. package/dist/chunks/studio-n0c5h6mf.js +5 -0
  106. package/dist/chunks/{studio-rv11kfwa.js → studio-nh6d342n.js} +7 -7
  107. package/dist/chunks/studio-nqxqf8p2.js +4 -0
  108. package/dist/chunks/studio-p4nrkvqr.js +5 -0
  109. package/dist/chunks/{studio-h46vtzk8.js → studio-pbxa5fpc.js} +4 -4
  110. package/dist/chunks/studio-pgmvdv7z.js +7 -0
  111. package/dist/chunks/studio-ph84avkf.js +5 -0
  112. package/dist/chunks/{studio-wszjyh0j.js → studio-q0mvbaq6.js} +4 -4
  113. package/dist/chunks/studio-q0tccd43.js +5 -0
  114. package/dist/chunks/studio-q7rtx6zq.js +14 -0
  115. package/dist/chunks/{studio-pre0skq6.js → studio-qgh13jtz.js} +4 -4
  116. package/dist/chunks/studio-qmn1xc24.js +5 -0
  117. package/dist/chunks/studio-qwdqwkj0.js +5 -0
  118. package/dist/chunks/{studio-t6b6qe31.js → studio-r5qy30vx.js} +4 -4
  119. package/dist/chunks/studio-rj9eamf8.js +5 -0
  120. package/dist/chunks/studio-rptgsk96.js +5 -0
  121. package/dist/chunks/studio-rthyg42z.js +928 -0
  122. package/dist/chunks/studio-s19tp1xr.js +5 -0
  123. package/dist/chunks/studio-s32578pn.js +5 -0
  124. package/dist/chunks/studio-svb7yyve.js +5 -0
  125. package/dist/chunks/studio-syreb644.js +5 -0
  126. package/dist/chunks/studio-tf9jryb1.js +10 -0
  127. package/dist/chunks/studio-tfkznv39.js +5 -0
  128. package/dist/chunks/studio-tft6r105.js +5 -0
  129. package/dist/chunks/studio-txf2kysx.js +5 -0
  130. package/dist/chunks/studio-v8867ddv.js +12 -0
  131. package/dist/chunks/studio-vxq7fcvv.js +5 -0
  132. package/dist/chunks/studio-w4rz9hdk.js +5 -0
  133. package/dist/chunks/studio-wbcjbhy1.js +9 -0
  134. package/dist/chunks/studio-wc649wss.js +5 -0
  135. package/dist/chunks/studio-wys23mxz.js +5 -0
  136. package/dist/chunks/studio-x1x167jh.js +5 -0
  137. package/dist/chunks/studio-x9hsze61.js +5 -0
  138. package/dist/chunks/studio-y0n7yxea.js +9 -0
  139. package/dist/chunks/studio-y3ahhdpx.js +5 -0
  140. package/dist/chunks/studio-z97c48fk.js +5 -0
  141. package/dist/chunks/studio-zat62m0c.js +5 -0
  142. package/dist/chunks/studio-zcd2e7yz.js +5 -0
  143. package/dist/chunks/studio-zz9qe3rw.js +64 -0
  144. package/dist/chunks/swatch-group-ewh24n1f.js +4 -0
  145. package/dist/chunks/tabs-f5cw3tgp.js +4 -0
  146. package/dist/chunks/textfield-wewc8rq2.js +4 -0
  147. package/dist/chunks/toast-1gv0h53h.js +4 -0
  148. package/dist/chunks/toast-host-1yg5ar8d.js +4 -0
  149. package/dist/chunks/{toolbar-2nnzqhrj.js → toolbar-44cm5cta.js} +3 -3
  150. package/dist/chunks/tooltip-yypz28gq.js +4 -0
  151. package/dist/chunks/tree-9xa4hm7n.js +4 -0
  152. package/dist/chunks/tsMode-epyfz1hv.js +14 -0
  153. package/dist/chunks/workspace-dz7nxfhv.js +4 -0
  154. package/dist/chunks/workspace-home-xsd7hkjw.js +4 -0
  155. package/dist/chunks/ws-client-bv552sfx.js +4 -0
  156. package/dist/iframe-entry.js +20 -16
  157. package/dist/manifest.json +77 -63
  158. package/dist/studio.js +106 -107
  159. package/dist/workers/ts.worker.js +3 -3
  160. package/package.json +17 -16
  161. package/src/about/about-modal.ts +4 -3
  162. package/src/account/action-flow.ts +45 -38
  163. package/src/account-status.ts +7 -2
  164. package/src/browse/component-examples.ts +272 -0
  165. package/src/browse/library-commands.ts +64 -104
  166. package/src/browse/library-layouts.ts +270 -53
  167. package/src/browse/library-model.ts +194 -134
  168. package/src/browse/library-pane.ts +748 -440
  169. package/src/browse/library-preview.ts +161 -26
  170. package/src/browse/library-source.ts +308 -41
  171. package/src/browse/preview-root.ts +78 -0
  172. package/src/browse/preview-style.ts +155 -0
  173. package/src/canvas/asset-refs.ts +40 -10
  174. package/src/canvas/asset-resolve.ts +19 -23
  175. package/src/canvas/canvas-helpers.ts +7 -6
  176. package/src/canvas/canvas-live-render.ts +260 -77
  177. package/src/canvas/canvas-origin.ts +37 -12
  178. package/src/canvas/canvas-page-context.ts +112 -0
  179. package/src/canvas/canvas-patcher.ts +30 -30
  180. package/src/canvas/canvas-perf.ts +11 -5
  181. package/src/canvas/canvas-render.ts +175 -148
  182. package/src/canvas/canvas-surface.ts +5 -3
  183. package/src/canvas/canvas-utils.ts +147 -61
  184. package/src/canvas/dialog-path.ts +9 -4
  185. package/src/canvas/dialog-state.ts +1 -2
  186. package/src/canvas/diff-marks.ts +9 -16
  187. package/src/canvas/diff-toolbar.ts +8 -7
  188. package/src/canvas/edit-width-drag.ts +4 -1
  189. package/src/canvas/edit-width.ts +1 -3
  190. package/src/canvas/iframe-channel.ts +27 -13
  191. package/src/canvas/iframe-drop.ts +120 -12
  192. package/src/canvas/iframe-editable-root.ts +29 -16
  193. package/src/canvas/iframe-entry.ts +104 -75
  194. package/src/canvas/iframe-eval.ts +73 -49
  195. package/src/canvas/iframe-host.ts +269 -158
  196. package/src/canvas/iframe-inline-edit.ts +49 -30
  197. package/src/canvas/iframe-insert.ts +5 -4
  198. package/src/canvas/iframe-interaction.ts +30 -25
  199. package/src/canvas/iframe-keys.ts +11 -0
  200. package/src/canvas/iframe-overlay.ts +1 -1
  201. package/src/canvas/iframe-patch.ts +25 -21
  202. package/src/canvas/iframe-position.ts +12 -6
  203. package/src/canvas/iframe-protocol.ts +36 -21
  204. package/src/canvas/iframe-render.ts +84 -35
  205. package/src/canvas/iframe-slash.ts +24 -11
  206. package/src/canvas/iframe-subtree.ts +10 -3
  207. package/src/canvas/npm-modules.ts +22 -0
  208. package/src/canvas/path-mapping.ts +19 -12
  209. package/src/canvas/popover-path.ts +7 -3
  210. package/src/canvas/popover-state.ts +1 -2
  211. package/src/canvas/preview-navigate.ts +16 -0
  212. package/src/canvas/repeater-sources.ts +200 -0
  213. package/src/canvas/serialize-scope.ts +13 -5
  214. package/src/canvas/stage-scrollbar.ts +7 -2
  215. package/src/canvas/surface-registry.ts +27 -3
  216. package/src/collab/collab-commands.ts +7 -2
  217. package/src/collab/collab-session.ts +84 -45
  218. package/src/collab/collab-state.ts +4 -3
  219. package/src/collab/monaco-binding.ts +16 -13
  220. package/src/collab/monaco-cursors.ts +5 -2
  221. package/src/commands/app-commands.ts +16 -6
  222. package/src/commands/budget.ts +13 -11
  223. package/src/commands/command-args.ts +103 -71
  224. package/src/commands/context.ts +55 -28
  225. package/src/commands/defaults.ts +69 -45
  226. package/src/commands/keymap.ts +56 -43
  227. package/src/commands/levels.ts +14 -8
  228. package/src/commands/live-context.ts +9 -7
  229. package/src/commands/reference.ts +2 -1
  230. package/src/commands/registry.ts +22 -11
  231. package/src/commands/run-reported.ts +15 -10
  232. package/src/component-props.ts +46 -30
  233. package/src/content/collection-match.ts +11 -9
  234. package/src/content/collection-pages.ts +412 -0
  235. package/src/content/content-collections.ts +270 -0
  236. package/src/content/draft-state.ts +4 -3
  237. package/src/content/entry-commands.ts +54 -62
  238. package/src/content/entry-editor.ts +137 -32
  239. package/src/content/entry-fields.ts +25 -8
  240. package/src/content/entry-inspector.ts +225 -0
  241. package/src/content/entry-model.ts +38 -15
  242. package/src/content/entry-open.ts +80 -0
  243. package/src/content/entry-summaries.ts +440 -0
  244. package/src/content/file-record-ids.ts +80 -0
  245. package/src/content/file-records.ts +125 -0
  246. package/src/content/page-summaries.ts +129 -0
  247. package/src/content/record-entry.ts +201 -0
  248. package/src/content/writing-banner.ts +177 -0
  249. package/src/create/add-new-commands.ts +185 -0
  250. package/src/create/add-new-flow.ts +1116 -0
  251. package/src/create/add-new.ts +1014 -0
  252. package/src/create/element-name.ts +121 -0
  253. package/src/editor/canvas-context-menu.ts +1 -2
  254. package/src/editor/canvas-slash-bridge.ts +3 -6
  255. package/src/editor/content-slice.ts +16 -14
  256. package/src/editor/context-menu.ts +35 -22
  257. package/src/editor/convert-targets.ts +30 -35
  258. package/src/editor/convert-to-component.ts +78 -48
  259. package/src/editor/convert-to-repeater.ts +34 -22
  260. package/src/editor/editable-tags.ts +17 -2
  261. package/src/editor/file-drop-action.ts +29 -22
  262. package/src/editor/inline-edit-apply.ts +79 -17
  263. package/src/editor/inline-edit.ts +76 -50
  264. package/src/editor/inline-format.ts +59 -56
  265. package/src/editor/inline-link.ts +40 -15
  266. package/src/editor/insert-component.ts +91 -0
  267. package/src/editor/insert-zone-action.ts +14 -5
  268. package/src/editor/merge-tags.ts +58 -19
  269. package/src/editor/repeater-scope.ts +39 -28
  270. package/src/editor/shortcuts.ts +76 -42
  271. package/src/editor/slash-menu.ts +52 -14
  272. package/src/files/asset-versions.ts +4 -4
  273. package/src/files/components.ts +89 -20
  274. package/src/files/elements.ts +5 -6
  275. package/src/files/file-ops.ts +92 -41
  276. package/src/files/files.ts +248 -239
  277. package/src/files/fs-events.ts +18 -7
  278. package/src/files/media-meta.ts +97 -2
  279. package/src/files/media-paths.ts +3 -0
  280. package/src/files/media-types.ts +55 -0
  281. package/src/files/media-upload.ts +209 -52
  282. package/src/files/new-file-name.ts +156 -0
  283. package/src/files/serialize-document.ts +15 -5
  284. package/src/format/constraints.ts +1 -1
  285. package/src/format/convert-file.ts +27 -13
  286. package/src/format/format-choices.ts +2 -1
  287. package/src/format/format-host.ts +91 -50
  288. package/src/github/github-auth-status.ts +27 -3
  289. package/src/github/github-auth.ts +21 -11
  290. package/src/github/github-publish.ts +28 -23
  291. package/src/grid/cell-editors.ts +46 -31
  292. package/src/grid/cell-popovers.ts +5 -3
  293. package/src/grid/edit-buffer.ts +10 -9
  294. package/src/grid/grid-controller.ts +25 -23
  295. package/src/grid/grid-layout.ts +21 -5
  296. package/src/grid/grid-open.ts +3 -33
  297. package/src/grid/grid-panel.ts +65 -6
  298. package/src/grid/grid-reveal.ts +34 -0
  299. package/src/grid/grid-source.ts +9 -31
  300. package/src/grid/grid-view.ts +45 -23
  301. package/src/grid/redirects-grid.ts +14 -5
  302. package/src/grid/redirects.ts +16 -14
  303. package/src/grid/schema-columns.ts +25 -19
  304. package/src/grid/sources/connector-source.ts +47 -20
  305. package/src/grid/sources/content-source.ts +100 -31
  306. package/src/grid/sources/csv-file-source.ts +2 -2
  307. package/src/grid/tabulator-tables.d.ts +61 -34
  308. package/src/hosting/document.ts +2 -2
  309. package/src/hosting/stage.ts +7 -7
  310. package/src/i18n/i18n-commands.ts +3 -3
  311. package/src/media/media-commands.ts +181 -0
  312. package/src/media/media-library-model.ts +232 -0
  313. package/src/media/media-library.ts +1283 -0
  314. package/src/media/media-pane.ts +51 -20
  315. package/src/new-project/add-repo-modal.ts +20 -19
  316. package/src/new-project/import-tab.ts +10 -14
  317. package/src/new-project/location-fields.ts +2 -1
  318. package/src/new-project/new-project-modal.ts +12 -9
  319. package/src/packages/jxsuite-update.ts +4 -3
  320. package/src/packages/pull-package-sync.ts +26 -25
  321. package/src/page-params.ts +97 -68
  322. package/src/panels/activity-panel.ts +38 -14
  323. package/src/panels/ai-chat/attached-context.ts +13 -7
  324. package/src/panels/ai-chat/chat-markdown.ts +8 -8
  325. package/src/panels/ai-chat/chat-view.ts +80 -73
  326. package/src/panels/ai-chat/composer.ts +30 -33
  327. package/src/panels/ai-chat/sessions-view.ts +1 -2
  328. package/src/panels/ai-panel.ts +23 -20
  329. package/src/panels/block-action-bar.ts +57 -46
  330. package/src/panels/bottom-dock.ts +5 -3
  331. package/src/panels/canvas-dnd-bridge.ts +36 -26
  332. package/src/panels/chat-panel.ts +6 -6
  333. package/src/panels/collections-panel.ts +306 -0
  334. package/src/panels/component-preview.ts +35 -13
  335. package/src/panels/data-explorer.ts +63 -26
  336. package/src/panels/data-grid.ts +18 -11
  337. package/src/panels/dnd.ts +115 -138
  338. package/src/panels/editors.ts +52 -21
  339. package/src/panels/elements-panel.ts +19 -5
  340. package/src/panels/empty-state.ts +2 -2
  341. package/src/panels/events-panel.ts +84 -69
  342. package/src/panels/formula-workspace.ts +78 -54
  343. package/src/panels/frontmatter-fields.ts +33 -28
  344. package/src/panels/git-diff-open.ts +10 -6
  345. package/src/panels/head-panel.ts +488 -202
  346. package/src/panels/i18n-panel.ts +20 -12
  347. package/src/panels/imports-panel.ts +25 -47
  348. package/src/panels/jump-bar.ts +75 -31
  349. package/src/panels/layers-panel.ts +130 -101
  350. package/src/panels/left-panel.ts +25 -11
  351. package/src/panels/navigator-panels.ts +23 -11
  352. package/src/panels/pane-context.ts +140 -49
  353. package/src/panels/pane-grid.ts +55 -26
  354. package/src/panels/panel-registry.ts +36 -46
  355. package/src/panels/properties-panel.ts +182 -124
  356. package/src/panels/quick-search.ts +53 -31
  357. package/src/panels/right-panel.ts +201 -45
  358. package/src/panels/seo-modal.ts +54 -125
  359. package/src/panels/settings-menu.ts +63 -61
  360. package/src/panels/settings-pane.ts +268 -162
  361. package/src/panels/signals-panel.ts +156 -135
  362. package/src/panels/site-model.ts +367 -0
  363. package/src/panels/site-panel.ts +638 -0
  364. package/src/panels/statement-editor.ts +230 -140
  365. package/src/panels/style-panel.ts +253 -206
  366. package/src/panels/style-utils.ts +114 -51
  367. package/src/panels/stylebook-doc.ts +195 -60
  368. package/src/panels/stylebook-layers-panel.ts +48 -89
  369. package/src/panels/stylebook-panel.ts +60 -27
  370. package/src/panels/styles-panel.ts +327 -0
  371. package/src/panels/tab-drop.ts +27 -11
  372. package/src/panels/tab-strip.ts +143 -49
  373. package/src/platform-errors.ts +57 -43
  374. package/src/platform.ts +59 -31
  375. package/src/platforms/cloud.ts +373 -176
  376. package/src/platforms/default-platform.ts +14 -8
  377. package/src/platforms/devserver.ts +180 -142
  378. package/src/platforms/read-batcher.ts +16 -8
  379. package/src/project-list.ts +2 -1
  380. package/src/publish/deploy-checklist.ts +20 -9
  381. package/src/publish/pages-service.ts +66 -27
  382. package/src/publish/publish-changes.ts +491 -0
  383. package/src/publish/publish-commands.ts +88 -22
  384. package/src/publish/publish-ids.ts +49 -0
  385. package/src/publish/publish-panel.ts +10 -6
  386. package/src/publish/publish-quick.ts +148 -0
  387. package/src/publish/publish-workspace.ts +926 -0
  388. package/src/publish/source-control.ts +907 -0
  389. package/src/recent-projects.ts +15 -8
  390. package/src/resize-edges.ts +26 -36
  391. package/src/services/a11y-report.ts +26 -19
  392. package/src/services/agent-seed.ts +23 -11
  393. package/src/services/ai-ask.ts +9 -12
  394. package/src/services/ai-command-tools.ts +68 -62
  395. package/src/services/ai-import-tools.ts +80 -67
  396. package/src/services/ai-models.ts +17 -13
  397. package/src/services/ai-project-tools.ts +68 -32
  398. package/src/services/ai-session-store.ts +19 -10
  399. package/src/services/ai-system-prompt.ts +46 -20
  400. package/src/services/ai-tools.ts +71 -27
  401. package/src/services/ai-write-report.ts +20 -12
  402. package/src/services/ai-writes.ts +4 -4
  403. package/src/services/automation.ts +74 -51
  404. package/src/services/cem-export.ts +149 -58
  405. package/src/services/cf-settings.ts +4 -4
  406. package/src/services/clock.ts +6 -1
  407. package/src/services/code-services.ts +37 -31
  408. package/src/services/connection.ts +2 -2
  409. package/src/services/context-manager.ts +14 -10
  410. package/src/services/context-resolver.ts +20 -8
  411. package/src/services/data-service.ts +19 -15
  412. package/src/services/directory-picker.ts +20 -14
  413. package/src/services/document-assistant.ts +39 -19
  414. package/src/services/gated-registry.ts +10 -6
  415. package/src/services/harness/chat-reducer.ts +23 -1
  416. package/src/services/import-client.ts +91 -38
  417. package/src/services/import-seed.ts +8 -2
  418. package/src/services/jx-validate.ts +28 -31
  419. package/src/services/live-preview.ts +0 -0
  420. package/src/services/live-surfaces.ts +6 -3
  421. package/src/services/model-uri.ts +10 -2
  422. package/src/services/module-preloads.ts +12 -8
  423. package/src/services/monaco-buffer.ts +43 -24
  424. package/src/services/monaco-lazy.ts +7 -8
  425. package/src/services/monaco-setup.ts +23 -16
  426. package/src/services/notify.ts +44 -17
  427. package/src/services/popover-report.ts +25 -10
  428. package/src/services/preview-eval.ts +20 -8
  429. package/src/services/profile.ts +13 -6
  430. package/src/services/project-path.ts +13 -10
  431. package/src/services/references.ts +0 -0
  432. package/src/services/render-critic.ts +29 -9
  433. package/src/services/settings/definitions.ts +25 -14
  434. package/src/services/settings/kernel.ts +13 -4
  435. package/src/services/settings/write-queue.ts +9 -9
  436. package/src/services/token-lint.ts +12 -10
  437. package/src/services/tool-executor.ts +17 -5
  438. package/src/services/tool-outcomes.ts +44 -24
  439. package/src/services/trusted-types.ts +24 -7
  440. package/src/settings/contexts-section.ts +11 -8
  441. package/src/settings/contributed-section.ts +128 -70
  442. package/src/settings/css-vars-editor.ts +119 -32
  443. package/src/settings/defs-editor.ts +38 -35
  444. package/src/settings/developer-panels.ts +43 -0
  445. package/src/settings/extension-rows.ts +16 -8
  446. package/src/settings/extension-sections.ts +42 -14
  447. package/src/settings/extensions-section.ts +4 -1
  448. package/src/settings/general-settings.ts +101 -28
  449. package/src/settings/locales-section.ts +20 -12
  450. package/src/settings/preferences-dialog.ts +17 -7
  451. package/src/settings/preferences-keymap.ts +7 -5
  452. package/src/settings/preferences-sections.ts +11 -5
  453. package/src/settings/project-sections.ts +28 -11
  454. package/src/settings/schema-field-ui.ts +12 -1
  455. package/src/settings/section-registry.ts +116 -11
  456. package/src/settings/settings-dialog.ts +192 -0
  457. package/src/settings/settings-document.ts +186 -166
  458. package/src/shell/tree.ts +6 -5
  459. package/src/shell.ts +536 -477
  460. package/src/site-context.ts +101 -32
  461. package/src/state.ts +68 -57
  462. package/src/store.ts +54 -34
  463. package/src/studio.ts +219 -116
  464. package/src/style/live-preview.ts +1 -1
  465. package/src/style/project-styles.ts +40 -7
  466. package/src/style/stylebook-specimens.ts +89 -0
  467. package/src/style/stylebook-target.ts +26 -0
  468. package/src/style/tag-inheritance.ts +105 -0
  469. package/src/style/token-ref.ts +5 -4
  470. package/src/style/variables-focus.ts +61 -0
  471. package/src/style/variables-view.ts +235 -0
  472. package/src/surfaces/about.ts +18 -19
  473. package/src/surfaces/add-new.json +1482 -0
  474. package/src/surfaces/add-new.ts +325 -0
  475. package/src/surfaces/add-repo.ts +17 -19
  476. package/src/surfaces/ai-chat.ts +33 -38
  477. package/src/surfaces/ai-credentials-form.ts +6 -16
  478. package/src/surfaces/ai-managed-connect.ts +3 -4
  479. package/src/surfaces/ai-model-picker.ts +3 -5
  480. package/src/surfaces/block-action-bar.ts +22 -11
  481. package/src/surfaces/boot-failure.json +4 -3
  482. package/src/surfaces/boot-failure.ts +4 -5
  483. package/src/surfaces/bottom-dock.json +1 -1
  484. package/src/surfaces/bottom-dock.ts +9 -18
  485. package/src/surfaces/canvas-stage.json +30 -19
  486. package/src/surfaces/canvas-stage.ts +17 -16
  487. package/src/surfaces/cf-account-picker.ts +17 -18
  488. package/src/surfaces/collections-panel.json +615 -0
  489. package/src/surfaces/collections-panel.ts +168 -0
  490. package/src/surfaces/commandbar.json +241 -96
  491. package/src/surfaces/commandbar.ts +145 -105
  492. package/src/surfaces/convert-repeater.ts +17 -19
  493. package/src/surfaces/data-actions.ts +9 -7
  494. package/src/surfaces/dialog.ts +26 -28
  495. package/src/surfaces/diff-toolbar.ts +9 -7
  496. package/src/surfaces/empty-state.json +1 -1
  497. package/src/surfaces/empty-state.ts +7 -10
  498. package/src/surfaces/entry-editor.json +136 -0
  499. package/src/surfaces/entry-editor.ts +35 -11
  500. package/src/surfaces/entry-inspector.json +371 -0
  501. package/src/surfaces/entry-inspector.ts +143 -0
  502. package/src/surfaces/expression-editor.ts +11 -25
  503. package/src/surfaces/files-panel.ts +27 -14
  504. package/src/surfaces/formula-palette.ts +4 -5
  505. package/src/surfaces/github-auth.ts +16 -20
  506. package/src/surfaces/github-publish.ts +17 -22
  507. package/src/surfaces/grid-cell.ts +30 -31
  508. package/src/surfaces/grid-open.ts +10 -14
  509. package/src/surfaces/grid-panel.ts +13 -9
  510. package/src/surfaces/grid-replace.ts +13 -13
  511. package/src/surfaces/grid-views.ts +15 -18
  512. package/src/surfaces/inspector-dock.json +162 -14
  513. package/src/surfaces/inspector-dock.ts +59 -31
  514. package/src/surfaces/jump-bar.ts +5 -6
  515. package/src/surfaces/jxsuite-update.ts +16 -22
  516. package/src/surfaces/library-pane.json +670 -437
  517. package/src/surfaces/library-pane.ts +111 -77
  518. package/src/surfaces/logic-panel.ts +17 -30
  519. package/src/surfaces/logic-workspace.ts +13 -15
  520. package/src/surfaces/media-browser.json +62 -6
  521. package/src/surfaces/media-browser.ts +26 -11
  522. package/src/surfaces/media-field.json +1 -1
  523. package/src/surfaces/media-field.ts +4 -5
  524. package/src/surfaces/media-library.json +1586 -0
  525. package/src/surfaces/media-library.ts +282 -0
  526. package/src/surfaces/media-pane.ts +8 -7
  527. package/src/surfaces/media-pick-dialog.json +71 -0
  528. package/src/surfaces/media-pick-dialog.ts +132 -0
  529. package/src/surfaces/menu.ts +47 -23
  530. package/src/surfaces/navigator-dock.ts +11 -12
  531. package/src/surfaces/new-project.ts +27 -26
  532. package/src/surfaces/pane-context.json +144 -77
  533. package/src/surfaces/pane-context.ts +44 -25
  534. package/src/surfaces/pane-grid.ts +15 -10
  535. package/src/surfaces/panel-activity.ts +5 -6
  536. package/src/surfaces/panel-data.ts +3 -4
  537. package/src/surfaces/panel-deploy-checklist.json +12 -6
  538. package/src/surfaces/panel-deploy-checklist.ts +8 -7
  539. package/src/surfaces/panel-elements.ts +5 -7
  540. package/src/surfaces/panel-i18n.ts +5 -7
  541. package/src/surfaces/panel-imports.ts +6 -13
  542. package/src/surfaces/panel-outline.ts +25 -19
  543. package/src/surfaces/panel-page.json +72 -2
  544. package/src/surfaces/panel-page.ts +49 -25
  545. package/src/surfaces/panel-problems.ts +5 -7
  546. package/src/surfaces/panel-signals.json +1 -1
  547. package/src/surfaces/panel-signals.ts +25 -39
  548. package/src/surfaces/panel-stylebook-layers.json +71 -204
  549. package/src/surfaces/panel-stylebook-layers.ts +5 -29
  550. package/src/surfaces/preferences.json +120 -48
  551. package/src/surfaces/preferences.ts +29 -11
  552. package/src/surfaces/progress-modal.ts +15 -9
  553. package/src/surfaces/properties-panel.json +1 -1
  554. package/src/surfaces/properties-panel.ts +20 -42
  555. package/src/surfaces/publish-quick.json +428 -0
  556. package/src/surfaces/publish-quick.ts +165 -0
  557. package/src/surfaces/publish-workspace.json +2892 -0
  558. package/src/surfaces/publish-workspace.ts +391 -0
  559. package/src/surfaces/publish.ts +18 -18
  560. package/src/surfaces/push-plan.ts +7 -8
  561. package/src/surfaces/rail.json +1 -159
  562. package/src/surfaces/rail.ts +22 -79
  563. package/src/surfaces/reference-field.ts +11 -15
  564. package/src/surfaces/schema-builder.ts +16 -22
  565. package/src/surfaces/schema-form.json +10 -2
  566. package/src/surfaces/schema-form.ts +17 -25
  567. package/src/surfaces/secret-field.ts +9 -6
  568. package/src/surfaces/seo.json +1 -1
  569. package/src/surfaces/seo.ts +21 -15
  570. package/src/surfaces/settings-contexts.ts +9 -7
  571. package/src/surfaces/settings-contributed.json +5 -5
  572. package/src/surfaces/settings-contributed.ts +32 -12
  573. package/src/surfaces/settings-css-vars.json +44 -36
  574. package/src/surfaces/settings-css-vars.ts +82 -16
  575. package/src/surfaces/settings-defs.json +2 -2
  576. package/src/surfaces/settings-defs.ts +17 -21
  577. package/src/surfaces/settings-deploy.json +2 -15
  578. package/src/surfaces/settings-deploy.ts +9 -16
  579. package/src/surfaces/settings-dialog.json +51 -0
  580. package/src/surfaces/settings-dialog.ts +169 -0
  581. package/src/surfaces/settings-extensions.ts +5 -6
  582. package/src/surfaces/settings-head.ts +33 -39
  583. package/src/surfaces/settings-locales.ts +8 -20
  584. package/src/surfaces/settings-overview.json +3 -3
  585. package/src/surfaces/settings-overview.ts +14 -8
  586. package/src/surfaces/settings-packages.ts +8 -7
  587. package/src/surfaces/settings-pane.json +269 -46
  588. package/src/surfaces/settings-pane.ts +88 -36
  589. package/src/surfaces/settings-rawjson.ts +5 -6
  590. package/src/surfaces/shell.json +2 -1
  591. package/src/surfaces/shell.ts +1 -2
  592. package/src/surfaces/site-panel.json +1029 -0
  593. package/src/surfaces/site-panel.ts +233 -0
  594. package/src/surfaces/slash-menu.json +63 -21
  595. package/src/surfaces/slash-menu.ts +42 -9
  596. package/src/surfaces/statements.ts +13 -18
  597. package/src/surfaces/statusbar.ts +56 -29
  598. package/src/surfaces/style-panel.ts +18 -31
  599. package/src/surfaces/stylebook-chrome.ts +3 -5
  600. package/src/surfaces/styles-panel.json +735 -0
  601. package/src/surfaces/styles-panel.ts +195 -0
  602. package/src/surfaces/styles-variables.json +149 -0
  603. package/src/surfaces/styles-variables.ts +145 -0
  604. package/src/surfaces/tab-strip.json +4 -4
  605. package/src/surfaces/tab-strip.ts +14 -13
  606. package/src/surfaces/target-line.ts +6 -7
  607. package/src/surfaces/welcome.ts +6 -8
  608. package/src/surfaces/writing-banner.json +94 -0
  609. package/src/surfaces/writing-banner.ts +80 -0
  610. package/src/tabs/bare-repeaters.ts +101 -0
  611. package/src/tabs/patch-ops.ts +4 -3
  612. package/src/tabs/project-config.ts +32 -21
  613. package/src/tabs/selection.ts +36 -8
  614. package/src/tabs/tab.ts +99 -48
  615. package/src/tabs/transact.ts +98 -53
  616. package/src/types.ts +53 -43
  617. package/src/ui/ai-credentials-form.ts +10 -13
  618. package/src/ui/ai-model-picker.ts +3 -3
  619. package/src/ui/cf-account-picker.ts +7 -9
  620. package/src/ui/color-selector.ts +9 -5
  621. package/src/ui/dynamic-slot.ts +7 -8
  622. package/src/ui/expression-editor.ts +112 -105
  623. package/src/ui/form-controls.ts +104 -56
  624. package/src/ui/formula-catalog.ts +239 -230
  625. package/src/ui/formula-chips.ts +33 -18
  626. package/src/ui/layers.ts +57 -31
  627. package/src/ui/media-picker.ts +300 -47
  628. package/src/ui/popover-surface.ts +20 -12
  629. package/src/ui/progress-modal.ts +13 -8
  630. package/src/ui/regions.ts +14 -12
  631. package/src/ui/schema-form.ts +372 -97
  632. package/src/ui/surface.ts +71 -8
  633. package/src/ui/timing.ts +9 -0
  634. package/src/ui/value-source.ts +44 -31
  635. package/src/ui/virtual-window.ts +29 -3
  636. package/src/utils/base64.ts +6 -4
  637. package/src/utils/edit-display.ts +366 -111
  638. package/src/utils/element-selectors.ts +3 -2
  639. package/src/utils/google-fonts.ts +15 -14
  640. package/src/utils/inherited-style.ts +18 -20
  641. package/src/utils/link-target.ts +1 -1
  642. package/src/utils/local-day.ts +18 -0
  643. package/src/utils/preview-format.ts +25 -3
  644. package/src/utils/strip-events.ts +49 -22
  645. package/src/utils/studio-utils.ts +29 -14
  646. package/src/view.ts +2 -3
  647. package/src/workspace/pane-derive.ts +14 -16
  648. package/src/workspace/session.ts +81 -50
  649. package/src/workspace/tab-workspace.ts +137 -0
  650. package/src/workspace/workspace-back.ts +189 -0
  651. package/src/workspace/workspace-home.ts +133 -0
  652. package/src/workspace/workspace-ids.ts +129 -0
  653. package/src/workspace/workspace-switch.ts +372 -0
  654. package/src/workspace/workspace.ts +165 -47
  655. package/styles/shell-frame.css +30 -7
  656. package/styles/shell-frame.json +15 -3
  657. package/dist/chunks/2020-va2wwra4.js +0 -4
  658. package/dist/chunks/adapter-f93pafd7.js +0 -4
  659. package/dist/chunks/cf-account-picker-af1h381v.js +0 -4
  660. package/dist/chunks/cf-settings-125tdm0w.js +0 -4
  661. package/dist/chunks/color-area-jqhna8zy.js +0 -4
  662. package/dist/chunks/color-field-embq5ctg.js +0 -4
  663. package/dist/chunks/color-fpezvnkt.js +0 -4
  664. package/dist/chunks/color-slider-1qmw7wqy.js +0 -4
  665. package/dist/chunks/combobox-773hdzyj.js +0 -4
  666. package/dist/chunks/components-ax2f1fnn.js +0 -4
  667. package/dist/chunks/content-source-108aqtk1.js +0 -4
  668. package/dist/chunks/convert-to-repeater-ry5rmppr.js +0 -4
  669. package/dist/chunks/dialog-mtm9fq5t.js +0 -4
  670. package/dist/chunks/editor-pfgdmkb0.js +0 -4
  671. package/dist/chunks/entry-commands-t0k1q0kx.js +0 -4
  672. package/dist/chunks/extension-sections-6mwh2hf8.js +0 -4
  673. package/dist/chunks/file-ops-meej5mqf.js +0 -4
  674. package/dist/chunks/files-44vp8a2s.js +0 -4
  675. package/dist/chunks/format-host-7q1petb9.js +0 -4
  676. package/dist/chunks/fs-events-h2mwnxaz.js +0 -4
  677. package/dist/chunks/git-panel-zngbymvd.js +0 -4
  678. package/dist/chunks/grid-view-sx9vynsp.js +0 -51
  679. package/dist/chunks/icons-p44xhjf0.js +0 -4
  680. package/dist/chunks/iframe-entry-f7mqjwpm.js +0 -5
  681. package/dist/chunks/iframe-entry-haw7jkvz.js +0 -5
  682. package/dist/chunks/iframe-entry-z6qrytv3.js +0 -5
  683. package/dist/chunks/iframe-host-qk3ycq87.js +0 -4
  684. package/dist/chunks/index-wkyfjeqz.js +0 -4
  685. package/dist/chunks/jsonMode-s8kt9dsj.js +0 -13
  686. package/dist/chunks/jx-validate-psgd7vsx.js +0 -4
  687. package/dist/chunks/layers-panel-1kq2jyfk.js +0 -4
  688. package/dist/chunks/layers-xd92fg8d.js +0 -4
  689. package/dist/chunks/listbox-s8fkmnq8.js +0 -4
  690. package/dist/chunks/lit-html-ac4cwwr4.js +0 -4
  691. package/dist/chunks/media-picker-0svzkdyb.js +0 -4
  692. package/dist/chunks/menu-37d07z9m.js +0 -4
  693. package/dist/chunks/menu-5c55ea3d.js +0 -4
  694. package/dist/chunks/monaco-binding-z6r70pdt.js +0 -4
  695. package/dist/chunks/monaco-buffer-fz6gq5y7.js +0 -4
  696. package/dist/chunks/monaco-setup-q4axkgj7.js +0 -4
  697. package/dist/chunks/notify-0xgtn8q1.js +0 -4
  698. package/dist/chunks/number-field-gw7sq8rn.js +0 -4
  699. package/dist/chunks/parse-897fvqah.js +0 -4
  700. package/dist/chunks/platform-v1qctbe6.js +0 -4
  701. package/dist/chunks/popover-8htra4er.js +0 -4
  702. package/dist/chunks/publish-panel-ym1fmgq5.js +0 -4
  703. package/dist/chunks/quick-search-a54e6t5n.js +0 -4
  704. package/dist/chunks/references-gmqp82fs.js +0 -4
  705. package/dist/chunks/right-panel-v7t9awbk.js +0 -4
  706. package/dist/chunks/section-registry-vhyf3zsr.js +0 -4
  707. package/dist/chunks/select-n3v7gwas.js +0 -4
  708. package/dist/chunks/split-pff8f3ze.js +0 -4
  709. package/dist/chunks/studio-0bhx5hz6.js +0 -5
  710. package/dist/chunks/studio-0k1ddnyy.js +0 -6
  711. package/dist/chunks/studio-1b04pd0j.js +0 -64
  712. package/dist/chunks/studio-4dwbj6gb.js +0 -5
  713. package/dist/chunks/studio-4tanh828.js +0 -5
  714. package/dist/chunks/studio-55h4mstj.js +0 -4
  715. package/dist/chunks/studio-5tnvjkz4.js +0 -5
  716. package/dist/chunks/studio-60dqgb0c.js +0 -5
  717. package/dist/chunks/studio-61dp09qg.js +0 -9
  718. package/dist/chunks/studio-63epcrj2.js +0 -5
  719. package/dist/chunks/studio-74k29dy9.js +0 -5
  720. package/dist/chunks/studio-7vg6jcd3.js +0 -5
  721. package/dist/chunks/studio-7zx31knw.js +0 -9
  722. package/dist/chunks/studio-8bxk97km.js +0 -5
  723. package/dist/chunks/studio-933e30n4.js +0 -5
  724. package/dist/chunks/studio-98wnwhbg.js +0 -5
  725. package/dist/chunks/studio-9mccjwjh.js +0 -14
  726. package/dist/chunks/studio-a2ke1e4t.js +0 -5
  727. package/dist/chunks/studio-e3a2a6v3.js +0 -4
  728. package/dist/chunks/studio-e81q1vb9.js +0 -5
  729. package/dist/chunks/studio-epgrmqqm.js +0 -5
  730. package/dist/chunks/studio-ery42sqr.js +0 -4
  731. package/dist/chunks/studio-g1shz58g.js +0 -5
  732. package/dist/chunks/studio-gf0fz03c.js +0 -5
  733. package/dist/chunks/studio-gjtpe62q.js +0 -6
  734. package/dist/chunks/studio-gkskhg7m.js +0 -5
  735. package/dist/chunks/studio-gx4dnjzd.js +0 -5
  736. package/dist/chunks/studio-j03zga3y.js +0 -9
  737. package/dist/chunks/studio-jhpxeckz.js +0 -5
  738. package/dist/chunks/studio-k01r7ykp.js +0 -5
  739. package/dist/chunks/studio-kk7h30ne.js +0 -7
  740. package/dist/chunks/studio-kt1zqney.js +0 -5
  741. package/dist/chunks/studio-m3cwhvye.js +0 -5
  742. package/dist/chunks/studio-mcayt6hz.js +0 -5
  743. package/dist/chunks/studio-myjcghv3.js +0 -5
  744. package/dist/chunks/studio-n8bxwc3y.js +0 -4
  745. package/dist/chunks/studio-ngm8gvpb.js +0 -5
  746. package/dist/chunks/studio-nj5a01jy.js +0 -928
  747. package/dist/chunks/studio-pcgz8heb.js +0 -5
  748. package/dist/chunks/studio-qcsq0t15.js +0 -5
  749. package/dist/chunks/studio-qkstvve9.js +0 -5
  750. package/dist/chunks/studio-qv1pwd3c.js +0 -5
  751. package/dist/chunks/studio-rc6dvxjb.js +0 -7
  752. package/dist/chunks/studio-s8dmmz66.js +0 -5
  753. package/dist/chunks/studio-sp5xzbj4.js +0 -6
  754. package/dist/chunks/studio-szsjbj0g.js +0 -5
  755. package/dist/chunks/studio-t1xzawhr.js +0 -16
  756. package/dist/chunks/studio-tdcprbqb.js +0 -5
  757. package/dist/chunks/studio-vrmcjf9g.js +0 -7
  758. package/dist/chunks/studio-vyc0b4he.js +0 -10
  759. package/dist/chunks/studio-w0cgf6jg.js +0 -5
  760. package/dist/chunks/studio-w3hskzqk.js +0 -5
  761. package/dist/chunks/studio-xgrgcdyh.js +0 -9
  762. package/dist/chunks/studio-xz2yxfcb.js +0 -5
  763. package/dist/chunks/studio-y6n42tgs.js +0 -5
  764. package/dist/chunks/studio-yb560vxr.js +0 -5
  765. package/dist/chunks/studio-yn9f8vtx.js +0 -5
  766. package/dist/chunks/studio-yw05w8f0.js +0 -7
  767. package/dist/chunks/studio-z16sgavc.js +0 -5
  768. package/dist/chunks/studio-zey7zsdw.js +0 -12
  769. package/dist/chunks/studio-zyqn40w4.js +0 -5
  770. package/dist/chunks/swatch-group-8qh9a3bm.js +0 -4
  771. package/dist/chunks/tabs-jwthg40w.js +0 -4
  772. package/dist/chunks/textfield-spy3hc77.js +0 -4
  773. package/dist/chunks/toast-4d35zd64.js +0 -4
  774. package/dist/chunks/toast-host-8sjmfed3.js +0 -4
  775. package/dist/chunks/tooltip-fd6g9xy3.js +0 -4
  776. package/dist/chunks/tree-h19v1jfz.js +0 -4
  777. package/dist/chunks/tsMode-2frah6h1.js +0 -14
  778. package/dist/chunks/workspace-zt81g1ms.js +0 -4
  779. package/dist/chunks/ws-client-n2bh4hkf.js +0 -4
  780. package/src/panels/frontmatter-panel.ts +0 -701
  781. package/src/panels/git-panel.ts +0 -1120
  782. package/src/surfaces/doc-header.json +0 -776
  783. package/src/surfaces/doc-header.ts +0 -231
  784. package/src/surfaces/git-panel.json +0 -1880
  785. package/src/surfaces/git-panel.ts +0 -272
@@ -8,11 +8,12 @@
8
8
  * @docs framework/site/i18n
9
9
  */
10
10
 
11
+ import { isNonNullObject, isString } from "@jxsuite/schema/guards";
11
12
  import { projectState } from "./store";
12
13
  import { getPlatform } from "./platform";
13
14
  import { commitProjectConfig } from "./tabs/project-config";
14
15
 
15
- import { resolveI18n } from "@jxsuite/schema/locale";
16
+ import { canonicalizeLocale, localeOfPath, resolveI18n } from "@jxsuite/schema/locale";
16
17
  import type { ResolvedI18n } from "@jxsuite/schema/locale";
17
18
  import type {
18
19
  JxElement,
@@ -21,6 +22,7 @@ import type {
21
22
  JxStyle,
22
23
  ProjectConfig,
23
24
  } from "@jxsuite/schema/types";
25
+ import type { ExtensionsInfo } from "./types";
24
26
 
25
27
  /**
26
28
  * Merge site $media with document $media. Document keys win on conflict.
@@ -57,10 +59,8 @@ export function getEffectiveStyle(docStyle?: JxStyle) {
57
59
  }
58
60
  const merged = { ...siteStyle };
59
61
  for (const [k, v] of Object.entries(docStyle)) {
60
- merged[k] =
61
- typeof v === "object" && v !== null && typeof merged[k] === "object" && merged[k] !== null
62
- ? { ...(merged[k] as JxStyle), ...(v as JxStyle) }
63
- : v;
62
+ const base = merged[k];
63
+ merged[k] = isNonNullObject(v) && isNonNullObject(base) ? { ...base, ...v } : v;
64
64
  }
65
65
  return merged;
66
66
  }
@@ -72,15 +72,35 @@ export function getEffectiveStyle(docStyle?: JxStyle) {
72
72
  * undefined)
73
73
  * @returns {Record<string, string>}
74
74
  */
75
- export function getEffectiveImports(docImports?: Record<string, string>) {
76
- const siteImports = projectState?.projectConfig?.imports;
77
- if (!siteImports) {
78
- return docImports || {};
79
- }
80
- if (!docImports) {
81
- return { ...siteImports };
82
- }
83
- 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());
84
104
  }
85
105
 
86
106
  /**
@@ -101,7 +121,8 @@ export function getEffectiveElements(docElements?: (JxElement | string)[]) {
101
121
  const seen = new Set<string>();
102
122
  const merged: (JxElement | string)[] = [];
103
123
  for (const entry of [...siteElements, ...docElements]) {
104
- const key = typeof entry === "string" ? entry : entry?.$ref;
124
+ // A null entry in hand-edited JSON has no key, and is skipped rather than thrown on.
125
+ const key = isString(entry) ? entry : isNonNullObject(entry) ? entry.$ref : undefined;
105
126
  if (key && !seen.has(key)) {
106
127
  seen.add(key);
107
128
  merged.push(entry);
@@ -127,8 +148,9 @@ export function getEffectiveHead(docHead?: JxHeadEntry[]) {
127
148
  const seen = new Set<string>();
128
149
  const merged: JxHeadEntry[] = [];
129
150
  for (const entry of [...siteHead, ...docHead]) {
130
- const key =
131
- String(entry?.attributes?.href || entry?.attributes?.src || "") || JSON.stringify(entry);
151
+ // A null entry in hand-edited JSON is keyed by its serialisation, like any entry without a URL.
152
+ const attributes = isNonNullObject(entry) ? entry.attributes : undefined;
153
+ const key = String(attributes?.href || attributes?.src || "") || JSON.stringify(entry);
132
154
  if (!seen.has(key)) {
133
155
  seen.add(key);
134
156
  merged.push(entry);
@@ -158,6 +180,39 @@ export function getEffectiveLocales(): ResolvedI18n | null {
158
180
  return config ? resolveI18n(config).i18n : null;
159
181
  }
160
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
+
161
216
  // ─── Layout resolution ──────────────────────────────────────────────────────
162
217
 
163
218
  const layoutCache = new Map<string, JxMutableNode>();
@@ -189,13 +244,16 @@ export function getEffectiveLayoutPath(docLayout: string | false | undefined) {
189
244
  */
190
245
  export async function resolveLayoutDoc(layoutPath: string) {
191
246
  const normalized = layoutPath.replace(/^\.\//, "");
192
- if (layoutCache.has(normalized)) {
193
- return structuredClone(layoutCache.get(normalized) as JxMutableNode);
247
+ const cached = layoutCache.get(normalized);
248
+ if (cached !== undefined) {
249
+ return structuredClone(cached);
194
250
  }
195
251
 
196
252
  try {
197
253
  const platform = getPlatform();
198
254
  const content = await platform.readFile(normalized);
255
+ /* SAFETY: a `$layout` target is a Jx document file, which is a JSON element object; the slot
256
+ walk that consumes it checks `children` is an array before reading any of it. */
199
257
  const doc = JSON.parse(content) as JxMutableNode;
200
258
  layoutCache.set(normalized, doc);
201
259
  return structuredClone(doc);
@@ -220,8 +278,8 @@ export function distributePageIntoLayout(layoutDoc: JxMutableNode, pageDoc: JxMu
220
278
  const defaults: (JxMutableNode | string)[] = [];
221
279
 
222
280
  for (const child of children) {
223
- const slotName = typeof child === "object" ? child.attributes?.slot : undefined;
224
- if (typeof child === "object" && typeof slotName === "string" && slotName) {
281
+ const slotName = isString(child) ? undefined : child.attributes?.slot;
282
+ if (!isString(child) && isString(slotName) && slotName) {
225
283
  if (!named.has(slotName)) {
226
284
  named.set(slotName, []);
227
285
  }
@@ -254,18 +312,15 @@ function fillSlots(
254
312
  named: Map<string, JxMutableNode[]>,
255
313
  defaults: (JxMutableNode | string)[],
256
314
  ) {
257
- if (!node || typeof node !== "object") {
258
- return;
259
- }
260
315
  if (!Array.isArray(node.children)) {
261
316
  return;
262
317
  }
263
318
 
264
319
  const newChildren: (JxMutableNode | string)[] = [];
265
320
  for (const child of node.children) {
266
- if (child && typeof child === "object" && child.tagName === "slot") {
321
+ if (isNonNullObject(child) && child.tagName === "slot") {
267
322
  const slotName = child.attributes?.name;
268
- if (typeof slotName === "string" && slotName && named.has(slotName)) {
323
+ if (isString(slotName) && slotName && named.has(slotName)) {
269
324
  newChildren.push(...named.get(slotName)!);
270
325
  named.delete(slotName);
271
326
  } else if (!slotName && defaults.length > 0) {
@@ -274,15 +329,26 @@ function fillSlots(
274
329
  newChildren.push(...child.children);
275
330
  }
276
331
  } else {
277
- if (typeof child !== "string") {
332
+ /* Only an element has slots to fill. A null child (hand-edited JSON) used to reach the
333
+ `!node` guard this function opened with; it now stops here, with the same outcome. */
334
+ if (isNonNullObject(child)) {
278
335
  fillSlots(child, named, defaults);
279
336
  }
280
337
  newChildren.push(child);
281
338
  }
282
339
  }
283
- node.children = newChildren as JxMutableNode[];
340
+ node.children = newChildren;
284
341
  }
285
342
 
343
+ /**
344
+ * A `project.json` patch: each key's new value, or `undefined` to remove the key.
345
+ *
346
+ * `Partial<ProjectConfig>` cannot say the second half under `exactOptionalPropertyTypes` — its
347
+ * `url` is `string` when present, never `undefined` — so clearing a setting had to be spelled as a
348
+ * double cast at every call site that wanted to.
349
+ */
350
+ export type ProjectConfigPatch = { [K in keyof ProjectConfig]?: ProjectConfig[K] | undefined };
351
+
286
352
  /**
287
353
  * Merge a partial patch into the project's configuration and persist it.
288
354
  *
@@ -297,12 +363,15 @@ function fillSlots(
297
363
  * Problem, because the eight other sites reach this through `void updateSiteConfig(...)` and used
298
364
  * to drop it on the floor.
299
365
  *
300
- * @param {Partial<ProjectConfig>} patch - Fields to merge into the current projectConfig; a value
301
- * of `undefined` clears the key.
366
+ * @param {ProjectConfigPatch} patch - Fields to merge into the current projectConfig; a value of
367
+ * `undefined` clears the key.
302
368
  * @throws {unknown} The platform's rejection, when the write fails.
303
369
  */
304
- export async function updateSiteConfig(patch: Partial<ProjectConfig>) {
305
- const result = await commitProjectConfig(patch);
370
+ export async function updateSiteConfig(patch: ProjectConfigPatch) {
371
+ /* SAFETY: `commitProjectConfig` spreads the patch over the current config and serialises the
372
+ result with JSON.stringify, so an `undefined` member reaches disk as an absent key and the
373
+ written file is a ProjectConfig; every other member already has its ProjectConfig type. */
374
+ const result = await commitProjectConfig(patch as Partial<ProjectConfig>);
306
375
  if (!result.ok) {
307
376
  throw result.error;
308
377
  }
package/src/state.ts CHANGED
@@ -12,7 +12,15 @@
12
12
  */
13
13
 
14
14
  import type { ProjectState } from "./types";
15
- import { displayTagName, isRef } from "@jxsuite/schema/guards";
15
+ import {
16
+ displayTagName,
17
+ isBoolean,
18
+ isMappedArray,
19
+ isNonNullObject,
20
+ isNumber,
21
+ isRef,
22
+ isString,
23
+ } from "@jxsuite/schema/guards";
16
24
  import type { JxMutableNode } from "@jxsuite/schema/types";
17
25
 
18
26
  export type JxPath = (string | number)[];
@@ -20,23 +28,10 @@ export type JxPath = (string | number)[];
20
28
  // ─── Path utilities ───────────────────────────────────────────────────────────
21
29
 
22
30
  /**
23
- * Walk the document tree and return the node at the given path.
24
- *
25
- * @param {JxMutableNode} doc
26
- * @param {JxPath} path
27
- * @returns {JxMutableNode}
31
+ * Walk the document tree and return the node at the given path, or `undefined` when a step falls
32
+ * off the tree (a path gone stale since it was taken). One walk, shared with the document ops.
28
33
  */
29
- export function getNodeAtPath(doc: JxMutableNode, path: JxPath) {
30
- let node = doc;
31
- for (const key of path) {
32
- if (node == null) {
33
- return undefined as unknown as JxMutableNode;
34
- }
35
- // Paths address nodes by construction; non-node leaves surface as undefined above.
36
- node = node[key] as JxMutableNode;
37
- }
38
- return node;
39
- }
34
+ export { getNodeAtPath } from "@jxsuite/schema/doc-ops";
40
35
 
41
36
  /**
42
37
  * The node's children when they are a static array (the edit-mode invariant); an empty array for
@@ -56,45 +51,62 @@ export function childList(node: JxMutableNode | null | undefined): (JxMutableNod
56
51
  * `$switch` cases. Runs once when a document is loaded into a tab so every in-studio doc — and its
57
52
  * history checkpoints — uses the member form before any mutation.
58
53
  *
59
- * @param {unknown} node
60
- * @returns {unknown} The same node (mutated)
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
+ *
58
+ * @param {T} node
59
+ * @param {BareRepeaterVisitor} [onBare]
60
+ * @param {string} [pointer] - The node's JSON Pointer, `""` for the root.
61
+ * @returns {T} The same node (mutated)
61
62
  */
62
- export function normalizeArrayChildren(node: unknown): unknown {
63
- if (!node || typeof node !== "object") {
63
+ export function normalizeArrayChildren<T>(node: T, onBare?: BareRepeaterVisitor, pointer = ""): T {
64
+ if (!isNonNullObject(node)) {
64
65
  return node;
65
66
  }
66
67
  if (Array.isArray(node)) {
67
- for (const child of node) {
68
- normalizeArrayChildren(child);
68
+ for (const [i, child] of node.entries()) {
69
+ normalizeArrayChildren(child, onBare, `${pointer}/${i}`);
69
70
  }
70
71
  return node;
71
72
  }
73
+ /* SAFETY: A non-array object reached from a document root, a children array, a repeater `map` or
74
+ a `$switch` case is a node definition, and JxMutableNode is the editor's open node shape. */
72
75
  const n = node as JxMutableNode;
73
76
  const { children } = n;
74
- if (
75
- children &&
76
- typeof children === "object" &&
77
- !Array.isArray(children) &&
78
- (children as JxMutableNode).$prototype === "Array"
79
- ) {
80
- n.children = [children as JxMutableNode];
77
+ if (isMappedArray(children)) {
78
+ // SAFETY: A legacy whole-children repeater is the same repeater node that becomes the member.
79
+ const repeater = children as JxMutableNode;
80
+ onBare?.(pointer, repeater);
81
+ n.children = [repeater];
81
82
  }
82
83
  if (Array.isArray(n.children)) {
83
- for (const child of n.children) {
84
- normalizeArrayChildren(child);
84
+ for (const [i, child] of n.children.entries()) {
85
+ normalizeArrayChildren(child, onBare, `${pointer}/children/${i}`);
85
86
  }
86
87
  }
87
- if (n.$prototype === "Array" && n.map && typeof n.map === "object") {
88
- normalizeArrayChildren(n.map);
88
+ if (n.$prototype === "Array" && isNonNullObject(n.map)) {
89
+ normalizeArrayChildren(n.map, onBare, `${pointer}/map`);
89
90
  }
90
- if (n.cases && typeof n.cases === "object") {
91
- for (const caseDef of Object.values(n.cases)) {
92
- normalizeArrayChildren(caseDef);
91
+ if (isNonNullObject(n.cases)) {
92
+ for (const [key, caseDef] of Object.entries(n.cases)) {
93
+ normalizeArrayChildren(caseDef, onBare, `${pointer}/cases/${pointerToken(key)}`);
93
94
  }
94
95
  }
95
96
  return node;
96
97
  }
97
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
+
98
110
  /**
99
111
  * Return the path to the parent element (strips trailing 'children' + index).
100
112
  *
@@ -209,7 +221,7 @@ function collectRows(
209
221
  skipSelf: boolean,
210
222
  ): void {
211
223
  // Text node children: bare primitives get a "text" row
212
- if (typeof doc === "string" || typeof doc === "number" || typeof doc === "boolean") {
224
+ if (isString(doc) || isNumber(doc) || isBoolean(doc)) {
213
225
  if (!skipSelf) {
214
226
  out.push({ depth, node: doc, nodeType: "text", path });
215
227
  }
@@ -220,13 +232,13 @@ function collectRows(
220
232
  // Recurse into its single template at `[...path, "map"]`. This is reached both when the array is
221
233
  // A member of a children array (path `[…, "children", i]`) and the legacy whole-children form
222
234
  // (path `[…, "children"]`).
223
- if ((doc as JxMutableNode).$prototype === "Array") {
235
+ if (doc.$prototype === "Array") {
224
236
  if (!skipSelf) {
225
237
  out.push({ depth, node: doc, nodeType: "map", path });
226
238
  }
227
- const mapDef = (doc as JxMutableNode).map;
228
- if (mapDef && typeof mapDef === "object") {
229
- collectRows(mapDef as JxMutableNode, [...path, "map"], depth + 1, out, false);
239
+ const mapDef = doc.map;
240
+ if (isNonNullObject(mapDef)) {
241
+ collectRows(mapDef, [...path, "map"], depth + 1, out, false);
230
242
  }
231
243
  return;
232
244
  }
@@ -247,36 +259,33 @@ function collectRows(
247
259
  const childPath = [...path, "children", i];
248
260
  collectRows(children[i]!, childPath, depth + 1, out, false);
249
261
  }
250
- } else if (
251
- children &&
252
- typeof children === "object" &&
253
- (children as JxMutableNode).$prototype === "Array"
254
- ) {
262
+ } else if (isMappedArray(children)) {
255
263
  // Legacy whole-children repeater: the array occupies the children slot itself.
264
+ // SAFETY: The repeater in the children slot is the same repeater node a children member is.
256
265
  collectRows(children as JxMutableNode, [...path, "children"], depth + 1, out, false);
257
266
  }
258
267
 
259
268
  // $switch — emit each case as a virtual child
260
- if (doc.$switch && doc.cases && typeof doc.cases === "object") {
269
+ if (doc.$switch && isNonNullObject(doc.cases)) {
261
270
  for (const [caseName, caseDef] of Object.entries(doc.cases)) {
262
271
  const casePath = [...path, "cases", caseName];
263
- if (caseDef && typeof caseDef === "object" && (caseDef as JxMutableNode).$ref) {
272
+ if (isNonNullObject(caseDef) && caseDef.$ref) {
264
273
  out.push({
265
274
  depth: depth + 1,
266
- node: caseDef as JxMutableNode,
275
+ node: caseDef,
267
276
  nodeType: "case-ref",
268
277
  path: casePath,
269
278
  });
270
- } else if (caseDef && typeof caseDef === "object") {
279
+ } else if (isNonNullObject(caseDef)) {
271
280
  out.push({
272
281
  depth: depth + 1,
273
- node: caseDef as JxMutableNode,
282
+ node: caseDef,
274
283
  nodeType: "case",
275
284
  path: casePath,
276
285
  });
277
286
  // Recurse into case children — skipSelf, because the "case" row above already stands in for
278
287
  // The case node itself (with its own nodeType).
279
- collectRows(caseDef as JxMutableNode, casePath, depth + 2, out, true);
288
+ collectRows(caseDef, casePath, depth + 2, out, true);
280
289
  }
281
290
  }
282
291
  }
@@ -285,10 +294,10 @@ function collectRows(
285
294
  /**
286
295
  * Get a display label for a node (for layers + overlays).
287
296
  *
288
- * @param {JxMutableNode | null} node
297
+ * @param {JxMutableNode | null | undefined} node
289
298
  * @returns {string}
290
299
  */
291
- export function nodeLabel(node: JxMutableNode | null) {
300
+ export function nodeLabel(node: JxMutableNode | null | undefined) {
292
301
  if (!node) {
293
302
  return "?";
294
303
  }
@@ -306,14 +315,14 @@ export function nodeLabel(node: JxMutableNode | null) {
306
315
  }
307
316
  if (node.tagName === "slot") {
308
317
  const name = node.attributes?.name;
309
- return typeof name === "string" && name.trim() ? `slot: ${name.trim()}` : "slot";
318
+ return isString(name) && name.trim() ? `slot: ${name.trim()}` : "slot";
310
319
  }
311
320
  /* `displayTagName`, because a tag may be CHOSEN rather than written: this label reached the
312
321
  Outline row, the Inspector's header and the jump bar, and a raw read rendered `[object Object]`
313
322
  in all three. `a|div` is the honest answer — one element, tag decided at creation. */
314
323
  const tag = displayTagName(node.tagName) || "div";
315
324
  const suffix = node.$switch ? " ⇆" : "";
316
- if (typeof node.textContent === "string" && node.textContent.length > 0) {
325
+ if (isString(node.textContent) && node.textContent.length > 0) {
317
326
  return `${tag} — ${node.textContent.slice(0, 24)}${suffix}`;
318
327
  }
319
328
  return tag + suffix;
@@ -340,5 +349,7 @@ export function setProjectState(ps: ProjectState | null) {
340
349
  * @returns {ProjectState}
341
350
  */
342
351
  export function requireProjectState() {
352
+ /* SAFETY: The contract above restricts callers to paths reached after `setProjectState` installed
353
+ a project (a project command, a panel that only mounts with one open); nothing here checks it. */
343
354
  return projectState as ProjectState;
344
355
  }
package/src/store.ts CHANGED
@@ -9,9 +9,10 @@
9
9
 
10
10
  // ─── Re-exports from state.js ────────────────────────────────────────────────
11
11
 
12
+ import { isFunction, isNonNullObject } from "@jxsuite/schema/guards";
12
13
  import { INPUT_DEBOUNCE } from "./ui/timing";
13
14
  import type { JxPath } from "./state";
14
- import type { Tab } from "./tabs/tab";
15
+ import type { Tab, TabUi } from "./tabs/tab";
15
16
  import type { JxMutableNode } from "@jxsuite/schema/types";
16
17
 
17
18
  export {
@@ -36,18 +37,38 @@ export {
36
37
  each of which meant "the pane I am acting on" and got "the pane that happens to be focused". A
37
38
  stage belongs to a pane (`canvas/canvas-surface.ts`), a pane's cell is built by
38
39
  `panels/pane-grid.ts`, and every one of those readers now takes its surface. */
39
- export let activityBar = null as unknown as HTMLElement;
40
- export let leftPanel = null as unknown as HTMLElement;
41
- export let rightPanel = null as unknown as HTMLElement;
42
- export let toolbarEl = null as unknown as HTMLElement;
43
- export let statusbarEl = null as unknown as HTMLElement;
40
+
41
+ /* Null until `initShellRefs()`, which `studio.ts` calls at boot right after mounting the shell
42
+ document; a render asked for before that (a test, or a command run ahead of the shell) reads null. */
43
+ export let activityBar: HTMLElement | null = null;
44
+ export let leftPanel: HTMLElement | null = null;
45
+ export let rightPanel: HTMLElement | null = null;
46
+ export let toolbarEl: HTMLElement | null = null;
47
+ export let statusbarEl: HTMLElement | null = null;
48
+
49
+ /** The shell region whose `id` is given, or null when the mounted shell has none. */
50
+ function shellRef(id: string): HTMLElement | null {
51
+ const element = document.querySelector(`#${id}`);
52
+ return element instanceof HTMLElement ? element : null;
53
+ }
44
54
 
45
55
  export function initShellRefs() {
46
- activityBar = document.querySelector("#activity-bar") as HTMLElement;
47
- leftPanel = document.querySelector("#left-panel") as HTMLElement;
48
- rightPanel = document.querySelector("#right-panel") as HTMLElement;
49
- toolbarEl = document.querySelector("#toolbar") as HTMLElement;
50
- statusbarEl = document.querySelector("#statusbar") as HTMLElement;
56
+ activityBar = shellRef("activity-bar");
57
+ leftPanel = shellRef("left-panel");
58
+ rightPanel = shellRef("right-panel");
59
+ toolbarEl = shellRef("toolbar");
60
+ statusbarEl = shellRef("statusbar");
61
+ }
62
+
63
+ /**
64
+ * A shell region for a caller that cannot work without it. Reading one before `initShellRefs()` has
65
+ * found it is a boot-order bug, so it throws a TypeError that names the region.
66
+ */
67
+ export function requireShellRef(ref: HTMLElement | null, id: string): HTMLElement {
68
+ if (!ref) {
69
+ throw new TypeError(`#${id} is not in the shell yet; initShellRefs() has not found it`);
70
+ }
71
+ return ref;
51
72
  }
52
73
 
53
74
  // ─── Shared constants ────────────────────────────────────────────────────────
@@ -130,6 +151,11 @@ export { stripEventHandlers } from "./utils/strip-events";
130
151
 
131
152
  const _renderers = new Map<string, () => void>();
132
153
 
154
+ /** Whether a renderer's return value is a thenable — an `async` renderer that is still painting. */
155
+ function isThenable(value: unknown): value is PromiseLike<unknown> {
156
+ return (isNonNullObject(value) || isFunction(value)) && "then" in value && isFunction(value.then);
157
+ }
158
+
133
159
  /**
134
160
  * How many registered renderers are mid-paint right now.
135
161
  *
@@ -154,9 +180,9 @@ function runRenderer(name: string, fn: () => void) {
154
180
  };
155
181
  let pending: PromiseLike<unknown> | null = null;
156
182
  try {
157
- const result = fn() as unknown;
158
- if (typeof (result as PromiseLike<unknown> | null)?.then === "function") {
159
- pending = result as PromiseLike<unknown>;
183
+ const result = fn();
184
+ if (isThenable(result)) {
185
+ pending = result;
160
186
  }
161
187
  } catch (error) {
162
188
  console.error(`Renderer "${name}" failed:`, error);
@@ -165,7 +191,7 @@ function runRenderer(name: string, fn: () => void) {
165
191
  done();
166
192
  return;
167
193
  }
168
- pending.then(done, (error: unknown) => {
194
+ pending.then(done, (error) => {
169
195
  console.error(`Renderer "${name}" failed:`, error);
170
196
  done();
171
197
  });
@@ -232,8 +258,8 @@ export function updateSession(
232
258
  selection?: JxPath[];
233
259
  hover?: JxPath | null;
234
260
  clipboard?: JxMutableNode | null;
235
- ui?: Record<string, unknown>;
236
- canvas?: Record<string, unknown>;
261
+ ui?: Partial<TabUi>;
262
+ canvas?: Partial<Tab["session"]["canvas"]>;
237
263
  },
238
264
  ) {
239
265
  if (tab) {
@@ -241,20 +267,16 @@ export function updateSession(
241
267
  tab.session.selection = patch.selection;
242
268
  }
243
269
  if (patch.hover !== undefined) {
244
- tab.session.hover = patch.hover as JxPath | null;
270
+ tab.session.hover = patch.hover;
245
271
  }
246
272
  if (patch.clipboard !== undefined) {
247
- tab.session.clipboard = patch.clipboard!;
273
+ tab.session.clipboard = patch.clipboard;
248
274
  }
249
275
  if (patch.ui) {
250
- for (const [k, v] of Object.entries(patch.ui)) {
251
- (tab.session.ui as unknown as Record<string, unknown>)[k] = v;
252
- }
276
+ Object.assign(tab.session.ui, patch.ui);
253
277
  }
254
278
  if (patch.canvas) {
255
- for (const [k, v] of Object.entries(patch.canvas)) {
256
- (tab.session.canvas as unknown as Record<string, unknown>)[k] = v;
257
- }
279
+ Object.assign(tab.session.canvas, patch.canvas);
258
280
  }
259
281
  }
260
282
  }
@@ -263,12 +285,12 @@ export function updateSession(
263
285
  * Update a single UI field on `tab`.
264
286
  *
265
287
  * @param {Tab | null} tab — the tab this field belongs to. `null` is a no-op.
266
- * @param {string} field
267
- * @param {unknown} value
288
+ * @param {K} field
289
+ * @param {TabUi[K]} value
268
290
  */
269
- export function updateUi(tab: Tab | null, field: string, value: unknown) {
291
+ export function updateUi<K extends keyof TabUi>(tab: Tab | null, field: K, value: TabUi[K]) {
270
292
  if (tab) {
271
- (tab.session.ui as unknown as Record<string, unknown>)[field] = value;
293
+ tab.session.ui[field] = value;
272
294
  }
273
295
  }
274
296
 
@@ -276,12 +298,10 @@ export function updateUi(tab: Tab | null, field: string, value: unknown) {
276
298
  * Update `tab`'s canvas async state (status, scope, error).
277
299
  *
278
300
  * @param {Tab | null} tab — the tab whose stage produced this state. `null` is a no-op.
279
- * @param {object} patch
301
+ * @param {Partial<Tab["session"]["canvas"]>} patch
280
302
  */
281
- export function updateCanvas(tab: Tab | null, patch: Record<string, unknown>) {
303
+ export function updateCanvas(tab: Tab | null, patch: Partial<Tab["session"]["canvas"]>) {
282
304
  if (tab) {
283
- for (const [k, v] of Object.entries(patch)) {
284
- (tab.session.canvas as Record<string, unknown>)[k] = v;
285
- }
305
+ Object.assign(tab.session.canvas, patch);
286
306
  }
287
307
  }