@jxsuite/studio 6.1.1 → 8.0.0

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 (785) hide show
  1. package/README.md +5 -5
  2. package/dist/chunks/2020-5wtzce5g.js +4 -0
  3. package/dist/chunks/{action-group-2mqby73c.js → action-group-4aan7g6g.js} +3 -3
  4. package/dist/chunks/adapter-5tphg7xe.js +4 -0
  5. package/dist/chunks/add-new-flow-psym14sn.js +4 -0
  6. package/dist/chunks/cf-account-picker-haqazq5r.js +4 -0
  7. package/dist/chunks/cf-settings-h2wrh6hq.js +4 -0
  8. package/dist/chunks/color-area-6rbra5dy.js +4 -0
  9. package/dist/chunks/color-field-gy56c94g.js +4 -0
  10. package/dist/chunks/color-m7r1vk54.js +4 -0
  11. package/dist/chunks/color-slider-sqqdyf6c.js +4 -0
  12. package/dist/chunks/combobox-72h32ejk.js +4 -0
  13. package/dist/chunks/components-r22xca09.js +4 -0
  14. package/dist/chunks/content-source-mmppmcyg.js +4 -0
  15. package/dist/chunks/convert-to-repeater-he70fc2b.js +4 -0
  16. package/dist/chunks/dialog-c4x05vyx.js +4 -0
  17. package/dist/chunks/editor-ccd9jwsa.js +4 -0
  18. package/dist/chunks/entry-commands-6qxz9e8p.js +4 -0
  19. package/dist/chunks/extension-sections-0egb88dm.js +4 -0
  20. package/dist/chunks/file-ops-qnab36ek.js +4 -0
  21. package/dist/chunks/files-rcn56qvm.js +4 -0
  22. package/dist/chunks/format-host-yxz0kjjs.js +4 -0
  23. package/dist/chunks/fs-events-d1qxq4z4.js +4 -0
  24. package/dist/chunks/grid-open-4z1g062t.js +4 -0
  25. package/dist/chunks/grid-view-qg1b5eqx.js +51 -0
  26. package/dist/chunks/icons-63bjtbs7.js +4 -0
  27. package/dist/chunks/iframe-entry-2zggzajv.js +5 -0
  28. package/dist/chunks/iframe-entry-76j8vwwx.js +5 -0
  29. package/dist/chunks/iframe-entry-99nr5zfb.js +5 -0
  30. package/dist/chunks/iframe-entry-pkgmcgp0.js +5 -0
  31. package/dist/chunks/iframe-host-ssv7kyj0.js +4 -0
  32. package/dist/chunks/{index-2veqmnhr.js → index-32eqzv1k.js} +3 -3
  33. package/dist/chunks/index-f0jn7nnp.js +4 -0
  34. package/dist/chunks/{javascript-8nbvs12s.js → javascript-pjp734q4.js} +3 -3
  35. package/dist/chunks/jsonMode-njkvsa02.js +13 -0
  36. package/dist/chunks/jx-validate-ttasrbh7.js +4 -0
  37. package/dist/chunks/layers-bgyr11tr.js +4 -0
  38. package/dist/chunks/layers-panel-7ez66zeq.js +4 -0
  39. package/dist/chunks/listbox-c421cf8c.js +4 -0
  40. package/dist/chunks/lit-html-v9gh687x.js +4 -0
  41. package/dist/chunks/media-library-sq468wts.js +4 -0
  42. package/dist/chunks/media-picker-shfe59pt.js +4 -0
  43. package/dist/chunks/menu-bdpzbfvs.js +4 -0
  44. package/dist/chunks/monaco-binding-vq1hgnn0.js +4 -0
  45. package/dist/chunks/monaco-buffer-3afgwvbp.js +4 -0
  46. package/dist/chunks/monaco-setup-xrd2cbkp.js +4 -0
  47. package/dist/chunks/notify-kzrjr3fv.js +4 -0
  48. package/dist/chunks/number-field-y62xq0ty.js +4 -0
  49. package/dist/chunks/parse-v77xtwv7.js +4 -0
  50. package/dist/chunks/platform-7v4rtd7m.js +4 -0
  51. package/dist/chunks/popover-b89sfej7.js +4 -0
  52. package/dist/chunks/publish-panel-2z9gw8ee.js +4 -0
  53. package/dist/chunks/publish-quick-qx2455cj.js +4 -0
  54. package/dist/chunks/publish-workspace-wrc1dgwx.js +4 -0
  55. package/dist/chunks/quick-search-n0t0eqxb.js +4 -0
  56. package/dist/chunks/references-9547rg5s.js +4 -0
  57. package/dist/chunks/right-panel-wsgnr9pn.js +4 -0
  58. package/dist/chunks/select-rzds841e.js +4 -0
  59. package/dist/chunks/source-control-kwktr9y6.js +4 -0
  60. package/dist/chunks/split-c9zfdgxf.js +4 -0
  61. package/dist/chunks/studio-03ct6yfv.js +9 -0
  62. package/dist/chunks/studio-07rcfje3.js +5 -0
  63. package/dist/chunks/studio-3e54qh39.js +7 -0
  64. package/dist/chunks/studio-3exxhz5g.js +5 -0
  65. package/dist/chunks/studio-3q40e3rj.js +5 -0
  66. package/dist/chunks/studio-3qeh9t0h.js +6 -0
  67. package/dist/chunks/studio-3qqjeep5.js +6 -0
  68. package/dist/chunks/studio-43sd2mam.js +4 -0
  69. package/dist/chunks/studio-4hp8pkyt.js +5 -0
  70. package/dist/chunks/studio-58xg6j2q.js +9 -0
  71. package/dist/chunks/studio-5g0rprdt.js +7 -0
  72. package/dist/chunks/studio-6m380wp7.js +5 -0
  73. package/dist/chunks/studio-80jyh1xh.js +4 -0
  74. package/dist/chunks/studio-83mk4bgg.js +9 -0
  75. package/dist/chunks/{studio-kggey1jt.js → studio-881z1xrx.js} +4 -4
  76. package/dist/chunks/studio-8m0y2qe7.js +5 -0
  77. package/dist/chunks/studio-8tr6cfrc.js +5 -0
  78. package/dist/chunks/studio-8vcvfs7r.js +6 -0
  79. package/dist/chunks/studio-9tmebf0s.js +5 -0
  80. package/dist/chunks/studio-a2bvaptz.js +5 -0
  81. package/dist/chunks/studio-b7y5mr30.js +5 -0
  82. package/dist/chunks/studio-bavb31r0.js +5 -0
  83. package/dist/chunks/studio-bbe4c90a.js +5 -0
  84. package/dist/chunks/studio-c05wdnt3.js +5 -0
  85. package/dist/chunks/studio-ccv2svc6.js +5 -0
  86. package/dist/chunks/studio-d5grtb9e.js +16 -0
  87. package/dist/chunks/studio-df0baea9.js +5 -0
  88. package/dist/chunks/studio-dgk4dqtx.js +7 -0
  89. package/dist/chunks/studio-e1g64q43.js +5 -0
  90. package/dist/chunks/studio-ed1hp6zf.js +6 -0
  91. package/dist/chunks/studio-ed3xx40h.js +7 -0
  92. package/dist/chunks/studio-f14e1zdj.js +5 -0
  93. package/dist/chunks/studio-fbhxxc5f.js +5 -0
  94. package/dist/chunks/studio-fyh0jc96.js +5 -0
  95. package/dist/chunks/studio-gcxk20n7.js +5 -0
  96. package/dist/chunks/studio-jaaz8ce9.js +5 -0
  97. package/dist/chunks/{studio-8grwxtqk.js → studio-jcnsdaep.js} +4 -4
  98. package/dist/chunks/studio-jsgf2q5k.js +7 -0
  99. package/dist/chunks/{studio-1q1sh2ax.js → studio-k3xxbagr.js} +3 -3
  100. package/dist/chunks/studio-k7evxqh4.js +5 -0
  101. package/dist/chunks/studio-kt3pjkwd.js +5 -0
  102. package/dist/chunks/studio-m8g16bgz.js +5 -0
  103. package/dist/chunks/studio-mn0476ag.js +5 -0
  104. package/dist/chunks/studio-mx1smyq0.js +5 -0
  105. package/dist/chunks/studio-n0c5h6mf.js +5 -0
  106. package/dist/chunks/{studio-rv11kfwa.js → studio-nh6d342n.js} +7 -7
  107. package/dist/chunks/studio-nqxqf8p2.js +4 -0
  108. package/dist/chunks/studio-p4nrkvqr.js +5 -0
  109. package/dist/chunks/{studio-h46vtzk8.js → studio-pbxa5fpc.js} +4 -4
  110. package/dist/chunks/studio-pgmvdv7z.js +7 -0
  111. package/dist/chunks/studio-ph84avkf.js +5 -0
  112. package/dist/chunks/{studio-wszjyh0j.js → studio-q0mvbaq6.js} +4 -4
  113. package/dist/chunks/studio-q0tccd43.js +5 -0
  114. package/dist/chunks/studio-q7rtx6zq.js +14 -0
  115. package/dist/chunks/{studio-pre0skq6.js → studio-qgh13jtz.js} +4 -4
  116. package/dist/chunks/studio-qmn1xc24.js +5 -0
  117. package/dist/chunks/studio-qwdqwkj0.js +5 -0
  118. package/dist/chunks/{studio-t6b6qe31.js → studio-r5qy30vx.js} +4 -4
  119. package/dist/chunks/studio-rj9eamf8.js +5 -0
  120. package/dist/chunks/studio-rptgsk96.js +5 -0
  121. package/dist/chunks/studio-rthyg42z.js +928 -0
  122. package/dist/chunks/studio-s19tp1xr.js +5 -0
  123. package/dist/chunks/studio-s32578pn.js +5 -0
  124. package/dist/chunks/studio-svb7yyve.js +5 -0
  125. package/dist/chunks/studio-syreb644.js +5 -0
  126. package/dist/chunks/studio-tf9jryb1.js +10 -0
  127. package/dist/chunks/studio-tfkznv39.js +5 -0
  128. package/dist/chunks/studio-tft6r105.js +5 -0
  129. package/dist/chunks/studio-txf2kysx.js +5 -0
  130. package/dist/chunks/studio-v8867ddv.js +12 -0
  131. package/dist/chunks/studio-vxq7fcvv.js +5 -0
  132. package/dist/chunks/studio-w4rz9hdk.js +5 -0
  133. package/dist/chunks/studio-wbcjbhy1.js +9 -0
  134. package/dist/chunks/studio-wc649wss.js +5 -0
  135. package/dist/chunks/studio-wys23mxz.js +5 -0
  136. package/dist/chunks/studio-x1x167jh.js +5 -0
  137. package/dist/chunks/studio-x9hsze61.js +5 -0
  138. package/dist/chunks/studio-y0n7yxea.js +9 -0
  139. package/dist/chunks/studio-y3ahhdpx.js +5 -0
  140. package/dist/chunks/studio-z97c48fk.js +5 -0
  141. package/dist/chunks/studio-zat62m0c.js +5 -0
  142. package/dist/chunks/studio-zcd2e7yz.js +5 -0
  143. package/dist/chunks/studio-zz9qe3rw.js +64 -0
  144. package/dist/chunks/swatch-group-ewh24n1f.js +4 -0
  145. package/dist/chunks/tabs-f5cw3tgp.js +4 -0
  146. package/dist/chunks/textfield-wewc8rq2.js +4 -0
  147. package/dist/chunks/toast-1gv0h53h.js +4 -0
  148. package/dist/chunks/toast-host-1yg5ar8d.js +4 -0
  149. package/dist/chunks/{toolbar-2nnzqhrj.js → toolbar-44cm5cta.js} +3 -3
  150. package/dist/chunks/tooltip-yypz28gq.js +4 -0
  151. package/dist/chunks/tree-9xa4hm7n.js +4 -0
  152. package/dist/chunks/tsMode-epyfz1hv.js +14 -0
  153. package/dist/chunks/workspace-dz7nxfhv.js +4 -0
  154. package/dist/chunks/workspace-home-xsd7hkjw.js +4 -0
  155. package/dist/chunks/ws-client-bv552sfx.js +4 -0
  156. package/dist/iframe-entry.js +20 -16
  157. package/dist/manifest.json +77 -63
  158. package/dist/studio.js +106 -107
  159. package/dist/workers/ts.worker.js +3 -3
  160. package/package.json +17 -16
  161. package/src/about/about-modal.ts +4 -3
  162. package/src/account/action-flow.ts +45 -38
  163. package/src/account-status.ts +7 -2
  164. package/src/browse/component-examples.ts +272 -0
  165. package/src/browse/library-commands.ts +64 -104
  166. package/src/browse/library-layouts.ts +270 -53
  167. package/src/browse/library-model.ts +194 -134
  168. package/src/browse/library-pane.ts +748 -440
  169. package/src/browse/library-preview.ts +161 -26
  170. package/src/browse/library-source.ts +308 -41
  171. package/src/browse/preview-root.ts +78 -0
  172. package/src/browse/preview-style.ts +155 -0
  173. package/src/canvas/asset-refs.ts +40 -10
  174. package/src/canvas/asset-resolve.ts +19 -23
  175. package/src/canvas/canvas-helpers.ts +7 -6
  176. package/src/canvas/canvas-live-render.ts +260 -77
  177. package/src/canvas/canvas-origin.ts +37 -12
  178. package/src/canvas/canvas-page-context.ts +112 -0
  179. package/src/canvas/canvas-patcher.ts +30 -30
  180. package/src/canvas/canvas-perf.ts +11 -5
  181. package/src/canvas/canvas-render.ts +175 -148
  182. package/src/canvas/canvas-surface.ts +5 -3
  183. package/src/canvas/canvas-utils.ts +147 -61
  184. package/src/canvas/dialog-path.ts +9 -4
  185. package/src/canvas/dialog-state.ts +1 -2
  186. package/src/canvas/diff-marks.ts +9 -16
  187. package/src/canvas/diff-toolbar.ts +8 -7
  188. package/src/canvas/edit-width-drag.ts +4 -1
  189. package/src/canvas/edit-width.ts +1 -3
  190. package/src/canvas/iframe-channel.ts +27 -13
  191. package/src/canvas/iframe-drop.ts +120 -12
  192. package/src/canvas/iframe-editable-root.ts +29 -16
  193. package/src/canvas/iframe-entry.ts +104 -75
  194. package/src/canvas/iframe-eval.ts +73 -49
  195. package/src/canvas/iframe-host.ts +269 -158
  196. package/src/canvas/iframe-inline-edit.ts +49 -30
  197. package/src/canvas/iframe-insert.ts +5 -4
  198. package/src/canvas/iframe-interaction.ts +30 -25
  199. package/src/canvas/iframe-keys.ts +11 -0
  200. package/src/canvas/iframe-overlay.ts +1 -1
  201. package/src/canvas/iframe-patch.ts +25 -21
  202. package/src/canvas/iframe-position.ts +12 -6
  203. package/src/canvas/iframe-protocol.ts +36 -21
  204. package/src/canvas/iframe-render.ts +84 -35
  205. package/src/canvas/iframe-slash.ts +24 -11
  206. package/src/canvas/iframe-subtree.ts +10 -3
  207. package/src/canvas/npm-modules.ts +22 -0
  208. package/src/canvas/path-mapping.ts +19 -12
  209. package/src/canvas/popover-path.ts +7 -3
  210. package/src/canvas/popover-state.ts +1 -2
  211. package/src/canvas/preview-navigate.ts +16 -0
  212. package/src/canvas/repeater-sources.ts +200 -0
  213. package/src/canvas/serialize-scope.ts +13 -5
  214. package/src/canvas/stage-scrollbar.ts +7 -2
  215. package/src/canvas/surface-registry.ts +27 -3
  216. package/src/collab/collab-commands.ts +7 -2
  217. package/src/collab/collab-session.ts +84 -45
  218. package/src/collab/collab-state.ts +4 -3
  219. package/src/collab/monaco-binding.ts +16 -13
  220. package/src/collab/monaco-cursors.ts +5 -2
  221. package/src/commands/app-commands.ts +16 -6
  222. package/src/commands/budget.ts +13 -11
  223. package/src/commands/command-args.ts +103 -71
  224. package/src/commands/context.ts +55 -28
  225. package/src/commands/defaults.ts +69 -45
  226. package/src/commands/keymap.ts +56 -43
  227. package/src/commands/levels.ts +14 -8
  228. package/src/commands/live-context.ts +9 -7
  229. package/src/commands/reference.ts +2 -1
  230. package/src/commands/registry.ts +22 -11
  231. package/src/commands/run-reported.ts +15 -10
  232. package/src/component-props.ts +46 -30
  233. package/src/content/collection-match.ts +11 -9
  234. package/src/content/collection-pages.ts +412 -0
  235. package/src/content/content-collections.ts +270 -0
  236. package/src/content/draft-state.ts +4 -3
  237. package/src/content/entry-commands.ts +54 -62
  238. package/src/content/entry-editor.ts +137 -32
  239. package/src/content/entry-fields.ts +25 -8
  240. package/src/content/entry-inspector.ts +225 -0
  241. package/src/content/entry-model.ts +38 -15
  242. package/src/content/entry-open.ts +80 -0
  243. package/src/content/entry-summaries.ts +440 -0
  244. package/src/content/file-record-ids.ts +80 -0
  245. package/src/content/file-records.ts +125 -0
  246. package/src/content/page-summaries.ts +129 -0
  247. package/src/content/record-entry.ts +201 -0
  248. package/src/content/writing-banner.ts +177 -0
  249. package/src/create/add-new-commands.ts +185 -0
  250. package/src/create/add-new-flow.ts +1116 -0
  251. package/src/create/add-new.ts +1014 -0
  252. package/src/create/element-name.ts +121 -0
  253. package/src/editor/canvas-context-menu.ts +1 -2
  254. package/src/editor/canvas-slash-bridge.ts +3 -6
  255. package/src/editor/content-slice.ts +16 -14
  256. package/src/editor/context-menu.ts +35 -22
  257. package/src/editor/convert-targets.ts +30 -35
  258. package/src/editor/convert-to-component.ts +78 -48
  259. package/src/editor/convert-to-repeater.ts +34 -22
  260. package/src/editor/editable-tags.ts +17 -2
  261. package/src/editor/file-drop-action.ts +29 -22
  262. package/src/editor/inline-edit-apply.ts +79 -17
  263. package/src/editor/inline-edit.ts +76 -50
  264. package/src/editor/inline-format.ts +59 -56
  265. package/src/editor/inline-link.ts +40 -15
  266. package/src/editor/insert-component.ts +91 -0
  267. package/src/editor/insert-zone-action.ts +14 -5
  268. package/src/editor/merge-tags.ts +58 -19
  269. package/src/editor/repeater-scope.ts +39 -28
  270. package/src/editor/shortcuts.ts +76 -42
  271. package/src/editor/slash-menu.ts +52 -14
  272. package/src/files/asset-versions.ts +4 -4
  273. package/src/files/components.ts +89 -20
  274. package/src/files/elements.ts +5 -6
  275. package/src/files/file-ops.ts +92 -41
  276. package/src/files/files.ts +248 -239
  277. package/src/files/fs-events.ts +18 -7
  278. package/src/files/media-meta.ts +97 -2
  279. package/src/files/media-paths.ts +3 -0
  280. package/src/files/media-types.ts +55 -0
  281. package/src/files/media-upload.ts +209 -52
  282. package/src/files/new-file-name.ts +156 -0
  283. package/src/files/serialize-document.ts +15 -5
  284. package/src/format/constraints.ts +1 -1
  285. package/src/format/convert-file.ts +27 -13
  286. package/src/format/format-choices.ts +2 -1
  287. package/src/format/format-host.ts +91 -50
  288. package/src/github/github-auth-status.ts +27 -3
  289. package/src/github/github-auth.ts +21 -11
  290. package/src/github/github-publish.ts +28 -23
  291. package/src/grid/cell-editors.ts +46 -31
  292. package/src/grid/cell-popovers.ts +5 -3
  293. package/src/grid/edit-buffer.ts +10 -9
  294. package/src/grid/grid-controller.ts +25 -23
  295. package/src/grid/grid-layout.ts +21 -5
  296. package/src/grid/grid-open.ts +3 -33
  297. package/src/grid/grid-panel.ts +65 -6
  298. package/src/grid/grid-reveal.ts +34 -0
  299. package/src/grid/grid-source.ts +9 -31
  300. package/src/grid/grid-view.ts +45 -23
  301. package/src/grid/redirects-grid.ts +14 -5
  302. package/src/grid/redirects.ts +16 -14
  303. package/src/grid/schema-columns.ts +25 -19
  304. package/src/grid/sources/connector-source.ts +47 -20
  305. package/src/grid/sources/content-source.ts +100 -31
  306. package/src/grid/sources/csv-file-source.ts +2 -2
  307. package/src/grid/tabulator-tables.d.ts +61 -34
  308. package/src/hosting/document.ts +2 -2
  309. package/src/hosting/stage.ts +7 -7
  310. package/src/i18n/i18n-commands.ts +3 -3
  311. package/src/media/media-commands.ts +181 -0
  312. package/src/media/media-library-model.ts +232 -0
  313. package/src/media/media-library.ts +1283 -0
  314. package/src/media/media-pane.ts +51 -20
  315. package/src/new-project/add-repo-modal.ts +20 -19
  316. package/src/new-project/import-tab.ts +10 -14
  317. package/src/new-project/location-fields.ts +2 -1
  318. package/src/new-project/new-project-modal.ts +12 -9
  319. package/src/packages/jxsuite-update.ts +4 -3
  320. package/src/packages/pull-package-sync.ts +26 -25
  321. package/src/page-params.ts +97 -68
  322. package/src/panels/activity-panel.ts +38 -14
  323. package/src/panels/ai-chat/attached-context.ts +13 -7
  324. package/src/panels/ai-chat/chat-markdown.ts +8 -8
  325. package/src/panels/ai-chat/chat-view.ts +80 -73
  326. package/src/panels/ai-chat/composer.ts +30 -33
  327. package/src/panels/ai-chat/sessions-view.ts +1 -2
  328. package/src/panels/ai-panel.ts +23 -20
  329. package/src/panels/block-action-bar.ts +57 -46
  330. package/src/panels/bottom-dock.ts +5 -3
  331. package/src/panels/canvas-dnd-bridge.ts +36 -26
  332. package/src/panels/chat-panel.ts +6 -6
  333. package/src/panels/collections-panel.ts +306 -0
  334. package/src/panels/component-preview.ts +35 -13
  335. package/src/panels/data-explorer.ts +63 -26
  336. package/src/panels/data-grid.ts +18 -11
  337. package/src/panels/dnd.ts +115 -138
  338. package/src/panels/editors.ts +52 -21
  339. package/src/panels/elements-panel.ts +19 -5
  340. package/src/panels/empty-state.ts +2 -2
  341. package/src/panels/events-panel.ts +84 -69
  342. package/src/panels/formula-workspace.ts +78 -54
  343. package/src/panels/frontmatter-fields.ts +33 -28
  344. package/src/panels/git-diff-open.ts +10 -6
  345. package/src/panels/head-panel.ts +488 -202
  346. package/src/panels/i18n-panel.ts +20 -12
  347. package/src/panels/imports-panel.ts +25 -47
  348. package/src/panels/jump-bar.ts +75 -31
  349. package/src/panels/layers-panel.ts +130 -101
  350. package/src/panels/left-panel.ts +25 -11
  351. package/src/panels/navigator-panels.ts +23 -11
  352. package/src/panels/pane-context.ts +140 -49
  353. package/src/panels/pane-grid.ts +55 -26
  354. package/src/panels/panel-registry.ts +36 -46
  355. package/src/panels/properties-panel.ts +182 -124
  356. package/src/panels/quick-search.ts +53 -31
  357. package/src/panels/right-panel.ts +201 -45
  358. package/src/panels/seo-modal.ts +54 -125
  359. package/src/panels/settings-menu.ts +63 -61
  360. package/src/panels/settings-pane.ts +268 -162
  361. package/src/panels/signals-panel.ts +156 -135
  362. package/src/panels/site-model.ts +367 -0
  363. package/src/panels/site-panel.ts +638 -0
  364. package/src/panels/statement-editor.ts +230 -140
  365. package/src/panels/style-panel.ts +253 -206
  366. package/src/panels/style-utils.ts +114 -51
  367. package/src/panels/stylebook-doc.ts +195 -60
  368. package/src/panels/stylebook-layers-panel.ts +48 -89
  369. package/src/panels/stylebook-panel.ts +60 -27
  370. package/src/panels/styles-panel.ts +327 -0
  371. package/src/panels/tab-drop.ts +27 -11
  372. package/src/panels/tab-strip.ts +143 -49
  373. package/src/platform-errors.ts +57 -43
  374. package/src/platform.ts +59 -31
  375. package/src/platforms/cloud.ts +373 -176
  376. package/src/platforms/default-platform.ts +14 -8
  377. package/src/platforms/devserver.ts +180 -142
  378. package/src/platforms/read-batcher.ts +16 -8
  379. package/src/project-list.ts +2 -1
  380. package/src/publish/deploy-checklist.ts +20 -9
  381. package/src/publish/pages-service.ts +66 -27
  382. package/src/publish/publish-changes.ts +491 -0
  383. package/src/publish/publish-commands.ts +88 -22
  384. package/src/publish/publish-ids.ts +49 -0
  385. package/src/publish/publish-panel.ts +10 -6
  386. package/src/publish/publish-quick.ts +148 -0
  387. package/src/publish/publish-workspace.ts +926 -0
  388. package/src/publish/source-control.ts +907 -0
  389. package/src/recent-projects.ts +15 -8
  390. package/src/resize-edges.ts +26 -36
  391. package/src/services/a11y-report.ts +26 -19
  392. package/src/services/agent-seed.ts +23 -11
  393. package/src/services/ai-ask.ts +9 -12
  394. package/src/services/ai-command-tools.ts +68 -62
  395. package/src/services/ai-import-tools.ts +80 -67
  396. package/src/services/ai-models.ts +17 -13
  397. package/src/services/ai-project-tools.ts +68 -32
  398. package/src/services/ai-session-store.ts +19 -10
  399. package/src/services/ai-system-prompt.ts +46 -20
  400. package/src/services/ai-tools.ts +71 -27
  401. package/src/services/ai-write-report.ts +20 -12
  402. package/src/services/ai-writes.ts +4 -4
  403. package/src/services/automation.ts +74 -51
  404. package/src/services/cem-export.ts +149 -58
  405. package/src/services/cf-settings.ts +4 -4
  406. package/src/services/clock.ts +6 -1
  407. package/src/services/code-services.ts +37 -31
  408. package/src/services/connection.ts +2 -2
  409. package/src/services/context-manager.ts +14 -10
  410. package/src/services/context-resolver.ts +20 -8
  411. package/src/services/data-service.ts +19 -15
  412. package/src/services/directory-picker.ts +20 -14
  413. package/src/services/document-assistant.ts +39 -19
  414. package/src/services/gated-registry.ts +10 -6
  415. package/src/services/harness/chat-reducer.ts +23 -1
  416. package/src/services/import-client.ts +91 -38
  417. package/src/services/import-seed.ts +8 -2
  418. package/src/services/jx-validate.ts +28 -31
  419. package/src/services/live-preview.ts +0 -0
  420. package/src/services/live-surfaces.ts +6 -3
  421. package/src/services/model-uri.ts +10 -2
  422. package/src/services/module-preloads.ts +12 -8
  423. package/src/services/monaco-buffer.ts +43 -24
  424. package/src/services/monaco-lazy.ts +7 -8
  425. package/src/services/monaco-setup.ts +23 -16
  426. package/src/services/notify.ts +44 -17
  427. package/src/services/popover-report.ts +25 -10
  428. package/src/services/preview-eval.ts +20 -8
  429. package/src/services/profile.ts +13 -6
  430. package/src/services/project-path.ts +13 -10
  431. package/src/services/references.ts +0 -0
  432. package/src/services/render-critic.ts +29 -9
  433. package/src/services/settings/definitions.ts +25 -14
  434. package/src/services/settings/kernel.ts +13 -4
  435. package/src/services/settings/write-queue.ts +9 -9
  436. package/src/services/token-lint.ts +12 -10
  437. package/src/services/tool-executor.ts +17 -5
  438. package/src/services/tool-outcomes.ts +44 -24
  439. package/src/services/trusted-types.ts +24 -7
  440. package/src/settings/contexts-section.ts +11 -8
  441. package/src/settings/contributed-section.ts +128 -70
  442. package/src/settings/css-vars-editor.ts +119 -32
  443. package/src/settings/defs-editor.ts +38 -35
  444. package/src/settings/developer-panels.ts +43 -0
  445. package/src/settings/extension-rows.ts +16 -8
  446. package/src/settings/extension-sections.ts +42 -14
  447. package/src/settings/extensions-section.ts +4 -1
  448. package/src/settings/general-settings.ts +101 -28
  449. package/src/settings/locales-section.ts +20 -12
  450. package/src/settings/preferences-dialog.ts +17 -7
  451. package/src/settings/preferences-keymap.ts +7 -5
  452. package/src/settings/preferences-sections.ts +11 -5
  453. package/src/settings/project-sections.ts +28 -11
  454. package/src/settings/schema-field-ui.ts +12 -1
  455. package/src/settings/section-registry.ts +116 -11
  456. package/src/settings/settings-dialog.ts +192 -0
  457. package/src/settings/settings-document.ts +186 -166
  458. package/src/shell/tree.ts +6 -5
  459. package/src/shell.ts +536 -477
  460. package/src/site-context.ts +101 -32
  461. package/src/state.ts +68 -57
  462. package/src/store.ts +54 -34
  463. package/src/studio.ts +219 -116
  464. package/src/style/live-preview.ts +1 -1
  465. package/src/style/project-styles.ts +40 -7
  466. package/src/style/stylebook-specimens.ts +89 -0
  467. package/src/style/stylebook-target.ts +26 -0
  468. package/src/style/tag-inheritance.ts +105 -0
  469. package/src/style/token-ref.ts +5 -4
  470. package/src/style/variables-focus.ts +61 -0
  471. package/src/style/variables-view.ts +235 -0
  472. package/src/surfaces/about.ts +18 -19
  473. package/src/surfaces/add-new.json +1482 -0
  474. package/src/surfaces/add-new.ts +325 -0
  475. package/src/surfaces/add-repo.ts +17 -19
  476. package/src/surfaces/ai-chat.ts +33 -38
  477. package/src/surfaces/ai-credentials-form.ts +6 -16
  478. package/src/surfaces/ai-managed-connect.ts +3 -4
  479. package/src/surfaces/ai-model-picker.ts +3 -5
  480. package/src/surfaces/block-action-bar.ts +22 -11
  481. package/src/surfaces/boot-failure.json +4 -3
  482. package/src/surfaces/boot-failure.ts +4 -5
  483. package/src/surfaces/bottom-dock.json +1 -1
  484. package/src/surfaces/bottom-dock.ts +9 -18
  485. package/src/surfaces/canvas-stage.json +30 -19
  486. package/src/surfaces/canvas-stage.ts +17 -16
  487. package/src/surfaces/cf-account-picker.ts +17 -18
  488. package/src/surfaces/collections-panel.json +615 -0
  489. package/src/surfaces/collections-panel.ts +168 -0
  490. package/src/surfaces/commandbar.json +241 -96
  491. package/src/surfaces/commandbar.ts +145 -105
  492. package/src/surfaces/convert-repeater.ts +17 -19
  493. package/src/surfaces/data-actions.ts +9 -7
  494. package/src/surfaces/dialog.ts +26 -28
  495. package/src/surfaces/diff-toolbar.ts +9 -7
  496. package/src/surfaces/empty-state.json +1 -1
  497. package/src/surfaces/empty-state.ts +7 -10
  498. package/src/surfaces/entry-editor.json +136 -0
  499. package/src/surfaces/entry-editor.ts +35 -11
  500. package/src/surfaces/entry-inspector.json +371 -0
  501. package/src/surfaces/entry-inspector.ts +143 -0
  502. package/src/surfaces/expression-editor.ts +11 -25
  503. package/src/surfaces/files-panel.ts +27 -14
  504. package/src/surfaces/formula-palette.ts +4 -5
  505. package/src/surfaces/github-auth.ts +16 -20
  506. package/src/surfaces/github-publish.ts +17 -22
  507. package/src/surfaces/grid-cell.ts +30 -31
  508. package/src/surfaces/grid-open.ts +10 -14
  509. package/src/surfaces/grid-panel.ts +13 -9
  510. package/src/surfaces/grid-replace.ts +13 -13
  511. package/src/surfaces/grid-views.ts +15 -18
  512. package/src/surfaces/inspector-dock.json +162 -14
  513. package/src/surfaces/inspector-dock.ts +59 -31
  514. package/src/surfaces/jump-bar.ts +5 -6
  515. package/src/surfaces/jxsuite-update.ts +16 -22
  516. package/src/surfaces/library-pane.json +670 -437
  517. package/src/surfaces/library-pane.ts +111 -77
  518. package/src/surfaces/logic-panel.ts +17 -30
  519. package/src/surfaces/logic-workspace.ts +13 -15
  520. package/src/surfaces/media-browser.json +62 -6
  521. package/src/surfaces/media-browser.ts +26 -11
  522. package/src/surfaces/media-field.json +1 -1
  523. package/src/surfaces/media-field.ts +4 -5
  524. package/src/surfaces/media-library.json +1586 -0
  525. package/src/surfaces/media-library.ts +282 -0
  526. package/src/surfaces/media-pane.ts +8 -7
  527. package/src/surfaces/media-pick-dialog.json +71 -0
  528. package/src/surfaces/media-pick-dialog.ts +132 -0
  529. package/src/surfaces/menu.ts +47 -23
  530. package/src/surfaces/navigator-dock.ts +11 -12
  531. package/src/surfaces/new-project.ts +27 -26
  532. package/src/surfaces/pane-context.json +144 -77
  533. package/src/surfaces/pane-context.ts +44 -25
  534. package/src/surfaces/pane-grid.ts +15 -10
  535. package/src/surfaces/panel-activity.ts +5 -6
  536. package/src/surfaces/panel-data.ts +3 -4
  537. package/src/surfaces/panel-deploy-checklist.json +12 -6
  538. package/src/surfaces/panel-deploy-checklist.ts +8 -7
  539. package/src/surfaces/panel-elements.ts +5 -7
  540. package/src/surfaces/panel-i18n.ts +5 -7
  541. package/src/surfaces/panel-imports.ts +6 -13
  542. package/src/surfaces/panel-outline.ts +25 -19
  543. package/src/surfaces/panel-page.json +72 -2
  544. package/src/surfaces/panel-page.ts +49 -25
  545. package/src/surfaces/panel-problems.ts +5 -7
  546. package/src/surfaces/panel-signals.json +1 -1
  547. package/src/surfaces/panel-signals.ts +25 -39
  548. package/src/surfaces/panel-stylebook-layers.json +71 -204
  549. package/src/surfaces/panel-stylebook-layers.ts +5 -29
  550. package/src/surfaces/preferences.json +120 -48
  551. package/src/surfaces/preferences.ts +29 -11
  552. package/src/surfaces/progress-modal.ts +15 -9
  553. package/src/surfaces/properties-panel.json +1 -1
  554. package/src/surfaces/properties-panel.ts +20 -42
  555. package/src/surfaces/publish-quick.json +428 -0
  556. package/src/surfaces/publish-quick.ts +165 -0
  557. package/src/surfaces/publish-workspace.json +2892 -0
  558. package/src/surfaces/publish-workspace.ts +391 -0
  559. package/src/surfaces/publish.ts +18 -18
  560. package/src/surfaces/push-plan.ts +7 -8
  561. package/src/surfaces/rail.json +1 -159
  562. package/src/surfaces/rail.ts +22 -79
  563. package/src/surfaces/reference-field.ts +11 -15
  564. package/src/surfaces/schema-builder.ts +16 -22
  565. package/src/surfaces/schema-form.json +10 -2
  566. package/src/surfaces/schema-form.ts +17 -25
  567. package/src/surfaces/secret-field.ts +9 -6
  568. package/src/surfaces/seo.json +1 -1
  569. package/src/surfaces/seo.ts +21 -15
  570. package/src/surfaces/settings-contexts.ts +9 -7
  571. package/src/surfaces/settings-contributed.json +5 -5
  572. package/src/surfaces/settings-contributed.ts +32 -12
  573. package/src/surfaces/settings-css-vars.json +44 -36
  574. package/src/surfaces/settings-css-vars.ts +82 -16
  575. package/src/surfaces/settings-defs.json +2 -2
  576. package/src/surfaces/settings-defs.ts +17 -21
  577. package/src/surfaces/settings-deploy.json +2 -15
  578. package/src/surfaces/settings-deploy.ts +9 -16
  579. package/src/surfaces/settings-dialog.json +51 -0
  580. package/src/surfaces/settings-dialog.ts +169 -0
  581. package/src/surfaces/settings-extensions.ts +5 -6
  582. package/src/surfaces/settings-head.ts +33 -39
  583. package/src/surfaces/settings-locales.ts +8 -20
  584. package/src/surfaces/settings-overview.json +3 -3
  585. package/src/surfaces/settings-overview.ts +14 -8
  586. package/src/surfaces/settings-packages.ts +8 -7
  587. package/src/surfaces/settings-pane.json +269 -46
  588. package/src/surfaces/settings-pane.ts +88 -36
  589. package/src/surfaces/settings-rawjson.ts +5 -6
  590. package/src/surfaces/shell.json +2 -1
  591. package/src/surfaces/shell.ts +1 -2
  592. package/src/surfaces/site-panel.json +1029 -0
  593. package/src/surfaces/site-panel.ts +233 -0
  594. package/src/surfaces/slash-menu.json +63 -21
  595. package/src/surfaces/slash-menu.ts +42 -9
  596. package/src/surfaces/statements.ts +13 -18
  597. package/src/surfaces/statusbar.ts +56 -29
  598. package/src/surfaces/style-panel.ts +18 -31
  599. package/src/surfaces/stylebook-chrome.ts +3 -5
  600. package/src/surfaces/styles-panel.json +735 -0
  601. package/src/surfaces/styles-panel.ts +195 -0
  602. package/src/surfaces/styles-variables.json +149 -0
  603. package/src/surfaces/styles-variables.ts +145 -0
  604. package/src/surfaces/tab-strip.json +4 -4
  605. package/src/surfaces/tab-strip.ts +14 -13
  606. package/src/surfaces/target-line.ts +6 -7
  607. package/src/surfaces/welcome.ts +6 -8
  608. package/src/surfaces/writing-banner.json +94 -0
  609. package/src/surfaces/writing-banner.ts +80 -0
  610. package/src/tabs/bare-repeaters.ts +101 -0
  611. package/src/tabs/patch-ops.ts +4 -3
  612. package/src/tabs/project-config.ts +32 -21
  613. package/src/tabs/selection.ts +36 -8
  614. package/src/tabs/tab.ts +99 -48
  615. package/src/tabs/transact.ts +98 -53
  616. package/src/types.ts +53 -43
  617. package/src/ui/ai-credentials-form.ts +10 -13
  618. package/src/ui/ai-model-picker.ts +3 -3
  619. package/src/ui/cf-account-picker.ts +7 -9
  620. package/src/ui/color-selector.ts +9 -5
  621. package/src/ui/dynamic-slot.ts +7 -8
  622. package/src/ui/expression-editor.ts +112 -105
  623. package/src/ui/form-controls.ts +104 -56
  624. package/src/ui/formula-catalog.ts +239 -230
  625. package/src/ui/formula-chips.ts +33 -18
  626. package/src/ui/layers.ts +57 -31
  627. package/src/ui/media-picker.ts +300 -47
  628. package/src/ui/popover-surface.ts +20 -12
  629. package/src/ui/progress-modal.ts +13 -8
  630. package/src/ui/regions.ts +14 -12
  631. package/src/ui/schema-form.ts +372 -97
  632. package/src/ui/surface.ts +71 -8
  633. package/src/ui/timing.ts +9 -0
  634. package/src/ui/value-source.ts +44 -31
  635. package/src/ui/virtual-window.ts +29 -3
  636. package/src/utils/base64.ts +6 -4
  637. package/src/utils/edit-display.ts +366 -111
  638. package/src/utils/element-selectors.ts +3 -2
  639. package/src/utils/google-fonts.ts +15 -14
  640. package/src/utils/inherited-style.ts +18 -20
  641. package/src/utils/link-target.ts +1 -1
  642. package/src/utils/local-day.ts +18 -0
  643. package/src/utils/preview-format.ts +25 -3
  644. package/src/utils/strip-events.ts +49 -22
  645. package/src/utils/studio-utils.ts +29 -14
  646. package/src/view.ts +2 -3
  647. package/src/workspace/pane-derive.ts +14 -16
  648. package/src/workspace/session.ts +81 -50
  649. package/src/workspace/tab-workspace.ts +137 -0
  650. package/src/workspace/workspace-back.ts +189 -0
  651. package/src/workspace/workspace-home.ts +133 -0
  652. package/src/workspace/workspace-ids.ts +129 -0
  653. package/src/workspace/workspace-switch.ts +372 -0
  654. package/src/workspace/workspace.ts +165 -47
  655. package/styles/shell-frame.css +30 -7
  656. package/styles/shell-frame.json +15 -3
  657. package/dist/chunks/2020-va2wwra4.js +0 -4
  658. package/dist/chunks/adapter-f93pafd7.js +0 -4
  659. package/dist/chunks/cf-account-picker-af1h381v.js +0 -4
  660. package/dist/chunks/cf-settings-125tdm0w.js +0 -4
  661. package/dist/chunks/color-area-jqhna8zy.js +0 -4
  662. package/dist/chunks/color-field-embq5ctg.js +0 -4
  663. package/dist/chunks/color-fpezvnkt.js +0 -4
  664. package/dist/chunks/color-slider-1qmw7wqy.js +0 -4
  665. package/dist/chunks/combobox-773hdzyj.js +0 -4
  666. package/dist/chunks/components-ax2f1fnn.js +0 -4
  667. package/dist/chunks/content-source-108aqtk1.js +0 -4
  668. package/dist/chunks/convert-to-repeater-ry5rmppr.js +0 -4
  669. package/dist/chunks/dialog-mtm9fq5t.js +0 -4
  670. package/dist/chunks/editor-pfgdmkb0.js +0 -4
  671. package/dist/chunks/entry-commands-t0k1q0kx.js +0 -4
  672. package/dist/chunks/extension-sections-6mwh2hf8.js +0 -4
  673. package/dist/chunks/file-ops-meej5mqf.js +0 -4
  674. package/dist/chunks/files-44vp8a2s.js +0 -4
  675. package/dist/chunks/format-host-7q1petb9.js +0 -4
  676. package/dist/chunks/fs-events-h2mwnxaz.js +0 -4
  677. package/dist/chunks/git-panel-zngbymvd.js +0 -4
  678. package/dist/chunks/grid-view-sx9vynsp.js +0 -51
  679. package/dist/chunks/icons-p44xhjf0.js +0 -4
  680. package/dist/chunks/iframe-entry-f7mqjwpm.js +0 -5
  681. package/dist/chunks/iframe-entry-haw7jkvz.js +0 -5
  682. package/dist/chunks/iframe-entry-z6qrytv3.js +0 -5
  683. package/dist/chunks/iframe-host-qk3ycq87.js +0 -4
  684. package/dist/chunks/index-wkyfjeqz.js +0 -4
  685. package/dist/chunks/jsonMode-s8kt9dsj.js +0 -13
  686. package/dist/chunks/jx-validate-psgd7vsx.js +0 -4
  687. package/dist/chunks/layers-panel-1kq2jyfk.js +0 -4
  688. package/dist/chunks/layers-xd92fg8d.js +0 -4
  689. package/dist/chunks/listbox-s8fkmnq8.js +0 -4
  690. package/dist/chunks/lit-html-ac4cwwr4.js +0 -4
  691. package/dist/chunks/media-picker-0svzkdyb.js +0 -4
  692. package/dist/chunks/menu-37d07z9m.js +0 -4
  693. package/dist/chunks/menu-5c55ea3d.js +0 -4
  694. package/dist/chunks/monaco-binding-z6r70pdt.js +0 -4
  695. package/dist/chunks/monaco-buffer-fz6gq5y7.js +0 -4
  696. package/dist/chunks/monaco-setup-q4axkgj7.js +0 -4
  697. package/dist/chunks/notify-0xgtn8q1.js +0 -4
  698. package/dist/chunks/number-field-gw7sq8rn.js +0 -4
  699. package/dist/chunks/parse-897fvqah.js +0 -4
  700. package/dist/chunks/platform-v1qctbe6.js +0 -4
  701. package/dist/chunks/popover-8htra4er.js +0 -4
  702. package/dist/chunks/publish-panel-ym1fmgq5.js +0 -4
  703. package/dist/chunks/quick-search-a54e6t5n.js +0 -4
  704. package/dist/chunks/references-gmqp82fs.js +0 -4
  705. package/dist/chunks/right-panel-v7t9awbk.js +0 -4
  706. package/dist/chunks/section-registry-vhyf3zsr.js +0 -4
  707. package/dist/chunks/select-n3v7gwas.js +0 -4
  708. package/dist/chunks/split-pff8f3ze.js +0 -4
  709. package/dist/chunks/studio-0bhx5hz6.js +0 -5
  710. package/dist/chunks/studio-0k1ddnyy.js +0 -6
  711. package/dist/chunks/studio-1b04pd0j.js +0 -64
  712. package/dist/chunks/studio-4dwbj6gb.js +0 -5
  713. package/dist/chunks/studio-4tanh828.js +0 -5
  714. package/dist/chunks/studio-55h4mstj.js +0 -4
  715. package/dist/chunks/studio-5tnvjkz4.js +0 -5
  716. package/dist/chunks/studio-60dqgb0c.js +0 -5
  717. package/dist/chunks/studio-61dp09qg.js +0 -9
  718. package/dist/chunks/studio-63epcrj2.js +0 -5
  719. package/dist/chunks/studio-74k29dy9.js +0 -5
  720. package/dist/chunks/studio-7vg6jcd3.js +0 -5
  721. package/dist/chunks/studio-7zx31knw.js +0 -9
  722. package/dist/chunks/studio-8bxk97km.js +0 -5
  723. package/dist/chunks/studio-933e30n4.js +0 -5
  724. package/dist/chunks/studio-98wnwhbg.js +0 -5
  725. package/dist/chunks/studio-9mccjwjh.js +0 -14
  726. package/dist/chunks/studio-a2ke1e4t.js +0 -5
  727. package/dist/chunks/studio-e3a2a6v3.js +0 -4
  728. package/dist/chunks/studio-e81q1vb9.js +0 -5
  729. package/dist/chunks/studio-epgrmqqm.js +0 -5
  730. package/dist/chunks/studio-ery42sqr.js +0 -4
  731. package/dist/chunks/studio-g1shz58g.js +0 -5
  732. package/dist/chunks/studio-gf0fz03c.js +0 -5
  733. package/dist/chunks/studio-gjtpe62q.js +0 -6
  734. package/dist/chunks/studio-gkskhg7m.js +0 -5
  735. package/dist/chunks/studio-gx4dnjzd.js +0 -5
  736. package/dist/chunks/studio-j03zga3y.js +0 -9
  737. package/dist/chunks/studio-jhpxeckz.js +0 -5
  738. package/dist/chunks/studio-k01r7ykp.js +0 -5
  739. package/dist/chunks/studio-kk7h30ne.js +0 -7
  740. package/dist/chunks/studio-kt1zqney.js +0 -5
  741. package/dist/chunks/studio-m3cwhvye.js +0 -5
  742. package/dist/chunks/studio-mcayt6hz.js +0 -5
  743. package/dist/chunks/studio-myjcghv3.js +0 -5
  744. package/dist/chunks/studio-n8bxwc3y.js +0 -4
  745. package/dist/chunks/studio-ngm8gvpb.js +0 -5
  746. package/dist/chunks/studio-nj5a01jy.js +0 -928
  747. package/dist/chunks/studio-pcgz8heb.js +0 -5
  748. package/dist/chunks/studio-qcsq0t15.js +0 -5
  749. package/dist/chunks/studio-qkstvve9.js +0 -5
  750. package/dist/chunks/studio-qv1pwd3c.js +0 -5
  751. package/dist/chunks/studio-rc6dvxjb.js +0 -7
  752. package/dist/chunks/studio-s8dmmz66.js +0 -5
  753. package/dist/chunks/studio-sp5xzbj4.js +0 -6
  754. package/dist/chunks/studio-szsjbj0g.js +0 -5
  755. package/dist/chunks/studio-t1xzawhr.js +0 -16
  756. package/dist/chunks/studio-tdcprbqb.js +0 -5
  757. package/dist/chunks/studio-vrmcjf9g.js +0 -7
  758. package/dist/chunks/studio-vyc0b4he.js +0 -10
  759. package/dist/chunks/studio-w0cgf6jg.js +0 -5
  760. package/dist/chunks/studio-w3hskzqk.js +0 -5
  761. package/dist/chunks/studio-xgrgcdyh.js +0 -9
  762. package/dist/chunks/studio-xz2yxfcb.js +0 -5
  763. package/dist/chunks/studio-y6n42tgs.js +0 -5
  764. package/dist/chunks/studio-yb560vxr.js +0 -5
  765. package/dist/chunks/studio-yn9f8vtx.js +0 -5
  766. package/dist/chunks/studio-yw05w8f0.js +0 -7
  767. package/dist/chunks/studio-z16sgavc.js +0 -5
  768. package/dist/chunks/studio-zey7zsdw.js +0 -12
  769. package/dist/chunks/studio-zyqn40w4.js +0 -5
  770. package/dist/chunks/swatch-group-8qh9a3bm.js +0 -4
  771. package/dist/chunks/tabs-jwthg40w.js +0 -4
  772. package/dist/chunks/textfield-spy3hc77.js +0 -4
  773. package/dist/chunks/toast-4d35zd64.js +0 -4
  774. package/dist/chunks/toast-host-8sjmfed3.js +0 -4
  775. package/dist/chunks/tooltip-fd6g9xy3.js +0 -4
  776. package/dist/chunks/tree-h19v1jfz.js +0 -4
  777. package/dist/chunks/tsMode-2frah6h1.js +0 -14
  778. package/dist/chunks/workspace-zt81g1ms.js +0 -4
  779. package/dist/chunks/ws-client-n2bh4hkf.js +0 -4
  780. package/src/panels/frontmatter-panel.ts +0 -701
  781. package/src/panels/git-panel.ts +0 -1120
  782. package/src/surfaces/doc-header.json +0 -776
  783. package/src/surfaces/doc-header.ts +0 -231
  784. package/src/surfaces/git-panel.json +0 -1880
  785. package/src/surfaces/git-panel.ts +0 -272
@@ -1,11 +1,18 @@
1
1
  /// <reference lib="dom" />
2
2
  /**
3
- * Media Picker — the project's media, and the two surfaces that offer them.
3
+ * Media Picker — the project's media, and the compact surfaces that offer them.
4
4
  *
5
5
  * The FIELD (`surfaces/media-field.json`) is a control a row draws: a thumbnail of what the value
6
6
  * names, the value itself, an Upload button that adds a new file to the project and assigns it, and
7
- * a Browse button. The BROWSER (`surfaces/media-browser.json`) is the panel Browse opens: a search
8
- * box over the files under `public/`, with thumbnail previews for images.
7
+ * a Browse button. The BROWSER (`surfaces/media-browser.json`) is the compact panel Browse opens: a
8
+ * search box over the project's media, with thumbnail previews for images, and a last row, **Browse
9
+ * all media…**, that opens the Media workspace's own surface in a dialog in pick mode
10
+ * (`media/media-library.ts`, studio.md §9.3). One picker, two sizes.
11
+ *
12
+ * **What media the project has is answered here, once.** {@link projectMediaFiles} walks
13
+ * `public/**` and every collection's `content/<collection>/images/**`, and the Media workspace, the
14
+ * Site panel's Media section, both pickers and the search-appearance dialog all read that one
15
+ * listing, so "what media does this project have" cannot have two answers in two choosers.
9
16
  *
10
17
  * **This module is the flow, not the markup.** Both surfaces are Jx documents now; what is left
11
18
  * here is which files count as media, what a row's caption says, how long a keystroke waits before
@@ -20,13 +27,13 @@
20
27
  * `<img>` has finished by the time `load` fires, so the caption is a read of work already done
21
28
  * rather than a second fetch per row. What is NOT here is a usage count: `findReferences` sweeps
22
29
  * every document in the project per query, and fifty of those to caption a list is the wrong trade.
23
- * Usage is asked once, about one file, where it changes a decision — the delete confirmation
24
- * (`files/media-usage.ts`).
30
+ * Usage is asked about one file where it changes a decision (the delete confirmation, the Media
31
+ * workspace's detail pane), and about every file only when the reader asks for **Unused**.
25
32
  *
26
33
  * @docs studio/projects/media
27
34
  */
28
35
 
29
- import { getPlatform } from "../platform";
36
+ import { getPlatform, hasPlatform } from "../platform";
30
37
  import { debouncedStyleCommit, renderOnly } from "../store";
31
38
  import { mountMediaFieldSurface } from "../surfaces/media-field";
32
39
  import { openMediaBrowserSurface } from "../surfaces/media-browser";
@@ -35,12 +42,15 @@ import { previewAssetSrc } from "../canvas/asset-refs";
35
42
  import {
36
43
  IMAGE_EXTENSIONS,
37
44
  MEDIA_EXTENSIONS,
38
- uploadAccept,
39
45
  extensionOf,
46
+ mediaFileKind,
47
+ uploadAccept,
40
48
  uploadAssets,
41
49
  } from "../files/media-upload";
42
50
  import {
43
51
  invalidateMediaMeta,
52
+ loadMediaMeta,
53
+ mediaMetaSettled,
44
54
  mediaMetaSummary,
45
55
  peekMediaMeta,
46
56
  recordImageSize,
@@ -48,24 +58,51 @@ import {
48
58
  } from "../files/media-meta";
49
59
  import { mediaSiteUrl, previewFileSrc } from "../files/media-paths";
50
60
  import { notedListing } from "../files/asset-versions";
51
- import type { MediaBrowserRow, MediaBrowserSurfaceHandle } from "../surfaces/media-browser";
61
+ import type { MediaFileKind } from "../files/media-upload";
62
+ import type {
63
+ MediaBrowserRow,
64
+ MediaBrowserSurfaceHandle,
65
+ MediaBrowserView,
66
+ } from "../surfaces/media-browser";
52
67
  import type { MediaFieldHandle, MediaFieldView } from "../surfaces/media-field";
68
+ import type * as MediaLibraryModule from "../media/media-library";
53
69
 
54
70
  // ─── Media file cache ────────────────────────────────────────────────────────
55
71
 
56
- /** One browsable media file: the ref a pick writes, and the file that ref names. */
57
- interface MediaEntry {
58
- /** The value committed to the field — the site URL, which is the authored form. */
59
- path: string;
60
- /** Project-relative path on disk, the key everything in `media-meta` is stored under. */
72
+ /** One media file of the project, as every browsing surface lists it. */
73
+ export interface ProjectMediaFile {
74
+ /** The project-relative path on disk, the key everything in `media-meta` is stored under. */
61
75
  file: string;
62
76
  name: string;
77
+ /** The site URL a document authors for it, which is what a pick commits. */
78
+ ref: string;
63
79
  isImage: boolean;
80
+ /** What the file is, as the Media workspace's filters name it. */
81
+ kind: MediaFileKind;
64
82
  }
65
83
 
66
- let mediaCache: MediaEntry[] = [];
84
+ let mediaCache: ProjectMediaFile[] = [];
67
85
  let mediaCacheLoaded = false;
68
86
 
87
+ /**
88
+ * The directory every collection co-locates its uploads in (`files/media-upload.ts`
89
+ * `uploadDirFor`).
90
+ */
91
+ const COLLECTION_IMAGES = "images";
92
+
93
+ /**
94
+ * Whether a project path is inside the media scan: under `public/`, or under a collection's
95
+ * `content/<collection>/images/`. A filesystem batch that touches neither cannot change what
96
+ * {@link projectMediaFiles} lists, so the listing is kept.
97
+ */
98
+ export function isMediaScanPath(path: string): boolean {
99
+ const normalized = path.replaceAll("\\", "/");
100
+ return (
101
+ normalized.startsWith("public/") ||
102
+ new RegExp(`^content/[^/]+/${COLLECTION_IMAGES}/`).test(normalized)
103
+ );
104
+ }
105
+
69
106
  /**
70
107
  * Recursively collect media files from a directory, seeding {@link seedMediaMeta} with the listing
71
108
  * on the way past — the size of every row is already in the response that enumerated it.
@@ -73,8 +110,8 @@ let mediaCacheLoaded = false;
73
110
  async function collectMedia(
74
111
  dir: string,
75
112
  platform: ReturnType<typeof getPlatform>,
76
- ): Promise<MediaEntry[]> {
77
- const results: MediaEntry[] = [];
113
+ ): Promise<ProjectMediaFile[]> {
114
+ const results: ProjectMediaFile[] = [];
78
115
  try {
79
116
  const entries = await notedListing(() => platform.listDirectory(dir));
80
117
  seedMediaMeta(entries);
@@ -88,10 +125,11 @@ async function collectMedia(
88
125
  results.push({
89
126
  file: entry.path,
90
127
  isImage: IMAGE_EXTENSIONS.has(ext),
128
+ kind: mediaFileKind(entry.name),
91
129
  name: entry.name,
92
130
  // The site URL is what production serves and therefore what a document should say.
93
- // Media-paths holds the one definition of that mapping.
94
- path: mediaSiteUrl(entry.path),
131
+ // Media-paths holds the one definition of that mapping, a collection's mount included.
132
+ ref: mediaSiteUrl(entry.path),
95
133
  });
96
134
  }
97
135
  }
@@ -102,16 +140,141 @@ async function collectMedia(
102
140
  return results;
103
141
  }
104
142
 
105
- async function loadMediaCache() {
143
+ /**
144
+ * Every collection's co-located `images/` folder: `content/<collection>/images/**`.
145
+ *
146
+ * Listed from `content/` itself rather than from `project.json`'s declarations, because the folder
147
+ * is where an upload from an entry lands whatever its collection's `source` says, and a picker that
148
+ * could not see it could not choose a cover image the author had just uploaded to an entry.
149
+ */
150
+ async function collectCollectionImages(
151
+ platform: ReturnType<typeof getPlatform>,
152
+ ): Promise<ProjectMediaFile[]> {
153
+ let collections: string[];
154
+ try {
155
+ const entries = await platform.listDirectory("content");
156
+ collections = entries.filter((entry) => entry.type === "directory").map((entry) => entry.path);
157
+ } catch {
158
+ return [];
159
+ }
160
+ const results: ProjectMediaFile[] = [];
161
+ for (const dir of collections) {
162
+ /* Descend only into an `images/` the collection actually holds: most collections have none,
163
+ and asking the backend to list a directory that does not exist is a 404 in the console. */
164
+ let holdsImages = false;
165
+ try {
166
+ const entries = await platform.listDirectory(dir);
167
+ holdsImages = entries.some(
168
+ (entry) => entry.type === "directory" && entry.name === COLLECTION_IMAGES,
169
+ );
170
+ } catch {
171
+ // An unreadable collection folder has no images to offer.
172
+ }
173
+ if (holdsImages) {
174
+ results.push(...(await collectMedia(`${dir}/${COLLECTION_IMAGES}`, platform)));
175
+ }
176
+ }
177
+ return results;
178
+ }
179
+
180
+ /**
181
+ * Which of the two scan roots, `public` and `content`, the project root holds as folders. A root
182
+ * listing that fails says nothing either way, so both are then walked, each tolerating its own
183
+ * absence as it always has.
184
+ */
185
+ async function projectScanRoots(platform: ReturnType<typeof getPlatform>): Promise<Set<string>> {
186
+ try {
187
+ const entries = await platform.listDirectory(".");
188
+ return new Set(
189
+ entries
190
+ .filter((entry) => entry.type === "directory")
191
+ .map((entry) => entry.name)
192
+ .filter((name) => name === "public" || name === "content"),
193
+ );
194
+ } catch {
195
+ return new Set(["public", "content"]);
196
+ }
197
+ }
198
+
199
+ /** The walk in flight, so every caller that asks while it runs shares it instead of starting one. */
200
+ let _mediaLoading: Promise<void> | null = null;
201
+ /** Bumped by {@link invalidateMediaCache}, so a walk that started before it cannot land after it. */
202
+ let _mediaEpoch = 0;
203
+
204
+ /** Surfaces that own their own repaint and want to hear when the listing moves. */
205
+ const _listeners = new Set<() => void>();
206
+
207
+ /**
208
+ * Hear about every change to the listing: a walk landing, or an invalidation dropping it.
209
+ *
210
+ * For a surface that is not one of the named panels {@link loadMediaCache} repaints — the Media
211
+ * workspace's library, which owns its own reactivity the way the Library pane does.
212
+ *
213
+ * @returns The unsubscribe.
214
+ */
215
+ export function onProjectMediaChange(listener: () => void): () => void {
216
+ _listeners.add(listener);
217
+ return () => {
218
+ _listeners.delete(listener);
219
+ };
220
+ }
221
+
222
+ function announce(): void {
223
+ for (const listener of _listeners) {
224
+ listener();
225
+ }
226
+ }
227
+
228
+ function loadMediaCache(): Promise<void> {
106
229
  if (mediaCacheLoaded) {
107
- return;
230
+ return Promise.resolve();
231
+ }
232
+ if (_mediaLoading) {
233
+ return _mediaLoading;
108
234
  }
109
- const platform = getPlatform();
110
- mediaCache = await collectMedia("public", platform);
111
- mediaCacheLoaded = true;
112
- // Re-render the host panels so the browse panel has entries to show once the async listing
113
- // Resolves. Mirrors loadLayoutEntries()'s renderOnly() in head-panel.
114
- renderOnly("leftPanel", "rightPanel", "frontmatterPanel");
235
+ if (!hasPlatform()) {
236
+ // No backend to list (a window still booting): nothing is known, and nothing is claimed.
237
+ return Promise.resolve();
238
+ }
239
+ const epoch = _mediaEpoch;
240
+ const walk = (async () => {
241
+ const platform = getPlatform();
242
+ /* Descend only into the scan roots the project actually has: a project with no `content/` (a
243
+ site of pages alone) or no `public/` would otherwise ask the backend to list a folder that
244
+ does not exist, which is a 404 in the console on every visit to Media. */
245
+ const roots = await projectScanRoots(platform);
246
+ const [published, collections] = await Promise.all([
247
+ roots.has("public") ? collectMedia("public", platform) : [],
248
+ roots.has("content") ? collectCollectionImages(platform) : [],
249
+ ]);
250
+ if (epoch !== _mediaEpoch) {
251
+ // Superseded: this listing is older than the invalidation, and a newer walk owns the cache.
252
+ return;
253
+ }
254
+ mediaCache = [...published, ...collections];
255
+ mediaCacheLoaded = true;
256
+ _mediaLoading = null;
257
+ // Re-render the host panels so the browse panel has entries to show once the async listing
258
+ // Resolves. Mirrors loadLayoutEntries()'s renderOnly() in head-panel.
259
+ renderOnly("leftPanel", "rightPanel");
260
+ announce();
261
+ })();
262
+ _mediaLoading = walk;
263
+ return walk;
264
+ }
265
+
266
+ /**
267
+ * The project's media, or `null` while the listing is still being read — the same cache the picker
268
+ * browses, so the Site panel's Media section, the Media workspace and the image field cannot
269
+ * disagree about what exists. Asking starts the read; it repaints the panels that read it when it
270
+ * lands, and tells every {@link onProjectMediaChange} listener.
271
+ */
272
+ export function projectMediaFiles(): readonly ProjectMediaFile[] | null {
273
+ if (!mediaCacheLoaded) {
274
+ void loadMediaCache();
275
+ return null;
276
+ }
277
+ return mediaCache;
115
278
  }
116
279
 
117
280
  /**
@@ -123,30 +286,74 @@ async function loadMediaCache() {
123
286
  export function invalidateMediaCache() {
124
287
  mediaCache = [];
125
288
  mediaCacheLoaded = false;
289
+ _mediaEpoch += 1;
290
+ _mediaLoading = null;
126
291
  invalidateMediaMeta();
292
+ announce();
293
+ }
294
+
295
+ // ─── The full-size picker ────────────────────────────────────────────────────
296
+
297
+ /** What a chooser offers: every media file, or only images, for a field whose value is a picture. */
298
+ export interface MediaPickOptions {
299
+ images?: boolean;
300
+ }
301
+
302
+ /**
303
+ * The library flow, imported on the first **Browse all media…**. One cached promise, because two
304
+ * dynamic imports of a module in flight at once is the shape that loses its coverage record, and a
305
+ * field nobody opened the big picker from should not load the workspace's surface.
306
+ */
307
+ let _library: Promise<typeof MediaLibraryModule> | null = null;
308
+
309
+ function mediaLibrary(): Promise<typeof MediaLibraryModule> {
310
+ _library ??= import("../media/media-library");
311
+ return _library;
312
+ }
313
+
314
+ /**
315
+ * Open the Media workspace's surface in a dialog, in pick mode, and commit what is chosen.
316
+ *
317
+ * @param {(val: string) => void} onCommit - What a pick writes: the file's site URL
318
+ * @param {MediaPickOptions} options - Images only, for a field that holds a picture
319
+ */
320
+ export async function openFullMediaPicker(
321
+ onCommit: (val: string) => void,
322
+ options: MediaPickOptions = {},
323
+ ): Promise<void> {
324
+ const library = await mediaLibrary();
325
+ library.openMediaPickDialog({ images: options.images === true, onPick: onCommit });
127
326
  }
128
327
 
129
328
  // ─── The browser ─────────────────────────────────────────────────────────────
130
329
 
131
- /** The most rows the panel lists. Everything past it is counted rather than drawn. */
330
+ /**
331
+ * How many rows the panel lists at first, and how many more each **Show N more** adds. Past the cap
332
+ * the rows are counted, and the count is the control that lists them, so every file the Media
333
+ * workspace has can be reached from here: the cap bounds the first paint, never the answer.
334
+ */
132
335
  const BROWSE_LIMIT = 50;
133
336
 
134
337
  /** The open panel, and what a pick in it commits. One at a time. */
135
338
  let _browser: MediaBrowserSurfaceHandle | null = null;
136
339
  let _browserCommit: ((value: string) => void) | null = null;
137
340
  let _browserFilter = "";
341
+ /** How many rows the open panel lists; raised by Show more, and never lowered while it is open. */
342
+ let _browserLimit = BROWSE_LIMIT;
343
+ let _browserOptions: MediaPickOptions = {};
138
344
  /** Where the panel was opened, kept so a filter keystroke does not move it. */
139
345
  let _browserOrigin = { x: 0, y: 0 };
140
346
 
141
347
  /** What the panel shows for the filter that stands now. */
142
- function browserView() {
348
+ function browserView(): MediaBrowserView {
143
349
  const query = _browserFilter.toLowerCase();
350
+ const offered = _browserOptions.images ? mediaCache.filter((m) => m.isImage) : mediaCache;
144
351
  const filtered = query
145
- ? mediaCache.filter(
146
- (m) => m.path.toLowerCase().includes(query) || m.name.toLowerCase().includes(query),
352
+ ? offered.filter(
353
+ (m) => m.ref.toLowerCase().includes(query) || m.name.toLowerCase().includes(query),
147
354
  )
148
- : mediaCache;
149
- const listed = filtered.slice(0, BROWSE_LIMIT);
355
+ : offered;
356
+ const listed = filtered.slice(0, _browserLimit);
150
357
  const rows: MediaBrowserRow[] = listed.map((m) => {
151
358
  const caption = mediaMetaSummary(peekMediaMeta(m.file));
152
359
  return {
@@ -155,18 +362,26 @@ function browserView() {
155
362
  file: m.file,
156
363
  key: m.file,
157
364
  name: m.name,
158
- path: m.path,
365
+ path: m.ref,
159
366
  thumbSrc: m.isImage ? previewFileSrc(m.file) : "",
160
367
  thumbState: m.isImage ? "shown" : "hidden",
161
368
  };
162
369
  });
163
370
  return {
164
- emptyLabel: "No matches",
371
+ browseAllLabel: _browserOptions.images ? "Browse all images…" : "Browse all media…",
372
+ /* An empty project says so, rather than "No matches" over a search nobody typed: the Upload
373
+ beside the field and the row below are what to do about it. */
374
+ emptyLabel:
375
+ offered.length > 0
376
+ ? "No matches"
377
+ : _browserOptions.images
378
+ ? "No images in this project yet"
379
+ : "No media in this project yet",
165
380
  filter: _browserFilter,
166
- moreLabel: `…${filtered.length - BROWSE_LIMIT} more`,
167
- moreState: (filtered.length > BROWSE_LIMIT ? "shown" : "hidden") as "hidden" | "shown",
381
+ moreLabel: `Show ${Math.min(filtered.length - _browserLimit, BROWSE_LIMIT)} more`,
382
+ moreState: filtered.length > _browserLimit ? "shown" : "hidden",
168
383
  rows,
169
- rowsState: (rows.length > 0 ? "listed" : "empty") as "empty" | "listed",
384
+ rowsState: rows.length > 0 ? "listed" : "empty",
170
385
  x: _browserOrigin.x,
171
386
  y: _browserOrigin.y,
172
387
  };
@@ -178,6 +393,7 @@ function dismissMediaPickerPopover() {
178
393
  _browser = null;
179
394
  _browserCommit = null;
180
395
  _browserFilter = "";
396
+ _browserLimit = BROWSE_LIMIT;
181
397
  open?.close();
182
398
  }
183
399
 
@@ -194,7 +410,14 @@ let _sizeRepaint = 0;
194
410
  * because the measurement has not changed.
195
411
  */
196
412
  function noteImageSize(file: string, width: number, height: number) {
197
- if (!recordImageSize(file, width, height) || _sizeRepaint !== 0) {
413
+ if (!recordImageSize(file, width, height)) {
414
+ if (!mediaMetaSettled(file)) {
415
+ // An SVG's decode is not its size: the file says what it is, read once.
416
+ void loadMediaMeta(file).then(() => _browser?.update(browserView()));
417
+ }
418
+ return;
419
+ }
420
+ if (_sizeRepaint !== 0) {
198
421
  return;
199
422
  }
200
423
  _sizeRepaint = requestAnimationFrame(() => {
@@ -208,14 +431,23 @@ function noteImageSize(file: string, width: number, height: number) {
208
431
  *
209
432
  * Exported because the panel is a SURFACE OF ITS OWN — it renders into the popover layer, not into
210
433
  * the field that opened it — so a converted surface can offer the same browser without
211
- * re-implementing it. `surfaces/doc-header.ts`'s Browse button is the first such caller.
434
+ * re-implementing it. The Inspector's Page tab's Browse button is one such caller, and the
435
+ * search-appearance dialog's image rows another: the panel is a top-layer `jx-popover`, so it
436
+ * paints over the modal that opened it.
212
437
  *
213
438
  * @param {HTMLElement} anchorEl
214
439
  * @param {(val: string) => void} onCommit
440
+ * @param {MediaPickOptions} options - Images only, for a field that holds a picture
215
441
  */
216
- export function showMediaPickerPopover(anchorEl: HTMLElement, onCommit: (val: string) => void) {
442
+ export function showMediaPickerPopover(
443
+ anchorEl: HTMLElement,
444
+ onCommit: (val: string) => void,
445
+ options: MediaPickOptions = {},
446
+ ) {
217
447
  dismissMediaPickerPopover();
448
+ void loadMediaCache().then(() => _browser?.update(browserView()));
218
449
  _browserCommit = onCommit;
450
+ _browserOptions = options;
219
451
  const box = rectOf(anchorEl);
220
452
  /* Where it opens, once. `jx-popover` clamps a freshly shown panel into the viewport itself, so
221
453
  nothing here measures the panel or flips it above a low anchor — that was the layer-div
@@ -224,10 +456,19 @@ export function showMediaPickerPopover(anchorEl: HTMLElement, onCommit: (val: st
224
456
  _browser = openMediaBrowserSurface(
225
457
  browserView(),
226
458
  {
459
+ browseAll: () => {
460
+ const commit = _browserCommit;
461
+ const chosen = _browserOptions;
462
+ dismissMediaPickerPopover();
463
+ if (commit) {
464
+ void openFullMediaPicker(commit, chosen);
465
+ }
466
+ },
227
467
  dismissed: () => {
228
468
  _browser = null;
229
469
  _browserCommit = null;
230
470
  _browserFilter = "";
471
+ _browserLimit = BROWSE_LIMIT;
231
472
  },
232
473
  measure: noteImageSize,
233
474
  pick: (path: string) => {
@@ -235,6 +476,10 @@ export function showMediaPickerPopover(anchorEl: HTMLElement, onCommit: (val: st
235
476
  dismissMediaPickerPopover();
236
477
  commit?.(path);
237
478
  },
479
+ showMore: () => {
480
+ _browserLimit += BROWSE_LIMIT;
481
+ _browser?.update(browserView());
482
+ },
238
483
  setFilter: (value: string) => {
239
484
  _browserFilter = value;
240
485
  _browser?.update(browserView());
@@ -293,10 +538,15 @@ export function pickAndUpload(onCommit: (val: string) => void) {
293
538
  const FIELD_DEBOUNCE_MS = 400;
294
539
 
295
540
  /** One mounted field, and the decisions that move under it between repaints. */
296
- interface FieldEntry {
297
- handle: MediaFieldHandle;
541
+ /** What a field's callbacks read at call time; a re-mount rewrites both in place. */
542
+ interface FieldBinding {
298
543
  prop: string;
299
544
  commit: (value: string) => void;
545
+ options: MediaPickOptions;
546
+ }
547
+
548
+ interface FieldEntry extends FieldBinding {
549
+ handle: MediaFieldHandle;
300
550
  }
301
551
 
302
552
  /**
@@ -331,12 +581,14 @@ function fieldView(prop: string, value: string): MediaFieldView {
331
581
  * @param {string} prop - The attribute or prop being edited; the field's accessible name
332
582
  * @param {string} value - What it holds now
333
583
  * @param {(val: string) => void} onCommit - What a pick or a settled keystroke writes
584
+ * @param {MediaPickOptions} options - Images only, for a field whose value is a picture
334
585
  */
335
586
  export function mountMediaPicker(
336
587
  host: HTMLElement,
337
588
  prop: string,
338
589
  value: string,
339
590
  onCommit: (val: string) => void,
591
+ options: MediaPickOptions = {},
340
592
  ): void {
341
593
  // Kick off async load (won't block the mount)
342
594
  void loadMediaCache();
@@ -344,14 +596,14 @@ export function mountMediaPicker(
344
596
  if (existing) {
345
597
  existing.prop = prop;
346
598
  existing.commit = onCommit;
599
+ existing.options = options;
347
600
  existing.handle.update(fieldView(prop, value));
348
601
  return;
349
602
  }
350
- const entry: FieldEntry = { commit: onCommit, handle: null as unknown as MediaFieldHandle, prop };
351
- entry.handle = mountMediaFieldSurface(host, fieldView(prop, value), {
603
+ const entry: FieldBinding = { commit: onCommit, options, prop };
604
+ const handle = mountMediaFieldSurface(host, fieldView(prop, value), {
352
605
  browse: (anchor: HTMLElement) => {
353
- void loadMediaCache();
354
- showMediaPickerPopover(anchor, (val: string) => entry.commit(val));
606
+ showMediaPickerPopover(anchor, (val: string) => entry.commit(val), entry.options);
355
607
  },
356
608
  /* Debounced under the prop's own key, so the canvas follows the typing without a document write
357
609
  per keystroke and two fields never share a timer. */
@@ -364,7 +616,8 @@ export function mountMediaPicker(
364
616
  void loadMediaCache();
365
617
  },
366
618
  });
367
- _fields.set(host, entry);
619
+ // The same object, so the callbacks above see a later re-mount's `prop` and `commit`.
620
+ _fields.set(host, Object.assign(entry, { handle }));
368
621
  }
369
622
 
370
623
  /**
@@ -30,8 +30,8 @@
30
30
  import { layerHost } from "./layers";
31
31
  import { overlayRegion, REGION_ATTR } from "./regions";
32
32
  import { mountSurface } from "./surface";
33
- import type { JxMountOptions } from "@jxsuite/runtime/types";
34
- import type { SurfaceHandle } from "./surface";
33
+ import type { JxHostScope, JxMountOptions, JxScope } from "@jxsuite/runtime/types";
34
+ import type { MountSurfaceOptions, SurfaceHandle } from "./surface";
35
35
 
36
36
  /** A popover panel element, as the platform's popover API sees it. */
37
37
  type PanelElement = HTMLElement & {
@@ -51,13 +51,14 @@ export interface PopoverSurfaceHandle {
51
51
  readonly close: () => void;
52
52
  }
53
53
 
54
- export interface OpenPopoverSurfaceOptions {
54
+ /** How a popover surface is opened. `S` is the scope's own type, held to `JxHostScope` on open. */
55
+ export interface OpenPopoverSurfaceOptions<S = JxScope> {
55
56
  /** The registered surface name — its document's root must be a `jx-popover`. */
56
57
  name: string;
57
58
  /** The panel's instance name; its region becomes `overlay.<kind>:<id>`. */
58
59
  slot: string;
59
60
  /** The reactive scope the document reads. */
60
- scope: Record<string, unknown>;
61
+ scope: S;
61
62
  /**
62
63
  * The control it was opened from. It becomes the popover's invoker, so a press on that control
63
64
  * does not light-dismiss the panel its own click is about to toggle, and focus goes back to it.
@@ -78,7 +79,9 @@ export interface OpenPopoverSurfaceOptions {
78
79
  * @param {OpenPopoverSurfaceOptions} options
79
80
  * @returns {PopoverSurfaceHandle}
80
81
  */
81
- export function openPopoverSurface(options: OpenPopoverSurfaceOptions): PopoverSurfaceHandle {
82
+ export function openPopoverSurface<S extends JxHostScope<S>>(
83
+ options: OpenPopoverSurfaceOptions<S>,
84
+ ): PopoverSurfaceHandle {
82
85
  const { anchor, name, scope, slot: slotId } = options;
83
86
  const host = document.createElement("div");
84
87
  host.style.pointerEvents = "auto";
@@ -88,6 +91,8 @@ export function openPopoverSurface(options: OpenPopoverSurfaceOptions): PopoverS
88
91
  let panel: PanelElement | null = null;
89
92
  let mounted: SurfaceHandle | null = null;
90
93
  let closed = false;
94
+ // A function rather than a property read, because the signal can abort across every `await` below.
95
+ const aborted = (): boolean => controller.signal.aborted;
91
96
 
92
97
  const finish = (fromPlatform: boolean): void => {
93
98
  if (closed) {
@@ -104,21 +109,24 @@ export function openPopoverSurface(options: OpenPopoverSurfaceOptions): PopoverS
104
109
  };
105
110
 
106
111
  const ready = (async () => {
107
- const surface = await mountSurface(name, scope, host, {
108
- signal: controller.signal,
109
- ...(options.onNodeCreated ? { onNodeCreated: options.onNodeCreated } : {}),
110
- });
111
- if (controller.signal.aborted) {
112
+ const mountOptions: MountSurfaceOptions = { signal: controller.signal };
113
+ if (options.onNodeCreated) {
114
+ mountOptions.onNodeCreated = options.onNodeCreated;
115
+ }
116
+ const surface = await mountSurface(name, scope, host, mountOptions);
117
+ if (aborted()) {
112
118
  return;
113
119
  }
114
120
  mounted = surface;
121
+ /* SAFETY: `name` must register a document whose root is a `jx-popover` (see
122
+ OpenPopoverSurfaceOptions.name), an HTMLElement carrying `open` and the popover methods. */
115
123
  panel = surface.root as PanelElement;
116
124
  /* On the PANEL as well as the slot: a popover is `position: fixed` in the top layer, so the
117
125
  slot around it has a zero-height box and the screenshots lane refuses it ("has an empty
118
126
  box"). Both carry the id; the measurement takes the last match, which is the panel. */
119
127
  panel.setAttribute(REGION_ATTR, overlayRegion("popover", slotId));
120
128
  panel.addEventListener("toggle", (event) => {
121
- if ((event as { newState?: string }).newState === "closed") {
129
+ if ("newState" in event && event.newState === "closed") {
122
130
  finish(true);
123
131
  }
124
132
  });
@@ -130,7 +138,7 @@ export function openPopoverSurface(options: OpenPopoverSurfaceOptions): PopoverS
130
138
  panel?.addEventListener("jx-ready", () => resolve(), { once: true });
131
139
  });
132
140
  }
133
- if (controller.signal.aborted) {
141
+ if (aborted()) {
134
142
  return;
135
143
  }
136
144
  panel.showPopover(anchor ? { source: anchor } : undefined);
@@ -29,7 +29,7 @@ import { beginActivity } from "../panels/activity-panel";
29
29
  import { setBottomTab } from "../shell";
30
30
  import { layerHost } from "./layers";
31
31
  import { openProgressSurface } from "../surfaces/progress-modal";
32
- import type { ActivityHandle } from "../panels/activity-panel";
32
+ import type { ActivityHandle, ActivityOptions } from "../panels/activity-panel";
33
33
 
34
34
  export interface ProgressModalHandle {
35
35
  /** Update the status line shown under the title. Also the Activity entry's status. */
@@ -68,12 +68,17 @@ export interface ProgressModalOptions {
68
68
  export function showProgressModal(opts: ProgressModalOptions): ProgressModalHandle {
69
69
  let closed = false;
70
70
 
71
- const activity = beginActivity({
72
- title: opts.title,
73
- ...(opts.status === undefined ? {} : { status: opts.status }),
74
- ...(opts.source === undefined ? {} : { source: opts.source }),
75
- ...(opts.cancel === undefined ? {} : { cancel: opts.cancel }),
76
- });
71
+ const activityOptions: ActivityOptions = { title: opts.title };
72
+ if (opts.status !== undefined) {
73
+ activityOptions.status = opts.status;
74
+ }
75
+ if (opts.source !== undefined) {
76
+ activityOptions.source = opts.source;
77
+ }
78
+ if (opts.cancel !== undefined) {
79
+ activityOptions.cancel = opts.cancel;
80
+ }
81
+ const activity = beginActivity(activityOptions);
77
82
 
78
83
  const close = () => {
79
84
  if (closed) {
@@ -118,7 +123,7 @@ export function showProgressModal(opts: ProgressModalOptions): ProgressModalHand
118
123
  // CAPTURED LOG as their message — `result.log ?? "bun install failed"` — so a multi-line one
119
124
  // Is split the way the old view split it: "<title> failed" as the headline, the whole text
120
125
  // As the detail. A Problems list whose first row is 400 lines of `bun` output is not a list.
121
- const text = (message ?? "").trim();
126
+ const text = message.trim();
122
127
  if (text === "" || text.includes("\n")) {
123
128
  activity.log(text);
124
129
  activity.fail(`${opts.title} failed`);