@jxsuite/studio 6.1.0 → 6.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (645) hide show
  1. package/dist/chunks/2020-f2gkpy8d.js +4 -0
  2. package/dist/chunks/{action-group-2mqby73c.js → action-group-4aan7g6g.js} +3 -3
  3. package/dist/chunks/adapter-4912g339.js +4 -0
  4. package/dist/chunks/cf-account-picker-wccaenh6.js +4 -0
  5. package/dist/chunks/cf-settings-br6105tr.js +4 -0
  6. package/dist/chunks/color-28ksk2qm.js +4 -0
  7. package/dist/chunks/color-area-0fj8a4ga.js +4 -0
  8. package/dist/chunks/color-field-xch8kx2g.js +4 -0
  9. package/dist/chunks/color-slider-jxd8v350.js +4 -0
  10. package/dist/chunks/combobox-p0efwjke.js +4 -0
  11. package/dist/chunks/components-db68vsn7.js +4 -0
  12. package/dist/chunks/content-source-1449qesq.js +4 -0
  13. package/dist/chunks/convert-to-repeater-5h457egj.js +4 -0
  14. package/dist/chunks/dialog-c4x05vyx.js +4 -0
  15. package/dist/chunks/editor-x9jn86a7.js +4 -0
  16. package/dist/chunks/entry-commands-may24cpt.js +4 -0
  17. package/dist/chunks/extension-sections-pvr14vxr.js +4 -0
  18. package/dist/chunks/file-ops-x9v54pcj.js +4 -0
  19. package/dist/chunks/files-j3knqf0s.js +4 -0
  20. package/dist/chunks/format-host-tyre2trb.js +4 -0
  21. package/dist/chunks/fs-events-64ma9htc.js +4 -0
  22. package/dist/chunks/git-panel-84ps5dex.js +4 -0
  23. package/dist/chunks/grid-view-d2wq9ezg.js +51 -0
  24. package/dist/chunks/icons-pnfz478q.js +4 -0
  25. package/dist/chunks/iframe-entry-fvbk89gm.js +5 -0
  26. package/dist/chunks/iframe-entry-jdcktez8.js +5 -0
  27. package/dist/chunks/iframe-entry-x0ygf2yr.js +5 -0
  28. package/dist/chunks/iframe-entry-zap785cw.js +5 -0
  29. package/dist/chunks/iframe-host-ck6vejt5.js +4 -0
  30. package/dist/chunks/index-b8xw3vy9.js +4 -0
  31. package/dist/chunks/{index-gybvv7a6.js → index-zpjmzqfk.js} +3 -3
  32. package/dist/chunks/{javascript-rnvdp3k4.js → javascript-m54mnwp6.js} +3 -3
  33. package/dist/chunks/jsonMode-w15cmrcm.js +13 -0
  34. package/dist/chunks/jx-validate-at3zn8wa.js +4 -0
  35. package/dist/chunks/layers-h4xp1pss.js +4 -0
  36. package/dist/chunks/layers-panel-m5hw1d7g.js +4 -0
  37. package/dist/chunks/listbox-e74qjyq6.js +4 -0
  38. package/dist/chunks/lit-html-8t8t3dnr.js +4 -0
  39. package/dist/chunks/media-picker-2cweexc5.js +4 -0
  40. package/dist/chunks/menu-n6yzswmy.js +4 -0
  41. package/dist/chunks/menu-ynw13y0s.js +4 -0
  42. package/dist/chunks/monaco-binding-7gx83x3r.js +4 -0
  43. package/dist/chunks/monaco-buffer-qzxn567r.js +4 -0
  44. package/dist/chunks/monaco-setup-gxf6656g.js +4 -0
  45. package/dist/chunks/notify-cj5zbrs2.js +4 -0
  46. package/dist/chunks/number-field-y62xq0ty.js +4 -0
  47. package/dist/chunks/parse-b7ddhr8m.js +4 -0
  48. package/dist/chunks/platform-3dfws9js.js +4 -0
  49. package/dist/chunks/popover-jt2gxmzs.js +4 -0
  50. package/dist/chunks/publish-panel-1gvxbj21.js +4 -0
  51. package/dist/chunks/quick-search-0dajrwqg.js +4 -0
  52. package/dist/chunks/references-49qgt404.js +4 -0
  53. package/dist/chunks/right-panel-jm1bwe53.js +4 -0
  54. package/dist/chunks/section-registry-6kwc4fky.js +4 -0
  55. package/dist/chunks/select-rzds841e.js +4 -0
  56. package/dist/chunks/split-n2gfpm5m.js +4 -0
  57. package/dist/chunks/{studio-5g0ag7c0.js → studio-0q988f9w.js} +3 -3
  58. package/dist/chunks/studio-0rt52vpq.js +5 -0
  59. package/dist/chunks/studio-18vgbhs5.js +5 -0
  60. package/dist/chunks/{studio-pxg4ap1e.js → studio-1fxkaaea.js} +4 -4
  61. package/dist/chunks/studio-24mccdrj.js +5 -0
  62. package/dist/chunks/studio-2eh507zk.js +9 -0
  63. package/dist/chunks/studio-2hcbccfv.js +5 -0
  64. package/dist/chunks/studio-2j1cb95x.js +5 -0
  65. package/dist/chunks/studio-2jbs3rxv.js +5 -0
  66. package/dist/chunks/{studio-qbj760tx.js → studio-485046te.js} +7 -7
  67. package/dist/chunks/studio-4h8k4dw9.js +5 -0
  68. package/dist/chunks/studio-5f6n18kx.js +5 -0
  69. package/dist/chunks/studio-5gthpky6.js +5 -0
  70. package/dist/chunks/studio-5ve6bbep.js +5 -0
  71. package/dist/chunks/studio-6ep3js6b.js +9 -0
  72. package/dist/chunks/studio-6wkmf3wz.js +9 -0
  73. package/dist/chunks/studio-841rf3cg.js +5 -0
  74. package/dist/chunks/studio-8gmwgheg.js +5 -0
  75. package/dist/chunks/studio-8qm0ep50.js +5 -0
  76. package/dist/chunks/{studio-anyrgzvb.js → studio-90pq9km1.js} +4 -4
  77. package/dist/chunks/studio-924p1tm1.js +6 -0
  78. package/dist/chunks/{studio-v2bvmbjj.js → studio-a3g98wjr.js} +4 -4
  79. package/dist/chunks/studio-a3shpz9y.js +5 -0
  80. package/dist/chunks/studio-amsbaaar.js +6 -0
  81. package/dist/chunks/studio-at5spjbc.js +7 -0
  82. package/dist/chunks/studio-b2xv945e.js +5 -0
  83. package/dist/chunks/studio-bn5nkafw.js +5 -0
  84. package/dist/chunks/studio-bw6q5xjf.js +9 -0
  85. package/dist/chunks/studio-c7q0t9x1.js +5 -0
  86. package/dist/chunks/studio-camnhc96.js +6 -0
  87. package/dist/chunks/studio-cffqvnzd.js +5 -0
  88. package/dist/chunks/studio-d81xfh1g.js +5 -0
  89. package/dist/chunks/studio-dgz8d0c1.js +5 -0
  90. package/dist/chunks/studio-efvfrsf8.js +5 -0
  91. package/dist/chunks/studio-er30bpcx.js +5 -0
  92. package/dist/chunks/studio-ezscgr64.js +5 -0
  93. package/dist/chunks/studio-ffrrncvz.js +5 -0
  94. package/dist/chunks/studio-fpphgn8y.js +10 -0
  95. package/dist/chunks/studio-j1kvhdjk.js +4 -0
  96. package/dist/chunks/{studio-txjjzrsm.js → studio-j430n16g.js} +5 -5
  97. package/dist/chunks/studio-jjkg84nj.js +5 -0
  98. package/dist/chunks/studio-m0q32ars.js +4 -0
  99. package/dist/chunks/studio-m6bdst11.js +5 -0
  100. package/dist/chunks/studio-nv2cptd4.js +64 -0
  101. package/dist/chunks/studio-nwfrc98n.js +5 -0
  102. package/dist/chunks/studio-p1wgvp7r.js +5 -0
  103. package/dist/chunks/studio-pag2wncm.js +5 -0
  104. package/dist/chunks/studio-qvanvzfd.js +5 -0
  105. package/dist/chunks/studio-qwa64kt7.js +5 -0
  106. package/dist/chunks/studio-rk1zc4x3.js +928 -0
  107. package/dist/chunks/studio-se2r3ptc.js +5 -0
  108. package/dist/chunks/studio-sg2a0dh0.js +5 -0
  109. package/dist/chunks/studio-tjzjhe68.js +5 -0
  110. package/dist/chunks/{studio-0x3jyb8r.js → studio-tq0rtfwj.js} +4 -4
  111. package/dist/chunks/{studio-cpxkgjrj.js → studio-v0jzqdjm.js} +4 -4
  112. package/dist/chunks/studio-v2w7q8r1.js +7 -0
  113. package/dist/chunks/studio-v5vjq1h0.js +4 -0
  114. package/dist/chunks/studio-v8aga3vp.js +14 -0
  115. package/dist/chunks/studio-vfcdrfmv.js +5 -0
  116. package/dist/chunks/studio-vmfkgdjf.js +5 -0
  117. package/dist/chunks/studio-wt1816jj.js +5 -0
  118. package/dist/chunks/studio-wz73q5kq.js +4 -0
  119. package/dist/chunks/studio-y04qtxvp.js +7 -0
  120. package/dist/chunks/studio-y21g8zzg.js +5 -0
  121. package/dist/chunks/studio-y64hrt8p.js +12 -0
  122. package/dist/chunks/studio-ynn90f58.js +16 -0
  123. package/dist/chunks/studio-yxz682sx.js +5 -0
  124. package/dist/chunks/studio-zp7snvkq.js +5 -0
  125. package/dist/chunks/studio-zq4z6tm6.js +5 -0
  126. package/dist/chunks/swatch-group-ewh24n1f.js +4 -0
  127. package/dist/chunks/tabs-f5cw3tgp.js +4 -0
  128. package/dist/chunks/textfield-wewc8rq2.js +4 -0
  129. package/dist/chunks/toast-c9fn075p.js +4 -0
  130. package/dist/chunks/toast-host-ke5z4ng7.js +4 -0
  131. package/dist/chunks/{toolbar-2nnzqhrj.js → toolbar-44cm5cta.js} +3 -3
  132. package/dist/chunks/tooltip-5v8ngwj2.js +4 -0
  133. package/dist/chunks/tree-mdq3v5cw.js +4 -0
  134. package/dist/chunks/tsMode-sf49ee9x.js +14 -0
  135. package/dist/chunks/workspace-jtfahpee.js +4 -0
  136. package/dist/chunks/ws-client-nze0k6mv.js +4 -0
  137. package/dist/iframe-entry.js +16 -16
  138. package/dist/manifest.json +63 -63
  139. package/dist/studio.js +98 -98
  140. package/dist/workers/ts.worker.js +3 -3
  141. package/package.json +11 -11
  142. package/src/about/about-modal.ts +4 -3
  143. package/src/account/action-flow.ts +45 -38
  144. package/src/account-status.ts +7 -2
  145. package/src/browse/library-layouts.ts +8 -5
  146. package/src/browse/library-model.ts +18 -6
  147. package/src/browse/library-pane.ts +37 -21
  148. package/src/browse/library-preview.ts +14 -9
  149. package/src/browse/library-source.ts +1 -1
  150. package/src/canvas/asset-refs.ts +24 -9
  151. package/src/canvas/asset-resolve.ts +19 -23
  152. package/src/canvas/canvas-helpers.ts +7 -6
  153. package/src/canvas/canvas-live-render.ts +44 -53
  154. package/src/canvas/canvas-patcher.ts +30 -30
  155. package/src/canvas/canvas-perf.ts +11 -5
  156. package/src/canvas/canvas-render.ts +66 -42
  157. package/src/canvas/canvas-surface.ts +5 -3
  158. package/src/canvas/canvas-utils.ts +163 -64
  159. package/src/canvas/dialog-path.ts +9 -4
  160. package/src/canvas/dialog-state.ts +1 -2
  161. package/src/canvas/diff-marks.ts +9 -16
  162. package/src/canvas/diff-toolbar.ts +8 -7
  163. package/src/canvas/edit-width-drag.ts +4 -1
  164. package/src/canvas/edit-width.ts +1 -3
  165. package/src/canvas/iframe-channel.ts +27 -13
  166. package/src/canvas/iframe-drop.ts +13 -12
  167. package/src/canvas/iframe-editable-root.ts +29 -16
  168. package/src/canvas/iframe-entry.ts +80 -63
  169. package/src/canvas/iframe-eval.ts +73 -49
  170. package/src/canvas/iframe-host.ts +203 -118
  171. package/src/canvas/iframe-inline-edit.ts +69 -32
  172. package/src/canvas/iframe-insert.ts +5 -4
  173. package/src/canvas/iframe-interaction.ts +37 -26
  174. package/src/canvas/iframe-overlay.ts +1 -1
  175. package/src/canvas/iframe-patch.ts +18 -15
  176. package/src/canvas/iframe-position.ts +12 -6
  177. package/src/canvas/iframe-protocol.ts +15 -16
  178. package/src/canvas/iframe-render.ts +41 -36
  179. package/src/canvas/iframe-slash.ts +24 -11
  180. package/src/canvas/iframe-subtree.ts +6 -2
  181. package/src/canvas/path-mapping.ts +19 -12
  182. package/src/canvas/popover-path.ts +7 -3
  183. package/src/canvas/popover-state.ts +1 -2
  184. package/src/canvas/serialize-scope.ts +13 -5
  185. package/src/canvas/stage-scrollbar.ts +2 -1
  186. package/src/canvas/surface-registry.ts +21 -3
  187. package/src/collab/collab-commands.ts +7 -2
  188. package/src/collab/collab-session.ts +84 -45
  189. package/src/collab/collab-state.ts +4 -3
  190. package/src/collab/monaco-binding.ts +16 -13
  191. package/src/collab/monaco-cursors.ts +5 -2
  192. package/src/commands/budget.ts +3 -3
  193. package/src/commands/command-args.ts +103 -71
  194. package/src/commands/context.ts +22 -20
  195. package/src/commands/defaults.ts +4 -1
  196. package/src/commands/keymap.ts +47 -43
  197. package/src/commands/levels.ts +3 -3
  198. package/src/commands/live-context.ts +10 -8
  199. package/src/commands/reference.ts +2 -1
  200. package/src/commands/registry.ts +12 -10
  201. package/src/commands/run-reported.ts +15 -10
  202. package/src/component-props.ts +46 -30
  203. package/src/content/collection-match.ts +5 -4
  204. package/src/content/draft-state.ts +4 -3
  205. package/src/content/entry-commands.ts +3 -2
  206. package/src/content/entry-editor.ts +29 -17
  207. package/src/content/entry-fields.ts +12 -7
  208. package/src/content/entry-model.ts +21 -12
  209. package/src/editor/canvas-context-menu.ts +1 -2
  210. package/src/editor/canvas-slash-bridge.ts +3 -6
  211. package/src/editor/content-slice.ts +16 -14
  212. package/src/editor/context-menu.ts +35 -22
  213. package/src/editor/convert-targets.ts +30 -35
  214. package/src/editor/convert-to-component.ts +11 -5
  215. package/src/editor/convert-to-repeater.ts +34 -22
  216. package/src/editor/editable-tags.ts +17 -2
  217. package/src/editor/file-drop-action.ts +21 -22
  218. package/src/editor/inline-edit-apply.ts +35 -17
  219. package/src/editor/inline-edit.ts +66 -50
  220. package/src/editor/inline-format.ts +59 -56
  221. package/src/editor/inline-link.ts +40 -15
  222. package/src/editor/insert-zone-action.ts +1 -1
  223. package/src/editor/merge-tags.ts +58 -19
  224. package/src/editor/repeater-scope.ts +39 -28
  225. package/src/editor/shortcuts.ts +87 -47
  226. package/src/editor/slash-menu.ts +1 -6
  227. package/src/files/asset-versions.ts +4 -4
  228. package/src/files/components.ts +15 -10
  229. package/src/files/elements.ts +5 -6
  230. package/src/files/file-ops.ts +77 -36
  231. package/src/files/files.ts +90 -95
  232. package/src/files/media-meta.ts +2 -1
  233. package/src/files/media-paths.ts +6 -1
  234. package/src/files/serialize-document.ts +2 -2
  235. package/src/format/constraints.ts +1 -1
  236. package/src/format/convert-file.ts +27 -13
  237. package/src/format/format-choices.ts +2 -1
  238. package/src/format/format-host.ts +76 -50
  239. package/src/github/github-auth-status.ts +27 -3
  240. package/src/github/github-auth.ts +19 -9
  241. package/src/github/github-publish.ts +24 -20
  242. package/src/grid/cell-editors.ts +46 -31
  243. package/src/grid/cell-popovers.ts +5 -3
  244. package/src/grid/edit-buffer.ts +10 -9
  245. package/src/grid/grid-controller.ts +20 -22
  246. package/src/grid/grid-layout.ts +21 -5
  247. package/src/grid/grid-open.ts +3 -6
  248. package/src/grid/grid-panel.ts +11 -4
  249. package/src/grid/grid-source.ts +8 -8
  250. package/src/grid/grid-view.ts +14 -17
  251. package/src/grid/redirects-grid.ts +14 -5
  252. package/src/grid/redirects.ts +16 -14
  253. package/src/grid/schema-columns.ts +25 -19
  254. package/src/grid/sources/connector-source.ts +47 -20
  255. package/src/grid/sources/content-source.ts +25 -24
  256. package/src/grid/sources/csv-file-source.ts +2 -2
  257. package/src/grid/tabulator-tables.d.ts +55 -34
  258. package/src/hosting/stage.ts +7 -7
  259. package/src/i18n/i18n-commands.ts +1 -2
  260. package/src/media/media-pane.ts +4 -1
  261. package/src/new-project/add-repo-modal.ts +20 -19
  262. package/src/new-project/import-tab.ts +10 -14
  263. package/src/new-project/location-fields.ts +2 -1
  264. package/src/new-project/new-project-modal.ts +12 -9
  265. package/src/packages/jxsuite-update.ts +4 -3
  266. package/src/packages/pull-package-sync.ts +26 -25
  267. package/src/page-params.ts +97 -68
  268. package/src/panels/activity-panel.ts +17 -9
  269. package/src/panels/ai-chat/attached-context.ts +13 -7
  270. package/src/panels/ai-chat/chat-view.ts +80 -73
  271. package/src/panels/ai-chat/composer.ts +30 -33
  272. package/src/panels/ai-chat/sessions-view.ts +1 -2
  273. package/src/panels/ai-panel.ts +23 -20
  274. package/src/panels/block-action-bar.ts +46 -35
  275. package/src/panels/bottom-dock.ts +5 -3
  276. package/src/panels/canvas-dnd-bridge.ts +31 -24
  277. package/src/panels/data-explorer.ts +62 -25
  278. package/src/panels/data-grid.ts +14 -11
  279. package/src/panels/dnd.ts +108 -118
  280. package/src/panels/editors.ts +55 -22
  281. package/src/panels/elements-panel.ts +10 -3
  282. package/src/panels/events-panel.ts +84 -69
  283. package/src/panels/formula-workspace.ts +76 -51
  284. package/src/panels/frontmatter-fields.ts +24 -19
  285. package/src/panels/frontmatter-panel.ts +44 -34
  286. package/src/panels/git-diff-open.ts +4 -4
  287. package/src/panels/git-panel.ts +49 -61
  288. package/src/panels/head-panel.ts +131 -111
  289. package/src/panels/i18n-panel.ts +10 -3
  290. package/src/panels/imports-panel.ts +23 -47
  291. package/src/panels/jump-bar.ts +48 -29
  292. package/src/panels/layers-panel.ts +97 -74
  293. package/src/panels/left-panel.ts +3 -3
  294. package/src/panels/pane-context.ts +31 -22
  295. package/src/panels/pane-grid.ts +49 -20
  296. package/src/panels/panel-registry.ts +22 -37
  297. package/src/panels/properties-panel.ts +175 -121
  298. package/src/panels/quick-search.ts +53 -31
  299. package/src/panels/right-panel.ts +3 -3
  300. package/src/panels/seo-modal.ts +13 -17
  301. package/src/panels/settings-menu.ts +15 -15
  302. package/src/panels/signals-panel.ts +153 -131
  303. package/src/panels/statement-editor.ts +230 -140
  304. package/src/panels/style-panel.ts +254 -216
  305. package/src/panels/style-utils.ts +114 -51
  306. package/src/panels/stylebook-doc.ts +57 -54
  307. package/src/panels/stylebook-layers-panel.ts +9 -9
  308. package/src/panels/stylebook-panel.ts +13 -17
  309. package/src/panels/tab-drop.ts +27 -11
  310. package/src/panels/tab-strip.ts +36 -26
  311. package/src/platform-errors.ts +57 -43
  312. package/src/platform.ts +58 -30
  313. package/src/platforms/cloud.ts +345 -175
  314. package/src/platforms/default-platform.ts +10 -4
  315. package/src/platforms/devserver.ts +174 -127
  316. package/src/platforms/read-batcher.ts +16 -8
  317. package/src/project-list.ts +2 -1
  318. package/src/publish/deploy-checklist.ts +8 -2
  319. package/src/publish/pages-service.ts +28 -13
  320. package/src/publish/publish-commands.ts +5 -4
  321. package/src/publish/publish-panel.ts +10 -6
  322. package/src/recent-projects.ts +15 -8
  323. package/src/resize-edges.ts +26 -36
  324. package/src/services/a11y-report.ts +26 -19
  325. package/src/services/agent-seed.ts +23 -11
  326. package/src/services/ai-ask.ts +9 -12
  327. package/src/services/ai-command-tools.ts +68 -62
  328. package/src/services/ai-import-tools.ts +80 -67
  329. package/src/services/ai-models.ts +17 -13
  330. package/src/services/ai-project-tools.ts +68 -32
  331. package/src/services/ai-session-store.ts +19 -10
  332. package/src/services/ai-system-prompt.ts +46 -20
  333. package/src/services/ai-tools.ts +71 -27
  334. package/src/services/ai-write-report.ts +20 -12
  335. package/src/services/ai-writes.ts +4 -4
  336. package/src/services/automation.ts +58 -31
  337. package/src/services/cem-export.ts +149 -58
  338. package/src/services/clock.ts +6 -1
  339. package/src/services/code-services.ts +37 -31
  340. package/src/services/context-manager.ts +14 -10
  341. package/src/services/context-resolver.ts +20 -8
  342. package/src/services/data-service.ts +19 -15
  343. package/src/services/directory-picker.ts +18 -12
  344. package/src/services/document-assistant.ts +39 -19
  345. package/src/services/gated-registry.ts +10 -6
  346. package/src/services/harness/chat-reducer.ts +23 -1
  347. package/src/services/import-client.ts +91 -38
  348. package/src/services/import-seed.ts +8 -2
  349. package/src/services/jx-validate.ts +28 -31
  350. package/src/services/live-preview.ts +0 -0
  351. package/src/services/live-surfaces.ts +6 -3
  352. package/src/services/model-uri.ts +10 -2
  353. package/src/services/module-preloads.ts +12 -8
  354. package/src/services/monaco-buffer.ts +43 -24
  355. package/src/services/monaco-lazy.ts +7 -8
  356. package/src/services/monaco-setup.ts +23 -16
  357. package/src/services/notify.ts +44 -17
  358. package/src/services/popover-report.ts +25 -10
  359. package/src/services/preview-eval.ts +20 -8
  360. package/src/services/profile.ts +13 -6
  361. package/src/services/project-path.ts +13 -10
  362. package/src/services/references.ts +0 -0
  363. package/src/services/render-critic.ts +8 -7
  364. package/src/services/settings/kernel.ts +13 -4
  365. package/src/services/settings/write-queue.ts +9 -9
  366. package/src/services/token-lint.ts +12 -10
  367. package/src/services/tool-executor.ts +17 -5
  368. package/src/services/tool-outcomes.ts +44 -24
  369. package/src/services/trusted-types.ts +24 -7
  370. package/src/settings/contexts-section.ts +11 -8
  371. package/src/settings/contributed-section.ts +79 -60
  372. package/src/settings/css-vars-editor.ts +37 -16
  373. package/src/settings/defs-editor.ts +38 -35
  374. package/src/settings/extension-rows.ts +16 -8
  375. package/src/settings/extension-sections.ts +23 -13
  376. package/src/settings/extensions-section.ts +4 -1
  377. package/src/settings/general-settings.ts +11 -8
  378. package/src/settings/locales-section.ts +20 -12
  379. package/src/settings/preferences-dialog.ts +9 -6
  380. package/src/settings/preferences-keymap.ts +7 -5
  381. package/src/settings/preferences-sections.ts +11 -5
  382. package/src/settings/project-sections.ts +1 -1
  383. package/src/settings/schema-field-ui.ts +9 -0
  384. package/src/settings/settings-document.ts +5 -5
  385. package/src/shell/tree.ts +6 -5
  386. package/src/shell.ts +104 -81
  387. package/src/site-context.ts +37 -22
  388. package/src/state.ts +41 -49
  389. package/src/store.ts +54 -34
  390. package/src/studio.ts +39 -77
  391. package/src/style/live-preview.ts +1 -1
  392. package/src/style/project-styles.ts +6 -7
  393. package/src/style/token-ref.ts +5 -4
  394. package/src/surfaces/about.ts +18 -19
  395. package/src/surfaces/add-repo.ts +17 -19
  396. package/src/surfaces/ai-chat.ts +31 -36
  397. package/src/surfaces/ai-credentials-form.ts +6 -16
  398. package/src/surfaces/ai-managed-connect.ts +3 -4
  399. package/src/surfaces/ai-model-picker.ts +3 -5
  400. package/src/surfaces/block-action-bar.ts +22 -11
  401. package/src/surfaces/boot-failure.ts +4 -5
  402. package/src/surfaces/bottom-dock.ts +9 -18
  403. package/src/surfaces/canvas-stage.ts +12 -11
  404. package/src/surfaces/cf-account-picker.ts +17 -18
  405. package/src/surfaces/commandbar.ts +14 -9
  406. package/src/surfaces/convert-repeater.ts +17 -19
  407. package/src/surfaces/data-actions.ts +9 -7
  408. package/src/surfaces/dialog.ts +26 -28
  409. package/src/surfaces/diff-toolbar.ts +9 -7
  410. package/src/surfaces/doc-header.ts +10 -19
  411. package/src/surfaces/empty-state.ts +7 -10
  412. package/src/surfaces/entry-editor.ts +14 -11
  413. package/src/surfaces/expression-editor.ts +11 -25
  414. package/src/surfaces/files-panel.ts +27 -14
  415. package/src/surfaces/formula-palette.ts +4 -5
  416. package/src/surfaces/git-panel.ts +7 -15
  417. package/src/surfaces/github-auth.ts +16 -20
  418. package/src/surfaces/github-publish.ts +17 -22
  419. package/src/surfaces/grid-cell.ts +30 -31
  420. package/src/surfaces/grid-open.ts +10 -14
  421. package/src/surfaces/grid-panel.ts +13 -9
  422. package/src/surfaces/grid-replace.ts +13 -13
  423. package/src/surfaces/grid-views.ts +15 -18
  424. package/src/surfaces/inspector-dock.ts +13 -12
  425. package/src/surfaces/jump-bar.ts +5 -6
  426. package/src/surfaces/jxsuite-update.ts +16 -22
  427. package/src/surfaces/library-pane.ts +25 -20
  428. package/src/surfaces/logic-panel.ts +17 -30
  429. package/src/surfaces/logic-workspace.ts +13 -15
  430. package/src/surfaces/media-browser.ts +11 -10
  431. package/src/surfaces/media-field.ts +4 -5
  432. package/src/surfaces/media-pane.ts +8 -7
  433. package/src/surfaces/menu.ts +29 -23
  434. package/src/surfaces/navigator-dock.ts +11 -12
  435. package/src/surfaces/new-project.ts +27 -26
  436. package/src/surfaces/pane-context.ts +20 -25
  437. package/src/surfaces/pane-grid.ts +15 -10
  438. package/src/surfaces/panel-activity.ts +5 -6
  439. package/src/surfaces/panel-data.ts +3 -4
  440. package/src/surfaces/panel-deploy-checklist.ts +5 -6
  441. package/src/surfaces/panel-elements.ts +5 -7
  442. package/src/surfaces/panel-i18n.ts +5 -7
  443. package/src/surfaces/panel-imports.ts +6 -13
  444. package/src/surfaces/panel-outline.ts +25 -19
  445. package/src/surfaces/panel-page.ts +11 -18
  446. package/src/surfaces/panel-problems.ts +5 -7
  447. package/src/surfaces/panel-signals.ts +20 -34
  448. package/src/surfaces/panel-stylebook-layers.ts +5 -8
  449. package/src/surfaces/preferences.ts +21 -11
  450. package/src/surfaces/progress-modal.ts +15 -9
  451. package/src/surfaces/properties-panel.json +1 -1
  452. package/src/surfaces/properties-panel.ts +20 -42
  453. package/src/surfaces/publish.ts +18 -18
  454. package/src/surfaces/push-plan.ts +7 -8
  455. package/src/surfaces/rail.json +126 -73
  456. package/src/surfaces/rail.ts +38 -12
  457. package/src/surfaces/reference-field.ts +11 -15
  458. package/src/surfaces/schema-builder.ts +16 -22
  459. package/src/surfaces/schema-form.ts +15 -25
  460. package/src/surfaces/secret-field.ts +9 -6
  461. package/src/surfaces/seo.ts +21 -15
  462. package/src/surfaces/settings-contexts.ts +9 -7
  463. package/src/surfaces/settings-contributed.ts +14 -10
  464. package/src/surfaces/settings-css-vars.ts +5 -12
  465. package/src/surfaces/settings-defs.json +2 -2
  466. package/src/surfaces/settings-defs.ts +17 -21
  467. package/src/surfaces/settings-deploy.ts +8 -15
  468. package/src/surfaces/settings-extensions.ts +5 -6
  469. package/src/surfaces/settings-head.ts +33 -39
  470. package/src/surfaces/settings-locales.ts +8 -20
  471. package/src/surfaces/settings-overview.ts +5 -6
  472. package/src/surfaces/settings-packages.ts +8 -7
  473. package/src/surfaces/settings-pane.ts +9 -18
  474. package/src/surfaces/settings-rawjson.ts +5 -6
  475. package/src/surfaces/shell.ts +1 -2
  476. package/src/surfaces/slash-menu.ts +19 -9
  477. package/src/surfaces/statements.ts +13 -18
  478. package/src/surfaces/statusbar.ts +17 -14
  479. package/src/surfaces/style-panel.ts +18 -31
  480. package/src/surfaces/stylebook-chrome.ts +3 -5
  481. package/src/surfaces/tab-strip.ts +14 -13
  482. package/src/surfaces/target-line.ts +6 -7
  483. package/src/surfaces/welcome.ts +5 -7
  484. package/src/tabs/patch-ops.ts +4 -3
  485. package/src/tabs/project-config.ts +32 -21
  486. package/src/tabs/selection.ts +36 -8
  487. package/src/tabs/tab.ts +52 -41
  488. package/src/tabs/transact.ts +98 -53
  489. package/src/tabs/typing.ts +31 -0
  490. package/src/types.ts +32 -17
  491. package/src/ui/ai-credentials-form.ts +10 -13
  492. package/src/ui/ai-model-picker.ts +3 -3
  493. package/src/ui/cf-account-picker.ts +7 -9
  494. package/src/ui/color-selector.ts +9 -5
  495. package/src/ui/dynamic-slot.ts +7 -8
  496. package/src/ui/expression-editor.ts +112 -105
  497. package/src/ui/form-controls.ts +57 -48
  498. package/src/ui/formula-catalog.ts +239 -230
  499. package/src/ui/formula-chips.ts +33 -18
  500. package/src/ui/layers.ts +44 -31
  501. package/src/ui/media-picker.ts +18 -9
  502. package/src/ui/popover-surface.ts +20 -12
  503. package/src/ui/progress-modal.ts +13 -8
  504. package/src/ui/regions.ts +7 -6
  505. package/src/ui/schema-form.ts +113 -70
  506. package/src/ui/surface.ts +71 -8
  507. package/src/ui/timing.ts +9 -0
  508. package/src/ui/value-source.ts +44 -31
  509. package/src/ui/virtual-window.ts +3 -2
  510. package/src/utils/base64.ts +3 -1
  511. package/src/utils/edit-display.ts +103 -74
  512. package/src/utils/element-selectors.ts +3 -2
  513. package/src/utils/google-fonts.ts +15 -14
  514. package/src/utils/inherited-style.ts +18 -20
  515. package/src/utils/link-target.ts +1 -1
  516. package/src/utils/preview-format.ts +25 -3
  517. package/src/utils/strip-events.ts +49 -22
  518. package/src/utils/studio-utils.ts +29 -14
  519. package/src/view.ts +2 -3
  520. package/src/workspace/pane-derive.ts +10 -12
  521. package/src/workspace/session.ts +53 -43
  522. package/src/workspace/workspace.ts +47 -36
  523. package/dist/chunks/2020-nkxms0ay.js +0 -4
  524. package/dist/chunks/adapter-m948ab5f.js +0 -4
  525. package/dist/chunks/cf-account-picker-n8hr38v7.js +0 -4
  526. package/dist/chunks/cf-settings-356xdtne.js +0 -4
  527. package/dist/chunks/color-area-jqhna8zy.js +0 -4
  528. package/dist/chunks/color-field-embq5ctg.js +0 -4
  529. package/dist/chunks/color-fpezvnkt.js +0 -4
  530. package/dist/chunks/color-slider-1qmw7wqy.js +0 -4
  531. package/dist/chunks/combobox-773hdzyj.js +0 -4
  532. package/dist/chunks/components-yk3t844e.js +0 -4
  533. package/dist/chunks/content-source-bawmyc09.js +0 -4
  534. package/dist/chunks/convert-to-repeater-7wns8kf1.js +0 -4
  535. package/dist/chunks/dialog-mtm9fq5t.js +0 -4
  536. package/dist/chunks/editor-6sc8nacq.js +0 -4
  537. package/dist/chunks/entry-commands-8ay9fh81.js +0 -4
  538. package/dist/chunks/extension-sections-na7rj3nr.js +0 -4
  539. package/dist/chunks/file-ops-gye0qw56.js +0 -4
  540. package/dist/chunks/files-dmc2xvcq.js +0 -4
  541. package/dist/chunks/format-host-t76b53f8.js +0 -4
  542. package/dist/chunks/fs-events-cg4tpz06.js +0 -4
  543. package/dist/chunks/git-panel-yef7bshy.js +0 -4
  544. package/dist/chunks/grid-view-7tt4bxw1.js +0 -51
  545. package/dist/chunks/icons-qbh8akb1.js +0 -4
  546. package/dist/chunks/iframe-entry-f7mqjwpm.js +0 -5
  547. package/dist/chunks/iframe-entry-haw7jkvz.js +0 -5
  548. package/dist/chunks/iframe-entry-z6qrytv3.js +0 -5
  549. package/dist/chunks/iframe-host-tmz30gfp.js +0 -4
  550. package/dist/chunks/index-nag78a9h.js +0 -4
  551. package/dist/chunks/jsonMode-zhwsprqk.js +0 -13
  552. package/dist/chunks/jx-validate-3gbp5nkn.js +0 -4
  553. package/dist/chunks/layers-fvz99859.js +0 -4
  554. package/dist/chunks/layers-panel-gchmbf9p.js +0 -4
  555. package/dist/chunks/listbox-s8fkmnq8.js +0 -4
  556. package/dist/chunks/lit-html-9agdspkt.js +0 -4
  557. package/dist/chunks/media-picker-rhjvyy00.js +0 -4
  558. package/dist/chunks/menu-2e4y9j7b.js +0 -4
  559. package/dist/chunks/menu-37d07z9m.js +0 -4
  560. package/dist/chunks/monaco-binding-2jnhjjvr.js +0 -4
  561. package/dist/chunks/monaco-buffer-rp21359g.js +0 -4
  562. package/dist/chunks/monaco-setup-vhh7gayr.js +0 -4
  563. package/dist/chunks/notify-h3www560.js +0 -4
  564. package/dist/chunks/number-field-gw7sq8rn.js +0 -4
  565. package/dist/chunks/parse-897fvqah.js +0 -4
  566. package/dist/chunks/platform-hz34wcd7.js +0 -4
  567. package/dist/chunks/popover-8htra4er.js +0 -4
  568. package/dist/chunks/publish-panel-exsmjzyj.js +0 -4
  569. package/dist/chunks/quick-search-pgaqeh0m.js +0 -4
  570. package/dist/chunks/references-2cgdxnb8.js +0 -4
  571. package/dist/chunks/right-panel-jf856w5w.js +0 -4
  572. package/dist/chunks/section-registry-jnf8r5gy.js +0 -4
  573. package/dist/chunks/select-n3v7gwas.js +0 -4
  574. package/dist/chunks/split-pff8f3ze.js +0 -4
  575. package/dist/chunks/studio-0f55h9ye.js +0 -5
  576. package/dist/chunks/studio-0sqdhnew.js +0 -12
  577. package/dist/chunks/studio-19x1c75w.js +0 -5
  578. package/dist/chunks/studio-2sqcndak.js +0 -5
  579. package/dist/chunks/studio-3aey7dd3.js +0 -5
  580. package/dist/chunks/studio-3bpdkq2s.js +0 -5
  581. package/dist/chunks/studio-47y6fbpf.js +0 -5
  582. package/dist/chunks/studio-4m3826v2.js +0 -5
  583. package/dist/chunks/studio-4nx2dj1g.js +0 -4
  584. package/dist/chunks/studio-4xv5s47r.js +0 -9
  585. package/dist/chunks/studio-5g4t8v6w.js +0 -5
  586. package/dist/chunks/studio-5py436sf.js +0 -5
  587. package/dist/chunks/studio-77kt594t.js +0 -5
  588. package/dist/chunks/studio-8f87n763.js +0 -10
  589. package/dist/chunks/studio-8mb00b84.js +0 -5
  590. package/dist/chunks/studio-8p51gq2h.js +0 -6
  591. package/dist/chunks/studio-954ds834.js +0 -5
  592. package/dist/chunks/studio-9ft45c83.js +0 -9
  593. package/dist/chunks/studio-a2138x5k.js +0 -7
  594. package/dist/chunks/studio-a9yzstqj.js +0 -5
  595. package/dist/chunks/studio-acdksxx6.js +0 -5
  596. package/dist/chunks/studio-ar8jcf2y.js +0 -5
  597. package/dist/chunks/studio-bmn4mn9j.js +0 -7
  598. package/dist/chunks/studio-e7xxa0sj.js +0 -5
  599. package/dist/chunks/studio-ecaz25vk.js +0 -5
  600. package/dist/chunks/studio-ery42sqr.js +0 -4
  601. package/dist/chunks/studio-fzdywr6p.js +0 -9
  602. package/dist/chunks/studio-g5fmf0c1.js +0 -5
  603. package/dist/chunks/studio-g7nse7zb.js +0 -5
  604. package/dist/chunks/studio-geq1ea6k.js +0 -14
  605. package/dist/chunks/studio-ghkb32r8.js +0 -5
  606. package/dist/chunks/studio-ghrhy2y7.js +0 -5
  607. package/dist/chunks/studio-grawhey1.js +0 -5
  608. package/dist/chunks/studio-h0xgswew.js +0 -5
  609. package/dist/chunks/studio-h9c4p2tx.js +0 -5
  610. package/dist/chunks/studio-jyzj5cxs.js +0 -5
  611. package/dist/chunks/studio-mgx8yhnz.js +0 -64
  612. package/dist/chunks/studio-mpb04y1d.js +0 -6
  613. package/dist/chunks/studio-n17mty64.js +0 -5
  614. package/dist/chunks/studio-nwh2eqsk.js +0 -6
  615. package/dist/chunks/studio-q1h883bt.js +0 -16
  616. package/dist/chunks/studio-q4tv82h7.js +0 -9
  617. package/dist/chunks/studio-qpqa7vk3.js +0 -5
  618. package/dist/chunks/studio-qqz8e5gk.js +0 -5
  619. package/dist/chunks/studio-qvasen3f.js +0 -5
  620. package/dist/chunks/studio-rggdb3hm.js +0 -5
  621. package/dist/chunks/studio-sghy936h.js +0 -4
  622. package/dist/chunks/studio-skprc6ef.js +0 -5
  623. package/dist/chunks/studio-tt2nactf.js +0 -5
  624. package/dist/chunks/studio-tyasmc39.js +0 -5
  625. package/dist/chunks/studio-vk9ezads.js +0 -5
  626. package/dist/chunks/studio-vzacdfsc.js +0 -4
  627. package/dist/chunks/studio-w4c0xmrw.js +0 -5
  628. package/dist/chunks/studio-wfjqhhbk.js +0 -5
  629. package/dist/chunks/studio-wgh5kxpj.js +0 -5
  630. package/dist/chunks/studio-xasj0796.js +0 -5
  631. package/dist/chunks/studio-y78s8r2n.js +0 -5
  632. package/dist/chunks/studio-z8w183sh.js +0 -5
  633. package/dist/chunks/studio-zscd9ty4.js +0 -928
  634. package/dist/chunks/studio-zxp13sss.js +0 -7
  635. package/dist/chunks/studio-zygnmm01.js +0 -5
  636. package/dist/chunks/swatch-group-8qh9a3bm.js +0 -4
  637. package/dist/chunks/tabs-jwthg40w.js +0 -4
  638. package/dist/chunks/textfield-spy3hc77.js +0 -4
  639. package/dist/chunks/toast-4d35zd64.js +0 -4
  640. package/dist/chunks/toast-host-8sjmfed3.js +0 -4
  641. package/dist/chunks/tooltip-fd6g9xy3.js +0 -4
  642. package/dist/chunks/tree-h19v1jfz.js +0 -4
  643. package/dist/chunks/tsMode-gr0m4dzr.js +0 -14
  644. package/dist/chunks/workspace-m15qtcqp.js +0 -4
  645. package/dist/chunks/ws-client-nf61frr1.js +0 -4
@@ -75,7 +75,7 @@ export interface DeployStep {
75
75
 
76
76
  /** The active project's configuration, or null when no project is open. */
77
77
  function currentConfig(): ProjectConfig | null {
78
- return (projectState?.projectConfig as ProjectConfig | undefined) ?? null;
78
+ return projectState?.projectConfig ?? null;
79
79
  }
80
80
 
81
81
  /**
@@ -152,6 +152,11 @@ function repoStep(): DeployStep {
152
152
  };
153
153
  }
154
154
 
155
+ /** The remotes a host's git status actually carries: a host may omit the array altogether. */
156
+ interface ReportedRemotes {
157
+ remotes?: string[] | undefined;
158
+ }
159
+
155
160
  function remoteStep(): DeployStep {
156
161
  const { status } = shell.git;
157
162
  if (status === null || !status.isRepo) {
@@ -165,7 +170,8 @@ function remoteStep(): DeployStep {
165
170
  }
166
171
  // A GitStatus from a host that reports no remotes array is not a repo with remotes — it is a
167
172
  // Host that did not say. Reading through it took the whole status bar down with a TypeError.
168
- if ((status.remotes ?? []).length === 0) {
173
+ const reported: ReportedRemotes = status;
174
+ if ((reported.remotes ?? []).length === 0) {
169
175
  return {
170
176
  command: "git.createGithubRepository",
171
177
  detail: "This repository is local only — nothing outside this machine can build it.",
@@ -10,15 +10,16 @@
10
10
  */
11
11
 
12
12
  import { updateWranglerConfig } from "@jxsuite/create/scaffold";
13
+ import { isFunction } from "@jxsuite/schema/guards";
13
14
  import type { DeployConfig, ProjectConfig } from "@jxsuite/schema/types";
15
+ import type { CfAccountSummary } from "../types";
14
16
  import { getPlatform } from "../platform";
15
17
  import { actIfRequired } from "../account/action-flow";
16
18
  import { updateSiteConfig } from "../site-context";
17
19
 
18
- export interface CfAccount {
19
- id: string;
20
- name: string;
21
- }
20
+ /* A Cloudflare account the connected token can reach is the platform's `CfAccountSummary` row;
21
+ `CfAccount` stays this module's name for it. */
22
+ export type { CfAccountSummary as CfAccount } from "../types";
22
23
 
23
24
  export interface PagesDeploymentInfo {
24
25
  id: string;
@@ -52,7 +53,7 @@ export function platformSupportsPublish(): boolean {
52
53
  // Publishing is not available yet. "Can this host publish?" has a truthful answer before the host
53
54
  // Exists, and it is no.
54
55
  try {
55
- return typeof getPlatform().cfApi === "function";
56
+ return isFunction(getPlatform().cfApi);
56
57
  } catch {
57
58
  return false;
58
59
  }
@@ -69,6 +70,8 @@ async function cfApi<T>(path: string, init?: { method?: string; body?: unknown }
69
70
  throw new Error("This platform cannot reach the Cloudflare API");
70
71
  }
71
72
  try {
73
+ /* SAFETY: every adapter's cfApi resolves to the Cloudflare v4 envelope's `result`, unvalidated,
74
+ and each caller names the shape Cloudflare documents for the endpoint it calls. */
72
75
  return (await api(path, init)) as T;
73
76
  } catch (error) {
74
77
  void actIfRequired(error);
@@ -76,8 +79,8 @@ async function cfApi<T>(path: string, init?: { method?: string; body?: unknown }
76
79
  }
77
80
  }
78
81
 
79
- export async function listAccounts(): Promise<CfAccount[]> {
80
- return cfApi<CfAccount[]>("/accounts");
82
+ export async function listAccounts(): Promise<CfAccountSummary[]> {
83
+ return cfApi<CfAccountSummary[]>("/accounts");
81
84
  }
82
85
 
83
86
  interface PagesProjectWire {
@@ -104,16 +107,19 @@ export async function getPagesProject(
104
107
  * with an install hint.
105
108
  */
106
109
  export async function createPagesProject(opts: ConnectOptions): Promise<PagesProjectWire> {
110
+ const buildConfig: PagesBuildConfigWire = {
111
+ build_command: "bunx jx build",
112
+ destination_dir: "dist",
113
+ };
114
+ if (opts.rootDir) {
115
+ buildConfig.root_dir = opts.rootDir;
116
+ }
107
117
  return cfApi<PagesProjectWire>(`/accounts/${opts.accountId}/pages/projects`, {
108
118
  method: "POST",
109
119
  body: {
110
120
  name: opts.projectName,
111
121
  production_branch: opts.productionBranch,
112
- build_config: {
113
- build_command: "bunx jx build",
114
- destination_dir: "dist",
115
- ...(opts.rootDir ? { root_dir: opts.rootDir } : {}),
116
- },
122
+ build_config: buildConfig,
117
123
  source: {
118
124
  type: "github",
119
125
  config: {
@@ -127,6 +133,13 @@ export async function createPagesProject(opts: ConnectOptions): Promise<PagesPro
127
133
  });
128
134
  }
129
135
 
136
+ /** The `build_config` Cloudflare stores on a GitHub-connected Pages project. */
137
+ interface PagesBuildConfigWire {
138
+ build_command: string;
139
+ destination_dir: string;
140
+ root_dir?: string;
141
+ }
142
+
130
143
  interface DeploymentWire {
131
144
  id: string;
132
145
  url: string;
@@ -205,8 +218,10 @@ export async function connectDeploy(
205
218
  provider: "cloudflare-pages",
206
219
  accountId: opts.accountId,
207
220
  projectName: opts.projectName,
208
- ...(project.subdomain ? { productionUrl: `https://${project.subdomain}` } : {}),
209
221
  };
222
+ if (project.subdomain) {
223
+ deploy.productionUrl = `https://${project.subdomain}`;
224
+ }
210
225
  await writeDeployConfig(config, deploy);
211
226
  return deploy;
212
227
  }
@@ -70,10 +70,11 @@ export async function runDeploy(
70
70
  options: { attempts?: number; delayMs?: number } = {},
71
71
  ): Promise<boolean> {
72
72
  const deploy = currentDeploy();
73
- let cancelled = false;
73
+ // Aborted by the activity's Cancel; the poll loop checks it between attempts.
74
+ const cancellation = new AbortController();
74
75
  const activity = beginActivity({
75
76
  cancel: () => {
76
- cancelled = true;
77
+ cancellation.abort();
77
78
  },
78
79
  source: "Publish",
79
80
  status: "Starting…",
@@ -104,7 +105,7 @@ export async function runDeploy(
104
105
  const attempts = options.attempts ?? DEPLOY_POLL.attempts;
105
106
  const delayMs = options.delayMs ?? DEPLOY_POLL.delayMs;
106
107
  for (let attempt = 0; attempt < attempts; attempt += 1) {
107
- if (cancelled) {
108
+ if (cancellation.signal.aborted) {
108
109
  return false;
109
110
  }
110
111
  let info;
@@ -123,7 +124,7 @@ export async function runDeploy(
123
124
  }
124
125
  await sleep(delayMs);
125
126
  }
126
- if (cancelled) {
127
+ if (cancellation.signal.aborted) {
127
128
  return false;
128
129
  }
129
130
  noteDeployment(null);
@@ -27,6 +27,7 @@
27
27
  * @docs studio/publish/cloudflare
28
28
  */
29
29
 
30
+ import { isFunction } from "@jxsuite/schema/guards";
30
31
  import type { DeployConfig, ProjectConfig } from "@jxsuite/schema/types";
31
32
  import { activeRegistry } from "../commands/active-registry";
32
33
  import { currentDeploy, noteDeployment } from "./deploy-checklist";
@@ -39,7 +40,7 @@ import { layerHost } from "../ui/layers";
39
40
  import { normalizeProjectDir } from "../utils/project-dir";
40
41
  import { openPublishSurface } from "../surfaces/publish";
41
42
  import type { PublishForm, PublishSurfaceHandle, PublishView } from "../surfaces/publish";
42
- import type { CfAccount, PagesDeploymentInfo } from "./pages-service";
43
+ import type { CfAccount, ConnectOptions, PagesDeploymentInfo } from "./pages-service";
43
44
  import {
44
45
  connectDeploy,
45
46
  latestDeployment,
@@ -59,7 +60,7 @@ let _replacing = false;
59
60
  let _form: PublishForm = { accountId: "", branch: "main", owner: "", projectName: "", repo: "" };
60
61
 
61
62
  function currentConfig(): ProjectConfig | null {
62
- return (projectState?.projectConfig as ProjectConfig | undefined) ?? null;
63
+ return projectState?.projectConfig ?? null;
63
64
  }
64
65
 
65
66
  function deriveSlug(name: string): string {
@@ -122,7 +123,7 @@ function viewOf(): PublishView {
122
123
  error: _error,
123
124
  form: { ..._form },
124
125
  // Asked only of a host that answered `true` above, which is the one that is known to exist.
125
- hosted: supported && typeof getPlatform().cfConnect === "function",
126
+ hosted: supported && isFunction(getPlatform().cfConnect),
126
127
  lapsed: connection?.connected === true && connection.needsReconnect === true,
127
128
  loading: _connection === "loading",
128
129
  replacing: _replacing,
@@ -270,14 +271,17 @@ async function submitConnect(): Promise<void> {
270
271
  paint();
271
272
  try {
272
273
  const rootDir = projectFolder();
273
- const deploy = await connectDeploy(config, {
274
+ const options: ConnectOptions = {
274
275
  accountId: _form.accountId,
275
276
  owner: _form.owner,
276
277
  productionBranch: _form.branch || "main",
277
278
  projectName: _form.projectName,
278
279
  repo: _form.repo,
279
- ...(rootDir ? { rootDir } : {}),
280
- });
280
+ };
281
+ if (rootDir) {
282
+ options.rootDir = rootDir;
283
+ }
284
+ const deploy = await connectDeploy(config, options);
281
285
  _deployment = await latestDeployment(deploy).catch(() => null);
282
286
  } catch (error) {
283
287
  _error = error instanceof Error ? error.message : String(error);
@@ -1,7 +1,7 @@
1
1
  /// <reference lib="dom" />
2
2
  import { getPlatform, hasPlatform } from "./platform";
3
3
  import { now } from "./services/clock";
4
- import type { RecentProjectEntry } from "./types";
4
+ import type { RecentProjectEntry, StudioPlatform } from "./types";
5
5
 
6
6
  interface RecentFile {
7
7
  path: string;
@@ -33,9 +33,7 @@ function backend(): StudioRecentStore | null {
33
33
  return null;
34
34
  }
35
35
  const platform = getPlatform();
36
- return platform.getRecentProjects && platform.saveRecentProjects
37
- ? (platform as StudioRecentStore)
38
- : null;
36
+ return isRecentStore(platform) ? platform : null;
39
37
  }
40
38
 
41
39
  interface StudioRecentStore {
@@ -43,14 +41,21 @@ interface StudioRecentStore {
43
41
  saveRecentProjects: (projects: RecentProjectEntry[]) => Promise<void>;
44
42
  }
45
43
 
44
+ /** True when the platform implements both halves of the optional recent-projects store. */
45
+ function isRecentStore(platform: StudioPlatform): platform is StudioPlatform & StudioRecentStore {
46
+ return Boolean(platform.getRecentProjects && platform.saveRecentProjects);
47
+ }
48
+
46
49
  function loadFromLocalStorage(): RecentProjectEntry[] {
47
50
  try {
48
51
  const raw = localStorage.getItem(STORAGE_KEY);
49
52
  if (!raw) {
50
53
  return [];
51
54
  }
52
- const parsed = JSON.parse(raw) as RecentProjectEntry[];
53
- return Array.isArray(parsed) ? parsed : [];
55
+ const parsed: unknown = JSON.parse(raw);
56
+ /* SAFETY: STORAGE_KEY is written only by this module, as JSON.stringify of a
57
+ RecentProjectEntry[]; the Array.isArray check discards any other value found under it. */
58
+ return Array.isArray(parsed) ? (parsed as RecentProjectEntry[]) : [];
54
59
  } catch {
55
60
  return [];
56
61
  }
@@ -132,8 +137,10 @@ function loadRecentFiles(): RecentFile[] {
132
137
  if (!raw) {
133
138
  return [];
134
139
  }
135
- const parsed = JSON.parse(raw) as RecentFile[];
136
- return Array.isArray(parsed) ? parsed : [];
140
+ const parsed: unknown = JSON.parse(raw);
141
+ /* SAFETY: FILES_STORAGE_KEY is written only by trackRecentFile below, as JSON.stringify of a
142
+ RecentFile[]; the Array.isArray check discards any other value found under it. */
143
+ return Array.isArray(parsed) ? (parsed as RecentFile[]) : [];
137
144
  } catch {
138
145
  return [];
139
146
  }
@@ -1,17 +1,27 @@
1
1
  /// <reference lib="dom" />
2
- const g = globalThis as unknown as {
3
- __jxPlatform?: {
4
- windowControls?: {
5
- getFrame: () => Promise<{
6
- x: number;
7
- y: number;
8
- width: number;
9
- height: number;
10
- }>;
11
- setFrame: (x: number, y: number, w: number, h: number) => void;
12
- };
13
- };
14
- };
2
+ import { isFunction, isNonNullObject } from "@jxsuite/schema/guards";
3
+ import type { SerializableRect } from "./canvas/iframe-protocol";
4
+
5
+ /** The desktop shell's frame controls; only desktop adapters add them to the platform. */
6
+ interface ResizeWindowControls {
7
+ getFrame: () => Promise<SerializableRect>;
8
+ setFrame: (x: number, y: number, w: number, h: number) => void;
9
+ }
10
+
11
+ /** True when `value` is a windowControls object that can at least read the window frame. */
12
+ function isResizeWindowControls(value: unknown): value is ResizeWindowControls {
13
+ return isNonNullObject(value) && "getFrame" in value && isFunction(value.getFrame);
14
+ }
15
+
16
+ /** The registered platform's window controls, when it is a desktop shell that exposes them. */
17
+ function readWindowControls(): ResizeWindowControls | undefined {
18
+ const platform = globalThis.__jxPlatform;
19
+ if (platform == null || !("windowControls" in platform)) {
20
+ return undefined;
21
+ }
22
+ const controls = platform.windowControls;
23
+ return isResizeWindowControls(controls) ? controls : undefined;
24
+ }
15
25
 
16
26
  const EDGES = [
17
27
  "top",
@@ -30,8 +40,8 @@ const MIN_HEIGHT = 300;
30
40
  let mounted = false;
31
41
 
32
42
  export function mountResizeEdges() {
33
- const wc = g.__jxPlatform?.windowControls;
34
- if (!wc || !wc.getFrame || mounted) {
43
+ const wc = readWindowControls();
44
+ if (!wc || mounted) {
35
45
  return;
36
46
  }
37
47
  mounted = true;
@@ -49,27 +59,7 @@ export function mountResizeEdges() {
49
59
  document.body.append(container);
50
60
  }
51
61
 
52
- /**
53
- * @param {MouseEvent} e
54
- * @param {string} edge
55
- * @param {{
56
- * getFrame: () => Promise<{ x: number; y: number; width: number; height: number }>;
57
- * setFrame: (x: number, y: number, w: number, h: number) => void;
58
- * }} wc
59
- */
60
- async function startResize(
61
- e: MouseEvent,
62
- edge: string,
63
- wc: {
64
- getFrame: () => Promise<{
65
- x: number;
66
- y: number;
67
- width: number;
68
- height: number;
69
- }>;
70
- setFrame: (x: number, y: number, w: number, h: number) => void;
71
- },
72
- ) {
62
+ async function startResize(e: MouseEvent, edge: string, wc: ResizeWindowControls) {
73
63
  e.preventDefault();
74
64
  e.stopPropagation();
75
65
 
@@ -38,8 +38,10 @@
38
38
  import { activeTab } from "../workspace/workspace";
39
39
  import { clearProblems, notify, problemFindings } from "./notify";
40
40
  import { findA11yDefects } from "@jxsuite/schema/a11y";
41
+ import { isNonNullObject, isNumber, isString } from "@jxsuite/schema/guards";
42
+ import type { NotifyOptions } from "./notify";
41
43
  import type { AnyCommand, CommandRegistry } from "../commands/registry";
42
- import type { JxElement } from "@jxsuite/schema/types";
44
+ import type { JxAttributeValue, JxElement } from "@jxsuite/schema/types";
43
45
 
44
46
  /** WCAG success criteria these checks bind to, by the id ATAG B.3.1 asks a report to carry. */
45
47
  export type A11yCriterion =
@@ -113,14 +115,14 @@ const VAGUE_LINK_TEXT = new Set([
113
115
  ]);
114
116
 
115
117
  /** The attribute bag, whatever shape the author wrote it in. */
116
- function attrs(node: JxElement): Record<string, unknown> {
117
- return (node.attributes ?? {}) as Record<string, unknown>;
118
+ function attrs(node: JxElement): Record<string, JxAttributeValue> {
119
+ return node.attributes ?? {};
118
120
  }
119
121
 
120
122
  /** An attribute's literal string value, or null when it is absent or a binding. */
121
123
  function literal(node: JxElement, name: string): string | null {
122
124
  const value = attrs(node)[name];
123
- return typeof value === "string" ? value : null;
125
+ return isString(value) ? value : null;
124
126
  }
125
127
 
126
128
  /** Whether an attribute is present at all, however it was written. */
@@ -131,15 +133,15 @@ function has(node: JxElement, name: string): boolean {
131
133
  /** The element's own text, when it is a literal rather than a binding. */
132
134
  function ownText(node: JxElement): string {
133
135
  const parts: string[] = [];
134
- if (typeof node.textContent === "string") {
136
+ if (isString(node.textContent)) {
135
137
  parts.push(node.textContent);
136
138
  }
137
139
  const { children } = node;
138
140
  if (Array.isArray(children)) {
139
141
  for (const child of children) {
140
- if (typeof child === "string") {
142
+ if (isString(child)) {
141
143
  parts.push(child);
142
- } else if (child && typeof child === "object") {
144
+ } else if (isNonNullObject(child)) {
143
145
  parts.push(ownText(child));
144
146
  }
145
147
  }
@@ -158,13 +160,13 @@ function* walk(node: JxElement): Generator<JxElement> {
158
160
  const { children } = node;
159
161
  if (Array.isArray(children)) {
160
162
  for (const child of children) {
161
- if (child && typeof child === "object") {
163
+ if (isNonNullObject(child)) {
162
164
  yield* walk(child);
163
165
  }
164
166
  }
165
167
  }
166
168
  for (const branch of Object.values(node.cases ?? {})) {
167
- if (branch && typeof branch === "object") {
169
+ if (isNonNullObject(branch)) {
168
170
  yield* walk(branch);
169
171
  }
170
172
  }
@@ -177,7 +179,7 @@ function hasAccessibleName(node: JxElement): boolean {
177
179
  literal(node, "aria-labelledby") !== null ||
178
180
  has(node, "aria-label") ||
179
181
  has(node, "aria-labelledby") ||
180
- (typeof node.title === "string" && node.title !== "") ||
182
+ (isString(node.title) && node.title !== "") ||
181
183
  ownText(node) !== ""
182
184
  );
183
185
  }
@@ -197,7 +199,7 @@ export function checkDocument(doc: JxElement): A11yFinding[] {
197
199
 
198
200
  for (const node of walk(doc)) {
199
201
  index += 1;
200
- const tag = typeof node.tagName === "string" ? node.tagName.toLowerCase() : "";
202
+ const tag = isString(node.tagName) ? node.tagName.toLowerCase() : "";
201
203
  const where = tag === "" ? `element ${index}` : `<${tag}>`;
202
204
 
203
205
  // ── 1.1.1 Non-text Content ────────────────────────────────────────────────
@@ -308,7 +310,7 @@ export function checkDocument(doc: JxElement): A11yFinding[] {
308
310
  }
309
311
 
310
312
  // ── 2.4.3 Focus Order — a positive tabindex reorders the whole page ──────
311
- if (typeof node.tabIndex === "number" && node.tabIndex > 0) {
313
+ if (isNumber(node.tabIndex) && node.tabIndex > 0) {
312
314
  findings.push({
313
315
  criterion: "1.3.1",
314
316
  detail:
@@ -322,7 +324,7 @@ export function checkDocument(doc: JxElement): A11yFinding[] {
322
324
  }
323
325
 
324
326
  // ── 4.1.1 Parsing — a duplicate id breaks every reference to it ──────────
325
- if (typeof node.id === "string" && node.id !== "") {
327
+ if (isString(node.id) && node.id !== "") {
326
328
  const seen = seenIds.get(node.id);
327
329
  if (seen !== undefined) {
328
330
  findings.push({
@@ -354,7 +356,7 @@ export function checkDocument(doc: JxElement): A11yFinding[] {
354
356
  }
355
357
 
356
358
  // ── 3.1.1 Language of Page ────────────────────────────────────────────────
357
- if (typeof doc.lang !== "string" || doc.lang === "") {
359
+ if (!isString(doc.lang) || doc.lang === "") {
358
360
  findings.push({
359
361
  criterion: "3.1.1",
360
362
  detail:
@@ -370,7 +372,7 @@ export function checkDocument(doc: JxElement): A11yFinding[] {
370
372
  // The structural rules, from the engine every judge of a Jx document shares.
371
373
  for (const defect of findA11yDefects(doc)) {
372
374
  findings.push({
373
- criterion: defect.criterion as A11yCriterion,
375
+ criterion: defect.criterion,
374
376
  detail: defect.detail,
375
377
  id: `${defect.rule}:${defect.path.join("/")}`,
376
378
  message: defect.message,
@@ -457,14 +459,19 @@ export function reportA11yProblems(doc: JxElement, path?: string): number {
457
459
  clearProblems((record) => record.source === A11Y_PROBLEM_SOURCE);
458
460
  const findings = checkDocument(doc);
459
461
  for (const finding of findings) {
460
- notify(finding.severity, finding.message, {
462
+ const options: NotifyOptions = {
461
463
  detail: `WCAG ${finding.criterion} — ${finding.detail}`,
462
464
  key: `a11y.${finding.id}`,
463
465
  source: A11Y_PROBLEM_SOURCE,
464
466
  tier: "problem",
465
- ...(finding.action === undefined ? {} : { action: finding.action }),
466
- ...(path === undefined ? {} : { path }),
467
- });
467
+ };
468
+ if (finding.action !== undefined) {
469
+ options.action = finding.action;
470
+ }
471
+ if (path !== undefined) {
472
+ options.path = path;
473
+ }
474
+ notify(finding.severity, finding.message, options);
468
475
  }
469
476
  /*
470
477
  * And then the honest half. A report that lists nothing reads as "this page is accessible", which
@@ -10,11 +10,19 @@
10
10
  * @license MIT
11
11
  */
12
12
 
13
+ import { isJsonObject, isNumber, isString } from "@jxsuite/schema/guards";
14
+ import type { JsonValue } from "@jxsuite/schema/types";
15
+
13
16
  const PENDING_PROMPT_PREFIX = "jx.ai.pendingAgentPrompt";
14
17
 
15
18
  /** Entries older than this are considered stale and dropped on read. */
16
19
  const MAX_AGE_MS = 15 * 60 * 1000;
17
20
 
21
+ /** `localStorage`, or `undefined` on a host that has none (a worker, a test run without a DOM). */
22
+ function storage(): Storage | undefined {
23
+ return typeof localStorage === "undefined" ? undefined : localStorage;
24
+ }
25
+
18
26
  function storageKey(root: string) {
19
27
  return `${PENDING_PROMPT_PREFIX}:${root}`;
20
28
  }
@@ -27,21 +35,25 @@ function storageKey(root: string) {
27
35
  */
28
36
  function readEntry(root: string): { prompt: string; ts: number } | null {
29
37
  try {
30
- const raw = globalThis.localStorage?.getItem(storageKey(root));
38
+ const raw = storage()?.getItem(storageKey(root));
31
39
  if (!raw) {
32
40
  return null;
33
41
  }
34
- const parsed = JSON.parse(raw) as { prompt?: unknown; ts?: unknown };
35
- const valid =
36
- typeof parsed.prompt === "string" &&
37
- typeof parsed.ts === "number" &&
38
- Date.now() - parsed.ts <= MAX_AGE_MS;
39
- if (!valid) {
42
+ // SAFETY: `JSON.parse` without a reviver yields nothing but JSON values.
43
+ const parsed = JSON.parse(raw) as JsonValue;
44
+ if (parsed === null) {
45
+ /* A stored JSON `null` reads as "no entry" but is left in place rather than dropped as
46
+ malformed, matching how this reader has always treated it. */
47
+ return null;
48
+ }
49
+ const prompt = isJsonObject(parsed) ? parsed.prompt : undefined;
50
+ const ts = isJsonObject(parsed) ? parsed.ts : undefined;
51
+ if (!isString(prompt) || !isNumber(ts) || !(Date.now() - ts <= MAX_AGE_MS)) {
40
52
  // Stale or malformed — remove so it never seeds a later session.
41
- globalThis.localStorage?.removeItem(storageKey(root));
53
+ storage()?.removeItem(storageKey(root));
42
54
  return null;
43
55
  }
44
- return { prompt: parsed.prompt as string, ts: parsed.ts as number };
56
+ return { prompt, ts };
45
57
  } catch {
46
58
  return null;
47
59
  }
@@ -55,7 +67,7 @@ function readEntry(root: string): { prompt: string; ts: number } | null {
55
67
  */
56
68
  export function setPendingAgentPrompt(root: string, prompt: string): void {
57
69
  try {
58
- globalThis.localStorage?.setItem(storageKey(root), JSON.stringify({ prompt, ts: Date.now() }));
70
+ storage()?.setItem(storageKey(root), JSON.stringify({ prompt, ts: Date.now() }));
59
71
  } catch {
60
72
  /* LocalStorage unavailable — the prompt is simply not handed off. */
61
73
  }
@@ -83,7 +95,7 @@ export function consumePendingAgentPrompt(root: string): string | null {
83
95
  return null;
84
96
  }
85
97
  try {
86
- globalThis.localStorage?.removeItem(storageKey(root));
98
+ storage()?.removeItem(storageKey(root));
87
99
  } catch {
88
100
  /* LocalStorage unavailable — nothing to delete. */
89
101
  }
@@ -12,8 +12,8 @@
12
12
  *
13
13
  * - **A skip is a SUCCESS.** "You decide" is a real answer to a question; only a stopped turn is a
14
14
  * failure. Reporting a skip as an error would make the model apologise for having asked.
15
- * - **The answer never becomes a user message.** `toMessagesArray` serialises the array verbatim
16
- * and a provider requires a `tool` reply to follow its `tool_calls` request; a user turn spliced
15
+ * - **The answer never becomes a user message.** `toMessagesArray` serialises the array verbatim and
16
+ * a provider requires a `tool` reply to follow its `tool_calls` request; a user turn spliced
17
17
  * between them is a 400. The answer travels as the tool result, and the chat view renders it into
18
18
  * the question's own chip.
19
19
  *
@@ -24,6 +24,7 @@
24
24
  */
25
25
 
26
26
  import { createToolDefinition, toolError, toolSuccess } from "@jxsuite/ai/tools";
27
+ import { isString } from "@jxsuite/schema/guards";
27
28
  import { reactive } from "../reactivity";
28
29
 
29
30
  import type { ToolRegistry } from "@jxsuite/ai/tools";
@@ -212,17 +213,13 @@ export function registerAskTool(
212
213
  required: ["question"],
213
214
  },
214
215
  execute: async (args, ctx) => {
215
- /* Everything `unknown`, and every field narrowed by `typeof` rather than by `?.`. The
216
- registry's `validate()` is "a lightweight structural check, not a JSON Schema validator",
216
+ /* Every field is any JSON value, narrowed by a guard rather than by `?.`. The registry's
217
+ `validate()` is "a lightweight structural check, not a JSON Schema validator",
217
218
  `strict: false` skips it entirely, and this tool may be registered into someone else's
218
219
  registry — so an argument that is a number is a case, not an impossibility. Optional
219
220
  chaining guards null, not type: `context?.trim()` threw on one. */
220
- const { question, options, context } = args as {
221
- question?: unknown;
222
- options?: unknown;
223
- context?: unknown;
224
- };
225
- if (typeof question !== "string" || !question.trim()) {
221
+ const { question, options, context } = args;
222
+ if (!isString(question) || !question.trim()) {
226
223
  return toolError('Pass "question" — the question to put to the user.');
227
224
  }
228
225
  if (isAwaitingAnswer()) {
@@ -230,13 +227,13 @@ export function registerAskTool(
230
227
  }
231
228
  const choices = Array.isArray(options)
232
229
  ? options
233
- .filter((o): o is string => typeof o === "string" && o.trim().length > 0)
230
+ .filter((o): o is string => isString(o) && o.trim().length > 0)
234
231
  .slice(0, MAX_OPTIONS)
235
232
  : [];
236
233
 
237
234
  const answering = askUser(
238
235
  {
239
- context: typeof context === "string" ? context.trim() : "",
236
+ context: isString(context) ? context.trim() : "",
240
237
  /* The tool-call id, so the chip the transcript draws and the question this registers
241
238
  are the same thing. Without it a restored, permanently unanswered question would
242
239
  render identically to the live one. */