@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
@@ -41,6 +41,7 @@
41
41
  import { errorMessage } from "@jxsuite/schema/parse";
42
42
  import { layerHost } from "../ui/layers";
43
43
  import { enumArg, enumProperty } from "../commands/command-args";
44
+ import type { CommandArgValues } from "../commands/command-args";
44
45
  import type { AnyCommand, CommandRegistry } from "../commands/registry";
45
46
  import { getPlatform } from "../platform";
46
47
  import { installUrlOf } from "../platform-errors";
@@ -118,9 +119,9 @@ let _nameError = "";
118
119
  /** GitHub-App install link carried by a structured needs_installation_access failure. */
119
120
  let _errorInstallUrl = "";
120
121
 
121
- function captureError(error: unknown) {
122
- _error = errorMessage(error);
123
- _errorInstallUrl = installUrlOf(error) ?? "";
122
+ function captureError(cause: unknown) {
123
+ _error = errorMessage(cause);
124
+ _errorInstallUrl = installUrlOf(cause) ?? "";
124
125
  }
125
126
 
126
127
  let _creating = false;
@@ -244,6 +245,8 @@ export function openNewProjectModal(options?: { tab?: NewProjectTab }): Promise<
244
245
  if (_creating) {
245
246
  return;
246
247
  }
248
+ /* SAFETY: `value` is the selected `jx-tab`'s value, and the strip renders one tab per
249
+ `viewOf().tabs` entry, whose values are "starter", "import" and "agent". */
247
250
  _tab = value as NewProjectTab;
248
251
  _error = "";
249
252
  redraw();
@@ -348,10 +351,10 @@ async function finishCreated(result: { root: string; config: ProjectConfig }) {
348
351
  getTab: () => null,
349
352
  });
350
353
  if (!adopted && !openedElsewhere) {
351
- notify.warn("Created the project, but could not open it here.", {
352
- ...(error === null ? {} : { detail: error }),
353
- source: "New Project",
354
- });
354
+ notify.warn(
355
+ "Created the project, but could not open it here.",
356
+ error === null ? { source: "New Project" } : { detail: error, source: "New Project" },
357
+ );
355
358
  }
356
359
  finish(result);
357
360
  }
@@ -708,9 +711,9 @@ export function newProjectCommands(): AnyCommand[] {
708
711
  group: "1_file",
709
712
  /* No `aiTool`: application-level, refused at registration; it opens the wizard, and the
710
713
  model's own door is `create_project` / `import_site` (studio-ui-guidelines.md §12.4). */
711
- run: (_commandCtx, args) => {
714
+ run: (_commandCtx, args: CommandArgValues) => {
712
715
  const tab =
713
- (args as { tab?: unknown }).tab === undefined
716
+ args.tab === undefined
714
717
  ? undefined
715
718
  : enumArg("project.new", args, "tab", NEW_PROJECT_TABS);
716
719
  void openNewProjectModal(tab === undefined ? {} : { tab });
@@ -29,9 +29,10 @@ import { openJxsuiteUpdateSurface } from "../surfaces/jxsuite-update";
29
29
  import { showProgressModal } from "../ui/progress-modal";
30
30
  import { notify } from "../services/notify";
31
31
  import { isUpgrade } from "./semver";
32
- import type { JxsuiteUpdateSurfaceHandle } from "../surfaces/jxsuite-update";
32
+ import type { DialogLayerHandle } from "../ui/surface";
33
33
 
34
- const JXSUITE_PREFIX = "@jxsuite/";
34
+ /** The npm scope every first-party package is published under. */
35
+ export const JXSUITE_PREFIX = "@jxsuite/";
35
36
 
36
37
  export interface JxsuiteUpdate {
37
38
  name: string;
@@ -170,7 +171,7 @@ function askToUpdate(outdated: JxsuiteUpdate[]): Promise<boolean> {
170
171
  closing = true;
171
172
  handle.close();
172
173
  };
173
- const handle: JxsuiteUpdateSurfaceHandle = openJxsuiteUpdateSurface({
174
+ const handle: DialogLayerHandle = openJxsuiteUpdateSurface({
174
175
  layer: layerHost("dialog"),
175
176
  onCancel: () => {
176
177
  takeDown();
@@ -10,11 +10,13 @@
10
10
  */
11
11
 
12
12
  import { errorMessage } from "@jxsuite/schema/parse";
13
+ import { isJsonObject } from "@jxsuite/schema/guards";
14
+ import type { JsonObject, JsonValue } from "@jxsuite/schema/types";
13
15
  import { getPlatform } from "../platform";
14
16
  import { showConfirmDialog } from "../ui/layers";
15
17
  import { showProgressModal } from "../ui/progress-modal";
16
18
  import { notify } from "../services/notify";
17
- import { applyJxsuiteUpdate, checkJxsuiteUpdate } from "./jxsuite-update";
19
+ import { JXSUITE_PREFIX, applyJxsuiteUpdate, checkJxsuiteUpdate } from "./jxsuite-update";
18
20
  import type { GitStatusResult } from "../types";
19
21
 
20
22
  const PKG_PATHS = ["package.json", "bun.lock", "bun.lockb"];
@@ -29,20 +31,16 @@ const UNTRACKED_STATUSES = new Set(["??", "U"]);
29
31
  /** Above this many dirty files, skip the per-file upstream comparison and leave the error as-is. */
30
32
  const MAX_CONFLICT_SCAN = 25;
31
33
 
32
- const JXSUITE_PREFIX = "@jxsuite/";
33
-
34
- function isRecord(value: unknown): value is Record<string, unknown> {
35
- return typeof value === "object" && value !== null && !Array.isArray(value);
36
- }
37
-
38
- function sortKeys(value: unknown): unknown {
34
+ /** A copy of a JSON value with every object's keys in sorted order, so equal data prints equal. */
35
+ function sortKeys(value: JsonValue): JsonValue {
39
36
  if (Array.isArray(value)) {
40
37
  return value.map((entry) => sortKeys(entry));
41
38
  }
42
- if (isRecord(value)) {
43
- const out: Record<string, unknown> = {};
44
- for (const key of Object.keys(value).toSorted()) {
45
- out[key] = sortKeys(value[key]);
39
+ if (isJsonObject(value)) {
40
+ const out: JsonObject = {};
41
+ // Keys are unique, so the comparator never sees a tie; `<` is the default sort's code-unit order.
42
+ for (const [key, entry] of Object.entries(value).toSorted(([a], [b]) => (a < b ? -1 : 1))) {
43
+ out[key] = sortKeys(entry);
46
44
  }
47
45
  return out;
48
46
  }
@@ -50,11 +48,11 @@ function sortKeys(value: unknown): unknown {
50
48
  }
51
49
 
52
50
  /** Replace every @jxsuite/* version in dependencies/devDependencies so they compare equal. */
53
- function maskJxsuiteVersions(pkg: Record<string, unknown>): Record<string, unknown> {
51
+ function maskJxsuiteVersions(pkg: JsonObject): JsonObject {
54
52
  const out = { ...pkg };
55
53
  for (const section of ["dependencies", "devDependencies"]) {
56
54
  const deps = out[section];
57
- if (!isRecord(deps)) {
55
+ if (!isJsonObject(deps)) {
58
56
  continue;
59
57
  }
60
58
  const masked = { ...deps };
@@ -88,7 +86,7 @@ export function isAutomatedPackageDiff(
88
86
  } catch {
89
87
  return false;
90
88
  }
91
- if (!isRecord(head) || !isRecord(working)) {
89
+ if (!isJsonObject(head) || !isJsonObject(working)) {
92
90
  return false;
93
91
  }
94
92
  return (
@@ -251,20 +249,20 @@ async function discardPullAndSync(plan: PackagePullPlan): Promise<void> {
251
249
  await syncPackagesAfterPull();
252
250
  }
253
251
 
254
- async function recoverAfterFailedPull(original: unknown): Promise<void> {
252
+ async function recoverAfterFailedPull(cause: unknown): Promise<void> {
255
253
  const platform = getPlatform();
256
254
  let status: GitStatusResult;
257
255
  try {
258
256
  status = await platform.gitStatus();
259
257
  } catch {
260
- throw original;
258
+ throw cause;
261
259
  }
262
260
  if (!(status.behind > 0)) {
263
- throw original;
261
+ throw cause;
264
262
  }
265
263
  const plan = await planPackageDiscard(status);
266
264
  if (planIsEmpty(plan) || (await otherFilesConflict(status))) {
267
- throw original;
265
+ throw cause;
268
266
  }
269
267
  if (!plan.automated) {
270
268
  const confirmed = await showConfirmDialog(
@@ -273,7 +271,7 @@ async function recoverAfterFailedPull(original: unknown): Promise<void> {
273
271
  { confirmLabel: "Discard and pull", destructive: true },
274
272
  );
275
273
  if (!confirmed) {
276
- throw original;
274
+ throw cause;
277
275
  }
278
276
  }
279
277
  await discardPullAndSync(plan);
@@ -346,15 +344,18 @@ export async function pullWithPackageSync(): Promise<void> {
346
344
  */
347
345
  export async function autoSyncProjectOnOpen(): Promise<void> {
348
346
  const platform = getPlatform();
349
- let status: GitStatusResult;
350
347
  try {
351
- status = await platform.gitStatus();
348
+ /* The status is host wire data. A host may leave `remotes` out (as `deploy-checklist.ts` and
349
+ `git-panel.ts` also allow), which reads as "nothing to sync"; a host that sends no status at
350
+ all throws on the first read and is caught below the same way, so a malformed status never
351
+ aborts the project open that awaits this. */
352
+ const status = await platform.gitStatus();
353
+ if (!status.isRepo || !Array.isArray(status.remotes) || status.remotes.length === 0) {
354
+ return;
355
+ }
352
356
  } catch {
353
357
  return;
354
358
  }
355
- if (!status?.isRepo || (status.remotes?.length ?? 0) === 0) {
356
- return;
357
- }
358
359
  notify.info("Syncing project…", { key: "project.sync", source: "Source Control" });
359
360
  try {
360
361
  await pullWithPackageSync();
@@ -10,14 +10,28 @@
10
10
  * produces for the matching built page.
11
11
  */
12
12
 
13
- import { documentUrlPattern as routePattern } from "@jxsuite/site/routes";
13
+ import { documentUrlPattern } from "@jxsuite/site/routes";
14
14
  import { getPlatform } from "./platform";
15
15
  import { loadExtensions } from "./format/format-host";
16
- import type { JxMutableNode, JxPathsDef } from "@jxsuite/schema/types";
16
+ import { isJsonObject, isRef, isString } from "@jxsuite/schema/guards";
17
+ import type {
18
+ JsonObject,
19
+ JsonValue,
20
+ JxDocumentValue,
21
+ JxMutableNode,
22
+ JxPathsDef,
23
+ JxStateDefinition,
24
+ } from "@jxsuite/schema/types";
17
25
 
18
26
  /** Param name → candidate values, in `$paths` declaration order. */
19
27
  export type ParamValues = Record<string, string[]>;
20
28
 
29
+ /** One entry of a resolved ContentCollection, as `/__jx_resolve__` serializes it to JSON. */
30
+ interface ResolvedContentEntry {
31
+ id?: JsonValue;
32
+ data?: JsonObject;
33
+ }
34
+
21
35
  /**
22
36
  * Route derivation is `@jxsuite/site/routes`, re-exported so this module stays the studio's one
23
37
  * import for everything `$params`.
@@ -34,14 +48,21 @@ export { documentUrlPattern, dynamicRouteParams } from "@jxsuite/site/routes";
34
48
  * The `$paths` declaration of an open document. JSON pages carry it on the document root;
35
49
  * format-class pages (markdown) keep it in the frontmatter.
36
50
  *
37
- * @param {{ document?: unknown; frontmatter?: Record<string, unknown> }} doc
51
+ * @param {{
52
+ * document?: JxMutableNode | null;
53
+ * frontmatter?: Record<string, JxDocumentValue | undefined> | null;
54
+ * }} doc
38
55
  * @returns {JxPathsDef | null}
39
56
  */
40
57
  export function pagePathsDef(doc: {
41
58
  document?: JxMutableNode | null;
42
- frontmatter?: Record<string, unknown> | null;
59
+ frontmatter?: Record<string, JxDocumentValue | undefined> | null;
43
60
  }) {
44
- const fromDoc = (doc.document as { $paths?: JxPathsDef } | null | undefined)?.$paths;
61
+ const fromDoc = doc.document?.$paths;
62
+ /* SAFETY: frontmatter `$paths` is the format-page form of the root `$paths` block
63
+ (site-architecture.md §4.3). Its only consumer, loadParamValues, re-checks every JxPathsDef
64
+ shape (array, contentType, values, $ref) before reading it and turns any other value into an
65
+ empty result, so an off-shape block degrades to "no candidates" rather than a crash. */
45
66
  const fromFrontmatter = doc.frontmatter?.$paths as JxPathsDef | undefined;
46
67
  return fromDoc ?? fromFrontmatter ?? null;
47
68
  }
@@ -67,15 +88,15 @@ export function loadParamValues(
67
88
  pathsDef: JxPathsDef | null,
68
89
  ) {
69
90
  if (!pathsDef) {
70
- return Promise.resolve({} as ParamValues);
91
+ return Promise.resolve<ParamValues>({});
71
92
  }
72
93
  const key = `${documentPath ?? ""}::${JSON.stringify(pathsDef)}`;
73
94
  let pending = valueCache.get(key);
74
95
  if (!pending) {
75
- pending = resolveParamValues(pathsDef).catch((error: unknown) => {
96
+ pending = resolveParamValues(pathsDef).catch((error): ParamValues => {
76
97
  valueCache.delete(key);
77
98
  console.warn("page-params: failed to enumerate $paths values:", error);
78
- return {} as ParamValues;
99
+ return {};
79
100
  });
80
101
  valueCache.set(key, pending);
81
102
  }
@@ -104,21 +125,19 @@ async function resolveParamValues(pathsDef: JxPathsDef): Promise<ParamValues> {
104
125
  // Discriminator member on JxPathsDef, so narrow to string. Resolved through the backend's
105
126
  // ContentCollection pipeline (the same one the canvas's ContentEntry uses), so every offered
106
127
  // Value is guaranteed to resolve in preview.
107
- if (
108
- "contentType" in pathsDef &&
109
- typeof pathsDef.contentType === "string" &&
110
- pathsDef.contentType
111
- ) {
128
+ if ("contentType" in pathsDef && isString(pathsDef.contentType) && pathsDef.contentType) {
112
129
  const param = pathsDef.param ?? "slug";
113
130
  const field = pathsDef.field ?? "id";
114
- const entries = (await resolveContentCollection(pathsDef.contentType)) as {
115
- id?: unknown;
116
- data?: Record<string, unknown>;
117
- }[];
118
- const out: ParamValues = { [param]: [] };
119
- if (!Array.isArray(entries)) {
131
+ const resolved = await resolveContentCollection(pathsDef.contentType);
132
+ const out = { [param]: [] } satisfies ParamValues;
133
+ if (!Array.isArray(resolved)) {
120
134
  return out;
121
135
  }
136
+ /* SAFETY: a resolved ContentCollection is its entries array, each `{ id, data }` (the parser's
137
+ ContentLoaderEntry after the JSON hop). Off-shape entries stay harmless: a primitive reads as
138
+ having no id and is skipped, and a null throws on `.id`, which loadParamValues catches and
139
+ degrades to an empty result. */
140
+ const entries = resolved as ResolvedContentEntry[];
122
141
  for (const entry of entries) {
123
142
  pushValue(out, param, field === "id" ? entry.id : (entry.data?.[field] ?? entry.id));
124
143
  }
@@ -128,7 +147,7 @@ async function resolveParamValues(pathsDef: JxPathsDef): Promise<ParamValues> {
128
147
  // Explicit values: { values: ["en", "fr"], param: "lang" }
129
148
  if ("values" in pathsDef && Array.isArray(pathsDef.values)) {
130
149
  const param = pathsDef.param ?? "value";
131
- const out: ParamValues = { [param]: [] };
150
+ const out = { [param]: [] } satisfies ParamValues;
132
151
  for (const value of pathsDef.values) {
133
152
  pushValue(out, param, value);
134
153
  }
@@ -137,17 +156,18 @@ async function resolveParamValues(pathsDef: JxPathsDef): Promise<ParamValues> {
137
156
 
138
157
  // Data file ref: { "$ref": "./data/products.json", param: "id", field: "sku" } — `$ref` also
139
158
  // Reaches here as an open discriminator key, so narrow to a non-empty string.
140
- if ("$ref" in pathsDef && typeof pathsDef.$ref === "string" && pathsDef.$ref) {
159
+ if ("$ref" in pathsDef && isString(pathsDef.$ref) && pathsDef.$ref) {
141
160
  const param = pathsDef.param ?? "id";
142
161
  const field = pathsDef.field ?? "id";
143
162
  const content = await getPlatform().readFile(pathsDef.$ref.replace(/^\.\//, ""));
144
- const data = JSON.parse(content) as unknown;
145
- const out: ParamValues = { [param]: [] };
163
+ // SAFETY: JSON.parse only ever produces JSON values.
164
+ const data = JSON.parse(content) as JsonValue;
165
+ const out = { [param]: [] } satisfies ParamValues;
146
166
  if (!Array.isArray(data)) {
147
167
  return out;
148
168
  }
149
- for (const item of data as Record<string, unknown>[]) {
150
- pushValue(out, param, item?.[field] ?? item?.id ?? item);
169
+ for (const item of data) {
170
+ pushValue(out, param, isJsonObject(item) ? (item[field] ?? item.id ?? item) : item);
151
171
  }
152
172
  return out;
153
173
  }
@@ -179,9 +199,9 @@ async function contentCollectionSrc(): Promise<string> {
179
199
  * fetch on platforms that predate `resolveClass`.
180
200
  *
181
201
  * @param {string} contentType
182
- * @returns {Promise<unknown>}
202
+ * @returns {Promise<JsonValue>}
183
203
  */
184
- async function resolveContentCollection(contentType: string) {
204
+ async function resolveContentCollection(contentType: string): Promise<JsonValue> {
185
205
  const body = {
186
206
  $prototype: "ContentCollection",
187
207
  $src: await contentCollectionSrc(),
@@ -189,26 +209,28 @@ async function resolveContentCollection(contentType: string) {
189
209
  };
190
210
  const platform = getPlatform();
191
211
  if (platform.resolveClass) {
192
- return platform.resolveClass(body);
212
+ /* SAFETY: resolveClass hands back the backend's parsed `/__jx_resolve__` response, and that
213
+ endpoint answers with a JSON body, so the value is a JSON value. */
214
+ return platform.resolveClass(body) as Promise<JsonValue>;
193
215
  }
194
216
  return fetch("/__jx_resolve__", {
195
217
  body: JSON.stringify(body),
196
218
  headers: { "content-type": "application/json" },
197
219
  method: "POST",
198
- }).then((res) => {
220
+ }).then((res): Promise<JsonValue> => {
199
221
  if (!res.ok) {
200
222
  throw new Error(`Class resolution failed: ${res.status}`);
201
223
  }
202
- return res.json() as Promise<unknown>;
224
+ return res.json();
203
225
  });
204
226
  }
205
227
 
206
228
  /**
207
229
  * @param {ParamValues} out
208
230
  * @param {string} param
209
- * @param {unknown} value
231
+ * @param {JsonValue | undefined} value
210
232
  */
211
- function pushValue(out: ParamValues, param: string, value: unknown) {
233
+ function pushValue(out: ParamValues, param: string, value: JsonValue | undefined) {
212
234
  if (value === null || value === undefined || value === "") {
213
235
  return;
214
236
  }
@@ -245,15 +267,15 @@ export function substitutePreviewParams(
245
267
  if (Object.keys(params).length === 0) {
246
268
  return renderDoc;
247
269
  }
248
- const doc = substituteParamRefs(renderDoc, params) as JxMutableNode & {
249
- state?: Record<string, unknown>;
250
- title?: unknown;
251
- };
270
+ /* SAFETY: a render document is a JSON tree (it reaches the canvas iframe by structured clone and
271
+ is serialized back to disk), so its root is a JSON object; substituteObjectRefs rebuilds it key
272
+ for key, replacing only `$params` ref values with strings, so the copy keeps the node's shape. */
273
+ const doc = substituteObjectRefs(renderDoc as JsonObject, params) as JxMutableNode;
252
274
  doc.state ??= {};
253
275
  doc.state.$page = {
254
276
  params: { ...params },
255
- title: typeof doc.title === "string" ? doc.title : "",
256
- url: routePattern(documentPath),
277
+ title: isString(doc.title) ? doc.title : "",
278
+ url: documentUrlPattern(documentPath),
257
279
  };
258
280
  return doc;
259
281
  }
@@ -263,21 +285,20 @@ export function substitutePreviewParams(
263
285
  * These are the entries `substitutePreviewParams` rewrites, and the ones `resolveParamBoundState`
264
286
  * bakes.
265
287
  *
266
- * @param {Record<string, unknown> | null | undefined} state - The ORIGINAL document state (with
267
- * `$ref`s intact — substitution removes the marker)
288
+ * @param {Record<string, JxStateDefinition> | null | undefined} state - The ORIGINAL document state
289
+ * (with `$ref`s intact — substitution removes the marker)
268
290
  * @returns {string[]}
269
291
  */
270
- export function paramBoundStateKeys(state: Record<string, unknown> | null | undefined) {
292
+ export function paramBoundStateKeys(state: Record<string, JxStateDefinition> | null | undefined) {
271
293
  if (!state) {
272
294
  return [];
273
295
  }
274
296
  return Object.keys(state).filter((key) => {
275
- const entry = state[key] as Record<string, unknown> | null;
297
+ const entry = state[key];
276
298
  return (
277
- entry &&
278
- typeof entry === "object" &&
279
- typeof entry.$prototype === "string" &&
280
- typeof entry.$src === "string" &&
299
+ isJsonObject(entry) &&
300
+ isString(entry.$prototype) &&
301
+ isString(entry.$src) &&
281
302
  JSON.stringify(entry).includes('"#/$params/')
282
303
  );
283
304
  });
@@ -306,24 +327,30 @@ export async function resolveParamBoundState(
306
327
  return;
307
328
  }
308
329
  const platform = getPlatform();
309
- if (!platform.resolveClass) {
330
+ const { resolveClass } = platform;
331
+ if (!resolveClass) {
310
332
  return;
311
333
  }
312
- const { state } = renderDoc as { state?: Record<string, unknown> };
334
+ const { state } = renderDoc;
313
335
  if (!state) {
314
336
  return;
315
337
  }
316
338
  await Promise.all(
317
339
  keys.map(async (key) => {
340
+ /* Keys come from paramBoundStateKeys, which only selects plain-object entries; substitution
341
+ keeps such an entry an object unless the whole entry was a param ref (then a string). */
318
342
  const entry = state[key];
319
- if (!entry || typeof entry !== "object") {
343
+ if (!isJsonObject(entry)) {
320
344
  return;
321
345
  }
346
+ const body = { ...entry };
347
+ if (docBase) {
348
+ body.$base = docBase;
349
+ }
322
350
  try {
323
- state[key] = await platform.resolveClass!({
324
- ...(entry as Record<string, unknown>),
325
- ...(docBase ? { $base: docBase } : {}),
326
- });
351
+ /* SAFETY: the backend answers with the class's resolved JSON value (no `$prototype`), which
352
+ the runtime reads as a naked-value state entry, so it is a JxStateDefinition. */
353
+ state[key] = (await resolveClass.call(platform, body)) as JxStateDefinition;
327
354
  } catch (error) {
328
355
  console.warn(`page-params: failed to resolve state.${key} for preview:`, error);
329
356
  }
@@ -332,22 +359,28 @@ export async function resolveParamBoundState(
332
359
  }
333
360
 
334
361
  /**
335
- * @param {unknown} node
362
+ * @param {JsonValue} node
336
363
  * @param {Record<string, string>} params
337
- * @returns {unknown} — a rebuilt copy with matched param refs replaced by literals
364
+ * @returns {JsonValue} — a rebuilt copy with matched param refs replaced by literals
338
365
  */
339
- function substituteParamRefs(node: unknown, params: Record<string, string>): unknown {
366
+ function substituteParamRefs(node: JsonValue, params: Record<string, string>): JsonValue {
340
367
  const replaced = paramRefValue(node, params);
341
368
  if (replaced !== null) {
342
369
  return replaced;
343
370
  }
344
- if (!node || typeof node !== "object") {
345
- return node;
346
- }
347
371
  if (Array.isArray(node)) {
348
372
  return node.map((item) => substituteParamRefs(item, params));
349
373
  }
350
- const out: Record<string, unknown> = {};
374
+ return isJsonObject(node) ? substituteObjectRefs(node, params) : node;
375
+ }
376
+
377
+ /**
378
+ * @param {JsonObject} node
379
+ * @param {Record<string, string>} params
380
+ * @returns {JsonObject} — a rebuilt copy of every member, param refs replaced by literals
381
+ */
382
+ function substituteObjectRefs(node: JsonObject, params: Record<string, string>): JsonObject {
383
+ const out: JsonObject = {};
351
384
  for (const [key, value] of Object.entries(node)) {
352
385
  out[key] = substituteParamRefs(value, params);
353
386
  }
@@ -358,17 +391,13 @@ function substituteParamRefs(node: unknown, params: Record<string, string>): unk
358
391
  * The chosen literal for a `{ "$ref": "#/$params/<name>" }` value, or null when the value is not a
359
392
  * param ref (or no value was chosen for it).
360
393
  *
361
- * @param {unknown} value
394
+ * @param {JsonValue} value
362
395
  * @param {Record<string, string>} params
363
396
  * @returns {string | null}
364
397
  */
365
- function paramRefValue(value: unknown, params: Record<string, string>) {
366
- if (!value || typeof value !== "object" || Array.isArray(value)) {
367
- return null;
368
- }
369
- const ref = (value as { $ref?: unknown }).$ref;
370
- if (typeof ref !== "string" || !ref.startsWith("#/$params/")) {
398
+ function paramRefValue(value: JsonValue, params: Record<string, string>) {
399
+ if (!isRef(value) || !value.$ref.startsWith("#/$params/")) {
371
400
  return null;
372
401
  }
373
- return params[ref.slice("#/$params/".length)] ?? null;
402
+ return params[value.$ref.slice("#/$params/".length)] ?? null;
374
403
  }
@@ -42,6 +42,7 @@ import { disposeActivitySurface, mountActivitySurface } from "../surfaces/panel-
42
42
  import { reactive } from "../reactivity";
43
43
  import { now } from "../services/clock";
44
44
  import { notify } from "../services/notify";
45
+ import type { NotifyOptions } from "../services/notify";
45
46
  import { registerPanel } from "./panel-registry";
46
47
  import type { PanelBody } from "./panel-registry";
47
48
  import type {
@@ -189,7 +190,7 @@ export interface ActivityHandle {
189
190
  * @returns {ActivityHandle}
190
191
  */
191
192
  export function beginActivity(options: ActivityOptions): ActivityHandle {
192
- const entry: ActivityEntry = {
193
+ const fields = {
193
194
  cancellable: options.cancel !== undefined,
194
195
  endedAt: null,
195
196
  expanded: false,
@@ -200,8 +201,9 @@ export function beginActivity(options: ActivityOptions): ActivityHandle {
200
201
  status: options.status ?? "",
201
202
  steps: (options.steps ?? []).map((label) => ({ label, state: "pending" as const })),
202
203
  title: options.title,
203
- ...(options.source === undefined ? {} : { source: options.source }),
204
- };
204
+ } satisfies ActivityEntry;
205
+ const entry: ActivityEntry =
206
+ options.source === undefined ? fields : { ...fields, source: options.source };
205
207
  if (options.cancel) {
206
208
  _cancels.set(entry.id, options.cancel);
207
209
  }
@@ -209,6 +211,7 @@ export function beginActivity(options: ActivityOptions): ActivityHandle {
209
211
  // The PROXY, not the literal: writing through the raw object a `reactive()` array was handed
210
212
  // Skips every effect depending on it, which is the one bug that would make a running operation
211
213
  // Look frozen. Read back before anything is retired, so the reference is unambiguous.
214
+ // SAFETY: `activities.push(entry)` just above guarantees the array has a last element.
212
215
  const live = activities.at(-1) as ActivityEntry;
213
216
  retireOldest();
214
217
 
@@ -243,12 +246,17 @@ export function beginActivity(options: ActivityOptions): ActivityHandle {
243
246
  }
244
247
  const detail = live.log.join("\n");
245
248
  finish("failed", message);
246
- notify.error(message, {
247
- source: live.source ?? live.title,
248
- ...(detail === "" ? {} : { detail }),
249
- ...(opts.action === undefined ? {} : { action: opts.action }),
250
- ...(opts.path === undefined ? {} : { path: opts.path }),
251
- });
249
+ const notice: NotifyOptions = { source: live.source ?? live.title };
250
+ if (detail !== "") {
251
+ notice.detail = detail;
252
+ }
253
+ if (opts.action !== undefined) {
254
+ notice.action = opts.action;
255
+ }
256
+ if (opts.path !== undefined) {
257
+ notice.path = opts.path;
258
+ }
259
+ notify.error(message, notice);
252
260
  },
253
261
  id: live.id,
254
262
  log(chunk: string) {
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * Attached-context.js — the composer's "attach context" message-content convention.
3
3
  *
4
- * Attached context (current page, selected element) is embedded into the user message
5
- * content after a delimiter line: it's the only channel the LLM sees (the streaming
6
- * payload carries message content only) and it persists with the session for free.
7
- * The chat view splits the content back apart to show chips instead of the raw block.
4
+ * Attached context (current page, selected element) is embedded into the user message content after
5
+ * a delimiter line: it's the only channel the LLM sees (the streaming payload carries message
6
+ * content only) and it persists with the session for free. The chat view splits the content back
7
+ * apart to show chips instead of the raw block.
8
8
  *
9
- * The delimiter is a soft convention — a model echoing it would at worst render stray
10
- * chips (no security impact; assistant markdown is sanitized separately).
9
+ * The delimiter is a soft convention — a model echoing it would at worst render stray chips (no
10
+ * security impact; assistant markdown is sanitized separately).
11
11
  *
12
12
  * @license MIT
13
13
  */
@@ -36,8 +36,14 @@ export function buildMessageWithContext(text: string, chips: ContextChip[]): str
36
36
  return `${text}\n\n${ATTACHED_CONTEXT_DELIMITER}\n${lines}`;
37
37
  }
38
38
 
39
+ /** A user message split into its typed body and its attached-context lines. */
40
+ export interface SplitMessage {
41
+ body: string;
42
+ contextLines: string[];
43
+ }
44
+
39
45
  /** Split a user message back into its typed body and any attached-context lines. */
40
- export function splitAttachedContext(content: string): { body: string; contextLines: string[] } {
46
+ export function splitAttachedContext(content: string): SplitMessage {
41
47
  const idx = content.indexOf(`\n\n${ATTACHED_CONTEXT_DELIMITER}\n`);
42
48
  if (idx === -1) {
43
49
  return { body: content, contextLines: [] };