@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
@@ -24,16 +24,15 @@ import { runOfferedAction } from "../account/action-flow";
24
24
  import { platformSupportsAddRepo } from "../new-project/add-repo-modal";
25
25
  import { getProjectList } from "../project-list";
26
26
  import { reactive } from "../reactivity";
27
- import { now } from "../services/clock";
27
+ import { MINUTE, now } from "../services/clock";
28
28
  import { clearRecentProjects, getRecentProjects, removeRecentProject } from "../recent-projects";
29
- import { platformSupportsClone } from "../panels/git-panel";
29
+ import { platformSupportsClone } from "../publish/source-control";
30
30
  import { mountSurface, registerSurface } from "../ui/surface";
31
31
  import welcomeDoc from "./welcome.json";
32
- import type { JxDocument } from "@jxsuite/schema/types";
33
32
  import type { SurfaceHandle } from "../ui/surface";
34
33
  import type { AccountNotice, OfferedAction } from "../types";
35
34
 
36
- registerSurface("welcome", welcomeDoc as unknown as JxDocument);
35
+ registerSurface("welcome", welcomeDoc);
37
36
 
38
37
  interface WelcomeCtx {
39
38
  openProject: () => void;
@@ -122,7 +121,6 @@ export function recentLocations(
122
121
  return labels;
123
122
  }
124
123
 
125
- const MINUTE = 60_000;
126
124
  const HOUR = 60 * MINUTE;
127
125
  const DAY = 24 * HOUR;
128
126
 
@@ -195,7 +193,7 @@ interface CatalogueRow {
195
193
  detail: string;
196
194
  }
197
195
 
198
- interface WelcomeScope extends Record<string, unknown> {
196
+ interface WelcomeScope {
199
197
  actions: StartAction[];
200
198
  installNeeded: boolean;
201
199
  installUrl: string;
@@ -292,7 +290,7 @@ function noticeAction(key: string): OfferedAction | null {
292
290
 
293
291
  /** The reactive scope the surface reads, made once. */
294
292
  function state(): WelcomeScope {
295
- _state ??= reactive({
293
+ _state ??= reactive<WelcomeScope>({
296
294
  actions: [],
297
295
  catalogue: [],
298
296
  clear: () => {
@@ -342,7 +340,7 @@ function state(): WelcomeScope {
342
340
  }
343
341
  }
344
342
  },
345
- }) as WelcomeScope;
343
+ });
346
344
  return _state;
347
345
  }
348
346
 
@@ -0,0 +1,94 @@
1
+ {
2
+ "$schema": "https://jxsuite.com/schema/v1",
3
+ "$id": "StudioWritingBanner",
4
+ "$description": "The writing-mode banner (specs/studio.md §22.5): one slim line above the canvas while a collection entry is written inside its template's layout, saying what the arrangement is (the text and media are editable, the layout is locked) with the door to the template, which opens it in Design. `content/writing-banner.ts` decides whether there is a template to open and what it is called; this document draws a sentence and, when there is one, the button.",
5
+ "tagName": "div",
6
+ "attributes": {
7
+ "part": "banner",
8
+ "role": "note",
9
+ "data-jx-region": "${state.region}"
10
+ },
11
+ "style": {
12
+ "$description": "A quiet band, the Content-Entry board's: the canvas is the subject, so the banner is a tinted line rather than a panel, and its action is a quiet button.",
13
+ "display": "flex",
14
+ "alignItems": "center",
15
+ "flexWrap": "wrap",
16
+ "gap": "var(--jx-space-2)",
17
+ "padding": "var(--jx-space-1) var(--jx-space-4)",
18
+ "background": "color-mix(in srgb, var(--accent) 10%, var(--bg-panel))",
19
+ "borderBottom": "1px solid var(--border)",
20
+ "fontFamily": "var(--jx-font-sans)",
21
+ "fontSize": "var(--jx-text-sm)",
22
+ "color": "var(--fg-dim)",
23
+ "& [part=\"glyph\"]": {
24
+ "flexShrink": "0",
25
+ "color": "var(--accent)"
26
+ },
27
+ "& [part=\"text\"]": {
28
+ "flex": "1",
29
+ "minWidth": "0"
30
+ },
31
+ "& [part=\"action-slot\"]": {
32
+ "display": "contents"
33
+ }
34
+ },
35
+ "children": [
36
+ {
37
+ "tagName": "jx-icon",
38
+ "attributes": {
39
+ "part": "glyph"
40
+ },
41
+ "$props": {
42
+ "name": "lock-simple"
43
+ }
44
+ },
45
+ {
46
+ "tagName": "span",
47
+ "attributes": {
48
+ "part": "text"
49
+ },
50
+ "textContent": "${state.text}"
51
+ },
52
+ {
53
+ "tagName": "div",
54
+ "attributes": {
55
+ "part": "action-slot",
56
+ "role": "none"
57
+ },
58
+ "$switch": {
59
+ "$ref": "#/state/actionState"
60
+ },
61
+ "cases": {
62
+ "shown": {
63
+ "tagName": "jx-action-button",
64
+ "attributes": {
65
+ "part": "edit-template"
66
+ },
67
+ "$props": {
68
+ "size": "sm",
69
+ "quiet": true
70
+ },
71
+ "onclick": {
72
+ "$prototype": "Function",
73
+ "body": [
74
+ {
75
+ "operator": "call",
76
+ "target": {
77
+ "$ref": "#/state/openTemplate"
78
+ },
79
+ "value": []
80
+ }
81
+ ],
82
+ "description": "Opening the template is activating it, which enters Design (studio.md §22.1)."
83
+ },
84
+ "children": [
85
+ {
86
+ "tagName": "span",
87
+ "textContent": "${state.actionLabel}"
88
+ }
89
+ ]
90
+ }
91
+ }
92
+ }
93
+ ]
94
+ }
@@ -0,0 +1,80 @@
1
+ /// <reference lib="dom" />
2
+ /**
3
+ * The writing-mode banner surface: one line over the canvas while a collection entry is written
4
+ * inside its template's layout (`specs/studio.md` §22.5).
5
+ *
6
+ * This is the adapter. `content/writing-banner.ts` decides what the line says and where its button
7
+ * goes; this module writes the projection into a scope and mounts `writing-banner.json`.
8
+ *
9
+ * @docs studio/projects/content-types
10
+ */
11
+
12
+ import { reactive } from "../reactivity";
13
+ import { mountSurface, registerSurface } from "../ui/surface";
14
+ import writingBannerDoc from "./writing-banner.json";
15
+ import type { SurfaceHandle } from "../ui/surface";
16
+
17
+ registerSurface("writing-banner", writingBannerDoc);
18
+
19
+ /** What the banner draws. */
20
+ export interface WritingBannerView {
21
+ /** The region id stamped on the root: `pane.<id>/writing-banner`. */
22
+ region: string;
23
+ text: string;
24
+ /** "Design the post page", or "Edit the Base template in Design" when the entry has no page. */
25
+ actionLabel: string;
26
+ /** Whether there is a template to open at all. */
27
+ actionState: "hidden" | "shown";
28
+ }
29
+
30
+ export interface WritingBannerActions {
31
+ /** Open the entry's template in Design. */
32
+ openTemplate: () => void;
33
+ }
34
+
35
+ export interface WritingBannerHandle {
36
+ readonly ready: Promise<unknown>;
37
+ update: (view: WritingBannerView) => void;
38
+ dispose: () => void;
39
+ }
40
+
41
+ interface WritingBannerScope extends WritingBannerView, WritingBannerActions {}
42
+
43
+ /**
44
+ * Mount the banner into `host`, the empty node the canvas stage drew for it.
45
+ *
46
+ * @param host The stage's `writing-banner` host.
47
+ * @param view What it says.
48
+ * @param actions What its button does.
49
+ */
50
+ export function mountWritingBannerSurface(
51
+ host: HTMLElement,
52
+ view: WritingBannerView,
53
+ actions: WritingBannerActions,
54
+ ): WritingBannerHandle {
55
+ const scope: WritingBannerScope = reactive<WritingBannerScope>({ ...view, ...actions });
56
+ let mounted: SurfaceHandle | null = null;
57
+ let disposed = false;
58
+ const ready = mountSurface("writing-banner", scope, host).then((surface) => {
59
+ if (disposed) {
60
+ surface.dispose();
61
+ } else {
62
+ mounted = surface;
63
+ }
64
+ return surface;
65
+ });
66
+ return {
67
+ dispose() {
68
+ disposed = true;
69
+ mounted?.dispose();
70
+ mounted = null;
71
+ },
72
+ ready,
73
+ update(next) {
74
+ scope.region = next.region;
75
+ scope.text = next.text;
76
+ scope.actionLabel = next.actionLabel;
77
+ scope.actionState = next.actionState;
78
+ },
79
+ };
80
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * The repeaters a file wrote as a node's whole `children`, so a save can write them back that way.
3
+ *
4
+ * A node may hold a repeater two ways: as a member of its children array (`children: [{ $prototype:
5
+ * "Array", … }]`) or as the whole children slot (`children: { $prototype: "Array", … }`). The two
6
+ * render the same, and the editor works in the first form only: `normalizeArrayChildren` rewrites
7
+ * every document a tab loads, because every mutation, path and history checkpoint assumes a
8
+ * children array. Without a record of what the file said, a save then rewrote every bare repeater
9
+ * in it into the member form, so one inserted paragraph produced a diff in a list nobody touched,
10
+ * and undoing every edit still left the file different from the one on disk.
11
+ *
12
+ * **Two keys, either of which is enough.** The pointer of the node that held the repeater survives
13
+ * an edit inside the repeater (a restyled template); the repeater's own JSON survives an edit that
14
+ * moves it (a sibling inserted above an ancestor shifts every pointer below it). A repeater both
15
+ * moved and changed loses both and is written in the member form, which renders the same. Only a
16
+ * children array whose ONLY member is a repeater is unwrapped: a node that has gained a sibling of
17
+ * its repeater can no longer be written the bare way at all.
18
+ *
19
+ * @docs studio/interface/tabs
20
+ */
21
+
22
+ import { isJsonObject, isMappedArray } from "@jxsuite/schema/guards";
23
+ import type { JsonObject, JsonValue, JxMutableNode } from "@jxsuite/schema/types";
24
+ import { normalizeArrayChildren, pointerToken } from "../state";
25
+
26
+ /** What a file said about its bare repeaters, in the normalized document's coordinates. */
27
+ export interface BareRepeaters {
28
+ /** The JSON Pointer of each node whose `children` WAS the repeater. */
29
+ readonly pointers: ReadonlySet<string>;
30
+ /** `JSON.stringify` of each such repeater as it was read. */
31
+ readonly fingerprints: ReadonlySet<string>;
32
+ }
33
+
34
+ /**
35
+ * Normalize a freshly read document in place (`normalizeArrayChildren`) and return what it rewrote,
36
+ * or null when the file held no bare repeater — the common case, which needs no record.
37
+ */
38
+ export function normalizeDocument(document: JxMutableNode): BareRepeaters | null {
39
+ const pointers = new Set<string>();
40
+ const fingerprints = new Set<string>();
41
+ normalizeArrayChildren(document, (pointer, repeater) => {
42
+ pointers.add(pointer);
43
+ fingerprints.add(JSON.stringify(repeater));
44
+ });
45
+ return pointers.size === 0 ? null : { fingerprints, pointers };
46
+ }
47
+
48
+ /**
49
+ * The document as the file should hold it: every single-member children array whose repeater the
50
+ * record names, written back as the node's whole `children`. Copy-on-write, so the tab's document
51
+ * (a reactive tree the editor owns) is never touched, and a document with nothing to restore is
52
+ * returned as it is.
53
+ */
54
+ export function restoreBareRepeaters(
55
+ document: JxMutableNode,
56
+ record: BareRepeaters | null,
57
+ ): JxMutableNode {
58
+ if (!record) {
59
+ return document;
60
+ }
61
+ /* SAFETY: a Jx document is JSON (it is read from, and written to, a JSON file); the restored copy
62
+ is the same node with some `children` slots holding their sole repeater directly — the bare
63
+ form the node's schema allows. */
64
+ return restoreValue(document as JsonValue, "", record) as JxMutableNode;
65
+ }
66
+
67
+ /** Restore inside one value of the tree, returning it unchanged when nothing below it moved. */
68
+ function restoreValue(value: JsonValue, pointer: string, record: BareRepeaters): JsonValue {
69
+ if (Array.isArray(value)) {
70
+ let copy: JsonValue[] | null = null;
71
+ for (const [i, item] of value.entries()) {
72
+ const next = restoreValue(item, `${pointer}/${i}`, record);
73
+ if (next !== item) {
74
+ copy ??= [...value];
75
+ copy[i] = next;
76
+ }
77
+ }
78
+ return copy ?? value;
79
+ }
80
+ if (!isJsonObject(value)) {
81
+ return value;
82
+ }
83
+ let copy: JsonObject | null = null;
84
+ for (const [key, child] of Object.entries(value)) {
85
+ let next = restoreValue(child, `${pointer}/${pointerToken(key)}`, record);
86
+ if (key === "children" && Array.isArray(next) && next.length === 1) {
87
+ const [only] = next;
88
+ if (
89
+ isMappedArray(only) &&
90
+ (record.pointers.has(pointer) || record.fingerprints.has(JSON.stringify(only)))
91
+ ) {
92
+ next = only;
93
+ }
94
+ }
95
+ if (next !== child) {
96
+ copy ??= { ...value };
97
+ copy[key] = next;
98
+ }
99
+ }
100
+ return copy ?? value;
101
+ }
@@ -7,6 +7,7 @@
7
7
 
8
8
  // oxlint-disable-next-line unicorn/prefer-export-from -- JxDocOpPair is also used locally (TransactionRecord)
9
9
  import type { JxDocOpPair } from "@jxsuite/schema/doc-ops";
10
+ import type { JxDocumentValue, JxMutableNode } from "@jxsuite/schema/types";
10
11
  import type { JxPath } from "../state";
11
12
  import type { Tab } from "./tab.js";
12
13
 
@@ -48,8 +49,8 @@ export type { JxDocOpPair };
48
49
  */
49
50
  export interface JxFmOp {
50
51
  field: string;
51
- before?: unknown;
52
- after?: unknown;
52
+ before?: JxDocumentValue | undefined;
53
+ after?: JxDocumentValue | undefined;
53
54
  }
54
55
 
55
56
  /** Everything recorded during one transaction. */
@@ -82,7 +83,7 @@ export interface PatchConsumer {
82
83
  * was consumed by whichever pane's effect ran first, so the second full-rendered every patched
83
84
  * edit while the skip counter reported one skip.
84
85
  */
85
- markConsumed: (docRef: object, tab: Tab) => void;
86
+ markConsumed: (docRef: JxMutableNode, tab: Tab) => void;
86
87
  /**
87
88
  * Apply the batch to all ready canvas panels. Throws on any failure (caller escalates). `record`
88
89
  * carries the value-carrying `docOps` the iframe consumer posts across the frame boundary; the
@@ -63,7 +63,7 @@ import { errorMessage } from "@jxsuite/schema/parse";
63
63
  import { effect, toRaw } from "../reactivity";
64
64
  import { getPlatform } from "../platform";
65
65
  import { notify } from "../services/notify";
66
- import { requireProjectState, setProjectState } from "../state";
66
+ import { projectState, requireProjectState, setProjectState } from "../state";
67
67
  import { setWorkspaceProject, workspace } from "../workspace/workspace";
68
68
  import { PROJECT_CONFIG_PATH, createTab, disposeTab } from "./tab";
69
69
  import { transactDoc } from "./transact";
@@ -71,7 +71,7 @@ import { deriveJsonLayout, parseJsonDocument, serializeJson } from "@jxsuite/sch
71
71
  import type { JsonLayout } from "@jxsuite/schema/json-layout";
72
72
 
73
73
  import type { Tab } from "./tab";
74
- import type { ProjectConfig } from "@jxsuite/schema/types";
74
+ import type { JxMutableNode, ProjectConfig } from "@jxsuite/schema/types";
75
75
 
76
76
  export { PROJECT_CONFIG_PATH } from "./tab";
77
77
 
@@ -147,7 +147,7 @@ let _seeding: Promise<void> | null = null;
147
147
  */
148
148
  function openConfigTab(): Tab | null {
149
149
  const tab = workspace.tabs.get(PROJECT_CONFIG_PATH);
150
- return tab ? (toRaw(tab as unknown as object) as Tab) : null;
150
+ return tab ? toRaw(tab) : null;
151
151
  }
152
152
 
153
153
  /** Drop the current binding, disposing the detached document if that is what it was. */
@@ -169,7 +169,8 @@ function seedCommitted(): Promise<void> {
169
169
  const text = await getPlatform().readFile(PROJECT_CONFIG_PATH);
170
170
  const { document, layout } = parseJsonDocument(text);
171
171
  _layout = layout;
172
- _committed = serializeProjectConfig(document as unknown as ProjectConfig);
172
+ // {@link serializeProjectConfig}'s serialisation, over the file's parse rather than a config.
173
+ _committed = serializeJson(document, configLayout());
173
174
  } catch {
174
175
  // No file, an unreadable one, or one that does not parse. "Unknown" is the honest answer,
175
176
  // And an unknown file is one every commit must write.
@@ -240,8 +241,22 @@ function syncProjectState(config: ProjectConfig): void {
240
241
  * @returns {ProjectConfig | null}
241
242
  */
242
243
  function liveConfig(): ProjectConfig | null {
243
- const config = requireProjectState()?.projectConfig;
244
- return config ? (toRaw(config as unknown as object) as ProjectConfig) : null;
244
+ const config = projectState?.projectConfig;
245
+ return config ? toRaw(config) : null;
246
+ }
247
+
248
+ /**
249
+ * The configuration a configuration document holds, unwrapped.
250
+ *
251
+ * @param {JxMutableNode} document The bound tab's `doc.document`.
252
+ * @returns {ProjectConfig}
253
+ */
254
+ function configOf(document: JxMutableNode): ProjectConfig {
255
+ /* SAFETY: every document this module reads is the `project.json` tab's root, and that root is
256
+ only ever installed as a ProjectConfig: `createTab` below seeds it from `projectConfig`, an open
257
+ tab parsed the file the schema gate wrote, and every transaction here assigns configuration
258
+ keys. The Tab type calls every root a JxMutableNode; this is the one place that says which. */
259
+ return toRaw(document) as ProjectConfig;
245
260
  }
246
261
 
247
262
  /**
@@ -261,10 +276,10 @@ function liveConfig(): ProjectConfig | null {
261
276
  * settings surfaces render from `projectState` and mutate it in place, and every reader of the
262
277
  * document follows the root reference {@link transactDoc} replaces when the transaction ends.
263
278
  *
264
- * @param {Record<string, unknown>} target
279
+ * @param {JxMutableNode} target
265
280
  * @param {ProjectConfig} source
266
281
  */
267
- function replaceContents(target: Record<string, unknown>, source: ProjectConfig): void {
282
+ function replaceContents(target: JxMutableNode, source: ProjectConfig): void {
268
283
  for (const key of Object.keys(target)) {
269
284
  delete target[key];
270
285
  }
@@ -282,10 +297,10 @@ function bind(tab: Tab): Tab {
282
297
  tab.scope.run(() => {
283
298
  effect(() => {
284
299
  const doc = tab.doc.document;
285
- if (_bound !== tab || !requireProjectState()) {
300
+ if (_bound !== tab || !projectState) {
286
301
  return;
287
302
  }
288
- syncProjectState(toRaw(doc) as unknown as ProjectConfig);
303
+ syncProjectState(configOf(doc));
289
304
  });
290
305
  });
291
306
  return tab;
@@ -316,7 +331,7 @@ export function projectConfigDocument(): Tab {
316
331
  return bind(open);
317
332
  }
318
333
  _detached = createTab({
319
- document: (state.projectConfig ?? {}) as unknown as Record<string, unknown>,
334
+ document: state.projectConfig ?? {},
320
335
  documentPath: PROJECT_CONFIG_PATH,
321
336
  id: PROJECT_CONFIG_PATH,
322
337
  });
@@ -380,7 +395,7 @@ export async function commitProjectConfig(
380
395
  // The seed, and the record it read handed to the document — so the tab the Settings door opened
381
396
  // Writes the same bytes from ⌘S that this commit is about to.
382
397
  await lendProjectConfigLayout(tab);
383
- const current = toRaw(tab.doc.document) as unknown as ProjectConfig;
398
+ const current = configOf(tab.doc.document);
384
399
  const currentText = serializeProjectConfig(current);
385
400
 
386
401
  // Two objects that disagree — whichever one loses, an edit written into it is lost. Null when
@@ -404,7 +419,7 @@ export async function commitProjectConfig(
404
419
  }
405
420
 
406
421
  const base = rival ?? current;
407
- const next = patch ? ({ ...base, ...patch } as ProjectConfig) : base;
422
+ const next: ProjectConfig = patch ? { ...base, ...patch } : base;
408
423
  const text = serializeProjectConfig(next);
409
424
 
410
425
  // Nothing the file does not already say: no transaction, no write, and therefore no diff. The
@@ -417,7 +432,7 @@ export async function commitProjectConfig(
417
432
 
418
433
  const before = extensionsKey(current);
419
434
  transactDoc(tab, (t) => {
420
- const doc = t.doc.document as unknown as Record<string, unknown>;
435
+ const doc = t.doc.document;
421
436
  if (rival) {
422
437
  replaceContents(doc, rival);
423
438
  }
@@ -429,7 +444,7 @@ export async function commitProjectConfig(
429
444
  // Serialised from what the transaction actually LANDED, not from the `next` computed above: a
430
445
  // Gate on `transactDoc` can refuse a mutation, and writing the value it refused would put the
431
446
  // File and the document into the one disagreement this module exists to make impossible.
432
- const config = toRaw(tab.doc.document) as unknown as ProjectConfig;
447
+ const config = configOf(tab.doc.document);
433
448
  const output = serializeProjectConfig(config);
434
449
  try {
435
450
  await getPlatform().writeFile(PROJECT_CONFIG_PATH, output);
@@ -480,18 +495,14 @@ export async function commitProjectConfig(
480
495
  * @returns {Promise<void>}
481
496
  */
482
497
  export async function adoptProjectConfig(config: ProjectConfig, text: string): Promise<void> {
483
- if (!requireProjectState()) {
498
+ if (!projectState) {
484
499
  // No project state is no configuration document either ({@link projectConfigDocument} reads
485
500
  // One). The workspace copy is then the only thing there is to keep true.
486
501
  setWorkspaceProject(workspace.projectRoot, config);
487
502
  return;
488
503
  }
489
504
  const tab = projectConfigDocument();
490
- transactDoc(
491
- tab,
492
- (t) => replaceContents(t.doc.document as unknown as Record<string, unknown>, config),
493
- { skipHistory: true },
494
- );
505
+ transactDoc(tab, (t) => replaceContents(t.doc.document, config), { skipHistory: true });
495
506
  tab.doc.dirty = false;
496
507
  // Settle a read already in flight before saying what the file holds, or it would resolve after
497
508
  // These lines with the PREVIOUS bytes and record, and make the next real commit look like a
@@ -42,6 +42,8 @@
42
42
  * standing between a mixed selection and a half-applied, unrecorded delete.
43
43
  */
44
44
 
45
+ import { isNumber } from "@jxsuite/schema/guards";
46
+
45
47
  import type { JxPath } from "../state";
46
48
  import { isAncestor, pathsEqual } from "../state";
47
49
 
@@ -52,7 +54,7 @@ import { isAncestor, pathsEqual } from "../state";
52
54
  * @returns {JxPath | null}
53
55
  */
54
56
  export function primarySelection(selection: readonly JxPath[] | null | undefined): JxPath | null {
55
- return selection && selection.length > 0 ? (selection.at(-1) as JxPath) : null;
57
+ return selection?.at(-1) ?? null;
56
58
  }
57
59
 
58
60
  /**
@@ -62,7 +64,7 @@ export function primarySelection(selection: readonly JxPath[] | null | undefined
62
64
  * @returns {JxPath | null}
63
65
  */
64
66
  export function selectionAnchor(selection: readonly JxPath[] | null | undefined): JxPath | null {
65
- return selection && selection.length > 0 ? (selection[0] as JxPath) : null;
67
+ return selection?.[0] ?? null;
66
68
  }
67
69
 
68
70
  /**
@@ -187,7 +189,7 @@ export function comparePaths(a: JxPath, b: JxPath): number {
187
189
  if (x === y) {
188
190
  continue;
189
191
  }
190
- if (typeof x === "number" && typeof y === "number") {
192
+ if (isNumber(x) && isNumber(y)) {
191
193
  return x - y;
192
194
  }
193
195
  return String(x) < String(y) ? -1 : 1;
@@ -231,7 +233,27 @@ export function topLevelSelection(selection: readonly JxPath[]): JxPath[] {
231
233
  * @returns {boolean}
232
234
  */
233
235
  export function isSpliceablePath(path: JxPath): boolean {
234
- return path.at(-2) === "children" && typeof path.at(-1) === "number";
236
+ return spliceCoordinate(path) !== null;
237
+ }
238
+
239
+ /** Where a structural verb splices: the parent element's path and the index in its children. */
240
+ export interface SpliceCoordinate {
241
+ parentPath: JxPath;
242
+ index: number;
243
+ }
244
+
245
+ /**
246
+ * The splice coordinate `path` names, or `null` for no path and for every path
247
+ * {@link isSpliceablePath} refuses.
248
+ *
249
+ * @param {JxPath | null | undefined} path
250
+ * @returns {SpliceCoordinate | null}
251
+ */
252
+ export function spliceCoordinate(path: JxPath | null | undefined): SpliceCoordinate | null {
253
+ const index = path?.at(-1);
254
+ return path && path.at(-2) === "children" && isNumber(index)
255
+ ? { index, parentPath: path.slice(0, -2) }
256
+ : null;
235
257
  }
236
258
 
237
259
  /**
@@ -289,7 +311,13 @@ export function selectionsEqual(
289
311
  ): boolean {
290
312
  const x = a ?? [];
291
313
  const y = b ?? [];
292
- return x.length === y.length && x.every((p, i) => pathsEqual(p, y[i] as JxPath));
314
+ return x.length === y.length && x.every((p, i) => pathsEqual(p, y[i] ?? null));
315
+ }
316
+
317
+ /** One field's value read across the selection: `mixed` when the selected nodes disagree. */
318
+ export interface UnifiedValue<T> {
319
+ mixed: boolean;
320
+ value: T | undefined;
293
321
  }
294
322
 
295
323
  /**
@@ -306,13 +334,13 @@ export function selectionsEqual(
306
334
  *
307
335
  * @template T
308
336
  * @param {readonly T[]} values One per selected node, in selection order.
309
- * @returns {{ mixed: boolean; value: T | undefined }}
337
+ * @returns {UnifiedValue<T>}
310
338
  */
311
- export function unifyValues<T>(values: readonly T[]): { mixed: boolean; value: T | undefined } {
339
+ export function unifyValues<T>(values: readonly T[]): UnifiedValue<T> {
312
340
  if (values.length === 0) {
313
341
  return { mixed: false, value: undefined };
314
342
  }
315
- const first = values[0] as T;
343
+ const [first] = values;
316
344
  const key = JSON.stringify(first ?? null);
317
345
  for (let i = 1; i < values.length; i++) {
318
346
  if (JSON.stringify(values[i] ?? null) !== key) {