@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
package/src/state.ts CHANGED
@@ -12,7 +12,15 @@
12
12
  */
13
13
 
14
14
  import type { ProjectState } from "./types";
15
- import { displayTagName, isRef } from "@jxsuite/schema/guards";
15
+ import {
16
+ displayTagName,
17
+ isBoolean,
18
+ isMappedArray,
19
+ isNonNullObject,
20
+ isNumber,
21
+ isRef,
22
+ isString,
23
+ } from "@jxsuite/schema/guards";
16
24
  import type { JxMutableNode } from "@jxsuite/schema/types";
17
25
 
18
26
  export type JxPath = (string | number)[];
@@ -20,23 +28,10 @@ export type JxPath = (string | number)[];
20
28
  // ─── Path utilities ───────────────────────────────────────────────────────────
21
29
 
22
30
  /**
23
- * Walk the document tree and return the node at the given path.
24
- *
25
- * @param {JxMutableNode} doc
26
- * @param {JxPath} path
27
- * @returns {JxMutableNode}
31
+ * Walk the document tree and return the node at the given path, or `undefined` when a step falls
32
+ * off the tree (a path gone stale since it was taken). One walk, shared with the document ops.
28
33
  */
29
- export function getNodeAtPath(doc: JxMutableNode, path: JxPath) {
30
- let node = doc;
31
- for (const key of path) {
32
- if (node == null) {
33
- return undefined as unknown as JxMutableNode;
34
- }
35
- // Paths address nodes by construction; non-node leaves surface as undefined above.
36
- node = node[key] as JxMutableNode;
37
- }
38
- return node;
39
- }
34
+ export { getNodeAtPath } from "@jxsuite/schema/doc-ops";
40
35
 
41
36
  /**
42
37
  * The node's children when they are a static array (the edit-mode invariant); an empty array for
@@ -56,11 +51,11 @@ export function childList(node: JxMutableNode | null | undefined): (JxMutableNod
56
51
  * `$switch` cases. Runs once when a document is loaded into a tab so every in-studio doc — and its
57
52
  * history checkpoints — uses the member form before any mutation.
58
53
  *
59
- * @param {unknown} node
60
- * @returns {unknown} The same node (mutated)
54
+ * @param {T} node
55
+ * @returns {T} The same node (mutated)
61
56
  */
62
- export function normalizeArrayChildren(node: unknown): unknown {
63
- if (!node || typeof node !== "object") {
57
+ export function normalizeArrayChildren<T>(node: T): T {
58
+ if (!isNonNullObject(node)) {
64
59
  return node;
65
60
  }
66
61
  if (Array.isArray(node)) {
@@ -69,14 +64,12 @@ export function normalizeArrayChildren(node: unknown): unknown {
69
64
  }
70
65
  return node;
71
66
  }
67
+ /* SAFETY: A non-array object reached from a document root, a children array, a repeater `map` or
68
+ a `$switch` case is a node definition, and JxMutableNode is the editor's open node shape. */
72
69
  const n = node as JxMutableNode;
73
70
  const { children } = n;
74
- if (
75
- children &&
76
- typeof children === "object" &&
77
- !Array.isArray(children) &&
78
- (children as JxMutableNode).$prototype === "Array"
79
- ) {
71
+ if (isMappedArray(children)) {
72
+ // SAFETY: A legacy whole-children repeater is the same repeater node that becomes the member.
80
73
  n.children = [children as JxMutableNode];
81
74
  }
82
75
  if (Array.isArray(n.children)) {
@@ -84,10 +77,10 @@ export function normalizeArrayChildren(node: unknown): unknown {
84
77
  normalizeArrayChildren(child);
85
78
  }
86
79
  }
87
- if (n.$prototype === "Array" && n.map && typeof n.map === "object") {
80
+ if (n.$prototype === "Array" && isNonNullObject(n.map)) {
88
81
  normalizeArrayChildren(n.map);
89
82
  }
90
- if (n.cases && typeof n.cases === "object") {
83
+ if (isNonNullObject(n.cases)) {
91
84
  for (const caseDef of Object.values(n.cases)) {
92
85
  normalizeArrayChildren(caseDef);
93
86
  }
@@ -209,7 +202,7 @@ function collectRows(
209
202
  skipSelf: boolean,
210
203
  ): void {
211
204
  // Text node children: bare primitives get a "text" row
212
- if (typeof doc === "string" || typeof doc === "number" || typeof doc === "boolean") {
205
+ if (isString(doc) || isNumber(doc) || isBoolean(doc)) {
213
206
  if (!skipSelf) {
214
207
  out.push({ depth, node: doc, nodeType: "text", path });
215
208
  }
@@ -220,13 +213,13 @@ function collectRows(
220
213
  // Recurse into its single template at `[...path, "map"]`. This is reached both when the array is
221
214
  // A member of a children array (path `[…, "children", i]`) and the legacy whole-children form
222
215
  // (path `[…, "children"]`).
223
- if ((doc as JxMutableNode).$prototype === "Array") {
216
+ if (doc.$prototype === "Array") {
224
217
  if (!skipSelf) {
225
218
  out.push({ depth, node: doc, nodeType: "map", path });
226
219
  }
227
- const mapDef = (doc as JxMutableNode).map;
228
- if (mapDef && typeof mapDef === "object") {
229
- collectRows(mapDef as JxMutableNode, [...path, "map"], depth + 1, out, false);
220
+ const mapDef = doc.map;
221
+ if (isNonNullObject(mapDef)) {
222
+ collectRows(mapDef, [...path, "map"], depth + 1, out, false);
230
223
  }
231
224
  return;
232
225
  }
@@ -247,36 +240,33 @@ function collectRows(
247
240
  const childPath = [...path, "children", i];
248
241
  collectRows(children[i]!, childPath, depth + 1, out, false);
249
242
  }
250
- } else if (
251
- children &&
252
- typeof children === "object" &&
253
- (children as JxMutableNode).$prototype === "Array"
254
- ) {
243
+ } else if (isMappedArray(children)) {
255
244
  // Legacy whole-children repeater: the array occupies the children slot itself.
245
+ // SAFETY: The repeater in the children slot is the same repeater node a children member is.
256
246
  collectRows(children as JxMutableNode, [...path, "children"], depth + 1, out, false);
257
247
  }
258
248
 
259
249
  // $switch — emit each case as a virtual child
260
- if (doc.$switch && doc.cases && typeof doc.cases === "object") {
250
+ if (doc.$switch && isNonNullObject(doc.cases)) {
261
251
  for (const [caseName, caseDef] of Object.entries(doc.cases)) {
262
252
  const casePath = [...path, "cases", caseName];
263
- if (caseDef && typeof caseDef === "object" && (caseDef as JxMutableNode).$ref) {
253
+ if (isNonNullObject(caseDef) && caseDef.$ref) {
264
254
  out.push({
265
255
  depth: depth + 1,
266
- node: caseDef as JxMutableNode,
256
+ node: caseDef,
267
257
  nodeType: "case-ref",
268
258
  path: casePath,
269
259
  });
270
- } else if (caseDef && typeof caseDef === "object") {
260
+ } else if (isNonNullObject(caseDef)) {
271
261
  out.push({
272
262
  depth: depth + 1,
273
- node: caseDef as JxMutableNode,
263
+ node: caseDef,
274
264
  nodeType: "case",
275
265
  path: casePath,
276
266
  });
277
267
  // Recurse into case children — skipSelf, because the "case" row above already stands in for
278
268
  // The case node itself (with its own nodeType).
279
- collectRows(caseDef as JxMutableNode, casePath, depth + 2, out, true);
269
+ collectRows(caseDef, casePath, depth + 2, out, true);
280
270
  }
281
271
  }
282
272
  }
@@ -285,10 +275,10 @@ function collectRows(
285
275
  /**
286
276
  * Get a display label for a node (for layers + overlays).
287
277
  *
288
- * @param {JxMutableNode | null} node
278
+ * @param {JxMutableNode | null | undefined} node
289
279
  * @returns {string}
290
280
  */
291
- export function nodeLabel(node: JxMutableNode | null) {
281
+ export function nodeLabel(node: JxMutableNode | null | undefined) {
292
282
  if (!node) {
293
283
  return "?";
294
284
  }
@@ -306,14 +296,14 @@ export function nodeLabel(node: JxMutableNode | null) {
306
296
  }
307
297
  if (node.tagName === "slot") {
308
298
  const name = node.attributes?.name;
309
- return typeof name === "string" && name.trim() ? `slot: ${name.trim()}` : "slot";
299
+ return isString(name) && name.trim() ? `slot: ${name.trim()}` : "slot";
310
300
  }
311
301
  /* `displayTagName`, because a tag may be CHOSEN rather than written: this label reached the
312
302
  Outline row, the Inspector's header and the jump bar, and a raw read rendered `[object Object]`
313
303
  in all three. `a|div` is the honest answer — one element, tag decided at creation. */
314
304
  const tag = displayTagName(node.tagName) || "div";
315
305
  const suffix = node.$switch ? " ⇆" : "";
316
- if (typeof node.textContent === "string" && node.textContent.length > 0) {
306
+ if (isString(node.textContent) && node.textContent.length > 0) {
317
307
  return `${tag} — ${node.textContent.slice(0, 24)}${suffix}`;
318
308
  }
319
309
  return tag + suffix;
@@ -340,5 +330,7 @@ export function setProjectState(ps: ProjectState | null) {
340
330
  * @returns {ProjectState}
341
331
  */
342
332
  export function requireProjectState() {
333
+ /* SAFETY: The contract above restricts callers to paths reached after `setProjectState` installed
334
+ a project (a project command, a panel that only mounts with one open); nothing here checks it. */
343
335
  return projectState as ProjectState;
344
336
  }
package/src/store.ts CHANGED
@@ -9,9 +9,10 @@
9
9
 
10
10
  // ─── Re-exports from state.js ────────────────────────────────────────────────
11
11
 
12
+ import { isFunction, isNonNullObject } from "@jxsuite/schema/guards";
12
13
  import { INPUT_DEBOUNCE } from "./ui/timing";
13
14
  import type { JxPath } from "./state";
14
- import type { Tab } from "./tabs/tab";
15
+ import type { Tab, TabUi } from "./tabs/tab";
15
16
  import type { JxMutableNode } from "@jxsuite/schema/types";
16
17
 
17
18
  export {
@@ -36,18 +37,38 @@ export {
36
37
  each of which meant "the pane I am acting on" and got "the pane that happens to be focused". A
37
38
  stage belongs to a pane (`canvas/canvas-surface.ts`), a pane's cell is built by
38
39
  `panels/pane-grid.ts`, and every one of those readers now takes its surface. */
39
- export let activityBar = null as unknown as HTMLElement;
40
- export let leftPanel = null as unknown as HTMLElement;
41
- export let rightPanel = null as unknown as HTMLElement;
42
- export let toolbarEl = null as unknown as HTMLElement;
43
- export let statusbarEl = null as unknown as HTMLElement;
40
+
41
+ /* Null until `initShellRefs()`, which `studio.ts` calls at boot right after mounting the shell
42
+ document; a render asked for before that (a test, or a command run ahead of the shell) reads null. */
43
+ export let activityBar: HTMLElement | null = null;
44
+ export let leftPanel: HTMLElement | null = null;
45
+ export let rightPanel: HTMLElement | null = null;
46
+ export let toolbarEl: HTMLElement | null = null;
47
+ export let statusbarEl: HTMLElement | null = null;
48
+
49
+ /** The shell region whose `id` is given, or null when the mounted shell has none. */
50
+ function shellRef(id: string): HTMLElement | null {
51
+ const element = document.querySelector(`#${id}`);
52
+ return element instanceof HTMLElement ? element : null;
53
+ }
44
54
 
45
55
  export function initShellRefs() {
46
- activityBar = document.querySelector("#activity-bar") as HTMLElement;
47
- leftPanel = document.querySelector("#left-panel") as HTMLElement;
48
- rightPanel = document.querySelector("#right-panel") as HTMLElement;
49
- toolbarEl = document.querySelector("#toolbar") as HTMLElement;
50
- statusbarEl = document.querySelector("#statusbar") as HTMLElement;
56
+ activityBar = shellRef("activity-bar");
57
+ leftPanel = shellRef("left-panel");
58
+ rightPanel = shellRef("right-panel");
59
+ toolbarEl = shellRef("toolbar");
60
+ statusbarEl = shellRef("statusbar");
61
+ }
62
+
63
+ /**
64
+ * A shell region for a caller that cannot work without it. Reading one before `initShellRefs()` has
65
+ * found it is a boot-order bug, so it throws a TypeError that names the region.
66
+ */
67
+ export function requireShellRef(ref: HTMLElement | null, id: string): HTMLElement {
68
+ if (!ref) {
69
+ throw new TypeError(`#${id} is not in the shell yet; initShellRefs() has not found it`);
70
+ }
71
+ return ref;
51
72
  }
52
73
 
53
74
  // ─── Shared constants ────────────────────────────────────────────────────────
@@ -130,6 +151,11 @@ export { stripEventHandlers } from "./utils/strip-events";
130
151
 
131
152
  const _renderers = new Map<string, () => void>();
132
153
 
154
+ /** Whether a renderer's return value is a thenable — an `async` renderer that is still painting. */
155
+ function isThenable(value: unknown): value is PromiseLike<unknown> {
156
+ return (isNonNullObject(value) || isFunction(value)) && "then" in value && isFunction(value.then);
157
+ }
158
+
133
159
  /**
134
160
  * How many registered renderers are mid-paint right now.
135
161
  *
@@ -154,9 +180,9 @@ function runRenderer(name: string, fn: () => void) {
154
180
  };
155
181
  let pending: PromiseLike<unknown> | null = null;
156
182
  try {
157
- const result = fn() as unknown;
158
- if (typeof (result as PromiseLike<unknown> | null)?.then === "function") {
159
- pending = result as PromiseLike<unknown>;
183
+ const result = fn();
184
+ if (isThenable(result)) {
185
+ pending = result;
160
186
  }
161
187
  } catch (error) {
162
188
  console.error(`Renderer "${name}" failed:`, error);
@@ -165,7 +191,7 @@ function runRenderer(name: string, fn: () => void) {
165
191
  done();
166
192
  return;
167
193
  }
168
- pending.then(done, (error: unknown) => {
194
+ pending.then(done, (error) => {
169
195
  console.error(`Renderer "${name}" failed:`, error);
170
196
  done();
171
197
  });
@@ -232,8 +258,8 @@ export function updateSession(
232
258
  selection?: JxPath[];
233
259
  hover?: JxPath | null;
234
260
  clipboard?: JxMutableNode | null;
235
- ui?: Record<string, unknown>;
236
- canvas?: Record<string, unknown>;
261
+ ui?: Partial<TabUi>;
262
+ canvas?: Partial<Tab["session"]["canvas"]>;
237
263
  },
238
264
  ) {
239
265
  if (tab) {
@@ -241,20 +267,16 @@ export function updateSession(
241
267
  tab.session.selection = patch.selection;
242
268
  }
243
269
  if (patch.hover !== undefined) {
244
- tab.session.hover = patch.hover as JxPath | null;
270
+ tab.session.hover = patch.hover;
245
271
  }
246
272
  if (patch.clipboard !== undefined) {
247
- tab.session.clipboard = patch.clipboard!;
273
+ tab.session.clipboard = patch.clipboard;
248
274
  }
249
275
  if (patch.ui) {
250
- for (const [k, v] of Object.entries(patch.ui)) {
251
- (tab.session.ui as unknown as Record<string, unknown>)[k] = v;
252
- }
276
+ Object.assign(tab.session.ui, patch.ui);
253
277
  }
254
278
  if (patch.canvas) {
255
- for (const [k, v] of Object.entries(patch.canvas)) {
256
- (tab.session.canvas as unknown as Record<string, unknown>)[k] = v;
257
- }
279
+ Object.assign(tab.session.canvas, patch.canvas);
258
280
  }
259
281
  }
260
282
  }
@@ -263,12 +285,12 @@ export function updateSession(
263
285
  * Update a single UI field on `tab`.
264
286
  *
265
287
  * @param {Tab | null} tab — the tab this field belongs to. `null` is a no-op.
266
- * @param {string} field
267
- * @param {unknown} value
288
+ * @param {K} field
289
+ * @param {TabUi[K]} value
268
290
  */
269
- export function updateUi(tab: Tab | null, field: string, value: unknown) {
291
+ export function updateUi<K extends keyof TabUi>(tab: Tab | null, field: K, value: TabUi[K]) {
270
292
  if (tab) {
271
- (tab.session.ui as unknown as Record<string, unknown>)[field] = value;
293
+ tab.session.ui[field] = value;
272
294
  }
273
295
  }
274
296
 
@@ -276,12 +298,10 @@ export function updateUi(tab: Tab | null, field: string, value: unknown) {
276
298
  * Update `tab`'s canvas async state (status, scope, error).
277
299
  *
278
300
  * @param {Tab | null} tab — the tab whose stage produced this state. `null` is a no-op.
279
- * @param {object} patch
301
+ * @param {Partial<Tab["session"]["canvas"]>} patch
280
302
  */
281
- export function updateCanvas(tab: Tab | null, patch: Record<string, unknown>) {
303
+ export function updateCanvas(tab: Tab | null, patch: Partial<Tab["session"]["canvas"]>) {
282
304
  if (tab) {
283
- for (const [k, v] of Object.entries(patch)) {
284
- (tab.session.canvas as Record<string, unknown>)[k] = v;
285
- }
305
+ Object.assign(tab.session.canvas, patch);
286
306
  }
287
307
  }
package/src/studio.ts CHANGED
@@ -21,6 +21,7 @@ import {
21
21
  registerRenderer,
22
22
  render,
23
23
  requireProjectState,
24
+ requireShellRef,
24
25
  setProjectState,
25
26
  toolbarEl,
26
27
  updateSession,
@@ -117,13 +118,12 @@ import {
117
118
  import {
118
119
  loadProject as _loadProject,
119
120
  openProject as _openProject,
120
- renderFilesTemplate,
121
121
  findHomePage,
122
122
  loadDirectory,
123
+ loadProjectDirectories,
123
124
  openFileInPane,
124
125
  openFileInTab,
125
126
  openLastSessionOrHome,
126
- registerFileTreeDnD,
127
127
  reloadCleanTab,
128
128
  reloadTabsIfChanged,
129
129
  } from "./files/files";
@@ -136,9 +136,7 @@ import {
136
136
  configureCollabParser,
137
137
  configureCollabSerializer,
138
138
  } from "./collab/collab-session";
139
- import { renderImportsTemplate } from "./panels/imports-panel";
140
- import { invalidateLayoutPickerCache, renderHeadTemplate } from "./panels/head-panel";
141
- import { exportCemManifest as _exportCemManifest } from "./services/cem-export";
139
+ import { invalidateLayoutPickerCache } from "./panels/head-panel";
142
140
  import { installAutomationHook } from "./services/automation";
143
141
  import { invalidateLibrary } from "./browse/library-pane";
144
142
  import { invalidateMediaCache } from "./ui/media-picker";
@@ -175,7 +173,6 @@ import {
175
173
  cloneRepository,
176
174
  loadDiffForLens,
177
175
  registerSourceControlCommands,
178
- renderGitPanel,
179
176
  noteFileSaved,
180
177
  } from "./panels/git-panel";
181
178
 
@@ -191,7 +188,7 @@ import { chordsInScopes } from "./commands/keymap";
191
188
  import { FRAME_KEY_SCOPES } from "./canvas/iframe-keys";
192
189
  import { createLiveContext } from "./commands/live-context";
193
190
  import { hasAiCredentials } from "./services/ai-models";
194
- import { mount as mountActivityBar } from "./surfaces/rail";
191
+ import { mount } from "./surfaces/rail";
195
192
  import * as toolbarPanel from "./surfaces/commandbar";
196
193
  import * as overlaysPanel from "./panels/overlays";
197
194
  import * as frontmatterPanelMod from "./panels/frontmatter-panel";
@@ -200,7 +197,8 @@ import * as chatPanelMod from "./panels/chat-panel";
200
197
  import { setProjectAdopter } from "./services/project-adoption";
201
198
  import { setImportHandoff } from "./services/import-seed";
202
199
  import { watchConnection } from "./services/connection";
203
- import { tabBufferUnsaved } from "./services/monaco-buffer";
200
+ import { commitTabBuffers, tabBufferUnsaved } from "./services/monaco-buffer";
201
+ import { clearTyping } from "./tabs/typing";
204
202
  import * as leftPanelMod from "./panels/left-panel";
205
203
  import * as tabStrip from "./panels/tab-strip";
206
204
  import * as paneContext from "./panels/pane-context";
@@ -267,7 +265,7 @@ import { registerI18nCommands } from "./i18n/i18n-commands";
267
265
  import { convertToComponent } from "./editor/convert-to-component";
268
266
  import type { GitDiffState } from "./types";
269
267
  import type { Tab } from "./tabs/tab";
270
- import type { JxDocument, JxMutableNode, ProjectConfig } from "@jxsuite/schema/types";
268
+ import type { JxDocument, ProjectConfig } from "@jxsuite/schema/types";
271
269
  import { setBundleBase } from "./services/bundle-base";
272
270
  import { mountBootFailureTree, mountShellTree } from "./shell/tree";
273
271
 
@@ -498,7 +496,7 @@ initShellRefs();
498
496
  mountShell();
499
497
 
500
498
  // Mount extracted panel modules
501
- toolbarPanel.mount(toolbarEl, {
499
+ toolbarPanel.mount(requireShellRef(toolbarEl, "toolbar"), {
502
500
  closeFunctionEditor: () => closeFunctionEditor(),
503
501
  getCanvasMode,
504
502
  openProject: () => openProject(),
@@ -640,9 +638,8 @@ window.addEventListener("beforeunload", (e: BeforeUnloadEvent) => {
640
638
  // Author may cancel the close, and the record is the same either way.
641
639
  flushSession();
642
640
  if (hasUnsavedTabs()) {
641
+ // The HTML standard's trigger for the leave-page prompt; the legacy `returnValue` is deprecated.
643
642
  e.preventDefault();
644
- // Legacy browsers require a truthy returnValue to trigger the native confirm prompt.
645
- e.returnValue = "";
646
643
  }
647
644
  });
648
645
 
@@ -742,11 +739,8 @@ function installPaneRenderEffects(paneId: string): void {
742
739
  installDerivationEffects(paneId, derivationDeps);
743
740
  effect(() => {
744
741
  const tab = tabOfPane(paneId);
745
- if (tab) {
746
- const doc = tab.doc.document;
747
- if (doc && consumePatchedDocument(doc, paneId)) {
748
- return;
749
- }
742
+ if (tab && consumePatchedDocument(tab.doc.document, paneId)) {
743
+ return;
750
744
  }
751
745
  scheduleCanvasRender(paneId);
752
746
  });
@@ -870,7 +864,6 @@ leftPanelMod.mount({
870
864
  navigateToComponent,
871
865
  registerComponentsDnD,
872
866
  registerElementsDnD,
873
- registerFileTreeDnD,
874
867
  registerLayersDnD,
875
868
  renderCanvas: () => renderCanvas(),
876
869
  // The Data panel's Refresh: a canvas re-render that ALSO lets automatic `Request` state entries
@@ -893,10 +886,6 @@ leftPanelMod.mount({
893
886
  }
894
887
  renderCanvas(paneId);
895
888
  },
896
- renderFilesTemplate,
897
- renderGitPanel,
898
- renderHeadTemplate,
899
- renderImportsTemplate,
900
889
  mountSignalsPanel,
901
890
  setCanvasMode,
902
891
  setGitDiffState: (state: GitDiffState | null) => {
@@ -918,7 +907,7 @@ renderStatusbar();
918
907
  // The status bar mounts the jump bar too: the focused pane's breadcrumb trail is its DOCUMENT
919
908
  // Field, and the only breadcrumb in the shell.
920
909
  mountStatusbar();
921
- mountActivityBar();
910
+ mount();
922
911
 
923
912
  /* The background-click deselect moved into `editor/shortcuts.ts`'s `installStageGestures`, beside
924
913
  the wheel and the middle-drag, because it is a STAGE gesture: it compared against the app's one
@@ -982,10 +971,10 @@ if (!_projectParam) {
982
971
  const _bootPlatform = getPlatform();
983
972
  // oxlint-disable-next-line unicorn/prefer-top-level-await -- fire-and-forget: must not block the initial render
984
973
  void _bootPlatform
985
- .activate?.()
974
+ .activate()
986
975
  // No project is bound yet, so this call only warms the canvasUrl; a backend that refuses it
987
976
  // Still gets the render below rather than an unhandled rejection.
988
- ?.catch((error: unknown) => {
977
+ .catch((error) => {
989
978
  // A refusal that offers an action is the action flow's to explain; it is not a fault.
990
979
  if (!isActionRequired(error)) {
991
980
  console.error("Boot activation failed:", error);
@@ -1017,18 +1006,14 @@ if (_projectParam) {
1017
1006
  // Report a bare `Error: <message>` because the only identifying fact was still block-scoped.
1018
1007
  let fileRelPath = _urlParams.get("file") || _projectParam;
1019
1008
  try {
1020
- const siteCtx = platform.resolveSiteContext
1021
- ? await platform.resolveSiteContext(_projectParam)
1022
- : { sitePath: null };
1009
+ const siteCtx = await platform.resolveSiteContext(_projectParam);
1023
1010
 
1024
1011
  if (siteCtx.sitePath) {
1025
1012
  // Set PAL project root to absolute path so file ops work
1026
1013
  if (siteCtx.sitePath) {
1027
1014
  platform.projectRoot = siteCtx.sitePath;
1028
1015
  // Await activation so the server resolves project-relative static files
1029
- if (platform.activate) {
1030
- await platform.activate();
1031
- }
1016
+ await platform.activate();
1032
1017
  }
1033
1018
 
1034
1019
  resetIgnoreCache();
@@ -1052,31 +1037,9 @@ if (_projectParam) {
1052
1037
  await ensureDependenciesInstalled();
1053
1038
  await loadComponentRegistry();
1054
1039
 
1055
- // Load directory tree and populate projectDirs from conventional dirs found
1056
- const conventionalDirs = new Set([
1057
- "pages",
1058
- "layouts",
1059
- "components",
1060
- "content",
1061
- "data",
1062
- "public",
1063
- "styles",
1064
- ]);
1065
- /* Through `loadDirectory`, not `platform.listDirectory`: this is the second copy of the
1066
- conventional-dir walk (the first is `openProject` in files/files.ts), and the loader is
1067
- what reads the `.gitignore` chain governing each directory. Listing around it left the
1068
- `?project=` boot as the one door into a project whose tree knew no ignore rules. */
1069
- await loadDirectory(".");
1070
- const dirEntries = requireProjectState().dirs.get(".") ?? [];
1071
- const foundDirs = [];
1072
- for (const e of dirEntries) {
1073
- if (e.type === "directory" && conventionalDirs.has(e.name)) {
1074
- foundDirs.push(e.name);
1075
- requireProjectState().expanded.add(e.path || e.name);
1076
- await loadDirectory(e.path || e.name);
1077
- }
1078
- }
1079
- requireProjectState().projectDirs = foundDirs;
1040
+ /* Through `loadDirectory` (inside `loadProjectDirectories`), not `platform.listDirectory`:
1041
+ the loader is what reads the `.gitignore` chain governing each directory. */
1042
+ await loadProjectDirectories();
1080
1043
  void maybePromptJxsuiteUpdate(siteCtx.sitePath);
1081
1044
  }
1082
1045
 
@@ -1143,7 +1106,7 @@ if (_projectParam) {
1143
1106
  openTab({
1144
1107
  id: fileRelPath,
1145
1108
  documentPath: fileRelPath,
1146
- document: parsedDoc as JxMutableNode,
1109
+ document: parsedDoc,
1147
1110
  ...(frontmatter != null && { frontmatter }),
1148
1111
  layout,
1149
1112
  sourceFormat: fileFormat?.name ?? null,
@@ -1364,6 +1327,9 @@ async function openRecentProject(root: string) {
1364
1327
  void loadFormats();
1365
1328
  refreshExtensionUi(platform);
1366
1329
  const content = await platform.readFile("project.json");
1330
+ /* SAFETY: This is `project.json` at the root the user chose to open, the project's own config
1331
+ file whose schema is ProjectConfig; Studio edits it in that shape and does not re-validate it
1332
+ on open, as the folder-picker path in `platforms/devserver.ts` does not either. */
1367
1333
  const config = JSON.parse(content) as ProjectConfig;
1368
1334
 
1369
1335
  closeAllTabs();
@@ -1388,26 +1354,9 @@ async function openRecentProject(root: string) {
1388
1354
  activity.step("Install dependencies");
1389
1355
  await ensureDependenciesInstalled();
1390
1356
  activity.step("Read the project");
1391
- await loadDirectory(".");
1357
+ await loadProjectDirectories();
1392
1358
  await loadComponentRegistry();
1393
1359
 
1394
- const conventionalDirs = new Set([
1395
- "pages",
1396
- "layouts",
1397
- "components",
1398
- "content",
1399
- "data",
1400
- "public",
1401
- "styles",
1402
- ]);
1403
- const entries = requireProjectState().dirs.get(".") || [];
1404
- for (const e of entries) {
1405
- if (e.type === "directory" && conventionalDirs.has(e.name)) {
1406
- requireProjectState().expanded.add(e.path || e.name);
1407
- await loadDirectory(e.path || e.name);
1408
- }
1409
- }
1410
-
1411
1360
  addRecentProject(requireProjectState().name, root);
1412
1361
  setActivityTab("files");
1413
1362
  renderLeftPanel();
@@ -1492,7 +1441,18 @@ registerStudioCommands(
1492
1441
  // Whether the bytes landed, and a hook that neither supplies one nor reads the answer must not
1493
1442
  // Silently forward its own first argument as the tab to save.
1494
1443
  saveDocument: async () => {
1495
- await saveFile();
1444
+ const tab = activeTab.value;
1445
+ if (!tab) {
1446
+ return;
1447
+ }
1448
+ // What a source buffer holds goes into the document first, or ⌘S inside the commit's
1449
+ // Debounce would save the text from before the last keystrokes.
1450
+ await commitTabBuffers(tab);
1451
+ await saveFile(tab);
1452
+ // Text that would not parse is still only in the buffer, so it is still unsaved.
1453
+ if (!tabBufferUnsaved(tab)) {
1454
+ clearTyping(tab.id);
1455
+ }
1496
1456
  },
1497
1457
  },
1498
1458
  stageContext,
@@ -1549,7 +1509,9 @@ const liveChrome = createLiveSurfaceSaver({
1549
1509
  registry reactively. */
1550
1510
  setDocumentSavedListener((path, doc) => {
1551
1511
  void noteFileSaved(path);
1552
- void liveChrome(path, doc as unknown as JxDocument);
1512
+ /* SAFETY: The listener fires for a tab's saved ROOT document, and a root document is a
1513
+ JxDocument held in the editor's mutable node form; `liveChrome` only acts on surface paths. */
1514
+ void liveChrome(path, doc as JxDocument);
1553
1515
  if (noteComponentSaved(path, doc)) {
1554
1516
  renderPropertiesPanel();
1555
1517
  renderLeftPanel();
@@ -32,5 +32,5 @@ import { activeTab } from "../workspace/workspace";
32
32
  export function pushProjectStylesToCanvas(): void {
33
33
  postSiteStyleToLiveHosts();
34
34
  const style = transposeStylebookStyle(getEffectiveStyle(activeTab.value?.doc.document?.style));
35
- postStyleUpdateToStylebookHosts(style as Record<string, unknown>);
35
+ postStyleUpdateToStylebookHosts(style);
36
36
  }