@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
@@ -39,6 +39,7 @@
39
39
  * text. It is one value now, and the field shows it.
40
40
  */
41
41
 
42
+ import { isFunction, isJsonObject, isNonNullObject, isString } from "@jxsuite/schema/guards";
42
43
  import { errorMessage } from "@jxsuite/schema/parse";
43
44
  import { getPlatform } from "../platform";
44
45
  import { commitProjectConfig } from "../tabs/project-config";
@@ -53,7 +54,8 @@ import { paneOfContainer } from "../canvas/canvas-surface";
53
54
  import { mountContributedSurface } from "../surfaces/settings-contributed";
54
55
 
55
56
  import type { JsonSchema, SchemaFormContext } from "../ui/schema-form";
56
- import type { ProjectConfig } from "@jxsuite/schema/types";
57
+ import type { JsonObject, JsonValue } from "@jxsuite/schema/types";
58
+ import type { ResolveContextOptions } from "../services/context-resolver";
57
59
  import type {
58
60
  ContributedActions,
59
61
  ContributedSurfaceHandle,
@@ -74,7 +76,7 @@ export interface SettingsContribution {
74
76
  entry?:
75
77
  | {
76
78
  ui?: Record<string, { control?: string; enum?: unknown }> | undefined;
77
- newEntry?: Record<string, unknown> | undefined;
79
+ newEntry?: JsonObject | undefined;
78
80
  }
79
81
  | undefined;
80
82
  };
@@ -139,13 +141,8 @@ export function resetContributedSectionState(): void {
139
141
  * such entry, so the caller's refusal can name both sides.
140
142
  */
141
143
  export function selectContributedEntry(sectionKey: string, entryKey: string): string[] | null {
142
- const section = (projectState?.projectConfig as Record<string, unknown> | null | undefined)?.[
143
- sectionKey
144
- ];
145
- const entries =
146
- section && typeof section === "object" && !Array.isArray(section)
147
- ? (section as Record<string, unknown>)
148
- : {};
144
+ const section = projectState?.projectConfig?.[sectionKey];
145
+ const entries = isJsonObject(section) ? section : {};
149
146
  if (!Object.hasOwn(entries, entryKey)) {
150
147
  return Object.keys(entries);
151
148
  }
@@ -170,6 +167,14 @@ export function resetContributedDiagnostics(): void {
170
167
  diagnostics.clear();
171
168
  }
172
169
 
170
+ /** {@link routeDiagnostics}' answer: per-field messages, and the ones about the record itself. */
171
+ export interface RoutedDiagnostics {
172
+ /** The first message for each property one level under the base, keyed by property name. */
173
+ fields: Record<string, string>;
174
+ /** Messages whose pointer is the base itself, for the section line. */
175
+ section: string[];
176
+ }
177
+
173
178
  /**
174
179
  * Route `jx-validate` messages ("/search/index: must be string") to the field they are about.
175
180
  *
@@ -182,10 +187,7 @@ export function resetContributedDiagnostics(): void {
182
187
  * @param {string[]} messages
183
188
  * @returns
184
189
  */
185
- export function routeDiagnostics(
186
- base: string,
187
- messages: string[],
188
- ): { fields: Record<string, string>; section: string[] } {
190
+ export function routeDiagnostics(base: string, messages: string[]): RoutedDiagnostics {
189
191
  const fields: Record<string, string> = {};
190
192
  const section: string[] = [];
191
193
  for (const message of messages) {
@@ -230,7 +232,12 @@ export function routeDiagnostics(
230
232
  * @param {() => void} rerender
231
233
  */
232
234
  async function saveProjectConfig(base: string, rerender: () => void) {
233
- const config = (projectState as { projectConfig: ProjectConfig }).projectConfig;
235
+ /* Every caller reached this through `sectionValue`, which returns null without a config, so a
236
+ project is open here; the guard only states that to the compiler. */
237
+ const config = projectState?.projectConfig;
238
+ if (!config) {
239
+ return;
240
+ }
234
241
 
235
242
  const commit = await commitProjectConfig();
236
243
  if (!commit.ok) {
@@ -258,7 +265,7 @@ async function saveProjectConfig(base: string, rerender: () => void) {
258
265
  // ─── Helpers ──────────────────────────────────────────────────────────────────
259
266
 
260
267
  /** Apply a schema-form patch onto a record in place; `undefined` values unset the key. */
261
- function applyPatch(target: Record<string, unknown>, patch: Record<string, unknown>) {
268
+ function applyPatch<V>(target: Record<string, V>, patch: Record<string, V | undefined>) {
262
269
  for (const [key, value] of Object.entries(patch)) {
263
270
  if (value === undefined) {
264
271
  delete target[key];
@@ -277,30 +284,30 @@ function slugify(name: string): string {
277
284
  }
278
285
 
279
286
  /** Instantiate a newEntry template, substituting `${key}` in every string value. */
280
- function instantiateNewEntry(
281
- template: Record<string, unknown> | undefined,
282
- key: string,
283
- ): Record<string, unknown> {
287
+ function instantiateNewEntry(template: JsonObject | undefined, key: string): JsonObject {
284
288
  if (!template) {
285
289
  return {};
286
290
  }
287
- const substitute = (value: unknown): unknown => {
288
- if (typeof value === "string") {
291
+ const substituteObject = (value: JsonObject): JsonObject => {
292
+ const out: JsonObject = {};
293
+ for (const [k, v] of Object.entries(value)) {
294
+ out[k] = substitute(v);
295
+ }
296
+ return out;
297
+ };
298
+ const substitute = (value: JsonValue): JsonValue => {
299
+ if (isString(value)) {
289
300
  return value.replaceAll("${key}", key);
290
301
  }
291
302
  if (Array.isArray(value)) {
292
303
  return value.map((item) => substitute(item));
293
304
  }
294
- if (value && typeof value === "object") {
295
- const out: Record<string, unknown> = {};
296
- for (const [k, v] of Object.entries(value)) {
297
- out[k] = substitute(v);
298
- }
299
- return out;
305
+ if (isJsonObject(value)) {
306
+ return substituteObject(value);
300
307
  }
301
308
  return value;
302
309
  };
303
- return substitute(template) as Record<string, unknown>;
310
+ return substituteObject(template);
304
311
  }
305
312
 
306
313
  /**
@@ -314,37 +321,44 @@ function buildContext(
314
321
  entryKey: string | null = null,
315
322
  ): SchemaFormContext {
316
323
  const platform = getPlatform();
317
- return {
324
+ const context: SchemaFormContext = {
318
325
  fieldKeyPrefix: `$settings.${sectionKey}`,
319
- resolvePointer: (pointer, scope) =>
320
- resolveContextPointer(pointer, {
321
- projectConfig: (projectState?.projectConfig ?? {}) as Record<string, unknown>,
322
- ...(scope !== undefined && { scope }),
323
- ...(opts.formats !== undefined && { formats: opts.formats }),
324
- }),
325
- ...(typeof platform.setSecrets === "function"
326
- ? {
327
- commitSecret: async (key: string, value: string) => {
328
- const envName = deriveSecretEnvName(sectionKey, entryKey, key);
329
- await platform.setSecrets!({ set: { [envName]: value } });
330
- return envName;
331
- },
332
- }
333
- : {}),
326
+ resolvePointer: (pointer, scope) => {
327
+ const resolveOpts: ResolveContextOptions = {
328
+ projectConfig: projectState?.projectConfig ?? {},
329
+ };
330
+ /* The scope is the form's current value record, which is section JSON; the guard is what
331
+ lets the compiler see that, and it also stands for the old `!== undefined` test. */
332
+ if (isJsonObject(scope)) {
333
+ resolveOpts.scope = scope;
334
+ }
335
+ if (opts.formats !== undefined) {
336
+ resolveOpts.formats = opts.formats;
337
+ }
338
+ return resolveContextPointer(pointer, resolveOpts);
339
+ },
334
340
  };
341
+ if (isFunction(platform.setSecrets)) {
342
+ context.commitSecret = async (key: string, value: string) => {
343
+ const envName = deriveSecretEnvName(sectionKey, entryKey, key);
344
+ await platform.setSecrets!({ set: { [envName]: value } });
345
+ return envName;
346
+ };
347
+ }
348
+ return context;
335
349
  }
336
350
 
337
351
  /** The section's value object in the project config, created on demand. */
338
- function sectionValue(key: string): Record<string, unknown> | null {
339
- const config = projectState?.projectConfig as Record<string, unknown> | null | undefined;
352
+ function sectionValue(key: string): JsonObject | null {
353
+ const config = projectState?.projectConfig;
340
354
  if (!config) {
341
355
  return null;
342
356
  }
343
357
  const existing = config[key];
344
- if (existing && typeof existing === "object" && !Array.isArray(existing)) {
345
- return existing as Record<string, unknown>;
358
+ if (isJsonObject(existing)) {
359
+ return existing;
346
360
  }
347
- const fresh: Record<string, unknown> = {};
361
+ const fresh: JsonObject = {};
348
362
  config[key] = fresh;
349
363
  return fresh;
350
364
  }
@@ -360,7 +374,8 @@ function sectionValue(key: string): Record<string, unknown> | null {
360
374
  interface SectionMount {
361
375
  /** The element the registry handed the renderer, and this record's identity. */
362
376
  container: HTMLElement;
363
- handle: ContributedSurfaceHandle;
377
+ /** The mounted document, or `null` for the instant between creating this record and mounting. */
378
+ handle: ContributedSurfaceHandle | null;
364
379
  contribution: SettingsContribution;
365
380
  opts: ContributedSectionOptions;
366
381
  /** Where the schema form goes, once the document has made one. */
@@ -423,8 +438,7 @@ function project(record: SectionMount): ContributedView {
423
438
  const entries = sectionValue(sectionKey) ?? {};
424
439
  const selected = selectedEntries.get(sectionKey) ?? null;
425
440
  const value = selected === null ? undefined : entries[selected];
426
- const editing =
427
- selected !== null && value !== undefined && value !== null && typeof value === "object";
441
+ const editing = selected !== null && isNonNullObject(value);
428
442
  return {
429
443
  actionsState,
430
444
  editorRegion,
@@ -499,11 +513,14 @@ function paintForm(record: SectionMount): void {
499
513
  const entries = sectionValue(sectionKey) ?? {};
500
514
  const selected = selectedEntries.get(sectionKey) ?? null;
501
515
  const value = selected === null ? undefined : entries[selected];
502
- if (selected === null || !value || typeof value !== "object") {
516
+ if (selected === null || !isNonNullObject(value)) {
503
517
  host.replaceChildren();
504
518
  return;
505
519
  }
506
- const entry = value as Record<string, unknown>;
520
+ /* SAFETY: a map section's entries are objects by the section schema (`additionalProperties`
521
+ of type object), and the check above admits only objects; an array entry is malformed config
522
+ the form still treats as the record it should be, reading and writing named members. */
523
+ const entry = value as JsonObject;
507
524
  const base = `/${sectionKey}/${selected}`;
508
525
  place(
509
526
  mountSchemaForm(`section:${sectionKey}:${selected}`, contribution.entrySchema, entry, {
@@ -619,7 +636,7 @@ function actionsFor(record: SectionMount): ContributedActions {
619
636
  return;
620
637
  }
621
638
  // Rebuild the map to preserve entry order under the new key
622
- const next: Record<string, unknown> = {};
639
+ const next: JsonObject = {};
623
640
  for (const [k, v] of Object.entries(target)) {
624
641
  next[k === selected ? slug : k] = v;
625
642
  delete target[k];
@@ -655,19 +672,20 @@ export function renderContributedSection(
655
672
  record.contribution = contribution;
656
673
  record.opts = opts;
657
674
  }
658
- if (!record?.handle.attached()) {
659
- record?.handle.dispose();
675
+ let handle = record?.handle ?? null;
676
+ if (!record || !handle?.attached()) {
677
+ handle?.dispose();
660
678
  const fresh: SectionMount = {
661
679
  actionsHost: null,
662
680
  container,
663
681
  contribution,
664
682
  echo: null,
665
683
  formHost: null,
666
- handle: undefined as unknown as ContributedSurfaceHandle,
684
+ handle: null,
667
685
  opts,
668
686
  };
669
687
  mounts.set(container, fresh);
670
- fresh.handle = mountContributedSurface(container, actionsFor(fresh), {
688
+ handle = mountContributedSurface(container, actionsFor(fresh), {
671
689
  actionsSlot: (host) => {
672
690
  fresh.actionsHost = host;
673
691
  paintActions(fresh);
@@ -677,9 +695,10 @@ export function renderContributedSection(
677
695
  paintForm(fresh);
678
696
  },
679
697
  });
698
+ fresh.handle = handle;
680
699
  record = fresh;
681
700
  }
682
- record.handle.update(project(record));
701
+ handle.update(project(record));
683
702
  paintActions(record);
684
703
  paintForm(record);
685
704
  }
@@ -26,6 +26,7 @@
26
26
  * change" true of the specimen canvas as well as the page one.
27
27
  */
28
28
 
29
+ import { isNumber, isString } from "@jxsuite/schema/guards";
29
30
  import { errorMessage } from "@jxsuite/schema/parse";
30
31
  import { notify } from "../services/notify";
31
32
  import { projectState } from "../store";
@@ -110,7 +111,7 @@ function pending(container: HTMLElement, group: TokenGroupId): { name: string; v
110
111
 
111
112
  /** The live project configuration, or an empty one before a project is open. */
112
113
  function config(): ProjectConfig {
113
- return (projectState?.projectConfig || {}) as ProjectConfig;
114
+ return projectState?.projectConfig || {};
114
115
  }
115
116
 
116
117
  /**
@@ -121,7 +122,7 @@ function config(): ProjectConfig {
121
122
  * write, because there is no object here for it to have been written into.
122
123
  */
123
124
  function style(): JxStyle {
124
- return (config().style || {}) as JxStyle;
125
+ return config().style || {};
125
126
  }
126
127
 
127
128
  /** Every rendering context this project declares, schemes first. */
@@ -159,10 +160,18 @@ async function persist(container: HTMLElement): Promise<void> {
159
160
  // ─── Projection ──────────────────────────────────────────────────────────────
160
161
 
161
162
  /** The colour a well is painted, and the colour the native input under it opens on. */
162
- function well(
163
- resolved: string | number | undefined,
164
- fallback: string,
165
- ): { swatchBg: string; swatchInput: string } {
163
+ interface SwatchWell {
164
+ /** The resolved value as a CSS background, or `transparent` when the token resolves to nothing. */
165
+ swatchBg: string;
166
+ /**
167
+ * What the native colour input opens on: the background when it is a hex colour, else the
168
+ * fallback.
169
+ */
170
+ swatchInput: string;
171
+ }
172
+
173
+ /** Paint one well from what the token resolves to. */
174
+ function well(resolved: string | number | undefined, fallback: string): SwatchWell {
166
175
  const swatchBg = resolved === undefined ? "transparent" : String(resolved);
167
176
  return { swatchBg, swatchInput: swatchBg.startsWith("#") ? swatchBg : fallback };
168
177
  }
@@ -344,13 +353,25 @@ function addOverride(container: HTMLElement, token: string, ctx: string): void {
344
353
  return;
345
354
  }
346
355
  const base = rootStyle[token];
347
- if (typeof base !== "string" && typeof base !== "number") {
356
+ if (!isString(base) && !isNumber(base)) {
348
357
  return;
349
358
  }
350
359
  writeTokenOverride(rootStyle, context, token, String(base));
351
360
  commit(container);
352
361
  }
353
362
 
363
+ /** Switch Settings to the Contexts section, saying so when the section registry will not load. */
364
+ async function openContextsSection(): Promise<void> {
365
+ try {
366
+ const { setSettingsSection } = await import("./section-registry");
367
+ setSettingsSection("contexts");
368
+ } catch (error) {
369
+ notify.error(`Could not open Settings › Contexts — ${errorMessage(error)}`, {
370
+ source: "Settings",
371
+ });
372
+ }
373
+ }
374
+
354
375
  /**
355
376
  * What the reader may do, bound to one container.
356
377
  *
@@ -378,13 +399,7 @@ function actions(container: HTMLElement): CssVarsActions {
378
399
  * breaks the css-vars-editor ↔ section-registry cycle.
379
400
  */
380
401
  manageContexts: () => {
381
- void import("./section-registry")
382
- .then(({ setSettingsSection }) => setSettingsSection("contexts"))
383
- .catch((error: unknown) => {
384
- notify.error(`Could not open Settings › Contexts — ${errorMessage(error)}`, {
385
- source: "Settings",
386
- });
387
- });
402
+ void openContextsSection();
388
403
  },
389
404
  removeToken: (name: string) => {
390
405
  delete style()[name];
@@ -399,10 +414,16 @@ function actions(container: HTMLElement): CssVarsActions {
399
414
  * predecessor's `ref()` into the DOM could never do.
400
415
  */
401
416
  setAddName: (groupId: string, value: string) => {
402
- pending(container, groupId as TokenGroupId).name = value;
417
+ const group = groupOf(groupId);
418
+ if (group) {
419
+ pending(container, group.id).name = value;
420
+ }
403
421
  },
404
422
  setAddValue: (groupId: string, value: string) => {
405
- pending(container, groupId as TokenGroupId).value = value;
423
+ const group = groupOf(groupId);
424
+ if (group) {
425
+ pending(container, group.id).value = value;
426
+ }
406
427
  },
407
428
  setOverride: (token: string, ctx: string, value: string) => {
408
429
  const context = contexts().find((c) => c.name === ctx);
@@ -40,10 +40,12 @@
40
40
  * @docs studio/projects/settings
41
41
  */
42
42
 
43
+ import { isBoolean, isJsonObject, isString } from "@jxsuite/schema/guards";
43
44
  import { projectState } from "../store";
44
45
  import { commitProjectConfig } from "../tabs/project-config";
45
46
  import { camelToLabel } from "../utils/studio-utils";
46
47
  import {
48
+ BLANK_FIELD,
47
49
  FIELD_TYPES,
48
50
  FORMAT_OPTIONS,
49
51
  detectFieldFormat,
@@ -52,39 +54,30 @@ import {
52
54
  } from "./schema-field-ui";
53
55
  import { mountDefsSurface } from "../surfaces/settings-defs";
54
56
 
55
- import type { SchemaProperty } from "./schema-field-ui";
57
+ import type { NestedFieldDraft, SchemaProperty } from "./schema-field-ui";
56
58
  import type {
57
59
  DefsActions,
58
- DefsChoice,
59
60
  DefsFieldView,
60
61
  DefsSurfaceHandle,
61
62
  DefsView,
62
63
  NestedFieldView,
63
64
  } from "../surfaces/settings-defs";
64
- import type { ContentTypeSchema, ContentTypeSchemaField } from "@jxsuite/schema/types";
65
+ import type { ContentTypeSchema } from "@jxsuite/schema/types";
66
+ import type { SurfaceOption } from "../ui/surface";
65
67
 
66
68
  // ─── The pickers ──────────────────────────────────────────────────────────────
67
69
 
68
70
  /** The field types, as picker rows. One array, made once: an equal write re-runs no binding. */
69
- const TYPE_ROWS: DefsChoice[] = FIELD_TYPES.map((type) => ({ label: type, value: type }));
71
+ const TYPE_ROWS: SurfaceOption[] = FIELD_TYPES.map((type) => ({ label: type, value: type }));
70
72
 
71
73
  /** The formats, with the empty one named: a blank row says nothing about what choosing it does. */
72
- const FORMAT_ROWS: DefsChoice[] = FORMAT_OPTIONS.map((format) => ({
74
+ const FORMAT_ROWS: SurfaceOption[] = FORMAT_OPTIONS.map((format) => ({
73
75
  label: format || "(none)",
74
76
  value: format,
75
77
  }));
76
78
 
77
- /** What a new field starts as. */
78
- const BLANK_FIELD = { format: "", name: "", required: false, type: "string" };
79
-
80
79
  // ─── Per-container state ──────────────────────────────────────────────────────
81
80
 
82
- /** One object field's unsubmitted nested field. */
83
- interface Draft {
84
- name: string;
85
- type: string;
86
- }
87
-
88
81
  /**
89
82
  * What the reader is part-way through, per rendered container.
90
83
  *
@@ -100,7 +93,7 @@ interface DefsUi {
100
93
  addOpen: boolean;
101
94
  add: { format: string; name: string; required: boolean; type: string };
102
95
  /** Each object field's nested add row, by the field's name on disk. */
103
- drafts: Map<string, Draft>;
96
+ drafts: Map<string, NestedFieldDraft>;
104
97
  /**
105
98
  * The ONE control whose value has parted from what is on disk, and what it holds.
106
99
  *
@@ -166,9 +159,19 @@ function hush(container: HTMLElement): void {
166
159
  uiFor(container).echo = null;
167
160
  }
168
161
 
169
- /** What a control shows: what it was last told it holds, or what is on disk. */
170
- function shown<T extends string | boolean>(ui: DefsUi, id: string, disk: T): T {
171
- return ui.echo?.id === id ? (ui.echo.value as T) : disk;
162
+ /**
163
+ * What a text control shows: what it was last told it holds, or what is on disk.
164
+ *
165
+ * The echo's value is a string whenever its id is a {@link nameId}, because only the rename setters
166
+ * echo under one; the check states that rather than assuming it.
167
+ */
168
+ function shownText(ui: DefsUi, id: string, disk: string): string {
169
+ return ui.echo?.id === id && isString(ui.echo.value) ? ui.echo.value : disk;
170
+ }
171
+
172
+ /** What a checkbox shows: what it was last told it holds, or what is on disk. */
173
+ function shownFlag(ui: DefsUi, id: string, disk: boolean): boolean {
174
+ return ui.echo?.id === id && isBoolean(ui.echo.value) ? ui.echo.value : disk;
172
175
  }
173
176
 
174
177
  // ─── Persistence ──────────────────────────────────────────────────────────────
@@ -200,6 +203,9 @@ function persist(): void {
200
203
  * outlive a projection, which makes reading through to the store the thing that keeps them honest.
201
204
  */
202
205
  function currentDefs(): Record<string, ContentTypeSchema> | undefined {
206
+ /* SAFETY: project `$defs` holds JSON Schema type definitions (project-schema.json, "Global type
207
+ definitions") and this editor is their writer; ContentTypeSchema is that schema object's view,
208
+ every member optional, and each read below falls back (`?? {}`, `?? []`) when one is absent. */
203
209
  return projectState?.projectConfig?.$defs as Record<string, ContentTypeSchema> | undefined;
204
210
  }
205
211
 
@@ -213,19 +219,16 @@ function selectedDef(ui: DefsUi): ContentTypeSchema | undefined {
213
219
  * resolves through `#/$context/content`, read here without a schema-form context to go through.
214
220
  */
215
221
  function contentTypeNames(): string[] {
216
- const content = (projectState?.projectConfig as Record<string, unknown> | null | undefined)
217
- ?.content;
218
- return content && typeof content === "object" && !Array.isArray(content)
219
- ? Object.keys(content)
220
- : [];
222
+ const content = projectState?.projectConfig?.content;
223
+ return isJsonObject(content) ? Object.keys(content) : [];
221
224
  }
222
225
 
223
226
  /** The last target list, so an unchanged one is the same array and re-runs no binding. */
224
- let targetRows: DefsChoice[] = [];
227
+ let targetRows: SurfaceOption[] = [];
225
228
  let targetNames = " ";
226
229
 
227
230
  /** The reference targets, as picker rows. */
228
- function targets(): DefsChoice[] {
231
+ function targets(): SurfaceOption[] {
229
232
  const names = contentTypeNames();
230
233
  const id = names.join(" ");
231
234
  if (id !== targetNames) {
@@ -256,9 +259,9 @@ function nestedView(
256
259
  format: detectFieldFormat(schema),
257
260
  hasFormat: takesFormat(type),
258
261
  key,
259
- name: shown(ui, nameId(id), key),
262
+ name: shownText(ui, nameId(id), key),
260
263
  parent,
261
- required: shown(ui, requiredId(id), required),
264
+ required: shownFlag(ui, requiredId(id), required),
262
265
  type,
263
266
  };
264
267
  }
@@ -290,9 +293,9 @@ function fieldView(
290
293
  hasFormat: takesFormat(type),
291
294
  key,
292
295
  label: camelToLabel(key),
293
- name: shown(ui, nameId(key), key),
296
+ name: shownText(ui, nameId(key), key),
294
297
  refTarget: schema.$ref ? schema.$ref.replace(/^#\/[^/]+\//, "") : "",
295
- required: shown(ui, requiredId(key), required),
298
+ required: shownFlag(ui, requiredId(key), required),
296
299
  type,
297
300
  };
298
301
  }
@@ -312,15 +315,15 @@ function project(container: HTMLElement): DefsView {
312
315
  addRequired: ui.add.required,
313
316
  addState: ui.addOpen && def ? "open" : "closed",
314
317
  addType: ui.add.type,
318
+ defs: Object.keys(defs).map((name) => ({ name, selected: name === ui.selected })),
315
319
  editorState: def ? "editing" : "empty",
316
320
  fields: Object.entries(properties).map(([key, schema]) =>
317
- fieldView(ui, key, schema as SchemaProperty, required.includes(key), rows.length > 0),
321
+ fieldView(ui, key, schema, required.includes(key), rows.length > 0),
318
322
  ),
319
323
  formatOptions: FORMAT_ROWS,
320
324
  newName: ui.newName,
321
325
  newState: ui.newOpen ? "open" : "closed",
322
326
  selected: def && ui.selected !== null ? ui.selected : "",
323
- shapes: Object.keys(defs).map((name) => ({ name, selected: name === ui.selected })),
324
327
  targets: rows,
325
328
  typeOptions: TYPE_ROWS,
326
329
  };
@@ -338,10 +341,10 @@ function actionsFor(container: HTMLElement): DefsActions {
338
341
 
339
342
  /** The parent object a nested edit is about, or `undefined` when it has gone underneath. */
340
343
  const parentOf = (parent: string): SchemaProperty | undefined =>
341
- selectedDef(ui)?.properties?.[parent] as SchemaProperty | undefined;
344
+ selectedDef(ui)?.properties?.[parent];
342
345
 
343
346
  /** One object field's add-row draft, made on first use. */
344
- const draftOf = (parent: string): Draft => {
347
+ const draftOf = (parent: string): NestedFieldDraft => {
345
348
  let draft = ui.drafts.get(parent);
346
349
  if (!draft) {
347
350
  draft = { name: "", type: "string" };
@@ -513,7 +516,7 @@ function actionsFor(container: HTMLElement): DefsActions {
513
516
  }
514
517
  done();
515
518
  },
516
- removeShape() {
519
+ removeSelected() {
517
520
  const defs = currentDefs();
518
521
  if (ui.selected === null || !defs?.[ui.selected]) {
519
522
  return;
@@ -613,7 +616,7 @@ function actionsFor(container: HTMLElement): DefsActions {
613
616
  }
614
617
  /* The pointer form is `#/content/<type>` — the same one `ui/form-controls.ts` writes, so a
615
618
  reference authored here and one authored in the content-types builder are the same value. */
616
- def.properties[key] = { $ref: `#/content/${value}` } as ContentTypeSchemaField;
619
+ def.properties[key] = { $ref: `#/content/${value}` };
617
620
  done();
618
621
  },
619
622
  setType(key, value) {
@@ -42,7 +42,7 @@ export interface ExtensionRow {
42
42
 
43
43
  /** The live project configuration, or an empty one before a project is open. */
44
44
  export function projectConfig(): ProjectConfig {
45
- return (projectState?.projectConfig ?? {}) as ProjectConfig;
45
+ return projectState?.projectConfig ?? {};
46
46
  }
47
47
 
48
48
  /** The specifiers `project.json` currently enables. */
@@ -71,7 +71,7 @@ export function buildRows(packages: PackageInfo[] | null = null): ExtensionRow[]
71
71
  const here = entry.installed ?? installed.has(entry.name);
72
72
  const bundled = entry.bundled ?? false;
73
73
  const info = resolved.get(entry.name);
74
- rows.push({
74
+ const row: ExtensionRow = {
75
75
  broken: enabled.has(specifier) && !here && !bundled,
76
76
  bundled,
77
77
  enabled: enabled.has(specifier),
@@ -83,9 +83,14 @@ export function buildRows(packages: PackageInfo[] | null = null): ExtensionRow[]
83
83
  : entry.sections.map((s) => s.key),
84
84
  specifier,
85
85
  title: entry.title ?? entry.name,
86
- ...(entry.description === undefined ? {} : { description: entry.description }),
87
- ...(entry.problem === undefined ? {} : { unavailable: entry.problem }),
88
- });
86
+ };
87
+ if (entry.description !== undefined) {
88
+ row.description = entry.description;
89
+ }
90
+ if (entry.problem !== undefined) {
91
+ row.unavailable = entry.problem;
92
+ }
93
+ rows.push(row);
89
94
  }
90
95
 
91
96
  // Anything project.json names that the backend did not describe. It can still be turned OFF,
@@ -95,7 +100,7 @@ export function buildRows(packages: PackageInfo[] | null = null): ExtensionRow[]
95
100
  continue;
96
101
  }
97
102
  const info = resolved.get(specifier);
98
- rows.push({
103
+ const row: ExtensionRow = {
99
104
  broken: !installed.has(specifier) && info === undefined,
100
105
  bundled: false,
101
106
  enabled: true,
@@ -105,8 +110,11 @@ export function buildRows(packages: PackageInfo[] | null = null): ExtensionRow[]
105
110
  sections: info ? info.contributions.map((c) => c.project.key) : [],
106
111
  specifier,
107
112
  title: info?.title ?? specifier,
108
- ...(info?.description === undefined ? {} : { description: info.description }),
109
- });
113
+ };
114
+ if (info?.description !== undefined) {
115
+ row.description = info.description;
116
+ }
117
+ rows.push(row);
110
118
  }
111
119
 
112
120
  return rows;