@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
@@ -59,6 +59,7 @@ import {
59
59
  dropTargetForElements,
60
60
  monitorForElements,
61
61
  } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
62
+ import type { ElementDragPayload } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
62
63
  import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine";
63
64
  import {
64
65
  PRIMARY_PANE,
@@ -99,9 +100,12 @@ import { restoreSession } from "../workspace/session";
99
100
  import { cleanupGitPanel } from "../panels/git-panel";
100
101
  import { addRecentProject, trackRecentFile } from "../recent-projects";
101
102
  import { listWindow, revealListRow, watchListWindow } from "../ui/virtual-window";
102
- import type { JxMutableNode } from "@jxsuite/schema/types";
103
+ import type { JsonObject, JxMutableNode } from "@jxsuite/schema/types";
104
+ import { isFunction, isString } from "@jxsuite/schema/guards";
105
+ import type { CommandArgValues } from "../commands/command-args";
106
+ import type { FormatFrontmatter } from "../format/format-host";
103
107
  import type { ResolvedI18n } from "@jxsuite/schema/locale";
104
- import type { ChoiceOption } from "../ui/layers";
108
+ import type { ChoiceOption, PromptDialogOptions } from "../ui/layers";
105
109
  import { emptyFilesPanelValues, mountFilesPanelSurface } from "../surfaces/files-panel";
106
110
  import { openMenu } from "../surfaces/menu";
107
111
  import type {
@@ -136,6 +140,42 @@ export async function loadDirectory(dirPath: string) {
136
140
  }
137
141
  }
138
142
 
143
+ /** The project directories the Library scans and the tree opens expanded, when present. */
144
+ const CONVENTIONAL_DIRS = new Set([
145
+ "pages",
146
+ "layouts",
147
+ "components",
148
+ "content",
149
+ "data",
150
+ "public",
151
+ "styles",
152
+ ]);
153
+
154
+ /**
155
+ * Load the project root, expand and load each conventional directory it holds, and record them as
156
+ * `projectDirs` — the list the Library scans.
157
+ *
158
+ * One function because there are four doors into a project (the folder picker, a recent project,
159
+ * the `?project=` boot and the root probe a fresh window runs), and each used to carry its own copy
160
+ * of this walk. Two of the copies expanded the directories without recording them, so on desktop
161
+ * the file tree was full and the Library said the project had no files.
162
+ */
163
+ export async function loadProjectDirectories(): Promise<void> {
164
+ if (!projectState) {
165
+ return;
166
+ }
167
+ await loadDirectory(".");
168
+ const found: string[] = [];
169
+ for (const entry of projectState.dirs.get(".") ?? []) {
170
+ if (entry.type === "directory" && CONVENTIONAL_DIRS.has(entry.name)) {
171
+ found.push(entry.name);
172
+ projectState.expanded.add(entry.path || entry.name);
173
+ await loadDirectory(entry.path || entry.name);
174
+ }
175
+ }
176
+ projectState.projectDirs = found;
177
+ }
178
+
139
179
  /**
140
180
  * Whether the tree currently draws the files `.gitignore` masks.
141
181
  *
@@ -196,7 +236,7 @@ export async function loadProject() {
196
236
  await loadFormats();
197
237
  refreshExtensionUi(platform);
198
238
  }
199
- await loadDirectory(".");
239
+ await loadProjectDirectories();
200
240
  await loadComponentRegistry();
201
241
  await openLastSessionOrHome();
202
242
  void maybePromptJxsuiteUpdate(meta.root);
@@ -268,30 +308,9 @@ export async function openProject({
268
308
  await loadFormats();
269
309
  refreshExtensionUi(platform);
270
310
  }
271
- await loadDirectory(".");
311
+ await loadProjectDirectories();
272
312
  await loadComponentRegistry();
273
313
 
274
- // Auto-expand key directories and populate projectDirs for Browse view
275
- const conventionalDirs = new Set([
276
- "pages",
277
- "layouts",
278
- "components",
279
- "content",
280
- "data",
281
- "public",
282
- "styles",
283
- ]);
284
- const entries = requireProjectState().dirs.get(".") || [];
285
- const foundDirs = [];
286
- for (const e of entries) {
287
- if (e.type === "directory" && conventionalDirs.has(e.name)) {
288
- foundDirs.push(e.name);
289
- requireProjectState().expanded.add(e.path || e.name);
290
- await loadDirectory(e.path || e.name);
291
- }
292
- }
293
- requireProjectState().projectDirs = foundDirs;
294
-
295
314
  // Source control, the stylebook selection and the settings tab describe the project being
296
315
  // Left behind. The poll timer goes with them; the panel re-arms it on its next render.
297
316
  cleanupGitPanel();
@@ -460,35 +479,6 @@ function fileIconName(name: string, type: string, expanded: boolean): string {
460
479
  }
461
480
  }
462
481
 
463
- /**
464
- * The Navigator no longer draws this panel with lit.
465
- *
466
- * The record below returns `nothing` and mounts `surfaces/files-panel.json` in `afterRender`, so
467
- * this is a stub: it survives only because `NavigatorPanelDeps` still declares the injection and
468
- * `studio.ts` still passes it. Both go in the change that deletes this.
469
- *
470
- * @deprecated The panel is `surfaces/files-panel.json`; call {@link mountFilesPanel}.
471
- */
472
- export function renderFilesTemplate(): typeof nothing {
473
- return nothing;
474
- }
475
-
476
- /**
477
- * Drag-and-drop is registered against the row elements the DOCUMENT creates, as they are created.
478
- *
479
- * The pass this replaced ran on a `requestAnimationFrame` after every repaint, found the tree and
480
- * its rows by class, and re-registered every one of them — which is exactly the acquisition
481
- * `studio-ui-guidelines.md` §9.4 objects to, and which a WINDOWED list makes wrong rather than
482
- * merely wasteful: the rows are re-used for different files as the window slides, so a pass that
483
- * arrives one frame late hands a file's drag source to whichever file is standing in its place.
484
- * {@link mountFilesPanel} adopts each row through `onNodeCreated` instead.
485
- *
486
- * @deprecated Registration is `onNodeCreated`; this exists for the deps entry alone.
487
- */
488
- export function registerFileTreeDnD(_ctx: { renderLeftPanel: () => void }): void {
489
- // Intentionally nothing: see the note above.
490
- }
491
-
492
482
  // ─── The row model, and the window onto it ───────────────────────────────────
493
483
 
494
484
  /**
@@ -1183,10 +1173,9 @@ export function canMoveInto(srcPath: string, targetDir: string): boolean {
1183
1173
  }
1184
1174
 
1185
1175
  /** {@link canMoveInto} for a ROW: only a directory has an inside to move something into. */
1186
- function acceptsDrop(srcPath: unknown, targetPath: string, targetType: string): boolean {
1187
- return (
1188
- targetType === "directory" && typeof srcPath === "string" && canMoveInto(srcPath, targetPath)
1189
- );
1176
+ function acceptsDrop(source: ElementDragPayload, targetPath: string, targetType: string): boolean {
1177
+ const srcPath = source.data.path;
1178
+ return targetType === "directory" && isString(srcPath) && canMoveInto(srcPath, targetPath);
1190
1179
  }
1191
1180
 
1192
1181
  /**
@@ -1310,15 +1299,15 @@ function adoptFileRow(element: HTMLElement, path: string, type: string): void {
1310
1299
  },
1311
1300
  element,
1312
1301
  getData({ source }) {
1313
- return acceptsDrop(source.data.path, path, type)
1302
+ return acceptsDrop(source, path, type)
1314
1303
  ? { targetDir: path, type: "file-tree-target" }
1315
1304
  : { type: "file-tree-refused" };
1316
1305
  },
1317
1306
  onDrag({ source }) {
1318
- setRowUnderDrag(path, acceptsDrop(source.data.path, path, type));
1307
+ setRowUnderDrag(path, acceptsDrop(source, path, type));
1319
1308
  },
1320
1309
  onDragEnter({ source }) {
1321
- setRowUnderDrag(path, acceptsDrop(source.data.path, path, type));
1310
+ setRowUnderDrag(path, acceptsDrop(source, path, type));
1322
1311
  },
1323
1312
  onDragLeave() {
1324
1313
  setRowUnderDrag("", false);
@@ -1361,7 +1350,8 @@ function adoptFileTreeElement(element: HTMLElement): void {
1361
1350
  pointer — {@link syncRootDrop} — because the row is what the drop will reach. */
1362
1351
  const rootCleanup = dropTargetForElements({
1363
1352
  canDrop({ source }) {
1364
- return source.data.type === "file-tree" && canMoveInto(source.data.path as string, ".");
1353
+ const srcPath = source.data.path;
1354
+ return source.data.type === "file-tree" && isString(srcPath) && canMoveInto(srcPath, ".");
1365
1355
  },
1366
1356
  element,
1367
1357
  getData() {
@@ -1393,9 +1383,11 @@ function adoptFileTreeElement(element: HTMLElement): void {
1393
1383
  return;
1394
1384
  }
1395
1385
 
1396
- const srcPath = source.data.path as string;
1397
- const targetDirPath = target.data.targetDir as string;
1398
- if (!canMoveInto(srcPath, targetDirPath)) {
1386
+ // A file-tree row's drag source always carries its string `path`, and an accepting row's
1387
+ // Target its string `targetDir` (see `adoptFileRow`); anything else is not a move.
1388
+ const srcPath = source.data.path;
1389
+ const targetDirPath = target.data.targetDir;
1390
+ if (!isString(srcPath) || !isString(targetDirPath) || !canMoveInto(srcPath, targetDirPath)) {
1399
1391
  return;
1400
1392
  }
1401
1393
  const fileName = srcPath.split("/").pop();
@@ -1520,8 +1512,8 @@ function dismissFileContextMenu(): void {
1520
1512
  * Entry Form" is not offered on it. A command whose required arguments this row cannot answer is
1521
1513
  * skipped — never rendered into a refusal the author cannot act on.
1522
1514
  */
1523
- function fileRowFacts(entry: { path: string; type: string }): Record<string, unknown> {
1524
- const facts: Record<string, unknown> = {};
1515
+ function fileRowFacts(entry: { path: string; type: string }): CommandArgValues {
1516
+ const facts: CommandArgValues = {};
1525
1517
  if (entry.type === "directory") {
1526
1518
  // The collection's own SOURCE ROOT, not any directory beneath it: "Edit Collection in Grid"
1527
1519
  // Opens the whole collection, so offering it on `content/posts/2026` would be a row whose label
@@ -1579,13 +1571,11 @@ function placedFileRows(entry: { path: string; type: string }): MenuRowProjectio
1579
1571
  const facts = fileRowFacts(entry);
1580
1572
  const rows: MenuRowProjection[] = [];
1581
1573
  for (const command of registry.forPlacement("context/file")) {
1582
- const schema = command.args as
1583
- | { properties?: Record<string, unknown>; required?: readonly string[] }
1584
- | undefined;
1574
+ const schema = command.args;
1585
1575
  if (!(schema?.required ?? []).every((key) => key in facts)) {
1586
1576
  continue;
1587
1577
  }
1588
- const args: Record<string, unknown> = {};
1578
+ const args: CommandArgValues = {};
1589
1579
  for (const key of Object.keys(schema?.properties ?? {})) {
1590
1580
  if (key in facts) {
1591
1581
  args[key] = facts[key];
@@ -1926,27 +1916,28 @@ export async function createFileIn(request: NewFileRequest): Promise<string | nu
1926
1916
  };
1927
1917
 
1928
1918
  let picked = initialPick;
1929
- const entered = await showPromptDialog(request.title ?? "New File", {
1930
- ...(rows === null
1931
- ? {}
1932
- : {
1933
- choice: {
1934
- initial: initialPick,
1935
- label: "Format",
1936
- onChange: (next: string) => {
1937
- picked = next;
1938
- },
1939
- options: () => rows,
1940
- },
1941
- }),
1919
+ const promptOptions: PromptDialogOptions = {
1942
1920
  confirmLabel: "Create",
1943
1921
  message: dir === "." ? "Creating in the project root." : `Creating in ${dir}/`,
1944
- ...(request.suggestedName === undefined ? {} : { placeholder: request.suggestedName }),
1945
1922
  // With a picker there is no extension in the field to preserve, so the whole name is the stem.
1946
1923
  select: rows === null ? "stem" : "all",
1947
1924
  validate,
1948
1925
  value: request.suggestedName ?? "untitled.json",
1949
- });
1926
+ };
1927
+ if (rows !== null) {
1928
+ promptOptions.choice = {
1929
+ initial: initialPick,
1930
+ label: "Format",
1931
+ onChange: (next: string) => {
1932
+ picked = next;
1933
+ },
1934
+ options: () => rows,
1935
+ };
1936
+ }
1937
+ if (request.suggestedName !== undefined) {
1938
+ promptOptions.placeholder = request.suggestedName;
1939
+ }
1940
+ const entered = await showPromptDialog(request.title ?? "New File", promptOptions);
1950
1941
  if (!entered) {
1951
1942
  return null;
1952
1943
  }
@@ -1955,10 +1946,9 @@ export async function createFileIn(request: NewFileRequest): Promise<string | nu
1955
1946
  const path = dir === "." ? fileName : `${dir}/${fileName}`;
1956
1947
  markLocalMutation(path);
1957
1948
  const format = formatForPath(fileName);
1958
- const suppliedBody =
1959
- typeof request.content === "function"
1960
- ? await request.content(extensionOfName(fileName), fileName)
1961
- : request.content;
1949
+ const suppliedBody = isFunction(request.content)
1950
+ ? await request.content(extensionOfName(fileName), fileName)
1951
+ : request.content;
1962
1952
  /*
1963
1953
  * What a new file starts as, in precedence order.
1964
1954
  *
@@ -2069,13 +2059,16 @@ async function createNewFile(dirPath: string, renderLeftPanel: () => void) {
2069
2059
  */
2070
2060
  async function showRenameFileDialog(currentName: string, path: string): Promise<string | null> {
2071
2061
  const message = await renamePromptMessage(path);
2072
- return showPromptDialog("Rename", {
2062
+ const promptOptions: PromptDialogOptions = {
2073
2063
  confirmLabel: "Rename",
2074
- ...(message === undefined ? {} : { message }),
2075
2064
  select: "stem",
2076
2065
  validate: (v) => (v.trim() ? "" : "Enter a file name."),
2077
2066
  value: currentName,
2078
- });
2067
+ };
2068
+ if (message !== undefined) {
2069
+ promptOptions.message = message;
2070
+ }
2071
+ return showPromptDialog("Rename", promptOptions);
2079
2072
  }
2080
2073
 
2081
2074
  /** Build the status-bar message for a rename, summarising any reference/tag rewrites. */
@@ -2376,8 +2369,8 @@ export async function openFileInTab(path: string, opts: OpenFileOpts = {}) {
2376
2369
  }
2377
2370
 
2378
2371
  await loadFormats();
2379
- let document: Record<string, unknown>;
2380
- let frontmatter: Record<string, unknown> | undefined;
2372
+ let document: JxMutableNode | JsonObject;
2373
+ let frontmatter: FormatFrontmatter | undefined;
2381
2374
  // The layout the JSON was written in, so a save reproduces it (`json-layout.ts`, issue 308). A
2382
2375
  // Format-class file has none: its serializer owns its layout.
2383
2376
  let layout: JsonLayout | null = null;
@@ -2522,6 +2515,8 @@ export async function reloadFileInTab(path: string, opts: { onlyIfChanged?: bool
2522
2515
  if (opts.onlyIfChanged && deepEqual(parsed.document, tab.doc.document)) {
2523
2516
  return;
2524
2517
  }
2518
+ /* SAFETY: this tab was opened on this `.json` path as a Jx document, and the file's schema
2519
+ Makes its top-level object a node — the object `parseJsonDocument` states it returns. */
2525
2520
  tab.doc.document = parsed.document as JxMutableNode;
2526
2521
  }
2527
2522
  tab.doc.dirty = false;
@@ -23,6 +23,7 @@
23
23
  * @docs studio/projects/media
24
24
  */
25
25
 
26
+ import { isNumber } from "@jxsuite/schema/guards";
26
27
  import { getPlatform } from "../platform";
27
28
  import { baseName, dirName, normalizeProjectPath } from "./media-paths";
28
29
  import { notedListing } from "./asset-versions";
@@ -67,7 +68,7 @@ function metaFrom(path: string, entry: DirEntry | undefined): MediaMeta {
67
68
  const name = baseName(path);
68
69
  const dims = measured.get(path);
69
70
  return {
70
- bytes: typeof entry?.size === "number" ? entry.size : null,
71
+ bytes: isNumber(entry?.size) ? entry.size : null,
71
72
  ext: extensionOf(name),
72
73
  height: dims?.height ?? null,
73
74
  kind: mediaKind({ name }),
@@ -66,6 +66,9 @@ export function dirName(path: string): string {
66
66
  /** The open project's content sections, or null when no project (or no `content:`) is loaded. */
67
67
  function contentSections(): Record<string, ContentSectionEntry> | null {
68
68
  const content = projectState?.projectConfig?.content;
69
+ /* SAFETY: `content` is the parser extension's section, which the schema types leave opaque; its
70
+ Project fragment schema shapes every entry as a `ContentSectionEntry`, and `contentMountFor`
71
+ (the only reader) touches nothing but an entry's optional `source` behind `def?.source`. */
69
72
  return (content as Record<string, ContentSectionEntry> | undefined) ?? null;
70
73
  }
71
74
 
@@ -134,5 +137,7 @@ export function previewFileSrc(path: string): string {
134
137
  if (space === "repo") {
135
138
  return withVersion(`${fileBaseUrl}${encodeProjectPath(normalized)}`, versionOf(normalized));
136
139
  }
137
- return loopbackAssetSrc(mediaSiteUrl(normalized));
140
+ /* Encoded per segment for the `src` only. `mediaSiteUrl` is also what an author's document is
141
+ given, and stays as typed; a `#` or `?` in a filename would cut this URL short. */
142
+ return loopbackAssetSrc(`/${encodeProjectPath(mediaSiteUrl(normalized).slice(1))}`);
138
143
  }
@@ -40,7 +40,7 @@ export async function serializeDocument(tab: Tab): Promise<string> {
40
40
  await loadFormats();
41
41
  const sourceFormat = formatByName(tab.doc.sourceFormat);
42
42
  if (sourceFormat?.capabilities.serialize) {
43
- const fm = tab.doc.content?.frontmatter || {};
43
+ const fm = tab.doc.content.frontmatter;
44
44
  const doc = tab.doc.document;
45
45
  const fullDoc = { ...fm, ...doc, children: doc.children ?? [] };
46
46
  return formatSerialize(sourceFormat.name, fullDoc, { mode: "roundtrip" });
@@ -48,7 +48,7 @@ export async function serializeDocument(tab: Tab): Promise<string> {
48
48
  if (tab.doc.mode === "content") {
49
49
  const format = defaultContentFormat();
50
50
  if (format) {
51
- const fm = tab.doc.content?.frontmatter ?? {};
51
+ const fm = tab.doc.content.frontmatter;
52
52
  const hasFrontmatter = Object.keys(fm).length > 0;
53
53
  const fullDoc = { ...fm, ...tab.doc.document };
54
54
  return formatSerialize(format.name, fullDoc, {
@@ -84,7 +84,7 @@ export function createNestingValidator(elements?: ElementsHints): NestingValidat
84
84
  *
85
85
  * Returned as a plain object because it crosses to the canvas frame with the render message.
86
86
  */
87
- export function formatEditableVerdicts(elements?: ElementsHints): Record<string, boolean> {
87
+ export function formatEditableVerdicts(elements?: ElementsHints) {
88
88
  const verdicts: Record<string, boolean> = {};
89
89
  for (const [tag, rule] of Object.entries(elements?.nesting ?? {})) {
90
90
  // "_root" is the document itself, not an element.
@@ -29,6 +29,10 @@ import {
29
29
  import { convertTargetExtensions, convertTargets } from "./format-choices";
30
30
  import { parseJsonDocument, serializeJson } from "@jxsuite/schema/json-layout";
31
31
  import type { JsonLayout } from "@jxsuite/schema/json-layout";
32
+ import { isString } from "@jxsuite/schema/guards";
33
+ import type { JsonValue, JxMutableNode } from "@jxsuite/schema/types";
34
+ import type { CommandArgValues } from "../commands/command-args";
35
+ import type { FormatFrontmatter } from "./format-host";
32
36
  import type { AnyCommand, CommandRegistry } from "../commands/registry";
33
37
 
34
38
  /** What a conversion will do, resolved in full before the reader is asked to confirm it. */
@@ -72,14 +76,17 @@ function withExtension(path: string, ext: string): string {
72
76
  async function readDocument(
73
77
  path: string,
74
78
  source: string,
75
- ): Promise<{ document: Record<string, unknown>; frontmatter: Record<string, unknown> }> {
79
+ ): Promise<{ document: JxMutableNode; frontmatter: FormatFrontmatter }> {
76
80
  const { formatForPath } = await import("./format-host");
77
81
  if (formatForPath(path)) {
78
82
  const { parseSourceForPath } = await import("../files/file-ops");
79
83
  const parsed = await parseSourceForPath(path, source);
80
84
  return { document: parsed.document, frontmatter: parsed.frontmatter };
81
85
  }
82
- return { document: JSON.parse(source) as Record<string, unknown>, frontmatter: {} };
86
+ /* SAFETY: a path no format claims is a `.json` document in pages/ or components/ (the only files
87
+ `convertTargets` offers a conversion for), and that file's schema requires a top-level object;
88
+ `JSON.parse` without a reviver yields a JSON value, so the object is a Jx document. */
89
+ return { document: JSON.parse(source) as JxMutableNode, frontmatter: {} };
83
90
  }
84
91
 
85
92
  /**
@@ -94,8 +101,8 @@ async function readDocument(
94
101
  */
95
102
  async function writeDocument(
96
103
  targetExt: string,
97
- document: Record<string, unknown>,
98
- frontmatter: Record<string, unknown>,
104
+ document: JxMutableNode,
105
+ frontmatter: FormatFrontmatter,
99
106
  ): Promise<string> {
100
107
  const merged = { ...frontmatter, ...document };
101
108
  if (targetExt === ".json") {
@@ -194,7 +201,9 @@ export async function buildPlan(
194
201
  errors, which is indistinguishable from a valid document. Claiming validity on the strength of
195
202
  a schema that was never compiled is the "never render 0" defect one layer down. */
196
203
  const { validateDocOrNull } = await import("../services/jx-validate");
197
- const errors = await validateDocOrNull(JSON.parse(text));
204
+ /* SAFETY: `text` is what `serializeJson` just wrote, and `JSON.parse` without a reviver yields
205
+ a JSON value. */
206
+ const errors = await validateDocOrNull(JSON.parse(text) as JsonValue);
198
207
  if (errors === null) {
199
208
  lines.push(
200
209
  "The result could not be checked against the document schema — that is not the same as " +
@@ -292,7 +301,9 @@ export async function convertFile(path: string, targetExt?: string): Promise<str
292
301
 
293
302
  let original: string;
294
303
  try {
295
- original = (await platform.readFile(path)) ?? "";
304
+ // The read crosses the PAL's wire, which can answer without a `content` field: read that as empty.
305
+ const read = await platform.readFile(path);
306
+ original = isString(read) ? read : "";
296
307
  } catch (error) {
297
308
  return fail(`Could not read ${path}.`, errorMessage(error));
298
309
  }
@@ -373,8 +384,8 @@ async function rebuildTab(from: string, to: string, text: string): Promise<void>
373
384
  const { formatForPath } = await import("./format-host");
374
385
  renameTab(from, to, to);
375
386
  const format = formatForPath(to);
376
- let document: Record<string, unknown>;
377
- let frontmatter: Record<string, unknown> | undefined;
387
+ let document: JxMutableNode;
388
+ let frontmatter: FormatFrontmatter | undefined;
378
389
  // The layout of the JSON just written, as every other JSON reader records it (`files/files.ts`,
379
390
  // `files/file-ops.ts`): the text is the serializer's own, so the record says what a layout-less
380
391
  // Write would do anyway — but the tab reads its file rather than assuming it.
@@ -392,14 +403,17 @@ async function rebuildTab(from: string, to: string, text: string): Promise<void>
392
403
  // Points at the file, and reopening it is one click.
393
404
  return;
394
405
  }
395
- openTab({
406
+ const options: Parameters<typeof openTab>[0] = {
396
407
  document,
397
408
  documentPath: to,
398
- ...(frontmatter === undefined ? {} : { frontmatter }),
399
409
  id: to,
400
410
  layout,
401
411
  sourceFormat: format?.name ?? null,
402
- });
412
+ };
413
+ if (frontmatter !== undefined) {
414
+ options.frontmatter = frontmatter;
415
+ }
416
+ openTab(options);
403
417
  }
404
418
 
405
419
  const CANNOT_CONVERT =
@@ -499,8 +513,8 @@ export function fileFormatCommands(): AnyCommand[] {
499
513
  undo: "none",
500
514
  /* No `aiTool`, by studio-ui-guidelines.md §12.4's second deletion rule: `run` awaits a
501
515
  confirm dialog the person answers. */
502
- run: async (_ctx, args: Record<string, unknown>) => {
503
- const target = typeof args.format === "string" ? args.format : undefined;
516
+ run: async (_ctx, args: CommandArgValues) => {
517
+ const target = isString(args.format) ? args.format : undefined;
504
518
  await convertFile(
505
519
  stringArg("file.convertFormat", args, "source"),
506
520
  ...(target === undefined ? [] : [target]),
@@ -11,6 +11,7 @@
11
11
  * context menu is built during a render and cannot await anything.
12
12
  */
13
13
 
14
+ import { isString } from "@jxsuite/schema/guards";
14
15
  import { collectionForFile } from "../content/collection-match";
15
16
  import { documentExtensions, formatByExtension, formatForPath, getFormats } from "./format-host";
16
17
  import { projectState } from "../store";
@@ -76,7 +77,7 @@ function declaresDocumentKind(kinds: readonly string[]): boolean {
76
77
  */
77
78
  function isLayoutPath(path: string): boolean {
78
79
  const declared = projectState?.projectConfig?.layout;
79
- if (typeof declared !== "string") {
80
+ if (!isString(declared)) {
80
81
  return false;
81
82
  }
82
83
  return normalize(declared).toLowerCase() === normalize(path).toLowerCase();