@jxsuite/studio 6.1.0 → 6.1.2

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 (645) hide show
  1. package/dist/chunks/2020-f2gkpy8d.js +4 -0
  2. package/dist/chunks/{action-group-2mqby73c.js → action-group-4aan7g6g.js} +3 -3
  3. package/dist/chunks/adapter-4912g339.js +4 -0
  4. package/dist/chunks/cf-account-picker-wccaenh6.js +4 -0
  5. package/dist/chunks/cf-settings-br6105tr.js +4 -0
  6. package/dist/chunks/color-28ksk2qm.js +4 -0
  7. package/dist/chunks/color-area-0fj8a4ga.js +4 -0
  8. package/dist/chunks/color-field-xch8kx2g.js +4 -0
  9. package/dist/chunks/color-slider-jxd8v350.js +4 -0
  10. package/dist/chunks/combobox-p0efwjke.js +4 -0
  11. package/dist/chunks/components-db68vsn7.js +4 -0
  12. package/dist/chunks/content-source-1449qesq.js +4 -0
  13. package/dist/chunks/convert-to-repeater-5h457egj.js +4 -0
  14. package/dist/chunks/dialog-c4x05vyx.js +4 -0
  15. package/dist/chunks/editor-x9jn86a7.js +4 -0
  16. package/dist/chunks/entry-commands-may24cpt.js +4 -0
  17. package/dist/chunks/extension-sections-pvr14vxr.js +4 -0
  18. package/dist/chunks/file-ops-x9v54pcj.js +4 -0
  19. package/dist/chunks/files-j3knqf0s.js +4 -0
  20. package/dist/chunks/format-host-tyre2trb.js +4 -0
  21. package/dist/chunks/fs-events-64ma9htc.js +4 -0
  22. package/dist/chunks/git-panel-84ps5dex.js +4 -0
  23. package/dist/chunks/grid-view-d2wq9ezg.js +51 -0
  24. package/dist/chunks/icons-pnfz478q.js +4 -0
  25. package/dist/chunks/iframe-entry-fvbk89gm.js +5 -0
  26. package/dist/chunks/iframe-entry-jdcktez8.js +5 -0
  27. package/dist/chunks/iframe-entry-x0ygf2yr.js +5 -0
  28. package/dist/chunks/iframe-entry-zap785cw.js +5 -0
  29. package/dist/chunks/iframe-host-ck6vejt5.js +4 -0
  30. package/dist/chunks/index-b8xw3vy9.js +4 -0
  31. package/dist/chunks/{index-gybvv7a6.js → index-zpjmzqfk.js} +3 -3
  32. package/dist/chunks/{javascript-rnvdp3k4.js → javascript-m54mnwp6.js} +3 -3
  33. package/dist/chunks/jsonMode-w15cmrcm.js +13 -0
  34. package/dist/chunks/jx-validate-at3zn8wa.js +4 -0
  35. package/dist/chunks/layers-h4xp1pss.js +4 -0
  36. package/dist/chunks/layers-panel-m5hw1d7g.js +4 -0
  37. package/dist/chunks/listbox-e74qjyq6.js +4 -0
  38. package/dist/chunks/lit-html-8t8t3dnr.js +4 -0
  39. package/dist/chunks/media-picker-2cweexc5.js +4 -0
  40. package/dist/chunks/menu-n6yzswmy.js +4 -0
  41. package/dist/chunks/menu-ynw13y0s.js +4 -0
  42. package/dist/chunks/monaco-binding-7gx83x3r.js +4 -0
  43. package/dist/chunks/monaco-buffer-qzxn567r.js +4 -0
  44. package/dist/chunks/monaco-setup-gxf6656g.js +4 -0
  45. package/dist/chunks/notify-cj5zbrs2.js +4 -0
  46. package/dist/chunks/number-field-y62xq0ty.js +4 -0
  47. package/dist/chunks/parse-b7ddhr8m.js +4 -0
  48. package/dist/chunks/platform-3dfws9js.js +4 -0
  49. package/dist/chunks/popover-jt2gxmzs.js +4 -0
  50. package/dist/chunks/publish-panel-1gvxbj21.js +4 -0
  51. package/dist/chunks/quick-search-0dajrwqg.js +4 -0
  52. package/dist/chunks/references-49qgt404.js +4 -0
  53. package/dist/chunks/right-panel-jm1bwe53.js +4 -0
  54. package/dist/chunks/section-registry-6kwc4fky.js +4 -0
  55. package/dist/chunks/select-rzds841e.js +4 -0
  56. package/dist/chunks/split-n2gfpm5m.js +4 -0
  57. package/dist/chunks/{studio-5g0ag7c0.js → studio-0q988f9w.js} +3 -3
  58. package/dist/chunks/studio-0rt52vpq.js +5 -0
  59. package/dist/chunks/studio-18vgbhs5.js +5 -0
  60. package/dist/chunks/{studio-pxg4ap1e.js → studio-1fxkaaea.js} +4 -4
  61. package/dist/chunks/studio-24mccdrj.js +5 -0
  62. package/dist/chunks/studio-2eh507zk.js +9 -0
  63. package/dist/chunks/studio-2hcbccfv.js +5 -0
  64. package/dist/chunks/studio-2j1cb95x.js +5 -0
  65. package/dist/chunks/studio-2jbs3rxv.js +5 -0
  66. package/dist/chunks/{studio-qbj760tx.js → studio-485046te.js} +7 -7
  67. package/dist/chunks/studio-4h8k4dw9.js +5 -0
  68. package/dist/chunks/studio-5f6n18kx.js +5 -0
  69. package/dist/chunks/studio-5gthpky6.js +5 -0
  70. package/dist/chunks/studio-5ve6bbep.js +5 -0
  71. package/dist/chunks/studio-6ep3js6b.js +9 -0
  72. package/dist/chunks/studio-6wkmf3wz.js +9 -0
  73. package/dist/chunks/studio-841rf3cg.js +5 -0
  74. package/dist/chunks/studio-8gmwgheg.js +5 -0
  75. package/dist/chunks/studio-8qm0ep50.js +5 -0
  76. package/dist/chunks/{studio-anyrgzvb.js → studio-90pq9km1.js} +4 -4
  77. package/dist/chunks/studio-924p1tm1.js +6 -0
  78. package/dist/chunks/{studio-v2bvmbjj.js → studio-a3g98wjr.js} +4 -4
  79. package/dist/chunks/studio-a3shpz9y.js +5 -0
  80. package/dist/chunks/studio-amsbaaar.js +6 -0
  81. package/dist/chunks/studio-at5spjbc.js +7 -0
  82. package/dist/chunks/studio-b2xv945e.js +5 -0
  83. package/dist/chunks/studio-bn5nkafw.js +5 -0
  84. package/dist/chunks/studio-bw6q5xjf.js +9 -0
  85. package/dist/chunks/studio-c7q0t9x1.js +5 -0
  86. package/dist/chunks/studio-camnhc96.js +6 -0
  87. package/dist/chunks/studio-cffqvnzd.js +5 -0
  88. package/dist/chunks/studio-d81xfh1g.js +5 -0
  89. package/dist/chunks/studio-dgz8d0c1.js +5 -0
  90. package/dist/chunks/studio-efvfrsf8.js +5 -0
  91. package/dist/chunks/studio-er30bpcx.js +5 -0
  92. package/dist/chunks/studio-ezscgr64.js +5 -0
  93. package/dist/chunks/studio-ffrrncvz.js +5 -0
  94. package/dist/chunks/studio-fpphgn8y.js +10 -0
  95. package/dist/chunks/studio-j1kvhdjk.js +4 -0
  96. package/dist/chunks/{studio-txjjzrsm.js → studio-j430n16g.js} +5 -5
  97. package/dist/chunks/studio-jjkg84nj.js +5 -0
  98. package/dist/chunks/studio-m0q32ars.js +4 -0
  99. package/dist/chunks/studio-m6bdst11.js +5 -0
  100. package/dist/chunks/studio-nv2cptd4.js +64 -0
  101. package/dist/chunks/studio-nwfrc98n.js +5 -0
  102. package/dist/chunks/studio-p1wgvp7r.js +5 -0
  103. package/dist/chunks/studio-pag2wncm.js +5 -0
  104. package/dist/chunks/studio-qvanvzfd.js +5 -0
  105. package/dist/chunks/studio-qwa64kt7.js +5 -0
  106. package/dist/chunks/studio-rk1zc4x3.js +928 -0
  107. package/dist/chunks/studio-se2r3ptc.js +5 -0
  108. package/dist/chunks/studio-sg2a0dh0.js +5 -0
  109. package/dist/chunks/studio-tjzjhe68.js +5 -0
  110. package/dist/chunks/{studio-0x3jyb8r.js → studio-tq0rtfwj.js} +4 -4
  111. package/dist/chunks/{studio-cpxkgjrj.js → studio-v0jzqdjm.js} +4 -4
  112. package/dist/chunks/studio-v2w7q8r1.js +7 -0
  113. package/dist/chunks/studio-v5vjq1h0.js +4 -0
  114. package/dist/chunks/studio-v8aga3vp.js +14 -0
  115. package/dist/chunks/studio-vfcdrfmv.js +5 -0
  116. package/dist/chunks/studio-vmfkgdjf.js +5 -0
  117. package/dist/chunks/studio-wt1816jj.js +5 -0
  118. package/dist/chunks/studio-wz73q5kq.js +4 -0
  119. package/dist/chunks/studio-y04qtxvp.js +7 -0
  120. package/dist/chunks/studio-y21g8zzg.js +5 -0
  121. package/dist/chunks/studio-y64hrt8p.js +12 -0
  122. package/dist/chunks/studio-ynn90f58.js +16 -0
  123. package/dist/chunks/studio-yxz682sx.js +5 -0
  124. package/dist/chunks/studio-zp7snvkq.js +5 -0
  125. package/dist/chunks/studio-zq4z6tm6.js +5 -0
  126. package/dist/chunks/swatch-group-ewh24n1f.js +4 -0
  127. package/dist/chunks/tabs-f5cw3tgp.js +4 -0
  128. package/dist/chunks/textfield-wewc8rq2.js +4 -0
  129. package/dist/chunks/toast-c9fn075p.js +4 -0
  130. package/dist/chunks/toast-host-ke5z4ng7.js +4 -0
  131. package/dist/chunks/{toolbar-2nnzqhrj.js → toolbar-44cm5cta.js} +3 -3
  132. package/dist/chunks/tooltip-5v8ngwj2.js +4 -0
  133. package/dist/chunks/tree-mdq3v5cw.js +4 -0
  134. package/dist/chunks/tsMode-sf49ee9x.js +14 -0
  135. package/dist/chunks/workspace-jtfahpee.js +4 -0
  136. package/dist/chunks/ws-client-nze0k6mv.js +4 -0
  137. package/dist/iframe-entry.js +16 -16
  138. package/dist/manifest.json +63 -63
  139. package/dist/studio.js +98 -98
  140. package/dist/workers/ts.worker.js +3 -3
  141. package/package.json +11 -11
  142. package/src/about/about-modal.ts +4 -3
  143. package/src/account/action-flow.ts +45 -38
  144. package/src/account-status.ts +7 -2
  145. package/src/browse/library-layouts.ts +8 -5
  146. package/src/browse/library-model.ts +18 -6
  147. package/src/browse/library-pane.ts +37 -21
  148. package/src/browse/library-preview.ts +14 -9
  149. package/src/browse/library-source.ts +1 -1
  150. package/src/canvas/asset-refs.ts +24 -9
  151. package/src/canvas/asset-resolve.ts +19 -23
  152. package/src/canvas/canvas-helpers.ts +7 -6
  153. package/src/canvas/canvas-live-render.ts +44 -53
  154. package/src/canvas/canvas-patcher.ts +30 -30
  155. package/src/canvas/canvas-perf.ts +11 -5
  156. package/src/canvas/canvas-render.ts +66 -42
  157. package/src/canvas/canvas-surface.ts +5 -3
  158. package/src/canvas/canvas-utils.ts +163 -64
  159. package/src/canvas/dialog-path.ts +9 -4
  160. package/src/canvas/dialog-state.ts +1 -2
  161. package/src/canvas/diff-marks.ts +9 -16
  162. package/src/canvas/diff-toolbar.ts +8 -7
  163. package/src/canvas/edit-width-drag.ts +4 -1
  164. package/src/canvas/edit-width.ts +1 -3
  165. package/src/canvas/iframe-channel.ts +27 -13
  166. package/src/canvas/iframe-drop.ts +13 -12
  167. package/src/canvas/iframe-editable-root.ts +29 -16
  168. package/src/canvas/iframe-entry.ts +80 -63
  169. package/src/canvas/iframe-eval.ts +73 -49
  170. package/src/canvas/iframe-host.ts +203 -118
  171. package/src/canvas/iframe-inline-edit.ts +69 -32
  172. package/src/canvas/iframe-insert.ts +5 -4
  173. package/src/canvas/iframe-interaction.ts +37 -26
  174. package/src/canvas/iframe-overlay.ts +1 -1
  175. package/src/canvas/iframe-patch.ts +18 -15
  176. package/src/canvas/iframe-position.ts +12 -6
  177. package/src/canvas/iframe-protocol.ts +15 -16
  178. package/src/canvas/iframe-render.ts +41 -36
  179. package/src/canvas/iframe-slash.ts +24 -11
  180. package/src/canvas/iframe-subtree.ts +6 -2
  181. package/src/canvas/path-mapping.ts +19 -12
  182. package/src/canvas/popover-path.ts +7 -3
  183. package/src/canvas/popover-state.ts +1 -2
  184. package/src/canvas/serialize-scope.ts +13 -5
  185. package/src/canvas/stage-scrollbar.ts +2 -1
  186. package/src/canvas/surface-registry.ts +21 -3
  187. package/src/collab/collab-commands.ts +7 -2
  188. package/src/collab/collab-session.ts +84 -45
  189. package/src/collab/collab-state.ts +4 -3
  190. package/src/collab/monaco-binding.ts +16 -13
  191. package/src/collab/monaco-cursors.ts +5 -2
  192. package/src/commands/budget.ts +3 -3
  193. package/src/commands/command-args.ts +103 -71
  194. package/src/commands/context.ts +22 -20
  195. package/src/commands/defaults.ts +4 -1
  196. package/src/commands/keymap.ts +47 -43
  197. package/src/commands/levels.ts +3 -3
  198. package/src/commands/live-context.ts +10 -8
  199. package/src/commands/reference.ts +2 -1
  200. package/src/commands/registry.ts +12 -10
  201. package/src/commands/run-reported.ts +15 -10
  202. package/src/component-props.ts +46 -30
  203. package/src/content/collection-match.ts +5 -4
  204. package/src/content/draft-state.ts +4 -3
  205. package/src/content/entry-commands.ts +3 -2
  206. package/src/content/entry-editor.ts +29 -17
  207. package/src/content/entry-fields.ts +12 -7
  208. package/src/content/entry-model.ts +21 -12
  209. package/src/editor/canvas-context-menu.ts +1 -2
  210. package/src/editor/canvas-slash-bridge.ts +3 -6
  211. package/src/editor/content-slice.ts +16 -14
  212. package/src/editor/context-menu.ts +35 -22
  213. package/src/editor/convert-targets.ts +30 -35
  214. package/src/editor/convert-to-component.ts +11 -5
  215. package/src/editor/convert-to-repeater.ts +34 -22
  216. package/src/editor/editable-tags.ts +17 -2
  217. package/src/editor/file-drop-action.ts +21 -22
  218. package/src/editor/inline-edit-apply.ts +35 -17
  219. package/src/editor/inline-edit.ts +66 -50
  220. package/src/editor/inline-format.ts +59 -56
  221. package/src/editor/inline-link.ts +40 -15
  222. package/src/editor/insert-zone-action.ts +1 -1
  223. package/src/editor/merge-tags.ts +58 -19
  224. package/src/editor/repeater-scope.ts +39 -28
  225. package/src/editor/shortcuts.ts +87 -47
  226. package/src/editor/slash-menu.ts +1 -6
  227. package/src/files/asset-versions.ts +4 -4
  228. package/src/files/components.ts +15 -10
  229. package/src/files/elements.ts +5 -6
  230. package/src/files/file-ops.ts +77 -36
  231. package/src/files/files.ts +90 -95
  232. package/src/files/media-meta.ts +2 -1
  233. package/src/files/media-paths.ts +6 -1
  234. package/src/files/serialize-document.ts +2 -2
  235. package/src/format/constraints.ts +1 -1
  236. package/src/format/convert-file.ts +27 -13
  237. package/src/format/format-choices.ts +2 -1
  238. package/src/format/format-host.ts +76 -50
  239. package/src/github/github-auth-status.ts +27 -3
  240. package/src/github/github-auth.ts +19 -9
  241. package/src/github/github-publish.ts +24 -20
  242. package/src/grid/cell-editors.ts +46 -31
  243. package/src/grid/cell-popovers.ts +5 -3
  244. package/src/grid/edit-buffer.ts +10 -9
  245. package/src/grid/grid-controller.ts +20 -22
  246. package/src/grid/grid-layout.ts +21 -5
  247. package/src/grid/grid-open.ts +3 -6
  248. package/src/grid/grid-panel.ts +11 -4
  249. package/src/grid/grid-source.ts +8 -8
  250. package/src/grid/grid-view.ts +14 -17
  251. package/src/grid/redirects-grid.ts +14 -5
  252. package/src/grid/redirects.ts +16 -14
  253. package/src/grid/schema-columns.ts +25 -19
  254. package/src/grid/sources/connector-source.ts +47 -20
  255. package/src/grid/sources/content-source.ts +25 -24
  256. package/src/grid/sources/csv-file-source.ts +2 -2
  257. package/src/grid/tabulator-tables.d.ts +55 -34
  258. package/src/hosting/stage.ts +7 -7
  259. package/src/i18n/i18n-commands.ts +1 -2
  260. package/src/media/media-pane.ts +4 -1
  261. package/src/new-project/add-repo-modal.ts +20 -19
  262. package/src/new-project/import-tab.ts +10 -14
  263. package/src/new-project/location-fields.ts +2 -1
  264. package/src/new-project/new-project-modal.ts +12 -9
  265. package/src/packages/jxsuite-update.ts +4 -3
  266. package/src/packages/pull-package-sync.ts +26 -25
  267. package/src/page-params.ts +97 -68
  268. package/src/panels/activity-panel.ts +17 -9
  269. package/src/panels/ai-chat/attached-context.ts +13 -7
  270. package/src/panels/ai-chat/chat-view.ts +80 -73
  271. package/src/panels/ai-chat/composer.ts +30 -33
  272. package/src/panels/ai-chat/sessions-view.ts +1 -2
  273. package/src/panels/ai-panel.ts +23 -20
  274. package/src/panels/block-action-bar.ts +46 -35
  275. package/src/panels/bottom-dock.ts +5 -3
  276. package/src/panels/canvas-dnd-bridge.ts +31 -24
  277. package/src/panels/data-explorer.ts +62 -25
  278. package/src/panels/data-grid.ts +14 -11
  279. package/src/panels/dnd.ts +108 -118
  280. package/src/panels/editors.ts +55 -22
  281. package/src/panels/elements-panel.ts +10 -3
  282. package/src/panels/events-panel.ts +84 -69
  283. package/src/panels/formula-workspace.ts +76 -51
  284. package/src/panels/frontmatter-fields.ts +24 -19
  285. package/src/panels/frontmatter-panel.ts +44 -34
  286. package/src/panels/git-diff-open.ts +4 -4
  287. package/src/panels/git-panel.ts +49 -61
  288. package/src/panels/head-panel.ts +131 -111
  289. package/src/panels/i18n-panel.ts +10 -3
  290. package/src/panels/imports-panel.ts +23 -47
  291. package/src/panels/jump-bar.ts +48 -29
  292. package/src/panels/layers-panel.ts +97 -74
  293. package/src/panels/left-panel.ts +3 -3
  294. package/src/panels/pane-context.ts +31 -22
  295. package/src/panels/pane-grid.ts +49 -20
  296. package/src/panels/panel-registry.ts +22 -37
  297. package/src/panels/properties-panel.ts +175 -121
  298. package/src/panels/quick-search.ts +53 -31
  299. package/src/panels/right-panel.ts +3 -3
  300. package/src/panels/seo-modal.ts +13 -17
  301. package/src/panels/settings-menu.ts +15 -15
  302. package/src/panels/signals-panel.ts +153 -131
  303. package/src/panels/statement-editor.ts +230 -140
  304. package/src/panels/style-panel.ts +254 -216
  305. package/src/panels/style-utils.ts +114 -51
  306. package/src/panels/stylebook-doc.ts +57 -54
  307. package/src/panels/stylebook-layers-panel.ts +9 -9
  308. package/src/panels/stylebook-panel.ts +13 -17
  309. package/src/panels/tab-drop.ts +27 -11
  310. package/src/panels/tab-strip.ts +36 -26
  311. package/src/platform-errors.ts +57 -43
  312. package/src/platform.ts +58 -30
  313. package/src/platforms/cloud.ts +345 -175
  314. package/src/platforms/default-platform.ts +10 -4
  315. package/src/platforms/devserver.ts +174 -127
  316. package/src/platforms/read-batcher.ts +16 -8
  317. package/src/project-list.ts +2 -1
  318. package/src/publish/deploy-checklist.ts +8 -2
  319. package/src/publish/pages-service.ts +28 -13
  320. package/src/publish/publish-commands.ts +5 -4
  321. package/src/publish/publish-panel.ts +10 -6
  322. package/src/recent-projects.ts +15 -8
  323. package/src/resize-edges.ts +26 -36
  324. package/src/services/a11y-report.ts +26 -19
  325. package/src/services/agent-seed.ts +23 -11
  326. package/src/services/ai-ask.ts +9 -12
  327. package/src/services/ai-command-tools.ts +68 -62
  328. package/src/services/ai-import-tools.ts +80 -67
  329. package/src/services/ai-models.ts +17 -13
  330. package/src/services/ai-project-tools.ts +68 -32
  331. package/src/services/ai-session-store.ts +19 -10
  332. package/src/services/ai-system-prompt.ts +46 -20
  333. package/src/services/ai-tools.ts +71 -27
  334. package/src/services/ai-write-report.ts +20 -12
  335. package/src/services/ai-writes.ts +4 -4
  336. package/src/services/automation.ts +58 -31
  337. package/src/services/cem-export.ts +149 -58
  338. package/src/services/clock.ts +6 -1
  339. package/src/services/code-services.ts +37 -31
  340. package/src/services/context-manager.ts +14 -10
  341. package/src/services/context-resolver.ts +20 -8
  342. package/src/services/data-service.ts +19 -15
  343. package/src/services/directory-picker.ts +18 -12
  344. package/src/services/document-assistant.ts +39 -19
  345. package/src/services/gated-registry.ts +10 -6
  346. package/src/services/harness/chat-reducer.ts +23 -1
  347. package/src/services/import-client.ts +91 -38
  348. package/src/services/import-seed.ts +8 -2
  349. package/src/services/jx-validate.ts +28 -31
  350. package/src/services/live-preview.ts +0 -0
  351. package/src/services/live-surfaces.ts +6 -3
  352. package/src/services/model-uri.ts +10 -2
  353. package/src/services/module-preloads.ts +12 -8
  354. package/src/services/monaco-buffer.ts +43 -24
  355. package/src/services/monaco-lazy.ts +7 -8
  356. package/src/services/monaco-setup.ts +23 -16
  357. package/src/services/notify.ts +44 -17
  358. package/src/services/popover-report.ts +25 -10
  359. package/src/services/preview-eval.ts +20 -8
  360. package/src/services/profile.ts +13 -6
  361. package/src/services/project-path.ts +13 -10
  362. package/src/services/references.ts +0 -0
  363. package/src/services/render-critic.ts +8 -7
  364. package/src/services/settings/kernel.ts +13 -4
  365. package/src/services/settings/write-queue.ts +9 -9
  366. package/src/services/token-lint.ts +12 -10
  367. package/src/services/tool-executor.ts +17 -5
  368. package/src/services/tool-outcomes.ts +44 -24
  369. package/src/services/trusted-types.ts +24 -7
  370. package/src/settings/contexts-section.ts +11 -8
  371. package/src/settings/contributed-section.ts +79 -60
  372. package/src/settings/css-vars-editor.ts +37 -16
  373. package/src/settings/defs-editor.ts +38 -35
  374. package/src/settings/extension-rows.ts +16 -8
  375. package/src/settings/extension-sections.ts +23 -13
  376. package/src/settings/extensions-section.ts +4 -1
  377. package/src/settings/general-settings.ts +11 -8
  378. package/src/settings/locales-section.ts +20 -12
  379. package/src/settings/preferences-dialog.ts +9 -6
  380. package/src/settings/preferences-keymap.ts +7 -5
  381. package/src/settings/preferences-sections.ts +11 -5
  382. package/src/settings/project-sections.ts +1 -1
  383. package/src/settings/schema-field-ui.ts +9 -0
  384. package/src/settings/settings-document.ts +5 -5
  385. package/src/shell/tree.ts +6 -5
  386. package/src/shell.ts +104 -81
  387. package/src/site-context.ts +37 -22
  388. package/src/state.ts +41 -49
  389. package/src/store.ts +54 -34
  390. package/src/studio.ts +39 -77
  391. package/src/style/live-preview.ts +1 -1
  392. package/src/style/project-styles.ts +6 -7
  393. package/src/style/token-ref.ts +5 -4
  394. package/src/surfaces/about.ts +18 -19
  395. package/src/surfaces/add-repo.ts +17 -19
  396. package/src/surfaces/ai-chat.ts +31 -36
  397. package/src/surfaces/ai-credentials-form.ts +6 -16
  398. package/src/surfaces/ai-managed-connect.ts +3 -4
  399. package/src/surfaces/ai-model-picker.ts +3 -5
  400. package/src/surfaces/block-action-bar.ts +22 -11
  401. package/src/surfaces/boot-failure.ts +4 -5
  402. package/src/surfaces/bottom-dock.ts +9 -18
  403. package/src/surfaces/canvas-stage.ts +12 -11
  404. package/src/surfaces/cf-account-picker.ts +17 -18
  405. package/src/surfaces/commandbar.ts +14 -9
  406. package/src/surfaces/convert-repeater.ts +17 -19
  407. package/src/surfaces/data-actions.ts +9 -7
  408. package/src/surfaces/dialog.ts +26 -28
  409. package/src/surfaces/diff-toolbar.ts +9 -7
  410. package/src/surfaces/doc-header.ts +10 -19
  411. package/src/surfaces/empty-state.ts +7 -10
  412. package/src/surfaces/entry-editor.ts +14 -11
  413. package/src/surfaces/expression-editor.ts +11 -25
  414. package/src/surfaces/files-panel.ts +27 -14
  415. package/src/surfaces/formula-palette.ts +4 -5
  416. package/src/surfaces/git-panel.ts +7 -15
  417. package/src/surfaces/github-auth.ts +16 -20
  418. package/src/surfaces/github-publish.ts +17 -22
  419. package/src/surfaces/grid-cell.ts +30 -31
  420. package/src/surfaces/grid-open.ts +10 -14
  421. package/src/surfaces/grid-panel.ts +13 -9
  422. package/src/surfaces/grid-replace.ts +13 -13
  423. package/src/surfaces/grid-views.ts +15 -18
  424. package/src/surfaces/inspector-dock.ts +13 -12
  425. package/src/surfaces/jump-bar.ts +5 -6
  426. package/src/surfaces/jxsuite-update.ts +16 -22
  427. package/src/surfaces/library-pane.ts +25 -20
  428. package/src/surfaces/logic-panel.ts +17 -30
  429. package/src/surfaces/logic-workspace.ts +13 -15
  430. package/src/surfaces/media-browser.ts +11 -10
  431. package/src/surfaces/media-field.ts +4 -5
  432. package/src/surfaces/media-pane.ts +8 -7
  433. package/src/surfaces/menu.ts +29 -23
  434. package/src/surfaces/navigator-dock.ts +11 -12
  435. package/src/surfaces/new-project.ts +27 -26
  436. package/src/surfaces/pane-context.ts +20 -25
  437. package/src/surfaces/pane-grid.ts +15 -10
  438. package/src/surfaces/panel-activity.ts +5 -6
  439. package/src/surfaces/panel-data.ts +3 -4
  440. package/src/surfaces/panel-deploy-checklist.ts +5 -6
  441. package/src/surfaces/panel-elements.ts +5 -7
  442. package/src/surfaces/panel-i18n.ts +5 -7
  443. package/src/surfaces/panel-imports.ts +6 -13
  444. package/src/surfaces/panel-outline.ts +25 -19
  445. package/src/surfaces/panel-page.ts +11 -18
  446. package/src/surfaces/panel-problems.ts +5 -7
  447. package/src/surfaces/panel-signals.ts +20 -34
  448. package/src/surfaces/panel-stylebook-layers.ts +5 -8
  449. package/src/surfaces/preferences.ts +21 -11
  450. package/src/surfaces/progress-modal.ts +15 -9
  451. package/src/surfaces/properties-panel.json +1 -1
  452. package/src/surfaces/properties-panel.ts +20 -42
  453. package/src/surfaces/publish.ts +18 -18
  454. package/src/surfaces/push-plan.ts +7 -8
  455. package/src/surfaces/rail.json +126 -73
  456. package/src/surfaces/rail.ts +38 -12
  457. package/src/surfaces/reference-field.ts +11 -15
  458. package/src/surfaces/schema-builder.ts +16 -22
  459. package/src/surfaces/schema-form.ts +15 -25
  460. package/src/surfaces/secret-field.ts +9 -6
  461. package/src/surfaces/seo.ts +21 -15
  462. package/src/surfaces/settings-contexts.ts +9 -7
  463. package/src/surfaces/settings-contributed.ts +14 -10
  464. package/src/surfaces/settings-css-vars.ts +5 -12
  465. package/src/surfaces/settings-defs.json +2 -2
  466. package/src/surfaces/settings-defs.ts +17 -21
  467. package/src/surfaces/settings-deploy.ts +8 -15
  468. package/src/surfaces/settings-extensions.ts +5 -6
  469. package/src/surfaces/settings-head.ts +33 -39
  470. package/src/surfaces/settings-locales.ts +8 -20
  471. package/src/surfaces/settings-overview.ts +5 -6
  472. package/src/surfaces/settings-packages.ts +8 -7
  473. package/src/surfaces/settings-pane.ts +9 -18
  474. package/src/surfaces/settings-rawjson.ts +5 -6
  475. package/src/surfaces/shell.ts +1 -2
  476. package/src/surfaces/slash-menu.ts +19 -9
  477. package/src/surfaces/statements.ts +13 -18
  478. package/src/surfaces/statusbar.ts +17 -14
  479. package/src/surfaces/style-panel.ts +18 -31
  480. package/src/surfaces/stylebook-chrome.ts +3 -5
  481. package/src/surfaces/tab-strip.ts +14 -13
  482. package/src/surfaces/target-line.ts +6 -7
  483. package/src/surfaces/welcome.ts +5 -7
  484. package/src/tabs/patch-ops.ts +4 -3
  485. package/src/tabs/project-config.ts +32 -21
  486. package/src/tabs/selection.ts +36 -8
  487. package/src/tabs/tab.ts +52 -41
  488. package/src/tabs/transact.ts +98 -53
  489. package/src/tabs/typing.ts +31 -0
  490. package/src/types.ts +32 -17
  491. package/src/ui/ai-credentials-form.ts +10 -13
  492. package/src/ui/ai-model-picker.ts +3 -3
  493. package/src/ui/cf-account-picker.ts +7 -9
  494. package/src/ui/color-selector.ts +9 -5
  495. package/src/ui/dynamic-slot.ts +7 -8
  496. package/src/ui/expression-editor.ts +112 -105
  497. package/src/ui/form-controls.ts +57 -48
  498. package/src/ui/formula-catalog.ts +239 -230
  499. package/src/ui/formula-chips.ts +33 -18
  500. package/src/ui/layers.ts +44 -31
  501. package/src/ui/media-picker.ts +18 -9
  502. package/src/ui/popover-surface.ts +20 -12
  503. package/src/ui/progress-modal.ts +13 -8
  504. package/src/ui/regions.ts +7 -6
  505. package/src/ui/schema-form.ts +113 -70
  506. package/src/ui/surface.ts +71 -8
  507. package/src/ui/timing.ts +9 -0
  508. package/src/ui/value-source.ts +44 -31
  509. package/src/ui/virtual-window.ts +3 -2
  510. package/src/utils/base64.ts +3 -1
  511. package/src/utils/edit-display.ts +103 -74
  512. package/src/utils/element-selectors.ts +3 -2
  513. package/src/utils/google-fonts.ts +15 -14
  514. package/src/utils/inherited-style.ts +18 -20
  515. package/src/utils/link-target.ts +1 -1
  516. package/src/utils/preview-format.ts +25 -3
  517. package/src/utils/strip-events.ts +49 -22
  518. package/src/utils/studio-utils.ts +29 -14
  519. package/src/view.ts +2 -3
  520. package/src/workspace/pane-derive.ts +10 -12
  521. package/src/workspace/session.ts +53 -43
  522. package/src/workspace/workspace.ts +47 -36
  523. package/dist/chunks/2020-nkxms0ay.js +0 -4
  524. package/dist/chunks/adapter-m948ab5f.js +0 -4
  525. package/dist/chunks/cf-account-picker-n8hr38v7.js +0 -4
  526. package/dist/chunks/cf-settings-356xdtne.js +0 -4
  527. package/dist/chunks/color-area-jqhna8zy.js +0 -4
  528. package/dist/chunks/color-field-embq5ctg.js +0 -4
  529. package/dist/chunks/color-fpezvnkt.js +0 -4
  530. package/dist/chunks/color-slider-1qmw7wqy.js +0 -4
  531. package/dist/chunks/combobox-773hdzyj.js +0 -4
  532. package/dist/chunks/components-yk3t844e.js +0 -4
  533. package/dist/chunks/content-source-bawmyc09.js +0 -4
  534. package/dist/chunks/convert-to-repeater-7wns8kf1.js +0 -4
  535. package/dist/chunks/dialog-mtm9fq5t.js +0 -4
  536. package/dist/chunks/editor-6sc8nacq.js +0 -4
  537. package/dist/chunks/entry-commands-8ay9fh81.js +0 -4
  538. package/dist/chunks/extension-sections-na7rj3nr.js +0 -4
  539. package/dist/chunks/file-ops-gye0qw56.js +0 -4
  540. package/dist/chunks/files-dmc2xvcq.js +0 -4
  541. package/dist/chunks/format-host-t76b53f8.js +0 -4
  542. package/dist/chunks/fs-events-cg4tpz06.js +0 -4
  543. package/dist/chunks/git-panel-yef7bshy.js +0 -4
  544. package/dist/chunks/grid-view-7tt4bxw1.js +0 -51
  545. package/dist/chunks/icons-qbh8akb1.js +0 -4
  546. package/dist/chunks/iframe-entry-f7mqjwpm.js +0 -5
  547. package/dist/chunks/iframe-entry-haw7jkvz.js +0 -5
  548. package/dist/chunks/iframe-entry-z6qrytv3.js +0 -5
  549. package/dist/chunks/iframe-host-tmz30gfp.js +0 -4
  550. package/dist/chunks/index-nag78a9h.js +0 -4
  551. package/dist/chunks/jsonMode-zhwsprqk.js +0 -13
  552. package/dist/chunks/jx-validate-3gbp5nkn.js +0 -4
  553. package/dist/chunks/layers-fvz99859.js +0 -4
  554. package/dist/chunks/layers-panel-gchmbf9p.js +0 -4
  555. package/dist/chunks/listbox-s8fkmnq8.js +0 -4
  556. package/dist/chunks/lit-html-9agdspkt.js +0 -4
  557. package/dist/chunks/media-picker-rhjvyy00.js +0 -4
  558. package/dist/chunks/menu-2e4y9j7b.js +0 -4
  559. package/dist/chunks/menu-37d07z9m.js +0 -4
  560. package/dist/chunks/monaco-binding-2jnhjjvr.js +0 -4
  561. package/dist/chunks/monaco-buffer-rp21359g.js +0 -4
  562. package/dist/chunks/monaco-setup-vhh7gayr.js +0 -4
  563. package/dist/chunks/notify-h3www560.js +0 -4
  564. package/dist/chunks/number-field-gw7sq8rn.js +0 -4
  565. package/dist/chunks/parse-897fvqah.js +0 -4
  566. package/dist/chunks/platform-hz34wcd7.js +0 -4
  567. package/dist/chunks/popover-8htra4er.js +0 -4
  568. package/dist/chunks/publish-panel-exsmjzyj.js +0 -4
  569. package/dist/chunks/quick-search-pgaqeh0m.js +0 -4
  570. package/dist/chunks/references-2cgdxnb8.js +0 -4
  571. package/dist/chunks/right-panel-jf856w5w.js +0 -4
  572. package/dist/chunks/section-registry-jnf8r5gy.js +0 -4
  573. package/dist/chunks/select-n3v7gwas.js +0 -4
  574. package/dist/chunks/split-pff8f3ze.js +0 -4
  575. package/dist/chunks/studio-0f55h9ye.js +0 -5
  576. package/dist/chunks/studio-0sqdhnew.js +0 -12
  577. package/dist/chunks/studio-19x1c75w.js +0 -5
  578. package/dist/chunks/studio-2sqcndak.js +0 -5
  579. package/dist/chunks/studio-3aey7dd3.js +0 -5
  580. package/dist/chunks/studio-3bpdkq2s.js +0 -5
  581. package/dist/chunks/studio-47y6fbpf.js +0 -5
  582. package/dist/chunks/studio-4m3826v2.js +0 -5
  583. package/dist/chunks/studio-4nx2dj1g.js +0 -4
  584. package/dist/chunks/studio-4xv5s47r.js +0 -9
  585. package/dist/chunks/studio-5g4t8v6w.js +0 -5
  586. package/dist/chunks/studio-5py436sf.js +0 -5
  587. package/dist/chunks/studio-77kt594t.js +0 -5
  588. package/dist/chunks/studio-8f87n763.js +0 -10
  589. package/dist/chunks/studio-8mb00b84.js +0 -5
  590. package/dist/chunks/studio-8p51gq2h.js +0 -6
  591. package/dist/chunks/studio-954ds834.js +0 -5
  592. package/dist/chunks/studio-9ft45c83.js +0 -9
  593. package/dist/chunks/studio-a2138x5k.js +0 -7
  594. package/dist/chunks/studio-a9yzstqj.js +0 -5
  595. package/dist/chunks/studio-acdksxx6.js +0 -5
  596. package/dist/chunks/studio-ar8jcf2y.js +0 -5
  597. package/dist/chunks/studio-bmn4mn9j.js +0 -7
  598. package/dist/chunks/studio-e7xxa0sj.js +0 -5
  599. package/dist/chunks/studio-ecaz25vk.js +0 -5
  600. package/dist/chunks/studio-ery42sqr.js +0 -4
  601. package/dist/chunks/studio-fzdywr6p.js +0 -9
  602. package/dist/chunks/studio-g5fmf0c1.js +0 -5
  603. package/dist/chunks/studio-g7nse7zb.js +0 -5
  604. package/dist/chunks/studio-geq1ea6k.js +0 -14
  605. package/dist/chunks/studio-ghkb32r8.js +0 -5
  606. package/dist/chunks/studio-ghrhy2y7.js +0 -5
  607. package/dist/chunks/studio-grawhey1.js +0 -5
  608. package/dist/chunks/studio-h0xgswew.js +0 -5
  609. package/dist/chunks/studio-h9c4p2tx.js +0 -5
  610. package/dist/chunks/studio-jyzj5cxs.js +0 -5
  611. package/dist/chunks/studio-mgx8yhnz.js +0 -64
  612. package/dist/chunks/studio-mpb04y1d.js +0 -6
  613. package/dist/chunks/studio-n17mty64.js +0 -5
  614. package/dist/chunks/studio-nwh2eqsk.js +0 -6
  615. package/dist/chunks/studio-q1h883bt.js +0 -16
  616. package/dist/chunks/studio-q4tv82h7.js +0 -9
  617. package/dist/chunks/studio-qpqa7vk3.js +0 -5
  618. package/dist/chunks/studio-qqz8e5gk.js +0 -5
  619. package/dist/chunks/studio-qvasen3f.js +0 -5
  620. package/dist/chunks/studio-rggdb3hm.js +0 -5
  621. package/dist/chunks/studio-sghy936h.js +0 -4
  622. package/dist/chunks/studio-skprc6ef.js +0 -5
  623. package/dist/chunks/studio-tt2nactf.js +0 -5
  624. package/dist/chunks/studio-tyasmc39.js +0 -5
  625. package/dist/chunks/studio-vk9ezads.js +0 -5
  626. package/dist/chunks/studio-vzacdfsc.js +0 -4
  627. package/dist/chunks/studio-w4c0xmrw.js +0 -5
  628. package/dist/chunks/studio-wfjqhhbk.js +0 -5
  629. package/dist/chunks/studio-wgh5kxpj.js +0 -5
  630. package/dist/chunks/studio-xasj0796.js +0 -5
  631. package/dist/chunks/studio-y78s8r2n.js +0 -5
  632. package/dist/chunks/studio-z8w183sh.js +0 -5
  633. package/dist/chunks/studio-zscd9ty4.js +0 -928
  634. package/dist/chunks/studio-zxp13sss.js +0 -7
  635. package/dist/chunks/studio-zygnmm01.js +0 -5
  636. package/dist/chunks/swatch-group-8qh9a3bm.js +0 -4
  637. package/dist/chunks/tabs-jwthg40w.js +0 -4
  638. package/dist/chunks/textfield-spy3hc77.js +0 -4
  639. package/dist/chunks/toast-4d35zd64.js +0 -4
  640. package/dist/chunks/toast-host-8sjmfed3.js +0 -4
  641. package/dist/chunks/tooltip-fd6g9xy3.js +0 -4
  642. package/dist/chunks/tree-h19v1jfz.js +0 -4
  643. package/dist/chunks/tsMode-gr0m4dzr.js +0 -14
  644. package/dist/chunks/workspace-m15qtcqp.js +0 -4
  645. package/dist/chunks/ws-client-nf61frr1.js +0 -4
@@ -22,6 +22,8 @@ import { componentRegistry } from "../files/components";
22
22
  import { uploadAssets } from "../files/media-upload";
23
23
  import { applyDropInstruction } from "../panels/dnd";
24
24
  import { mutateUpdateAttribute, mutateUpdateProp, transactDoc } from "../tabs/transact";
25
+ import { isNumber } from "@jxsuite/schema/guards";
26
+ import type { ComponentEntry } from "../files/components";
25
27
  import type { UploadedAsset } from "../files/media-upload";
26
28
  import type { DropPreview, FileDropHit } from "../canvas/iframe-protocol";
27
29
  import type { JxPath } from "../state";
@@ -30,12 +32,12 @@ import type { JxMutableNode } from "@jxsuite/schema/types";
30
32
  import { isMediaFormat } from "../utils/studio-utils";
31
33
 
32
34
  /** Where an asset's URL goes when it replaces an existing element's picture. */
33
- const REPLACE_ATTRS: Record<string, "src" | "poster"> = {
34
- img: "src",
35
- source: "src",
35
+ const REPLACE_ATTRS = new Map<string, "src" | "poster">([
36
+ ["img", "src"],
37
+ ["source", "src"],
36
38
  // A <video>'s own `src` is the movie; dropping an image on one sets its poster frame instead.
37
- video: "poster",
38
- };
39
+ ["video", "poster"],
40
+ ]);
39
41
 
40
42
  /** What a drop resolves to once the parent has applied its semantics. */
41
43
  export type FileDropTarget =
@@ -43,11 +45,8 @@ export type FileDropTarget =
43
45
  | { mode: "replace-prop"; path: JxPath; prop: string }
44
46
  | { mode: "insert" };
45
47
 
46
- /** A component prop the registry declares as an image, for {@link resolveFileDropTarget}. */
47
- interface RegistryEntry {
48
- tagName: string;
49
- props?: { name: string; format?: unknown; [k: string]: unknown }[];
50
- }
48
+ /** The part of a registry entry {@link resolveFileDropTarget} reads: its tag and declared props. */
49
+ type RegistryEntry = Pick<ComponentEntry, "tagName" | "props">;
51
50
 
52
51
  /**
53
52
  * Decide whether a drop replaces an existing picture or inserts a new element.
@@ -66,15 +65,15 @@ export function resolveFileDropTarget(
66
65
  if (!hit || kind !== "image") {
67
66
  return { mode: "insert" };
68
67
  }
69
- const attr = REPLACE_ATTRS[hit.tagName];
68
+ const attr = REPLACE_ATTRS.get(hit.tagName);
70
69
  if (attr) {
71
- return { attr, mode: "replace-attr", path: hit.path as JxPath };
70
+ return { attr, mode: "replace-attr", path: hit.path };
72
71
  }
73
72
  if (hit.tagName.includes("-")) {
74
73
  const entry = registry.find((c) => c.tagName === hit.tagName);
75
74
  const imageProps = (entry?.props ?? []).filter((p) => isMediaFormat(p.format));
76
75
  if (imageProps.length === 1) {
77
- return { mode: "replace-prop", path: hit.path as JxPath, prop: imageProps[0]!.name };
76
+ return { mode: "replace-prop", path: hit.path, prop: imageProps[0]!.name };
78
77
  }
79
78
  }
80
79
  return { mode: "insert" };
@@ -88,20 +87,20 @@ export function resolveFileDropTarget(
88
87
  export function elementForAsset(asset: UploadedAsset): JxMutableNode {
89
88
  switch (asset.kind) {
90
89
  case "image": {
91
- return { attributes: { alt: "", src: asset.ref }, tagName: "img" } as JxMutableNode;
90
+ return { attributes: { alt: "", src: asset.ref }, tagName: "img" };
92
91
  }
93
92
  case "video": {
94
- return { attributes: { controls: "", src: asset.ref }, tagName: "video" } as JxMutableNode;
93
+ return { attributes: { controls: "", src: asset.ref }, tagName: "video" };
95
94
  }
96
95
  case "audio": {
97
- return { attributes: { controls: "", src: asset.ref }, tagName: "audio" } as JxMutableNode;
96
+ return { attributes: { controls: "", src: asset.ref }, tagName: "audio" };
98
97
  }
99
98
  default: {
100
99
  return {
101
100
  attributes: { href: asset.ref },
102
101
  tagName: "a",
103
102
  textContent: asset.name,
104
- } as JxMutableNode;
103
+ };
105
104
  }
106
105
  }
107
106
  }
@@ -114,13 +113,13 @@ export function elementForAsset(asset: UploadedAsset): JxMutableNode {
114
113
  * they were dropped. `make-child` appends, which is already ordered.
115
114
  */
116
115
  export function nthDropPath(preview: DropPreview, n: number): JxPath {
117
- const path = [...preview.targetPath];
116
+ const path: JxPath = [...preview.targetPath];
118
117
  const tail = path.at(-1);
119
- if (n === 0 || typeof tail !== "number") {
120
- return path as JxPath;
118
+ if (n === 0 || !isNumber(tail)) {
119
+ return path;
121
120
  }
122
121
  path[path.length - 1] = tail + n;
123
- return path as JxPath;
122
+ return path;
124
123
  }
125
124
 
126
125
  /**
@@ -160,7 +159,7 @@ export async function applyFileDrop(
160
159
  if (preview) {
161
160
  applyDropInstruction(tab, { type: preview.instruction }, srcData, nthDropPath(preview, i));
162
161
  } else {
163
- applyDropInstruction(tab, { type: "make-child" }, srcData, [] as unknown as JxPath);
162
+ applyDropInstruction(tab, { type: "make-child" }, srcData, []);
164
163
  }
165
164
  }
166
165
  }
@@ -7,7 +7,9 @@
7
7
  * boundary.
8
8
  */
9
9
 
10
- import { childIndex, getNodeAtPath, parentElementPath } from "../store";
10
+ import { getNodeAtPath } from "@jxsuite/schema/doc-ops";
11
+ import { isNonNullObject, isNumber, isString } from "@jxsuite/schema/guards";
12
+ import { childIndex, parentElementPath } from "../store";
11
13
  import { isAncestor } from "../state";
12
14
  import { isTabActive } from "../workspace/workspace";
13
15
  import {
@@ -24,6 +26,7 @@ import type { JxContentResult, SlashCommand } from "./inline-edit";
24
26
  import type { JxPath } from "../state";
25
27
  import type { Tab } from "../tabs/tab";
26
28
  import type { JxMutableNode } from "@jxsuite/schema/types";
29
+ import type { SpliceCoordinate } from "../tabs/selection";
27
30
 
28
31
  /**
29
32
  * Whether a committed inline-edit result is effectively empty (blank text / lone whitespace /
@@ -43,10 +46,21 @@ export function isEmptyContent(commitData?: JxContentResult): boolean {
43
46
  if (kids.length === 0) {
44
47
  return true;
45
48
  }
46
- if (kids.length === 1 && typeof kids[0] === "string" && kids[0].trim() === "") {
49
+ const [only] = kids;
50
+ if (kids.length === 1 && isString(only) && only.trim() === "") {
47
51
  return true;
48
52
  }
49
- return kids.length === 1 && typeof kids[0] === "object" && kids[0]?.tagName === "br";
53
+ // The result crossed the frame boundary as JSON, so a `null` child is excluded here explicitly.
54
+ return kids.length === 1 && isNonNullObject(only) && only.tagName === "br";
55
+ }
56
+
57
+ /** The slot of the block at `path`. */
58
+ function blockSlot(path: JxPath): SpliceCoordinate {
59
+ /* SAFETY: a block with a sibling position has an element path ending in `"children", <index>`, so
60
+ it has a parent element path and its last segment is the numeric child index. A repeater's
61
+ template root (`…, "map"`) is editable too; callers do not exclude that case yet, so it reaches
62
+ here with a string segment exactly as before this cast. */
63
+ return { index: childIndex(path) as number, parentPath: parentElementPath(path) as JxPath };
50
64
  }
51
65
 
52
66
  /**
@@ -126,7 +140,7 @@ export function applyInlinePropCommit(
126
140
  if (!node) {
127
141
  return false;
128
142
  }
129
- const current = (node.$props as Record<string, unknown> | undefined)?.[prop];
143
+ const current = node.$props?.[prop];
130
144
  if (`${current ?? ""}` === value) {
131
145
  return false;
132
146
  }
@@ -155,8 +169,8 @@ export function applyBlockMerge(
155
169
  if (!tab) {
156
170
  return null;
157
171
  }
158
- const from = getNodeAtPath(tab.doc.document, fromPath) as JxMutableNode | undefined;
159
- const into = getNodeAtPath(tab.doc.document, intoPath) as JxMutableNode | undefined;
172
+ const from = getNodeAtPath(tab.doc.document, fromPath);
173
+ const into = getNodeAtPath(tab.doc.document, intoPath);
160
174
  if (!from || !into) {
161
175
  return null;
162
176
  }
@@ -184,8 +198,11 @@ export function applyBlockMerge(
184
198
  mutateUpdateProperty(t, intoPath, "textContent", merged.textContent ?? "");
185
199
  }
186
200
  mutateRemoveNode(t, fromPath);
187
- // A container emptied by the removal (the `<ul>` behind a list's last item) would otherwise
188
- // Linger as invisible structure that still occupies layout and shows up in the layers panel.
201
+ /* A container emptied by the removal (the `<ul>` behind a list's last item) would otherwise
202
+ linger as invisible structure that still occupies layout and shows up in the layers panel.
203
+ SAFETY: `fromPath` is not the root (the ancestor check above refuses `[]`), and any node below
204
+ the root is addressed by at least two segments (`"children", <index>`, `"cases", <name>`, or
205
+ `"map"` under its repeater), so parentElementPath returns a path. */
189
206
  pruneEmptyAncestors(t, parentElementPath(fromPath) as JxPath);
190
207
  if (isTabActive(tab)) {
191
208
  t.session.selection = [intoPath];
@@ -202,12 +219,12 @@ export function applyBlockMerge(
202
219
  function pruneEmptyAncestors(tab: Tab, path: JxPath): void {
203
220
  let cur = path;
204
221
  while (cur.length > 0) {
205
- const node = getNodeAtPath(tab.doc.document, cur) as JxMutableNode | undefined;
222
+ const node = getNodeAtPath(tab.doc.document, cur);
206
223
  const kids = node?.children;
207
224
  if (!node || !Array.isArray(kids) || kids.length > 0) {
208
225
  return;
209
226
  }
210
- const parent = parentElementPath(cur) as JxPath | null;
227
+ const parent = parentElementPath(cur);
211
228
  mutateRemoveNode(tab, cur);
212
229
  if (!parent) {
213
230
  return;
@@ -227,8 +244,7 @@ export function applyInlineSplit(
227
244
  before: JxContentResult,
228
245
  after: JxContentResult,
229
246
  ): JxPath {
230
- const parentPath = parentElementPath(path) as JxPath;
231
- const idx = childIndex(path) as number;
247
+ const { parentPath, index: idx } = blockSlot(path);
232
248
  const newPath = [...parentPath, "children", idx + 1];
233
249
  if (!tab) {
234
250
  return newPath;
@@ -291,8 +307,7 @@ export function applyInlineInsert(
291
307
  return path;
292
308
  }
293
309
 
294
- const parentPath = parentElementPath(path) as JxPath;
295
- const idx = childIndex(path) as number;
310
+ const { parentPath, index: idx } = blockSlot(path);
296
311
  const newPath = [...parentPath, "children", idx + 1];
297
312
  if (!tab) {
298
313
  return newPath;
@@ -336,8 +351,8 @@ export function applyRangeReplace(
336
351
  if (!tab) {
337
352
  return null;
338
353
  }
339
- const head = getNodeAtPath(tab.doc.document, from.path) as JxMutableNode | undefined;
340
- const tail = getNodeAtPath(tab.doc.document, to.path) as JxMutableNode | undefined;
354
+ const head = getNodeAtPath(tab.doc.document, from.path);
355
+ const tail = getNodeAtPath(tab.doc.document, to.path);
341
356
  if (!head || !tail) {
342
357
  return null;
343
358
  }
@@ -366,6 +381,9 @@ export function applyRangeReplace(
366
381
  for (const path of removals) {
367
382
  if (getNodeAtPath(t.doc.document, path)) {
368
383
  mutateRemoveNode(t, path);
384
+ /* SAFETY: every removal is the range's tail or a rendered block the iframe named between its
385
+ ends; none is the root, which contains both ends, and any node below the root is
386
+ addressed by at least two segments, so parentElementPath returns a path. */
369
387
  pruneEmptyAncestors(t, parentElementPath(path) as JxPath);
370
388
  }
371
389
  }
@@ -389,7 +407,7 @@ function comparePathsDescending(a: JxPath, b: JxPath): number {
389
407
  if (av === bv) {
390
408
  continue;
391
409
  }
392
- if (typeof av === "number" && typeof bv === "number") {
410
+ if (isNumber(av) && isNumber(bv)) {
393
411
  return bv - av;
394
412
  }
395
413
  return String(bv).localeCompare(String(av));
@@ -7,13 +7,13 @@
7
7
  * text formatting, Enter for new paragraphs, and slash commands for inserting elements.
8
8
  */
9
9
 
10
- import elementsMeta from "../../data/elements-meta.json";
11
- import { displayTagName } from "@jxsuite/schema/guards";
10
+ import { displayTagName, isNonNullObject, isString } from "@jxsuite/schema/guards";
12
11
  import { normalizeInlineContent } from "./inline-format";
13
- import { isEditableTag } from "./editable-tags";
12
+ import { execEditingCommand } from "./inline-link";
13
+ import { ELEMENT_DEFS, isEditableTag } from "./editable-tags";
14
14
  import type { EditableVerdicts } from "./editable-tags";
15
15
  import type { JxPath } from "../state";
16
- import type { JxMutableNode } from "@jxsuite/schema/types";
16
+ import type { JsonPrimitive, JxMutableNode } from "@jxsuite/schema/types";
17
17
 
18
18
  /**
19
19
  * The slash-menu surface inline editing drives. Injected (rather than imported) so this module
@@ -21,12 +21,15 @@ import type { JxMutableNode } from "@jxsuite/schema/types";
21
21
  * real menu, the canvas iframe supplies its own (or a no-op) without bloating the slim iframe
22
22
  * bundle.
23
23
  */
24
+ /** What a slash menu is opened with: the pick handler, and how the list is filtered and sourced. */
25
+ export interface SlashMenuOptions {
26
+ onSelect: (cmd: SlashCommand) => void;
27
+ showFilter?: boolean;
28
+ commands?: SlashCommand[];
29
+ }
30
+
24
31
  export interface SlashController {
25
- show: (
26
- anchorEl: HTMLElement,
27
- filter: string,
28
- cbs: { onSelect: (cmd: SlashCommand) => void; showFilter?: boolean; commands?: SlashCommand[] },
29
- ) => void;
32
+ show: (anchorEl: HTMLElement, filter: string, cbs: SlashMenuOptions) => void;
30
33
  dismiss: () => void;
31
34
  isOpen: () => boolean;
32
35
  }
@@ -74,11 +77,6 @@ export interface InlineAction {
74
77
  shortcut?: string;
75
78
  }
76
79
 
77
- interface ElementDef {
78
- $inlineChildren?: string[];
79
- $inlineActions?: InlineAction[] | string;
80
- }
81
-
82
80
  export interface SlashCommand {
83
81
  label: string;
84
82
  tag: string;
@@ -124,7 +122,7 @@ export function isInlineInContext(childTag: string, parentTag: string) {
124
122
  if (!parentTag) {
125
123
  return INLINE_TAGS.has(childTag);
126
124
  }
127
- const parentDef = (elementsMeta.$defs as Record<string, ElementDef>)[parentTag];
125
+ const parentDef = ELEMENT_DEFS[parentTag];
128
126
  if (!parentDef || !parentDef.$inlineChildren) {
129
127
  return false;
130
128
  }
@@ -139,13 +137,13 @@ export function isInlineInContext(childTag: string, parentTag: string) {
139
137
  * @returns {InlineAction[] | null}
140
138
  */
141
139
  export function getInlineActions(tag: string) {
142
- const def = (elementsMeta.$defs as Record<string, ElementDef>)[tag];
140
+ const def = ELEMENT_DEFS[tag];
143
141
  if (!def) {
144
142
  return null;
145
143
  }
146
144
  let actions = def.$inlineActions;
147
- if (typeof actions === "string") {
148
- const refDef = (elementsMeta.$defs as Record<string, ElementDef>)[actions];
145
+ if (isString(actions)) {
146
+ const refDef = ELEMENT_DEFS[actions];
149
147
  actions = refDef?.$inlineActions ?? undefined;
150
148
  }
151
149
  if (!Array.isArray(actions)) {
@@ -233,12 +231,13 @@ export function isEditableBlock(el: HTMLElement) {
233
231
  * Check if a node is an inline child. When parentNode is provided, uses context-aware scoping from
234
232
  * metadata. Without parent, uses the fallback INLINE_TAGS set.
235
233
  *
236
- * @param {JxMutableNode} node
234
+ * @param {JxMutableNode | JsonPrimitive} node A document child entry; a text or other scalar child
235
+ * is never an inline element.
237
236
  * @param {JxMutableNode} [parentNode]
238
237
  * @returns {boolean}
239
238
  */
240
- export function isInlineElement(node: JxMutableNode, parentNode?: JxMutableNode) {
241
- if (!node || typeof node !== "object") {
239
+ export function isInlineElement(node: JxMutableNode | JsonPrimitive, parentNode?: JxMutableNode) {
240
+ if (!isNonNullObject(node)) {
242
241
  return false;
243
242
  }
244
243
  const childTag = (displayTagName(node.tagName) || "div").toLowerCase();
@@ -304,7 +303,7 @@ export function startEditing(
304
303
  insertFn = callbacks.onInsert;
305
304
  endFn = callbacks.onEnd;
306
305
  _plainMode = opts?.plainText === true;
307
- _plainOriginal = _plainMode ? (el.textContent ?? "") : "";
306
+ _plainOriginal = _plainMode ? el.textContent : "";
308
307
  _plainPosted = false;
309
308
 
310
309
  // Mark the caret's block so the empty-block slash hint can target it. The editing host itself is
@@ -495,7 +494,7 @@ function handlePaste(e: ClipboardEvent) {
495
494
  e.preventDefault();
496
495
  // Paste as plain text to avoid foreign HTML
497
496
  const text = e.clipboardData?.getData("text/plain") ?? "";
498
- document.execCommand("insertText", false, text);
497
+ execEditingCommand("insertText", text);
499
498
  }
500
499
 
501
500
  // ─── Enter: split the active block ─────────────────────────────────────────
@@ -594,7 +593,7 @@ function commitChanges(inPlace: boolean) {
594
593
  if (_plainMode) {
595
594
  // A prop value is a plain single-line string (a directive attribute) — flatten any newline
596
595
  // That survived plaintext editing and skip the rich DOM→Jx serialization entirely.
597
- const text = (activeEl.textContent ?? "").replaceAll("\n", " ");
596
+ const text = activeEl.textContent.replaceAll("\n", " ");
598
597
  /*
599
598
  * A SESSION THAT CHANGED NOTHING MUST WRITE NOTHING.
600
599
  *
@@ -635,17 +634,18 @@ export function normalizeChildren(node: { children?: (JxMutableNode | string)[]
635
634
  }
636
635
 
637
636
  // Step 1: Merge adjacent text nodes
638
- const merged = [];
637
+ const merged: (JxMutableNode | string)[] = [];
639
638
  for (const child of node.children) {
640
- if (typeof child === "string" && merged.length > 0 && typeof merged.at(-1) === "string") {
641
- merged[merged.length - 1] += child;
639
+ const last = merged.at(-1);
640
+ if (isString(child) && isString(last)) {
641
+ merged[merged.length - 1] = last + child;
642
642
  } else {
643
643
  merged.push(child);
644
644
  }
645
645
  }
646
646
 
647
647
  // Step 2: If all children are text, fold into textContent
648
- if (merged.every((c: JxMutableNode | string) => typeof c === "string")) {
648
+ if (merged.every((c) => isString(c))) {
649
649
  return { textContent: merged.join("") };
650
650
  }
651
651
 
@@ -674,7 +674,7 @@ function elementToJx(el: HTMLElement): JxContentResult {
674
674
  const children: (JxMutableNode | string)[] = [];
675
675
  for (const child of nodes) {
676
676
  const jsx = domNodeToJx(child);
677
- if (jsx !== null && jsx !== undefined) {
677
+ if (jsx !== null) {
678
678
  children.push(jsx);
679
679
  }
680
680
  }
@@ -683,6 +683,23 @@ function elementToJx(el: HTMLElement): JxContentResult {
683
683
  return normalizeChildren({ children });
684
684
  }
685
685
 
686
+ /**
687
+ * Whether `node` is an element carrying `dataset` — an HTML, SVG or MathML element, which is every
688
+ * element an HTML editing host can hold. Decided by node type and feature, not `instanceof`, so it
689
+ * holds for a node of any realm.
690
+ */
691
+ function isDatasetElementNode(node: Node): node is Element & HTMLOrSVGElement {
692
+ return node.nodeType === Node.ELEMENT_NODE && "dataset" in node;
693
+ }
694
+
695
+ /** Browser execCommand output tags, mapped to the tags Jx documents use for the same formatting. */
696
+ const BROWSER_TAG_CONVENTIONS = new Map([
697
+ ["b", "strong"],
698
+ ["i", "em"],
699
+ ["s", "del"],
700
+ ["strike", "del"],
701
+ ]);
702
+
686
703
  /**
687
704
  * Convert a DOM node to a Jx element definition.
688
705
  *
@@ -698,23 +715,17 @@ function domNodeToJx(node: Node) {
698
715
  return text; // Bare string — text node child
699
716
  }
700
717
 
701
- if (node.nodeType !== Node.ELEMENT_NODE) {
718
+ if (!isDatasetElementNode(node)) {
702
719
  return null;
703
720
  }
704
721
 
705
- const el = node as HTMLElement;
722
+ const el = node;
706
723
  const tag = el.tagName.toLowerCase();
707
724
  const result: JxMutableNode = { tagName: tag };
708
725
 
709
- // Map browser execCommand output to our tag conventions
710
- const tagMap: Record<string, string> = {
711
- b: "strong",
712
- i: "em",
713
- s: "del",
714
- strike: "del",
715
- };
716
- if (tagMap[tag]) {
717
- result.tagName = tagMap[tag];
726
+ const conventional = BROWSER_TAG_CONVENTIONS.get(tag);
727
+ if (conventional) {
728
+ result.tagName = conventional;
718
729
  }
719
730
 
720
731
  // Attributes
@@ -725,8 +736,9 @@ function domNodeToJx(node: Node) {
725
736
  const href = el.dataset.jxHref ?? el.getAttribute("href");
726
737
  if (tag === "a" && href != null) {
727
738
  result.attributes = { href };
728
- if ((el as HTMLAnchorElement).title) {
729
- result.attributes.title = (el as HTMLAnchorElement).title;
739
+ // `title` is an HTMLElement property: an HTML `<a>` reflects the attribute, an SVG `<a>` has none.
740
+ if ("title" in el && isString(el.title) && el.title) {
741
+ result.attributes.title = el.title;
730
742
  }
731
743
  }
732
744
  if (tag === "code") {
@@ -776,13 +788,15 @@ function fragmentToJx(frag: DocumentFragment) {
776
788
  }
777
789
  }
778
790
 
791
+ const [only] = children;
779
792
  if (
780
793
  children.length === 1 &&
781
- typeof children[0] !== "string" &&
782
- children[0]!.tagName === "span" &&
783
- typeof children[0]!.textContent === "string"
794
+ only !== undefined &&
795
+ !isString(only) &&
796
+ only.tagName === "span" &&
797
+ isString(only.textContent)
784
798
  ) {
785
- return { textContent: children[0]!.textContent };
799
+ return { textContent: only.textContent };
786
800
  }
787
801
 
788
802
  return children.length > 0 ? { children } : { textContent: "" };
@@ -855,10 +869,11 @@ export function openSlashMenu(opts?: { anchored?: boolean }): void {
855
869
 
856
870
  // An unanchored menu carries its own filter field: there is no "/…" run in the document for the
857
871
  // Author to type into, so without one the list could only ever be filtered by scrolling it.
858
- slash.show(activeEl, "", {
859
- onSelect: handleSlashSelect,
860
- ...(_slashAnchored ? {} : { showFilter: true }),
861
- });
872
+ const menu: SlashMenuOptions = { onSelect: handleSlashSelect };
873
+ if (!_slashAnchored) {
874
+ menu.showFilter = true;
875
+ }
876
+ slash.show(activeEl, "", menu);
862
877
  }
863
878
 
864
879
  /**
@@ -935,6 +950,7 @@ function handleSlashSelect(cmd: SlashCommand) {
935
950
  let slashNode: Text | null = null;
936
951
  let slashOffset = 0;
937
952
  while (walker.nextNode()) {
953
+ // SAFETY: the walker shows only text nodes (SHOW_TEXT), and nextNode() just landed on one.
938
954
  const node = walker.currentNode as Text;
939
955
  if (charCount + node.length > slashIdx) {
940
956
  slashNode = node;