@jxsuite/studio 6.1.1 → 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 (637) hide show
  1. package/dist/chunks/{2020-va2wwra4.js → 2020-f2gkpy8d.js} +3 -3
  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-2veqmnhr.js → index-zpjmzqfk.js} +3 -3
  32. package/dist/chunks/{javascript-8nbvs12s.js → javascript-m54mnwp6.js} +3 -3
  33. package/dist/chunks/{jsonMode-s8kt9dsj.js → jsonMode-w15cmrcm.js} +8 -8
  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-1q1sh2ax.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-h46vtzk8.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-rv11kfwa.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-8grwxtqk.js → studio-90pq9km1.js} +4 -4
  77. package/dist/chunks/studio-924p1tm1.js +6 -0
  78. package/dist/chunks/{studio-pre0skq6.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-vrmcjf9g.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-wszjyh0j.js → studio-tq0rtfwj.js} +4 -4
  111. package/dist/chunks/{studio-kggey1jt.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-zey7zsdw.js → studio-y64hrt8p.js} +7 -7
  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-2frah6h1.js → tsMode-sf49ee9x.js} +7 -7
  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 +97 -97
  140. package/package.json +6 -6
  141. package/src/about/about-modal.ts +4 -3
  142. package/src/account/action-flow.ts +45 -38
  143. package/src/account-status.ts +7 -2
  144. package/src/browse/library-layouts.ts +8 -5
  145. package/src/browse/library-model.ts +18 -6
  146. package/src/browse/library-pane.ts +37 -21
  147. package/src/browse/library-preview.ts +14 -9
  148. package/src/browse/library-source.ts +1 -1
  149. package/src/canvas/asset-refs.ts +24 -9
  150. package/src/canvas/asset-resolve.ts +19 -23
  151. package/src/canvas/canvas-helpers.ts +7 -6
  152. package/src/canvas/canvas-live-render.ts +44 -53
  153. package/src/canvas/canvas-patcher.ts +30 -30
  154. package/src/canvas/canvas-perf.ts +11 -5
  155. package/src/canvas/canvas-render.ts +62 -41
  156. package/src/canvas/canvas-surface.ts +5 -3
  157. package/src/canvas/canvas-utils.ts +90 -49
  158. package/src/canvas/dialog-path.ts +9 -4
  159. package/src/canvas/dialog-state.ts +1 -2
  160. package/src/canvas/diff-marks.ts +9 -16
  161. package/src/canvas/diff-toolbar.ts +8 -7
  162. package/src/canvas/edit-width-drag.ts +4 -1
  163. package/src/canvas/edit-width.ts +1 -3
  164. package/src/canvas/iframe-channel.ts +27 -13
  165. package/src/canvas/iframe-drop.ts +13 -12
  166. package/src/canvas/iframe-editable-root.ts +29 -16
  167. package/src/canvas/iframe-entry.ts +80 -63
  168. package/src/canvas/iframe-eval.ts +73 -49
  169. package/src/canvas/iframe-host.ts +135 -96
  170. package/src/canvas/iframe-inline-edit.ts +49 -30
  171. package/src/canvas/iframe-insert.ts +5 -4
  172. package/src/canvas/iframe-interaction.ts +30 -25
  173. package/src/canvas/iframe-overlay.ts +1 -1
  174. package/src/canvas/iframe-patch.ts +18 -15
  175. package/src/canvas/iframe-position.ts +12 -6
  176. package/src/canvas/iframe-protocol.ts +12 -16
  177. package/src/canvas/iframe-render.ts +36 -34
  178. package/src/canvas/iframe-slash.ts +24 -11
  179. package/src/canvas/iframe-subtree.ts +6 -2
  180. package/src/canvas/path-mapping.ts +19 -12
  181. package/src/canvas/popover-path.ts +7 -3
  182. package/src/canvas/popover-state.ts +1 -2
  183. package/src/canvas/serialize-scope.ts +13 -5
  184. package/src/canvas/stage-scrollbar.ts +2 -1
  185. package/src/canvas/surface-registry.ts +21 -3
  186. package/src/collab/collab-commands.ts +7 -2
  187. package/src/collab/collab-session.ts +84 -45
  188. package/src/collab/collab-state.ts +4 -3
  189. package/src/collab/monaco-binding.ts +16 -13
  190. package/src/collab/monaco-cursors.ts +5 -2
  191. package/src/commands/budget.ts +3 -3
  192. package/src/commands/command-args.ts +103 -71
  193. package/src/commands/context.ts +22 -20
  194. package/src/commands/keymap.ts +47 -43
  195. package/src/commands/levels.ts +3 -3
  196. package/src/commands/live-context.ts +7 -7
  197. package/src/commands/reference.ts +2 -1
  198. package/src/commands/registry.ts +12 -10
  199. package/src/commands/run-reported.ts +15 -10
  200. package/src/component-props.ts +46 -30
  201. package/src/content/collection-match.ts +5 -4
  202. package/src/content/draft-state.ts +4 -3
  203. package/src/content/entry-commands.ts +3 -2
  204. package/src/content/entry-editor.ts +29 -17
  205. package/src/content/entry-fields.ts +12 -7
  206. package/src/content/entry-model.ts +21 -12
  207. package/src/editor/canvas-context-menu.ts +1 -2
  208. package/src/editor/canvas-slash-bridge.ts +3 -6
  209. package/src/editor/content-slice.ts +16 -14
  210. package/src/editor/context-menu.ts +35 -22
  211. package/src/editor/convert-targets.ts +30 -35
  212. package/src/editor/convert-to-component.ts +11 -5
  213. package/src/editor/convert-to-repeater.ts +34 -22
  214. package/src/editor/editable-tags.ts +17 -2
  215. package/src/editor/file-drop-action.ts +21 -22
  216. package/src/editor/inline-edit-apply.ts +35 -17
  217. package/src/editor/inline-edit.ts +66 -50
  218. package/src/editor/inline-format.ts +59 -56
  219. package/src/editor/inline-link.ts +40 -15
  220. package/src/editor/insert-zone-action.ts +1 -1
  221. package/src/editor/merge-tags.ts +58 -19
  222. package/src/editor/repeater-scope.ts +39 -28
  223. package/src/editor/shortcuts.ts +32 -20
  224. package/src/editor/slash-menu.ts +1 -6
  225. package/src/files/asset-versions.ts +4 -4
  226. package/src/files/components.ts +15 -10
  227. package/src/files/elements.ts +5 -6
  228. package/src/files/file-ops.ts +77 -36
  229. package/src/files/files.ts +90 -95
  230. package/src/files/media-meta.ts +2 -1
  231. package/src/files/media-paths.ts +3 -0
  232. package/src/files/serialize-document.ts +2 -2
  233. package/src/format/constraints.ts +1 -1
  234. package/src/format/convert-file.ts +27 -13
  235. package/src/format/format-choices.ts +2 -1
  236. package/src/format/format-host.ts +76 -50
  237. package/src/github/github-auth-status.ts +27 -3
  238. package/src/github/github-auth.ts +19 -9
  239. package/src/github/github-publish.ts +24 -20
  240. package/src/grid/cell-editors.ts +46 -31
  241. package/src/grid/cell-popovers.ts +5 -3
  242. package/src/grid/edit-buffer.ts +10 -9
  243. package/src/grid/grid-controller.ts +20 -22
  244. package/src/grid/grid-layout.ts +21 -5
  245. package/src/grid/grid-open.ts +3 -6
  246. package/src/grid/grid-panel.ts +11 -4
  247. package/src/grid/grid-source.ts +8 -8
  248. package/src/grid/grid-view.ts +14 -17
  249. package/src/grid/redirects-grid.ts +14 -5
  250. package/src/grid/redirects.ts +16 -14
  251. package/src/grid/schema-columns.ts +25 -19
  252. package/src/grid/sources/connector-source.ts +47 -20
  253. package/src/grid/sources/content-source.ts +25 -24
  254. package/src/grid/sources/csv-file-source.ts +2 -2
  255. package/src/grid/tabulator-tables.d.ts +55 -34
  256. package/src/hosting/stage.ts +7 -7
  257. package/src/i18n/i18n-commands.ts +1 -2
  258. package/src/media/media-pane.ts +4 -1
  259. package/src/new-project/add-repo-modal.ts +20 -19
  260. package/src/new-project/import-tab.ts +10 -14
  261. package/src/new-project/location-fields.ts +2 -1
  262. package/src/new-project/new-project-modal.ts +12 -9
  263. package/src/packages/jxsuite-update.ts +4 -3
  264. package/src/packages/pull-package-sync.ts +26 -25
  265. package/src/page-params.ts +97 -68
  266. package/src/panels/activity-panel.ts +17 -9
  267. package/src/panels/ai-chat/attached-context.ts +13 -7
  268. package/src/panels/ai-chat/chat-view.ts +80 -73
  269. package/src/panels/ai-chat/composer.ts +30 -33
  270. package/src/panels/ai-chat/sessions-view.ts +1 -2
  271. package/src/panels/ai-panel.ts +23 -20
  272. package/src/panels/block-action-bar.ts +46 -35
  273. package/src/panels/bottom-dock.ts +5 -3
  274. package/src/panels/canvas-dnd-bridge.ts +31 -24
  275. package/src/panels/data-explorer.ts +62 -25
  276. package/src/panels/data-grid.ts +14 -11
  277. package/src/panels/dnd.ts +108 -118
  278. package/src/panels/editors.ts +52 -21
  279. package/src/panels/elements-panel.ts +10 -3
  280. package/src/panels/events-panel.ts +84 -69
  281. package/src/panels/formula-workspace.ts +76 -51
  282. package/src/panels/frontmatter-fields.ts +24 -19
  283. package/src/panels/frontmatter-panel.ts +44 -34
  284. package/src/panels/git-diff-open.ts +4 -4
  285. package/src/panels/git-panel.ts +49 -61
  286. package/src/panels/head-panel.ts +131 -111
  287. package/src/panels/i18n-panel.ts +10 -3
  288. package/src/panels/imports-panel.ts +23 -47
  289. package/src/panels/jump-bar.ts +48 -29
  290. package/src/panels/layers-panel.ts +97 -74
  291. package/src/panels/left-panel.ts +3 -3
  292. package/src/panels/pane-context.ts +31 -22
  293. package/src/panels/pane-grid.ts +49 -20
  294. package/src/panels/panel-registry.ts +22 -37
  295. package/src/panels/properties-panel.ts +175 -121
  296. package/src/panels/quick-search.ts +53 -31
  297. package/src/panels/right-panel.ts +3 -3
  298. package/src/panels/seo-modal.ts +13 -17
  299. package/src/panels/settings-menu.ts +15 -15
  300. package/src/panels/signals-panel.ts +153 -131
  301. package/src/panels/statement-editor.ts +230 -140
  302. package/src/panels/style-panel.ts +218 -205
  303. package/src/panels/style-utils.ts +114 -51
  304. package/src/panels/stylebook-doc.ts +57 -54
  305. package/src/panels/stylebook-layers-panel.ts +9 -9
  306. package/src/panels/stylebook-panel.ts +13 -17
  307. package/src/panels/tab-drop.ts +27 -11
  308. package/src/panels/tab-strip.ts +36 -26
  309. package/src/platform-errors.ts +57 -43
  310. package/src/platform.ts +58 -30
  311. package/src/platforms/cloud.ts +345 -175
  312. package/src/platforms/default-platform.ts +10 -4
  313. package/src/platforms/devserver.ts +129 -117
  314. package/src/platforms/read-batcher.ts +16 -8
  315. package/src/project-list.ts +2 -1
  316. package/src/publish/deploy-checklist.ts +8 -2
  317. package/src/publish/pages-service.ts +28 -13
  318. package/src/publish/publish-commands.ts +5 -4
  319. package/src/publish/publish-panel.ts +10 -6
  320. package/src/recent-projects.ts +15 -8
  321. package/src/resize-edges.ts +26 -36
  322. package/src/services/a11y-report.ts +26 -19
  323. package/src/services/agent-seed.ts +23 -11
  324. package/src/services/ai-ask.ts +9 -12
  325. package/src/services/ai-command-tools.ts +68 -62
  326. package/src/services/ai-import-tools.ts +80 -67
  327. package/src/services/ai-models.ts +17 -13
  328. package/src/services/ai-project-tools.ts +68 -32
  329. package/src/services/ai-session-store.ts +19 -10
  330. package/src/services/ai-system-prompt.ts +46 -20
  331. package/src/services/ai-tools.ts +71 -27
  332. package/src/services/ai-write-report.ts +20 -12
  333. package/src/services/ai-writes.ts +4 -4
  334. package/src/services/automation.ts +58 -31
  335. package/src/services/cem-export.ts +149 -58
  336. package/src/services/clock.ts +6 -1
  337. package/src/services/code-services.ts +37 -31
  338. package/src/services/context-manager.ts +14 -10
  339. package/src/services/context-resolver.ts +20 -8
  340. package/src/services/data-service.ts +19 -15
  341. package/src/services/directory-picker.ts +18 -12
  342. package/src/services/document-assistant.ts +39 -19
  343. package/src/services/gated-registry.ts +10 -6
  344. package/src/services/harness/chat-reducer.ts +23 -1
  345. package/src/services/import-client.ts +91 -38
  346. package/src/services/import-seed.ts +8 -2
  347. package/src/services/jx-validate.ts +28 -31
  348. package/src/services/live-preview.ts +0 -0
  349. package/src/services/live-surfaces.ts +6 -3
  350. package/src/services/model-uri.ts +10 -2
  351. package/src/services/module-preloads.ts +12 -8
  352. package/src/services/monaco-buffer.ts +43 -24
  353. package/src/services/monaco-lazy.ts +7 -8
  354. package/src/services/monaco-setup.ts +23 -16
  355. package/src/services/notify.ts +44 -17
  356. package/src/services/popover-report.ts +25 -10
  357. package/src/services/preview-eval.ts +20 -8
  358. package/src/services/profile.ts +13 -6
  359. package/src/services/project-path.ts +13 -10
  360. package/src/services/references.ts +0 -0
  361. package/src/services/render-critic.ts +8 -7
  362. package/src/services/settings/kernel.ts +13 -4
  363. package/src/services/settings/write-queue.ts +9 -9
  364. package/src/services/token-lint.ts +12 -10
  365. package/src/services/tool-executor.ts +17 -5
  366. package/src/services/tool-outcomes.ts +44 -24
  367. package/src/services/trusted-types.ts +24 -7
  368. package/src/settings/contexts-section.ts +11 -8
  369. package/src/settings/contributed-section.ts +79 -60
  370. package/src/settings/css-vars-editor.ts +37 -16
  371. package/src/settings/defs-editor.ts +38 -35
  372. package/src/settings/extension-rows.ts +16 -8
  373. package/src/settings/extension-sections.ts +23 -13
  374. package/src/settings/extensions-section.ts +4 -1
  375. package/src/settings/general-settings.ts +11 -8
  376. package/src/settings/locales-section.ts +20 -12
  377. package/src/settings/preferences-dialog.ts +9 -6
  378. package/src/settings/preferences-keymap.ts +7 -5
  379. package/src/settings/preferences-sections.ts +11 -5
  380. package/src/settings/project-sections.ts +1 -1
  381. package/src/settings/schema-field-ui.ts +9 -0
  382. package/src/settings/settings-document.ts +5 -5
  383. package/src/shell/tree.ts +6 -5
  384. package/src/shell.ts +104 -81
  385. package/src/site-context.ts +37 -22
  386. package/src/state.ts +41 -49
  387. package/src/store.ts +54 -34
  388. package/src/studio.ts +25 -75
  389. package/src/style/live-preview.ts +1 -1
  390. package/src/style/project-styles.ts +6 -7
  391. package/src/style/token-ref.ts +5 -4
  392. package/src/surfaces/about.ts +18 -19
  393. package/src/surfaces/add-repo.ts +17 -19
  394. package/src/surfaces/ai-chat.ts +31 -36
  395. package/src/surfaces/ai-credentials-form.ts +6 -16
  396. package/src/surfaces/ai-managed-connect.ts +3 -4
  397. package/src/surfaces/ai-model-picker.ts +3 -5
  398. package/src/surfaces/block-action-bar.ts +22 -11
  399. package/src/surfaces/boot-failure.ts +4 -5
  400. package/src/surfaces/bottom-dock.ts +9 -18
  401. package/src/surfaces/canvas-stage.ts +12 -11
  402. package/src/surfaces/cf-account-picker.ts +17 -18
  403. package/src/surfaces/commandbar.ts +14 -9
  404. package/src/surfaces/convert-repeater.ts +17 -19
  405. package/src/surfaces/data-actions.ts +9 -7
  406. package/src/surfaces/dialog.ts +26 -28
  407. package/src/surfaces/diff-toolbar.ts +9 -7
  408. package/src/surfaces/doc-header.ts +10 -19
  409. package/src/surfaces/empty-state.ts +7 -10
  410. package/src/surfaces/entry-editor.ts +14 -11
  411. package/src/surfaces/expression-editor.ts +11 -25
  412. package/src/surfaces/files-panel.ts +27 -14
  413. package/src/surfaces/formula-palette.ts +4 -5
  414. package/src/surfaces/git-panel.ts +7 -15
  415. package/src/surfaces/github-auth.ts +16 -20
  416. package/src/surfaces/github-publish.ts +17 -22
  417. package/src/surfaces/grid-cell.ts +30 -31
  418. package/src/surfaces/grid-open.ts +10 -14
  419. package/src/surfaces/grid-panel.ts +13 -9
  420. package/src/surfaces/grid-replace.ts +13 -13
  421. package/src/surfaces/grid-views.ts +15 -18
  422. package/src/surfaces/inspector-dock.ts +13 -12
  423. package/src/surfaces/jump-bar.ts +5 -6
  424. package/src/surfaces/jxsuite-update.ts +16 -22
  425. package/src/surfaces/library-pane.ts +19 -20
  426. package/src/surfaces/logic-panel.ts +17 -30
  427. package/src/surfaces/logic-workspace.ts +13 -15
  428. package/src/surfaces/media-browser.ts +11 -10
  429. package/src/surfaces/media-field.ts +4 -5
  430. package/src/surfaces/media-pane.ts +8 -7
  431. package/src/surfaces/menu.ts +29 -23
  432. package/src/surfaces/navigator-dock.ts +11 -12
  433. package/src/surfaces/new-project.ts +27 -26
  434. package/src/surfaces/pane-context.ts +20 -25
  435. package/src/surfaces/pane-grid.ts +15 -10
  436. package/src/surfaces/panel-activity.ts +5 -6
  437. package/src/surfaces/panel-data.ts +3 -4
  438. package/src/surfaces/panel-deploy-checklist.ts +5 -6
  439. package/src/surfaces/panel-elements.ts +5 -7
  440. package/src/surfaces/panel-i18n.ts +5 -7
  441. package/src/surfaces/panel-imports.ts +6 -13
  442. package/src/surfaces/panel-outline.ts +25 -19
  443. package/src/surfaces/panel-page.ts +11 -18
  444. package/src/surfaces/panel-problems.ts +5 -7
  445. package/src/surfaces/panel-signals.ts +20 -34
  446. package/src/surfaces/panel-stylebook-layers.ts +5 -8
  447. package/src/surfaces/preferences.ts +21 -11
  448. package/src/surfaces/progress-modal.ts +15 -9
  449. package/src/surfaces/properties-panel.json +1 -1
  450. package/src/surfaces/properties-panel.ts +20 -42
  451. package/src/surfaces/publish.ts +18 -18
  452. package/src/surfaces/push-plan.ts +7 -8
  453. package/src/surfaces/rail.ts +13 -13
  454. package/src/surfaces/reference-field.ts +11 -15
  455. package/src/surfaces/schema-builder.ts +16 -22
  456. package/src/surfaces/schema-form.ts +15 -25
  457. package/src/surfaces/secret-field.ts +9 -6
  458. package/src/surfaces/seo.ts +21 -15
  459. package/src/surfaces/settings-contexts.ts +9 -7
  460. package/src/surfaces/settings-contributed.ts +14 -10
  461. package/src/surfaces/settings-css-vars.ts +5 -12
  462. package/src/surfaces/settings-defs.json +2 -2
  463. package/src/surfaces/settings-defs.ts +17 -21
  464. package/src/surfaces/settings-deploy.ts +8 -15
  465. package/src/surfaces/settings-extensions.ts +5 -6
  466. package/src/surfaces/settings-head.ts +33 -39
  467. package/src/surfaces/settings-locales.ts +8 -20
  468. package/src/surfaces/settings-overview.ts +5 -6
  469. package/src/surfaces/settings-packages.ts +8 -7
  470. package/src/surfaces/settings-pane.ts +9 -18
  471. package/src/surfaces/settings-rawjson.ts +5 -6
  472. package/src/surfaces/shell.ts +1 -2
  473. package/src/surfaces/slash-menu.ts +19 -9
  474. package/src/surfaces/statements.ts +13 -18
  475. package/src/surfaces/statusbar.ts +17 -14
  476. package/src/surfaces/style-panel.ts +18 -31
  477. package/src/surfaces/stylebook-chrome.ts +3 -5
  478. package/src/surfaces/tab-strip.ts +14 -13
  479. package/src/surfaces/target-line.ts +6 -7
  480. package/src/surfaces/welcome.ts +5 -7
  481. package/src/tabs/patch-ops.ts +4 -3
  482. package/src/tabs/project-config.ts +32 -21
  483. package/src/tabs/selection.ts +36 -8
  484. package/src/tabs/tab.ts +52 -41
  485. package/src/tabs/transact.ts +98 -53
  486. package/src/types.ts +32 -17
  487. package/src/ui/ai-credentials-form.ts +10 -13
  488. package/src/ui/ai-model-picker.ts +3 -3
  489. package/src/ui/cf-account-picker.ts +7 -9
  490. package/src/ui/color-selector.ts +9 -5
  491. package/src/ui/dynamic-slot.ts +7 -8
  492. package/src/ui/expression-editor.ts +112 -105
  493. package/src/ui/form-controls.ts +57 -48
  494. package/src/ui/formula-catalog.ts +239 -230
  495. package/src/ui/formula-chips.ts +33 -18
  496. package/src/ui/layers.ts +44 -31
  497. package/src/ui/media-picker.ts +18 -9
  498. package/src/ui/popover-surface.ts +20 -12
  499. package/src/ui/progress-modal.ts +13 -8
  500. package/src/ui/regions.ts +7 -6
  501. package/src/ui/schema-form.ts +113 -70
  502. package/src/ui/surface.ts +71 -8
  503. package/src/ui/timing.ts +9 -0
  504. package/src/ui/value-source.ts +44 -31
  505. package/src/ui/virtual-window.ts +3 -2
  506. package/src/utils/base64.ts +3 -1
  507. package/src/utils/edit-display.ts +73 -73
  508. package/src/utils/element-selectors.ts +3 -2
  509. package/src/utils/google-fonts.ts +15 -14
  510. package/src/utils/inherited-style.ts +18 -20
  511. package/src/utils/link-target.ts +1 -1
  512. package/src/utils/preview-format.ts +25 -3
  513. package/src/utils/strip-events.ts +49 -22
  514. package/src/utils/studio-utils.ts +29 -14
  515. package/src/view.ts +2 -3
  516. package/src/workspace/pane-derive.ts +10 -12
  517. package/src/workspace/session.ts +53 -43
  518. package/src/workspace/workspace.ts +40 -36
  519. package/dist/chunks/adapter-f93pafd7.js +0 -4
  520. package/dist/chunks/cf-account-picker-af1h381v.js +0 -4
  521. package/dist/chunks/cf-settings-125tdm0w.js +0 -4
  522. package/dist/chunks/color-area-jqhna8zy.js +0 -4
  523. package/dist/chunks/color-field-embq5ctg.js +0 -4
  524. package/dist/chunks/color-fpezvnkt.js +0 -4
  525. package/dist/chunks/color-slider-1qmw7wqy.js +0 -4
  526. package/dist/chunks/combobox-773hdzyj.js +0 -4
  527. package/dist/chunks/components-ax2f1fnn.js +0 -4
  528. package/dist/chunks/content-source-108aqtk1.js +0 -4
  529. package/dist/chunks/convert-to-repeater-ry5rmppr.js +0 -4
  530. package/dist/chunks/dialog-mtm9fq5t.js +0 -4
  531. package/dist/chunks/editor-pfgdmkb0.js +0 -4
  532. package/dist/chunks/entry-commands-t0k1q0kx.js +0 -4
  533. package/dist/chunks/extension-sections-6mwh2hf8.js +0 -4
  534. package/dist/chunks/file-ops-meej5mqf.js +0 -4
  535. package/dist/chunks/files-44vp8a2s.js +0 -4
  536. package/dist/chunks/format-host-7q1petb9.js +0 -4
  537. package/dist/chunks/fs-events-h2mwnxaz.js +0 -4
  538. package/dist/chunks/git-panel-zngbymvd.js +0 -4
  539. package/dist/chunks/grid-view-sx9vynsp.js +0 -51
  540. package/dist/chunks/icons-p44xhjf0.js +0 -4
  541. package/dist/chunks/iframe-entry-f7mqjwpm.js +0 -5
  542. package/dist/chunks/iframe-entry-haw7jkvz.js +0 -5
  543. package/dist/chunks/iframe-entry-z6qrytv3.js +0 -5
  544. package/dist/chunks/iframe-host-qk3ycq87.js +0 -4
  545. package/dist/chunks/index-wkyfjeqz.js +0 -4
  546. package/dist/chunks/jx-validate-psgd7vsx.js +0 -4
  547. package/dist/chunks/layers-panel-1kq2jyfk.js +0 -4
  548. package/dist/chunks/layers-xd92fg8d.js +0 -4
  549. package/dist/chunks/listbox-s8fkmnq8.js +0 -4
  550. package/dist/chunks/lit-html-ac4cwwr4.js +0 -4
  551. package/dist/chunks/media-picker-0svzkdyb.js +0 -4
  552. package/dist/chunks/menu-37d07z9m.js +0 -4
  553. package/dist/chunks/menu-5c55ea3d.js +0 -4
  554. package/dist/chunks/monaco-binding-z6r70pdt.js +0 -4
  555. package/dist/chunks/monaco-buffer-fz6gq5y7.js +0 -4
  556. package/dist/chunks/monaco-setup-q4axkgj7.js +0 -4
  557. package/dist/chunks/notify-0xgtn8q1.js +0 -4
  558. package/dist/chunks/number-field-gw7sq8rn.js +0 -4
  559. package/dist/chunks/parse-897fvqah.js +0 -4
  560. package/dist/chunks/platform-v1qctbe6.js +0 -4
  561. package/dist/chunks/popover-8htra4er.js +0 -4
  562. package/dist/chunks/publish-panel-ym1fmgq5.js +0 -4
  563. package/dist/chunks/quick-search-a54e6t5n.js +0 -4
  564. package/dist/chunks/references-gmqp82fs.js +0 -4
  565. package/dist/chunks/right-panel-v7t9awbk.js +0 -4
  566. package/dist/chunks/section-registry-vhyf3zsr.js +0 -4
  567. package/dist/chunks/select-n3v7gwas.js +0 -4
  568. package/dist/chunks/split-pff8f3ze.js +0 -4
  569. package/dist/chunks/studio-0bhx5hz6.js +0 -5
  570. package/dist/chunks/studio-0k1ddnyy.js +0 -6
  571. package/dist/chunks/studio-1b04pd0j.js +0 -64
  572. package/dist/chunks/studio-4dwbj6gb.js +0 -5
  573. package/dist/chunks/studio-4tanh828.js +0 -5
  574. package/dist/chunks/studio-55h4mstj.js +0 -4
  575. package/dist/chunks/studio-5tnvjkz4.js +0 -5
  576. package/dist/chunks/studio-60dqgb0c.js +0 -5
  577. package/dist/chunks/studio-61dp09qg.js +0 -9
  578. package/dist/chunks/studio-63epcrj2.js +0 -5
  579. package/dist/chunks/studio-74k29dy9.js +0 -5
  580. package/dist/chunks/studio-7vg6jcd3.js +0 -5
  581. package/dist/chunks/studio-7zx31knw.js +0 -9
  582. package/dist/chunks/studio-8bxk97km.js +0 -5
  583. package/dist/chunks/studio-933e30n4.js +0 -5
  584. package/dist/chunks/studio-98wnwhbg.js +0 -5
  585. package/dist/chunks/studio-9mccjwjh.js +0 -14
  586. package/dist/chunks/studio-a2ke1e4t.js +0 -5
  587. package/dist/chunks/studio-e3a2a6v3.js +0 -4
  588. package/dist/chunks/studio-e81q1vb9.js +0 -5
  589. package/dist/chunks/studio-epgrmqqm.js +0 -5
  590. package/dist/chunks/studio-ery42sqr.js +0 -4
  591. package/dist/chunks/studio-g1shz58g.js +0 -5
  592. package/dist/chunks/studio-gf0fz03c.js +0 -5
  593. package/dist/chunks/studio-gjtpe62q.js +0 -6
  594. package/dist/chunks/studio-gkskhg7m.js +0 -5
  595. package/dist/chunks/studio-gx4dnjzd.js +0 -5
  596. package/dist/chunks/studio-j03zga3y.js +0 -9
  597. package/dist/chunks/studio-jhpxeckz.js +0 -5
  598. package/dist/chunks/studio-k01r7ykp.js +0 -5
  599. package/dist/chunks/studio-kk7h30ne.js +0 -7
  600. package/dist/chunks/studio-kt1zqney.js +0 -5
  601. package/dist/chunks/studio-m3cwhvye.js +0 -5
  602. package/dist/chunks/studio-mcayt6hz.js +0 -5
  603. package/dist/chunks/studio-myjcghv3.js +0 -5
  604. package/dist/chunks/studio-n8bxwc3y.js +0 -4
  605. package/dist/chunks/studio-ngm8gvpb.js +0 -5
  606. package/dist/chunks/studio-nj5a01jy.js +0 -928
  607. package/dist/chunks/studio-pcgz8heb.js +0 -5
  608. package/dist/chunks/studio-qcsq0t15.js +0 -5
  609. package/dist/chunks/studio-qkstvve9.js +0 -5
  610. package/dist/chunks/studio-qv1pwd3c.js +0 -5
  611. package/dist/chunks/studio-rc6dvxjb.js +0 -7
  612. package/dist/chunks/studio-s8dmmz66.js +0 -5
  613. package/dist/chunks/studio-sp5xzbj4.js +0 -6
  614. package/dist/chunks/studio-szsjbj0g.js +0 -5
  615. package/dist/chunks/studio-t1xzawhr.js +0 -16
  616. package/dist/chunks/studio-t6b6qe31.js +0 -5
  617. package/dist/chunks/studio-tdcprbqb.js +0 -5
  618. package/dist/chunks/studio-vyc0b4he.js +0 -10
  619. package/dist/chunks/studio-w0cgf6jg.js +0 -5
  620. package/dist/chunks/studio-w3hskzqk.js +0 -5
  621. package/dist/chunks/studio-xgrgcdyh.js +0 -9
  622. package/dist/chunks/studio-xz2yxfcb.js +0 -5
  623. package/dist/chunks/studio-y6n42tgs.js +0 -5
  624. package/dist/chunks/studio-yb560vxr.js +0 -5
  625. package/dist/chunks/studio-yn9f8vtx.js +0 -5
  626. package/dist/chunks/studio-yw05w8f0.js +0 -7
  627. package/dist/chunks/studio-z16sgavc.js +0 -5
  628. package/dist/chunks/studio-zyqn40w4.js +0 -5
  629. package/dist/chunks/swatch-group-8qh9a3bm.js +0 -4
  630. package/dist/chunks/tabs-jwthg40w.js +0 -4
  631. package/dist/chunks/textfield-spy3hc77.js +0 -4
  632. package/dist/chunks/toast-4d35zd64.js +0 -4
  633. package/dist/chunks/toast-host-8sjmfed3.js +0 -4
  634. package/dist/chunks/tooltip-fd6g9xy3.js +0 -4
  635. package/dist/chunks/tree-h19v1jfz.js +0 -4
  636. package/dist/chunks/workspace-zt81g1ms.js +0 -4
  637. package/dist/chunks/ws-client-n2bh4hkf.js +0 -4
@@ -25,6 +25,7 @@
25
25
  * studio.ts, and lets a test state a context without standing up the app.
26
26
  */
27
27
 
28
+ import { isFunction, isString } from "@jxsuite/schema/guards";
28
29
  import { resolveI18n } from "@jxsuite/schema/locale";
29
30
  import { componentRegistry } from "../files/components";
30
31
  import { getNodeAtPath, projectState } from "../store";
@@ -36,7 +37,7 @@ import { hasTyping } from "../tabs/typing";
36
37
  import { collabState } from "../collab/collab-state";
37
38
 
38
39
  import { canvasViewForMode, editorKindForMode, emptyContext } from "./context";
39
- import type { CommandContext, FocusRegion } from "./context";
40
+ import type { CommandContext } from "./context";
40
41
  import type { StudioPlatform } from "../types";
41
42
 
42
43
  /** Elements that own the keyboard while focused. Matches the old listener's target test exactly. */
@@ -86,7 +87,7 @@ export interface LiveContextSources {
86
87
 
87
88
  /** `capability.*` is presence-of-method on the PAL — the check every call site does by hand today. */
88
89
  function capabilities(platform: StudioPlatform | null): CommandContext["capability"] {
89
- const has = (key: keyof StudioPlatform) => typeof platform?.[key] === "function";
90
+ const has = (key: keyof StudioPlatform) => isFunction(platform?.[key]);
90
91
  return {
91
92
  dataRows: has("dataRows"),
92
93
  // The real member now, not the `codeService` stand-in it was minted against: the usage query is
@@ -161,18 +162,17 @@ export function createLiveContext(sources: LiveContextSources): () => CommandCon
161
162
  const selection = primarySelection(paths);
162
163
  if (selection) {
163
164
  const node = getNodeAtPath(tab!.doc.document, selection);
165
+ const tagName = node?.tagName;
164
166
  ctx.selection.count = paths.length;
165
167
  ctx.selection.paths = paths.map((path) => [...path]);
166
168
  // Every remaining fact describes the PRIMARY — the one node a single-target verb addresses —
167
169
  // Except `isRoot`, which is the batch's own gate: a batch containing the document element
168
170
  // Cannot be deleted or duplicated any more than that element could be on its own.
169
- ctx.selection.kind = typeof node?.tagName === "string" ? node.tagName : "";
171
+ ctx.selection.kind = isString(tagName) ? tagName : "";
170
172
  // A path of fewer than two segments addresses the document element itself — the same test
171
173
  // `shortcuts.ts` spelled as `selection.length >= 2` at four separate call sites.
172
174
  ctx.selection.isRoot = paths.some((path) => path.length < 2);
173
- ctx.selection.isComponentInstance = componentRegistry.some(
174
- (c) => c.tagName === node?.tagName,
175
- );
175
+ ctx.selection.isComponentInstance = componentRegistry.some((c) => c.tagName === tagName);
176
176
  ctx.selection.isRepeater = node?.$prototype === "Array";
177
177
  }
178
178
  // Layout chrome is NOT a document selection: the node is not in the open page at all.
@@ -187,7 +187,7 @@ export function createLiveContext(sources: LiveContextSources): () => CommandCon
187
187
  being typed into. The stack asks "is something being typed into"; a record asks "is the
188
188
  thing being typed into the page". */
189
189
  ctx.caret.inCanvas = sources.isCaretActive();
190
- ctx.focus.region = shell.focusRegion as FocusRegion;
190
+ ctx.focus.region = shell.focusRegion;
191
191
  ctx.modal.open = sources.isModalOpen();
192
192
 
193
193
  if (tab) {
@@ -17,6 +17,7 @@
17
17
  * between runs is a CI diff nobody can review.
18
18
  */
19
19
 
20
+ import { isString } from "@jxsuite/schema/guards";
20
21
  import { formatChord, normalizeChord } from "./keymap";
21
22
  import { CATEGORIES } from "./levels";
22
23
  import type { KeybindingOverrides } from "./keymap";
@@ -83,7 +84,7 @@ function chordsOf(command: AnyCommand): string[] {
83
84
  if (!raw) {
84
85
  return [];
85
86
  }
86
- return (typeof raw === "string" ? [raw] : [...raw]).map((chord) => normalizeChord(chord));
87
+ return (isString(raw) ? [raw] : [...raw]).map((chord) => normalizeChord(chord));
87
88
  }
88
89
 
89
90
  /**
@@ -36,13 +36,12 @@ import { createKeymap } from "./keymap";
36
36
  import type { KeyChordEvent, Keymap, KeymapMatch } from "./keymap";
37
37
  import { checkRecordPlacements } from "./levels";
38
38
  import type { Category, KeyScope, Level, Placement } from "./levels";
39
+ import { isFunction } from "@jxsuite/schema/guards";
39
40
  import { coerceArgs } from "./command-args";
41
+ import type { CommandArgsSchema, CommandArgValues } from "./command-args";
40
42
  import { runReported } from "./run-reported";
41
43
  import type { CommandContext } from "./context";
42
44
 
43
- /** Arguments as they arrive from a palette prompt, an automation manifest step or an AI tool call. */
44
- export type CommandArgs = Record<string, unknown>;
45
-
46
45
  /** How an action's effect is undone — surfaced to the user before an agent runs it. */
47
46
  export type UndoScope = "document" | "project" | "none";
48
47
 
@@ -77,7 +76,7 @@ export interface Command<A = void> {
77
76
  * shot check's contract AND what {@link CommandRegistry.run} coerces the received record against
78
77
  * before `run` sees it (`command-args.ts`'s `coerceArgs`). One object, four readers.
79
78
  */
80
- args?: object;
79
+ args?: CommandArgsSchema;
81
80
  /** Surfaces this command renders in. Defaults to `["palette"]`. */
82
81
  menus?: readonly Placement[];
83
82
  /** Menu ordering key: "1_clipboard", "3_structure", "9_danger". */
@@ -216,7 +215,7 @@ export interface CommandRegistry {
216
215
  * `RangeError` naming the argument when `args` does not fit the record's schema — synchronously,
217
216
  * before `run` is entered, whichever surface the call came from.
218
217
  */
219
- run: (id: string, args?: CommandArgs) => void | Promise<void>;
218
+ run: (id: string, args?: CommandArgValues) => void | Promise<void>;
220
219
  /** The chord index, conflict-checked at registration. */
221
220
  keymap: Keymap;
222
221
  /** Resolve a keyboard event through a scope stack and run what it hits. */
@@ -254,7 +253,7 @@ function checkProjection(command: AnyCommand, toolNames: ReadonlyMap<string, str
254
253
  `command "${command.id}" aiTool name "${tool.name}" is already projected by "${claimant}"`,
255
254
  );
256
255
  }
257
- if (typeof tool.report !== "function") {
256
+ if (!isFunction(tool.report)) {
258
257
  throw new TypeError(
259
258
  `command "${command.id}" declares aiTool without a report: a tool that can only say ` +
260
259
  `"done" is refused`,
@@ -270,8 +269,7 @@ function checkProjection(command: AnyCommand, toolNames: ReadonlyMap<string, str
270
269
  selector's `paths` property in FRONT of the record's own `args`, so a record that declares its
271
270
  own `paths` would have two definitions of one argument — the model would read the record's
272
271
  description and the bridge would hand the value to the selector. */
273
- const properties = (command.args as { properties?: Record<string, unknown> } | undefined)
274
- ?.properties;
272
+ const properties = command.args?.properties;
275
273
  if (command.level === "selection" && properties && Object.hasOwn(properties, "paths")) {
276
274
  throw new Error(
277
275
  `command "${command.id}" is selection-level and may not declare "paths": the assistant ` +
@@ -341,11 +339,11 @@ export function createCommandRegistry(options: CommandRegistryOptions): CommandR
341
339
  if (violations.length > 0) {
342
340
  throw new Error(`command "${command.id}" ${violations[0]!.message}`);
343
341
  }
344
- checkProjection(command as AnyCommand, toolNames);
342
+ checkProjection(command, toolNames);
345
343
  // Chord conflicts throw from the keymap; do this LAST so a rejected record leaves the
346
344
  // Registry untouched in every failure mode — the tool name is claimed only after it.
347
345
  keymap.add(command);
348
- commands.set(command.id, command as AnyCommand);
346
+ commands.set(command.id, command);
349
347
  if (command.aiTool) {
350
348
  toolNames.set(command.aiTool.name, command.id);
351
349
  }
@@ -404,6 +402,10 @@ export function createCommandRegistry(options: CommandRegistryOptions): CommandR
404
402
  their typed readers; `coerceArgs` dispatches to the same functions, so the two cannot
405
403
  disagree. A record with no `args` takes whatever it was handed, as it always has. */
406
404
  const coerced = command.args ? coerceArgs(id, command.args, args) : args;
405
+ /* SAFETY: a stored record is `Command<never>` because the map erases each record's own `A`.
406
+ The runtime contract for that erased `A` is the record's `args` schema, which `coerceArgs`
407
+ has just applied (every key its reader's return value, an undeclared key refused); a
408
+ record with no schema takes the caller's record as it always has. */
407
409
  return command.run(ctx, coerced as never);
408
410
  },
409
411
  keymap,
@@ -55,7 +55,8 @@
55
55
  import { errorMessage } from "@jxsuite/schema/parse";
56
56
  import { notify } from "../services/notify";
57
57
  import { activeRegistry } from "./active-registry";
58
- import type { CommandArgs, CommandRegistry } from "./registry";
58
+ import type { CommandArgValues } from "./command-args";
59
+ import type { CommandRegistry } from "./registry";
59
60
 
60
61
  /**
61
62
  * Whether an error is one of the two REFUSAL shapes, whose message is written to be read whole.
@@ -64,10 +65,10 @@ import type { CommandArgs, CommandRegistry } from "./registry";
64
65
  * `handleKeyEvent`, and a value import back would close a cycle for one class whose constructor
65
66
  * sets exactly this name. `RangeError` is the shape `coerceArgs` and a `run` body refuse with.
66
67
  */
67
- function isRefusal(error: unknown): boolean {
68
+ function isRefusal(cause: unknown): boolean {
68
69
  return (
69
- error instanceof RangeError ||
70
- (error instanceof Error && error.name === "CommandUnavailableError")
70
+ cause instanceof RangeError ||
71
+ (cause instanceof Error && cause.name === "CommandUnavailableError")
71
72
  );
72
73
  }
73
74
 
@@ -86,15 +87,15 @@ function isRefusal(error: unknown): boolean {
86
87
  export function runReported(
87
88
  registry: CommandRegistry,
88
89
  id: string,
89
- args?: CommandArgs,
90
+ args?: CommandArgValues,
90
91
  source: string = id,
91
92
  ): Promise<void> {
92
- const report = (error: unknown) => {
93
- if (!isRefusal(error)) {
93
+ const report = (cause: unknown) => {
94
+ if (!isRefusal(cause)) {
94
95
  // A crash, not a refusal: the row below carries the sentence, the console keeps the stack.
95
- console.error(`${source}: command "${id}" failed`, error);
96
+ console.error(`${source}: command "${id}" failed`, cause);
96
97
  }
97
- notify.error(errorMessage(error), { key: `command.run:${id}`, source });
98
+ notify.error(errorMessage(cause), { key: `command.run:${id}`, source });
98
99
  };
99
100
  let result: void | Promise<void>;
100
101
  try {
@@ -114,7 +115,11 @@ export function runReported(
114
115
  * registry to refuse it, so there is no refusal to file. The resolved promise keeps the caller's
115
116
  * `void` honest either way.
116
117
  */
117
- export function runActiveReported(id: string, args?: CommandArgs, source?: string): Promise<void> {
118
+ export function runActiveReported(
119
+ id: string,
120
+ args?: CommandArgValues,
121
+ source?: string,
122
+ ): Promise<void> {
118
123
  const registry = activeRegistry();
119
124
  return registry ? runReported(registry, id, args, source) : Promise.resolve();
120
125
  }
@@ -11,8 +11,13 @@
11
11
  */
12
12
 
13
13
  import type { JsonValue } from "./types";
14
- import type { JxMutableNode } from "@jxsuite/schema/types";
15
- import { isPrivateStateKey } from "@jxsuite/schema/guards";
14
+ import type {
15
+ JsonPrimitive,
16
+ JxMutableNode,
17
+ JxStateDefinition,
18
+ JxStateObject,
19
+ } from "@jxsuite/schema/types";
20
+ import { isNonNullObject, isPrivateStateKey, isString } from "@jxsuite/schema/guards";
16
21
 
17
22
  /** One editable prop row: the state key and its current default value (undefined = none). */
18
23
  export interface ComponentPropEntry {
@@ -22,7 +27,16 @@ export interface ComponentPropEntry {
22
27
 
23
28
  /** Whether the doc is a component definition (a custom-element root) rather than a page. */
24
29
  export function isComponentDoc(doc: JxMutableNode | null | undefined): boolean {
25
- return typeof doc?.tagName === "string" && doc.tagName.includes("-");
30
+ const tagName = doc?.tagName;
31
+ return isString(tagName) && tagName.includes("-");
32
+ }
33
+
34
+ /** The object shapes a state entry can take: every `JxStateDefinition` but a primitive or array. */
35
+ type StateEntryObject = Exclude<JxStateDefinition, JsonPrimitive | JsonValue[]>;
36
+
37
+ /** Whether a state entry is one of its object shapes — a signal, a typed def, a naked object. */
38
+ function isStateEntryObject(def: JxStateDefinition | undefined): def is StateEntryObject {
39
+ return isNonNullObject(def) && !Array.isArray(def);
26
40
  }
27
41
 
28
42
  /**
@@ -31,26 +45,20 @@ export function isComponentDoc(doc: JxMutableNode | null | undefined): boolean {
31
45
  * templates, or $prototype data sources (overriding those would clobber behavior, the boundPropKey
32
46
  * rule).
33
47
  */
34
- function propShape(def: unknown): "literal" | "signal" | null {
35
- if (def === null || typeof def === "number" || typeof def === "boolean") {
36
- return "literal";
37
- }
38
- if (typeof def === "string") {
39
- return def.includes("${") ? null : "literal"; // Template strings render computed values.
40
- }
41
- if (Array.isArray(def)) {
42
- return "literal";
48
+ function propKind(def: JxStateDefinition | undefined): "literal" | "signal" | null {
49
+ if (def === undefined) {
50
+ return null;
43
51
  }
44
- if (typeof def === "object") {
45
- const d = def as Record<string, unknown>;
46
- if (d.$expression || d.$compute || d.$prototype || d.$handler) {
52
+ if (isStateEntryObject(def)) {
53
+ if (def.$expression || def.$compute || def.$prototype || def.$handler) {
47
54
  return null;
48
55
  }
49
56
  // An expanded signal ({default}) or a typed prop def ({type}/schema keywords) seeds through
50
57
  // Its `default`; any other plain object is a Shape-1 naked value.
51
- return "default" in d || "type" in d ? "signal" : "literal";
58
+ return "default" in def || "type" in def ? "signal" : "literal";
52
59
  }
53
- return null;
60
+ // Null, numbers, booleans and arrays are naked literals. Template strings render computed values.
61
+ return isString(def) && def.includes("${") ? null : "literal";
54
62
  }
55
63
 
56
64
  /**
@@ -58,20 +66,20 @@ function propShape(def: unknown): "literal" | "signal" | null {
58
66
  * entries with their current default values (the CEM-export "field" subset).
59
67
  */
60
68
  export function componentPropEntries(doc: JxMutableNode | null | undefined): ComponentPropEntry[] {
61
- const state = (doc?.state ?? {}) as Record<string, unknown>;
69
+ const state: Record<string, JxStateDefinition> = doc?.state ?? {};
62
70
  const out: ComponentPropEntry[] = [];
63
71
  for (const [name, def] of Object.entries(state)) {
64
72
  if (isPrivateStateKey(name)) {
65
73
  continue; // Private entries are not props (spec.md §5.6).
66
74
  }
67
- const shape = propShape(def);
68
- if (!shape) {
75
+ const kind = propKind(def);
76
+ if (!kind) {
69
77
  continue;
70
78
  }
71
- const value =
72
- shape === "signal"
73
- ? ((def as { default?: JsonValue }).default as JsonValue | undefined)
74
- : (def as JsonValue);
79
+ /* SAFETY: `propKind` refused every behavioral shape (expressions, computeds, `$prototype`
80
+ sources, handlers, template strings), so what is left is the document's plain data: a
81
+ literal entry IS the JSON value, and a signal entry is an object whose `default` is one. */
82
+ const value = kind === "signal" ? (def as { default?: JsonValue }).default : (def as JsonValue);
75
83
  out.push({ name, value });
76
84
  }
77
85
  return out;
@@ -87,19 +95,27 @@ export function substitutePreviewProps(
87
95
  renderDoc: JxMutableNode,
88
96
  props: Record<string, JsonValue>,
89
97
  ): JxMutableNode {
90
- const state = { ...((renderDoc.state ?? {}) as Record<string, unknown>) };
98
+ const state = { ...renderDoc.state };
91
99
  let seeded = false;
92
100
  for (const [name, value] of Object.entries(props)) {
93
- const shape = propShape(state[name]);
94
- if (!shape) {
101
+ const current = state[name];
102
+ const kind = propKind(current);
103
+ if (!kind) {
95
104
  continue; // Unknown/behavioral entries are never overridden by a stale test value.
96
105
  }
97
- state[name] =
98
- shape === "signal" ? { ...(state[name] as Record<string, unknown>), default: value } : value;
106
+ /* SAFETY: `propKind` answers "signal" only for an object that carries `default` or `type` and
107
+ none of the behavioral keys (`$expression`, `$compute`, `$prototype`, `$handler`) — the
108
+ expanded-signal / typed-def shape `JxStateObject` describes. A literal is replaced by the
109
+ JSON test value itself, which is a Shape-1 naked entry; `JxStateDefinition` spells that
110
+ shape as `JxStateObject`, whose typed keys neither a `JsonObject` nor a spread copy can prove
111
+ statically (the spread drops the index signature its typed keys are checked against). */
112
+ state[name] = (
113
+ kind === "signal" ? { ...(current as JxStateObject), default: value } : value
114
+ ) as JxStateDefinition;
99
115
  seeded = true;
100
116
  }
101
117
  if (!seeded) {
102
118
  return renderDoc;
103
119
  }
104
- return { ...renderDoc, state } as JxMutableNode;
120
+ return { ...renderDoc, state };
105
121
  }
@@ -32,12 +32,10 @@
32
32
  import { defaultContentFormat, formatByName } from "../format/format-host";
33
33
  import { projectState } from "../store";
34
34
  import { resolveI18n } from "@jxsuite/schema/locale";
35
+ import { LOCALE_PLACEHOLDER } from "../canvas/asset-resolve";
35
36
  import type { ContentSectionEntry } from "../types";
36
37
  import type { ProjectConfig } from "@jxsuite/schema/types";
37
38
 
38
- /** The placeholder a localized `source` carries, standing for one directory per declared locale. */
39
- export const LOCALE_PLACEHOLDER = "{locale}";
40
-
41
39
  /** What a path's collection is, and everything a caller needs in order to act on it. */
42
40
  export interface CollectionMatch {
43
41
  name: string;
@@ -69,11 +67,14 @@ function normalize(path: string): string {
69
67
 
70
68
  /** The config a lookup reads: the caller's, or the open project's. */
71
69
  function configOf(config: ProjectConfig | null | undefined): ProjectConfig | null {
72
- return config ?? (projectState?.projectConfig as ProjectConfig | null | undefined) ?? null;
70
+ return config ?? projectState?.projectConfig ?? null;
73
71
  }
74
72
 
75
73
  /** The `content` section of a config, or an empty one. */
76
74
  function contentSection(config: ProjectConfig | null): Record<string, ContentSectionEntry> {
75
+ /* SAFETY: `content` is the parser extension's section — collection name → entry object, its
76
+ project fragment schema the source of truth. `ContentSectionEntry` names only the fields Studio
77
+ reads, every one optional, and each reader below tests `source` before using it. */
77
78
  return (config?.content ?? {}) as Record<string, ContentSectionEntry>;
78
79
  }
79
80
 
@@ -20,6 +20,7 @@
20
20
 
21
21
  import { reactive } from "../reactivity";
22
22
  import type { ContentTypeSchema } from "@jxsuite/schema/types";
23
+ import type { EntryFields } from "./entry-fields";
23
24
 
24
25
  /** The conventional frontmatter boolean that marks an entry a draft (site-architecture.md §7.6). */
25
26
  export const DRAFT_FIELD = "draft";
@@ -44,7 +45,7 @@ export const DRAFT_MEANING =
44
45
  * Takes the entry's FIELDS, whichever record they live in — `content/entry-fields.ts` answers that,
45
46
  * because a JSON collection's entry has no frontmatter and its `draft` key is on the document.
46
47
  */
47
- export function isDraftEntry(fields: Record<string, unknown> | null | undefined): boolean {
48
+ export function isDraftEntry(fields: EntryFields | null | undefined): boolean {
48
49
  return fields?.[DRAFT_FIELD] === true;
49
50
  }
50
51
 
@@ -63,7 +64,7 @@ export function schemaDeclaresDraft(schema: ContentTypeSchema | null | undefined
63
64
  */
64
65
  export function hasDraftAxis(
65
66
  schema: ContentTypeSchema | null | undefined,
66
- fields?: Record<string, unknown> | null,
67
+ fields?: EntryFields | null,
67
68
  ): boolean {
68
69
  return schemaDeclaresDraft(schema) || isDraftEntry(fields);
69
70
  }
@@ -100,7 +101,7 @@ export function setIncludeDrafts(include: boolean): void {
100
101
  */
101
102
  export function applyDraftFilter<T>(
102
103
  items: readonly T[],
103
- fieldsOf: (item: T) => Record<string, unknown> | null | undefined,
104
+ fieldsOf: (item: T) => EntryFields | null | undefined,
104
105
  includeDrafts: boolean,
105
106
  ): readonly T[] {
106
107
  return includeDrafts ? items : items.filter((item) => !isDraftEntry(fieldsOf(item)));
@@ -33,7 +33,8 @@ import { invalidateReferenceEntries } from "../ui/form-controls";
33
33
  import { reloadDraftAwareGrids } from "../grid/sources/content-source";
34
34
  import { setIncludeDrafts } from "./draft-state";
35
35
  import { collectionOfPath, entryCollection, entryCollections, seedEntry } from "./entry-model";
36
- import { LOCALE_PLACEHOLDER, collectionForDirectory } from "./collection-match";
36
+ import { collectionForDirectory } from "./collection-match";
37
+ import { LOCALE_PLACEHOLDER } from "../canvas/asset-resolve";
37
38
  import { openEntryEditor, setEntryDraft } from "./entry-editor";
38
39
  import { errorMessage } from "@jxsuite/schema/parse";
39
40
  import type { EntryCollection } from "./entry-model";
@@ -167,7 +168,7 @@ export async function createEntry(
167
168
 
168
169
  /** The active tab, when it is a content entry — the subject of the document-level verbs. */
169
170
  function activeEntryTab(): Tab | null {
170
- const tab = activeTab.value as Tab | null;
171
+ const tab = activeTab.value;
171
172
  return tab && collectionOfPath(tab.documentPath) ? tab : null;
172
173
  }
173
174
 
@@ -50,6 +50,7 @@ import { mountEntryEditorSurface } from "../surfaces/entry-editor";
50
50
  import { paneRegion } from "../ui/regions";
51
51
  import { activateTab, workspace } from "../workspace/workspace";
52
52
  import { commitEntryFields, entryFields, mutateEntryField } from "./entry-fields";
53
+ import type { EntryFields } from "./entry-fields";
53
54
  import { DRAFT_FIELD, DRAFT_MEANING, hasDraftAxis, isDraftEntry } from "./draft-state";
54
55
  import { collectionOfPath, missingRequired } from "./entry-model";
55
56
  import type { EntryCollection } from "./entry-model";
@@ -57,7 +58,7 @@ import type { EntryEditorSurfaceHandle, EntryEditorView } from "../surfaces/entr
57
58
  import type { JsonSchema, SchemaFormContext } from "../ui/schema-form";
58
59
  import type { Tab } from "../tabs/tab";
59
60
  import type { CanvasSurface } from "../canvas/canvas-surface";
60
- import type { JsonValue } from "../types";
61
+ import type { JsonObject } from "@jxsuite/schema/types";
61
62
 
62
63
  /** The `canvasMode` the entry form draws under. */
63
64
  export const ENTRY_MODE = "entry";
@@ -120,7 +121,7 @@ export function detachEntryPane(paneId: string): void {
120
121
  * has explicitly published something should be able to see that they did.
121
122
  */
122
123
  export function setEntryDraft(tab: Tab, draft: boolean): void {
123
- transactDoc(tab, (t) => mutateEntryField(t, DRAFT_FIELD, draft as JsonValue));
124
+ transactDoc(tab, (t) => mutateEntryField(t, DRAFT_FIELD, draft));
124
125
  }
125
126
 
126
127
  /** What the tab chip's draft pill says. A value, drawn by `surfaces/tab-strip.json`. */
@@ -169,7 +170,7 @@ function formContext(tab: Tab): SchemaFormContext {
169
170
  fieldKeyPrefix: `entry:${tab.id}`,
170
171
  resolvePointer: (pointer, scope) =>
171
172
  resolveContextPointer(pointer, {
172
- projectConfig: (projectState?.projectConfig ?? {}) as Record<string, unknown>,
173
+ projectConfig: projectState?.projectConfig ?? {},
173
174
  scope,
174
175
  }),
175
176
  };
@@ -185,13 +186,14 @@ function formContext(tab: Tab): SchemaFormContext {
185
186
  */
186
187
  function absentRequiredErrors(
187
188
  collection: EntryCollection,
188
- fields: Record<string, unknown>,
189
+ fields: EntryFields,
189
190
  ): Record<string, string> {
190
- const errors: Record<string, string> = {};
191
- for (const field of missingRequired(collection.schema, fields)) {
192
- errors[field] = "Required — this entry does not have one.";
193
- }
194
- return errors;
191
+ return Object.fromEntries(
192
+ missingRequired(collection.schema, fields).map((field) => [
193
+ field,
194
+ "Required — this entry does not have one.",
195
+ ]),
196
+ );
195
197
  }
196
198
 
197
199
  /** What the document says when the file belongs to no collection: the reason, then the fix. */
@@ -280,12 +282,22 @@ export function renderEntryMode(surface: CanvasSurface, tab: Tab): void {
280
282
  return;
281
283
  }
282
284
  const fields = entryFields(tab);
283
- const form = mountSchemaForm(`entry:${paneId}`, collection.schema as JsonSchema, fields, {
284
- context: formContext(tab),
285
- errors: absentRequiredErrors(collection, fields),
286
- onChange: (patch) => commitEntryFields(tab, patch),
287
- rerender: redraw,
288
- });
285
+ /* SAFETY: `collection` comes from `collectionOfPath`, which matches only a content type that
286
+ declares a `schema` (`findContentTypeSchema` refuses one without), and that schema is the
287
+ collection's JSON Schema — the shape `JsonSchema` names for the form. `fields` is a
288
+ frontmatter block or a JSON entry's own root (entry-fields.ts), both parsed from YAML or
289
+ JSON text, so every value is JSON; a key an editor cleared reads as absent either way. */
290
+ const form = mountSchemaForm(
291
+ `entry:${paneId}`,
292
+ collection.schema as JsonSchema,
293
+ fields as JsonObject,
294
+ {
295
+ context: formContext(tab),
296
+ errors: absentRequiredErrors(collection, fields),
297
+ onChange: (patch) => commitEntryFields(tab, patch),
298
+ rerender: redraw,
299
+ },
300
+ );
289
301
  if (form.parentNode !== formHost) {
290
302
  formHost.replaceChildren(form);
291
303
  }
@@ -332,7 +344,7 @@ export function renderEntryMode(surface: CanvasSurface, tab: Tab): void {
332
344
  // Never this effect's guess. `tab.doc.document` is also the reference every transaction
333
345
  // Replaces, so it is how an undo reaches the form whichever store the edit was in.
334
346
  void tab.doc.document;
335
- void tab.doc.content?.frontmatter;
347
+ void tab.doc.content.frontmatter;
336
348
  void projectState?.projectConfig?.content;
337
349
  draw();
338
350
  });
@@ -365,7 +377,7 @@ export async function openEntryEditor(path: string): Promise<Tab | null> {
365
377
  tab.session.ui.canvasMode = ENTRY_MODE;
366
378
  tab.session.ui.preview = false;
367
379
  activateTab(id);
368
- return tab as Tab;
380
+ return tab;
369
381
  }
370
382
  return null;
371
383
  }
@@ -32,9 +32,16 @@ import { cloneValue } from "@jxsuite/schema/doc-ops";
32
32
  import { notePreviewOverlayEdit } from "../preview/preview-overlay";
33
33
  import { recordDocOp } from "../tabs/patch-ops";
34
34
  import { mutateUpdateFrontmatter, transactDoc } from "../tabs/transact";
35
+ import type { JxDocumentValue } from "@jxsuite/schema/types";
35
36
  import type { Tab } from "../tabs/tab";
36
37
  import type { JsonValue } from "../types";
37
38
 
39
+ /**
40
+ * An entry's fields, whichever record holds them: a frontmatter block's keys, or a JSON entry's own
41
+ * document keys. `undefined` is a key an editor has cleared.
42
+ */
43
+ export type EntryFields = Record<string, JxDocumentValue | undefined>;
44
+
38
45
  /**
39
46
  * Whether this tab's entry fields are the document itself rather than a frontmatter block.
40
47
  *
@@ -56,10 +63,8 @@ function fieldsAreDocument(tab: Tab): boolean {
56
63
  * reactive tab, and a copy would break that. It is also the identity a caller can compare against
57
64
  * `tab.doc.document` to see which store answered.
58
65
  */
59
- export function entryFields(tab: Tab): Record<string, unknown> {
60
- return fieldsAreDocument(tab)
61
- ? (tab.doc.document as unknown as Record<string, unknown>)
62
- : (tab.doc.content?.frontmatter ?? {});
66
+ export function entryFields(tab: Tab): EntryFields {
67
+ return fieldsAreDocument(tab) ? tab.doc.document : tab.doc.content.frontmatter;
63
68
  }
64
69
 
65
70
  /**
@@ -72,7 +77,7 @@ export function entryFields(tab: Tab): Record<string, unknown> {
72
77
  * is already the "not surgically patchable, fall back" signal `transactDoc` reads.
73
78
  */
74
79
  function mutateDocumentField(tab: Tab, field: string, value?: JsonValue): void {
75
- const doc = tab.doc.document as unknown as Record<string, unknown>;
80
+ const doc = tab.doc.document;
76
81
  const before = Object.hasOwn(doc, field) ? cloneValue(doc[field]) : undefined;
77
82
  const deletes = value === undefined || value === null || value === "";
78
83
  if (deletes) {
@@ -113,10 +118,10 @@ export function mutateEntryField(tab: Tab, field: string, value?: JsonValue): vo
113
118
  * `renderForm` emits single-key patches today, but committing per key would put a multi-key patch
114
119
  * on the undo stack as several steps — and an author who changed one thing expects one ⌘Z.
115
120
  */
116
- export function commitEntryFields(tab: Tab, patch: Record<string, unknown>): void {
121
+ export function commitEntryFields(tab: Tab, patch: Record<string, JsonValue | undefined>): void {
117
122
  transactDoc(tab, (t) => {
118
123
  for (const [field, value] of Object.entries(patch)) {
119
- mutateEntryField(t, field, value as JsonValue);
124
+ mutateEntryField(t, field, value);
120
125
  }
121
126
  });
122
127
  }