@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
@@ -9,32 +9,47 @@
9
9
  * identical sentence — "No files found" — which is the lie §16 exists to end.
10
10
  * {@link scanLibrary} returns {@link LibraryScan.failures} beside the files; the pane raises
11
11
  * them as Problems with a Retry and refuses to call an incomplete listing empty.
12
- * 2. **A category has a directory.** The Manage view filtered by category and uploaded to whatever
13
- * directory the active filter happened to name, which for "All" was nothing at all — the upload
14
- * landed wherever `uploadAssets` defaulted. {@link uploadDirForCategory} still answers, but the
15
- * pane never uploads to an unnamed destination: it asks.
12
+ * 2. **A file is in one collection or in none.** The Library this model served filtered by FOLDER
13
+ * (Pages, Layouts, Components, Content, Media) and matched content with a third matcher of its
14
+ * own, which disagreed with the collection grid about the same entry. Every file now carries the
15
+ * key of the collection the Content workspace lists it under ({@link LibraryFile.collection}),
16
+ * from `content/content-collections.ts`, whose one matcher is `content/collection-match.ts`
17
+ * (studio.md §9.1.2).
16
18
  *
17
19
  * Everything here is pure over its inputs (the scan takes the platform as an argument) so the
18
20
  * 300-page acceptance case can be measured without a DOM.
19
21
  */
20
22
 
21
23
  import { MEDIA_EXTENSIONS, extensionOf } from "../files/media-upload";
24
+ import { PAGES_COLLECTION, collectionKeyOfPath } from "../content/content-collections";
25
+ import { isRoutedPageFile } from "@jxsuite/site/routes";
26
+ import { collectionForFile } from "../content/collection-match";
27
+ import { LOCALE_PLACEHOLDER } from "@jxsuite/schema/asset-paths";
22
28
  import { projectState } from "../store";
23
29
  import { notedListing } from "../files/asset-versions";
30
+ import { localDay } from "../utils/local-day";
24
31
  import { errorMessage } from "@jxsuite/schema/parse";
32
+ import { isString } from "@jxsuite/schema/guards";
25
33
  import { resolveI18n, servedLocaleOfPath } from "@jxsuite/schema/locale";
26
34
  import type { ResolvedI18n } from "@jxsuite/schema/locale";
27
35
  import type { ContentSectionEntry, DirEntry, StudioPlatform } from "../types";
36
+ import type { ProjectConfig } from "@jxsuite/schema/types";
28
37
 
29
38
  // ─── Files ───────────────────────────────────────────────────────────────────
30
39
 
31
- /** One row of the Library, whichever layout is drawing it. */
40
+ /** One scanned file, whichever layout is drawing it. */
32
41
  export interface LibraryFile {
33
42
  name: string;
34
43
  path: string;
35
- /** The content type name for a content file; the extension otherwise. */
44
+ /** The extension, or `"file"` for a name without one. */
36
45
  type: string;
37
- category: string;
46
+ /**
47
+ * The key of the collection the file is in (`pages`, or a collection's name), or `null` for a
48
+ * file in none: a template, a component, a media file, anything else.
49
+ */
50
+ collection: string | null;
51
+ /** Whether the file is media by its extension — never an entry, whatever folder it is in. */
52
+ media: boolean;
38
53
  ext: string;
39
54
  /** Bytes, when the platform reported them. */
40
55
  size?: number | undefined;
@@ -52,6 +67,13 @@ export interface LibraryFile {
52
67
  * is in none.
53
68
  */
54
69
  locale?: string | undefined;
70
+ /**
71
+ * Set when this row is one RECORD of a file-backed collection rather than a file: `path` is then
72
+ * the record's key (`prices.csv#3`), and `source` the file it is stored in, which is what opening
73
+ * it opens (`content/file-records.ts`); `row` is its place among the file's data rows, which is
74
+ * the row that file's grid lands on.
75
+ */
76
+ record?: { source: string; row: number; fields: Readonly<Record<string, string>> } | undefined;
55
77
  }
56
78
 
57
79
  /** A directory the scan could not read. Its presence means the listing is INCOMPLETE, not empty. */
@@ -66,100 +88,117 @@ export interface LibraryScan {
66
88
  failures: ScanFailure[];
67
89
  }
68
90
 
69
- // ─── Categories ──────────────────────────────────────────────────────────────
91
+ // ─── The scan ────────────────────────────────────────────────────────────────
70
92
 
71
- /** A Library category: what it is called, and the directory an upload into it lands in. */
72
- export interface LibraryCategory {
73
- key: string;
74
- label: string;
75
- /** Absent for "All" — which is why "All" has no upload destination and must ask for one. */
76
- dir?: string;
93
+ /** A project-relative path without `./`, backslashes or a trailing slash. */
94
+ function normalizeDir(path: string): string {
95
+ return path
96
+ .replaceAll("\\", "/")
97
+ .replace(/^(?:\.\/)+/, "")
98
+ .replace(/\/+$/, "");
77
99
  }
78
100
 
79
- export const LIBRARY_CATEGORIES: readonly LibraryCategory[] = [
80
- { key: "all", label: "All" },
81
- { dir: "pages", key: "pages", label: "Pages" },
82
- { dir: "layouts", key: "layouts", label: "Layouts" },
83
- { dir: "components", key: "components", label: "Components" },
84
- { dir: "content", key: "content", label: "Content" },
85
- { dir: "public", key: "media", label: "Media" },
86
- ];
87
-
88
- /** The category keys, for a command's `enum` — so `library.setCategory` refuses an unknown one. */
89
- export const LIBRARY_CATEGORY_KEYS: readonly string[] = LIBRARY_CATEGORIES.map((c) => c.key);
90
-
91
- /** The category with this key, or undefined. */
92
- export function libraryCategory(key: string): LibraryCategory | undefined {
93
- return LIBRARY_CATEGORIES.find((c) => c.key === key);
101
+ /** Whether a `source` names one file (a CSV catalogue) rather than a directory to walk. */
102
+ function namesOneFile(source: string): boolean {
103
+ if (source.endsWith("/")) {
104
+ return false;
105
+ }
106
+ const base = source.slice(source.lastIndexOf("/") + 1);
107
+ return /\.[a-z\d]+$/i.test(base);
94
108
  }
95
109
 
96
110
  /**
97
- * The directory a drop on the Library targets while `key` is the active category.
111
+ * The directories the Content scan walks: the conventional project directories that exist, plus
112
+ * every declared directory-collection `source` none of them already covers.
113
+ *
114
+ * The conventional list alone missed two real collections. A collection may live BESIDE the project
115
+ * (`sites/jxsuite.com` declares `content.docs.source: "../../docs"`), which no project directory
116
+ * can contain; and a collection created after the project opened (Add new › Collection) has its
117
+ * source under a `content/` that did not exist when the conventional list was read. Both were
118
+ * listed as empty, which is the lie {@link LibraryScan.failures} exists to end.
98
119
  *
99
- * `undefined` for "All" and for any category without one, and the caller MUST treat that as "ask",
100
- * never as "use the default": an upload that lands somewhere the author did not choose is the same
101
- * class of surprise as a rename that silently rewrites files.
120
+ * A localized source is walked from the directory above its `{locale}` segment, which the walk
121
+ * descends into on its own. A file-backed source is a file, not a directory to walk.
122
+ *
123
+ * @param projectDirs The conventional directories present at the project root.
124
+ * @param config The project configuration whose `content` section declares the collections.
102
125
  */
103
- export function uploadDirForCategory(key: string): string | undefined {
104
- return libraryCategory(key)?.dir;
105
- }
106
-
107
- /** Map a file path to a display category. Media files override by extension. */
108
- export function categoryFor(dir: string, ext: string): string {
109
- if (ext && MEDIA_EXTENSIONS.has(ext)) {
110
- return "Media";
111
- }
112
- if (dir.startsWith("pages")) {
113
- return "Pages";
114
- }
115
- if (dir.startsWith("layouts")) {
116
- return "Layouts";
117
- }
118
- if (dir.startsWith("components")) {
119
- return "Components";
120
- }
121
- if (dir.startsWith("content")) {
122
- return "Content";
126
+ export function libraryScanDirs(
127
+ projectDirs: readonly string[],
128
+ config: ProjectConfig | null | undefined,
129
+ ): readonly string[] {
130
+ const dirs: string[] = [];
131
+ for (const dir of projectDirs) {
132
+ dirs.push(normalizeDir(dir));
123
133
  }
124
- if (dir.startsWith("public")) {
125
- return "Media";
126
- }
127
- if (dir.startsWith("data")) {
128
- return "Content";
129
- }
130
- if (dir.startsWith("styles")) {
131
- return "Components";
134
+ const extra: string[] = [];
135
+ /* SAFETY: `content` is the parser extension's section, collection name → entry object; only the
136
+ optional string `source` is read, and it is tested before use. */
137
+ const content = (config?.content ?? {}) as Record<string, ContentSectionEntry>;
138
+ for (const def of Object.values(content)) {
139
+ if (!isString(def.source) || def.source === "" || namesOneFile(def.source)) {
140
+ continue;
141
+ }
142
+ let source = normalizeDir(def.source);
143
+ const cut = source.indexOf(LOCALE_PLACEHOLDER);
144
+ if (cut !== -1) {
145
+ source = normalizeDir(source.slice(0, cut));
146
+ }
147
+ if (source === "" || source === ".") {
148
+ continue;
149
+ }
150
+ const covered = [...dirs, ...extra].some(
151
+ (dir) => source === dir || source.startsWith(`${dir}/`),
152
+ );
153
+ if (!covered) {
154
+ extra.push(source);
155
+ }
132
156
  }
133
- return "Other";
157
+ // The project's own list, unchanged, when every collection is already under it.
158
+ return extra.length === 0 ? projectDirs : [...projectDirs, ...extra];
134
159
  }
135
160
 
136
161
  /**
137
- * The content type a path belongs to, from the project's `content` section — capitalized, or null.
162
+ * The collection a scanned file is an ENTRY of, or `null`.
163
+ *
164
+ * `collectionKeyOfPath` answers which collection's folder holds a file, which is the question a
165
+ * convert or a creation asks. A listing asks a narrower one: is this a file the collection's loader
166
+ * reads? A Markdown collection's folder may hold a `nav.json` beside its pages (the jxsuite docs
167
+ * do), and counting it made the Content home and the Site panel disagree about one collection. So a
168
+ * collection that DECLARES its format lists only the files carrying that format's extension; one
169
+ * that declares none is left to the loader's reading of the source, as before.
138
170
  *
139
- * @param {string} filePath
140
- * @returns {string | null}
171
+ * Pages are judged the way the build's walk judges them: with `pageExtensions` given, a file under
172
+ * `pages/` is a page only when it carries one of them, so `index.json.bak` beside the home page is
173
+ * a file in the folder rather than a second page (it publishes nothing).
174
+ *
175
+ * @param path The project-relative file.
176
+ * @param pageExtensions The extensions the build routes (`routedPageExtensions`); omitted, a page's
177
+ * extension is not judged.
141
178
  */
142
- export function contentTypeFor(filePath: string): string | null {
143
- const content = (projectState?.projectConfig?.content ?? {}) as Record<
144
- string,
145
- ContentSectionEntry
146
- >;
147
- for (const [name, entry] of Object.entries(content)) {
148
- if (!entry.source) {
149
- continue;
150
- }
151
- const prefix = entry.source.replace(/^\.\//, "").replace(/\/$/, "");
152
- if (filePath.startsWith(`${prefix}/`) || filePath === prefix) {
153
- return name.charAt(0).toUpperCase() + name.slice(1);
154
- }
179
+ export function entryCollectionOf(path: string, pageExtensions?: readonly string[]): string | null {
180
+ const key = collectionKeyOfPath(path);
181
+ if (key === null) {
182
+ return null;
155
183
  }
156
- return null;
184
+ if (key === PAGES_COLLECTION) {
185
+ return pageExtensions === undefined || isRoutedPageFile(path, pageExtensions) ? key : null;
186
+ }
187
+ const match = collectionForFile(path);
188
+ if (!match || match.name !== key || !match.def.format || match.ext === null) {
189
+ return key;
190
+ }
191
+ return path.toLowerCase().endsWith(match.ext.toLowerCase()) ? key : null;
157
192
  }
158
193
 
159
- // ─── The scan ────────────────────────────────────────────────────────────────
160
-
161
- /** Directory names never worth walking — a `node_modules` scan is minutes, not milliseconds. */
162
- const SKIP_DIRS = new Set(["node_modules", ".git", ".jx", "dist", "build", ".cache"]);
194
+ /**
195
+ * Directory names never worth walking — a `node_modules` scan is minutes, not milliseconds.
196
+ *
197
+ * Not `build` or `dist`: the scan starts inside the project's own directories, never at its root
198
+ * where a build writes, and a collection is free to name a section `build` (the jxsuite docs file
199
+ * their CLI pages under `framework/build/`). Skipping the name dropped those entries silently.
200
+ */
201
+ const SKIP_DIRS = new Set(["node_modules", ".git", ".jx", ".cache"]);
163
202
 
164
203
  /**
165
204
  * Walk one directory tree, collecting files and recording — never swallowing — what it could not
@@ -172,13 +211,18 @@ async function walk(
172
211
  out: LibraryFile[],
173
212
  failures: ScanFailure[],
174
213
  i18n: ResolvedI18n | null,
214
+ optional = false,
215
+ pageExtensions?: readonly string[],
175
216
  ): Promise<void> {
176
217
  let entries: DirEntry[];
177
218
  try {
178
219
  // Noted: the Library walks every media directory, so it is where most versions are learned.
179
220
  entries = await notedListing(() => platform.listDirectory(dir));
180
221
  } catch (error) {
181
- failures.push({ dir, error: errorMessage(error) });
222
+ // A declared collection's folder that does not exist yet is an empty collection, not a fault.
223
+ if (!optional) {
224
+ failures.push({ dir, error: errorMessage(error) });
225
+ }
182
226
  return;
183
227
  }
184
228
  const subdirectories: string[] = [];
@@ -190,21 +234,23 @@ async function walk(
190
234
  continue;
191
235
  }
192
236
  const ext = extensionOf(entry.name);
193
- const category = categoryFor(entry.path, ext);
194
237
  out.push({
195
- category,
238
+ collection: entryCollectionOf(entry.path, pageExtensions),
196
239
  ext,
197
240
  locale: servedLocaleOfPath(entry.path, i18n) ?? undefined,
241
+ media: MEDIA_EXTENSIONS.has(ext),
198
242
  modified: entry.modified,
199
243
  name: entry.name,
200
244
  path: entry.path,
201
245
  size: entry.size,
202
- type: category === "Content" ? (contentTypeFor(entry.path) ?? ext ?? "file") : ext || "file",
246
+ type: ext || "file",
203
247
  });
204
248
  }
205
249
  // Siblings in parallel, depth serialized per branch: the platform counts every call as in-flight,
206
250
  // So `probe.idle()` already knows the scan is running without the Library declaring a source.
207
- await Promise.all(subdirectories.map((sub) => walk(sub, platform, out, failures, i18n)));
251
+ await Promise.all(
252
+ subdirectories.map((sub) => walk(sub, platform, out, failures, i18n, false, pageExtensions)),
253
+ );
208
254
  }
209
255
 
210
256
  /**
@@ -216,13 +262,19 @@ async function walk(
216
262
  export async function scanLibrary(
217
263
  dirs: readonly string[],
218
264
  platform: Pick<StudioPlatform, "listDirectory">,
265
+ optional: ReadonlySet<string> = new Set(),
266
+ pageExtensions?: readonly string[],
219
267
  ): Promise<LibraryScan> {
220
268
  const files: LibraryFile[] = [];
221
269
  const failures: ScanFailure[] = [];
222
270
  // Resolved ONCE for the whole walk. `resolveI18n` canonicalizes every declared tag through
223
271
  // `Intl.Locale`, and a project with 300 pages would otherwise pay for that per file.
224
272
  const { i18n } = resolveI18n(projectState?.projectConfig ?? {});
225
- await Promise.all(dirs.map((dir) => walk(dir, platform, files, failures, i18n)));
273
+ await Promise.all(
274
+ dirs.map((dir) =>
275
+ walk(dir, platform, files, failures, i18n, optional.has(dir), pageExtensions),
276
+ ),
277
+ );
226
278
  files.sort((a, b) => a.path.localeCompare(b.path));
227
279
  return { failures, files };
228
280
  }
@@ -230,25 +282,19 @@ export async function scanLibrary(
230
282
  // ─── Filtering ───────────────────────────────────────────────────────────────
231
283
 
232
284
  export interface LibraryFilter {
233
- category: string;
285
+ /** The collection key to keep: `pages`, or a declared collection's name. */
286
+ collection: string;
234
287
  query: string;
235
288
  /** A canonical tag, or "" for every language. Never a label — the labels are not unique. */
236
289
  locale?: string;
237
290
  }
238
291
 
239
- /**
240
- * Category, then text over name and path, then language. Returns the input array unchanged when
241
- * nothing filters.
242
- */
292
+ /** Collection, then text over name and path, then language. */
243
293
  export function filterLibrary(
244
294
  files: readonly LibraryFile[],
245
295
  filter: LibraryFilter,
246
296
  ): readonly LibraryFile[] {
247
- let result = files;
248
- const category = libraryCategory(filter.category);
249
- if (category && category.key !== "all") {
250
- result = result.filter((f) => f.category === category.label);
251
- }
297
+ let result = files.filter((f) => f.collection === filter.collection);
252
298
  const query = filter.query.trim().toLowerCase();
253
299
  if (query) {
254
300
  result = result.filter(
@@ -264,7 +310,8 @@ export function filterLibrary(
264
310
 
265
311
  // ─── Layouts ─────────────────────────────────────────────────────────────────
266
312
 
267
- export const LIBRARY_LAYOUTS = ["table", "cards", "media", "calendar", "board"] as const;
313
+ /** The Content home's four views (studio.md §22.5), in the order its view switch draws them. */
314
+ export const LIBRARY_LAYOUTS = ["table", "cards", "calendar", "board"] as const;
268
315
 
269
316
  export type LibraryLayout = (typeof LIBRARY_LAYOUTS)[number];
270
317
 
@@ -272,20 +319,16 @@ export const LIBRARY_LAYOUT_LABELS: Readonly<Record<LibraryLayout, string>> = {
272
319
  board: "Board",
273
320
  calendar: "Calendar",
274
321
  cards: "Cards",
275
- media: "Media",
276
322
  table: "Table",
277
323
  };
278
324
 
279
- /** Whether a string names a layout — the guard behind `library.setLayout`'s argument. */
325
+ /** Whether a string names a layout — the guard behind `content.setLayout`'s argument. */
280
326
  export function isLibraryLayout(value: string): value is LibraryLayout {
281
- return (LIBRARY_LAYOUTS as readonly string[]).includes(value);
327
+ return LIBRARY_LAYOUTS.some((layout) => layout === value);
282
328
  }
283
329
 
284
- /** Layouts that draw a live preview per item. Table and Board draw text, and stay cheap. */
285
- export const PREVIEW_LAYOUTS: ReadonlySet<LibraryLayout> = new Set<LibraryLayout>([
286
- "cards",
287
- "media",
288
- ]);
330
+ /** Layouts that draw a live preview per item. Table, Calendar and Board draw text. */
331
+ export const PREVIEW_LAYOUTS: ReadonlySet<LibraryLayout> = new Set<LibraryLayout>(["cards"]);
289
332
 
290
333
  // ─── Derived axes (Calendar and Board) ───────────────────────────────────────
291
334
 
@@ -305,9 +348,10 @@ export function libraryDate(file: LibraryFile): string | null {
305
348
  return prefix[1]!;
306
349
  }
307
350
  if (file.modified) {
308
- const parsed = new Date(file.modified);
309
- if (!Number.isNaN(parsed.getTime())) {
310
- return parsed.toISOString().slice(0, 10);
351
+ // The day it was modified where the reader is, not in UTC (`utils/local-day.ts`).
352
+ const day = localDay(new Date(file.modified));
353
+ if (day) {
354
+ return day;
311
355
  }
312
356
  }
313
357
  return null;
@@ -315,7 +359,7 @@ export function libraryDate(file: LibraryFile): string | null {
315
359
 
316
360
  /**
317
361
  * The locales this project DECLARES, canonical and in declaration order — the value space of the
318
- * Library's language facet and of `library.setLocale`'s `enum`.
362
+ * Content home's language facet and of `content.setLocale`'s `enum`.
319
363
  *
320
364
  * Read at call time rather than cached: `projectState` is a plain binding replaced wholesale on a
321
365
  * project switch, so a cached list would describe the project before last.
@@ -327,10 +371,9 @@ export function projectLocales(): readonly string[] {
327
371
  /**
328
372
  * The locales actually PRESENT among these files, in the project's declaration order.
329
373
  *
330
- * Ordered by the project and not by the scan for the reason {@link groupByCategory} orders its
331
- * columns by {@link LIBRARY_CATEGORIES}: a facet whose options reshuffle when a file is added is a
332
- * facet nobody can build muscle memory for. Declaration order also puts the default locale first,
333
- * because {@link resolveI18n} guarantees it is `locales[0]`.
374
+ * Ordered by the project and not by the scan: a facet whose options reshuffle when a file is added
375
+ * is a facet nobody can build muscle memory for. Declaration order also puts the default locale
376
+ * first, because {@link resolveI18n} guarantees it is `locales[0]`.
334
377
  *
335
378
  * Only declared tags can appear — `localeOfPath` matches nothing else — so filtering the
336
379
  * declaration through the presence set loses no file.
@@ -345,15 +388,27 @@ export function libraryLocales(files: readonly LibraryFile[]): string[] {
345
388
  return projectLocales().filter((tag) => present.has(tag));
346
389
  }
347
390
 
391
+ /** One Calendar day: the files whose derived date is `date`. */
392
+ export interface LibraryDay {
393
+ date: string;
394
+ files: LibraryFile[];
395
+ }
396
+
348
397
  /** Calendar buckets, newest day first, plus the files no date could be derived for. */
349
- export function groupByDate(files: readonly LibraryFile[]): {
350
- days: { date: string; files: LibraryFile[] }[];
398
+ export interface LibraryDateGroups {
399
+ days: LibraryDay[];
351
400
  undated: LibraryFile[];
352
- } {
401
+ }
402
+
403
+ /** Calendar buckets, newest day first, plus the files no date could be derived for. */
404
+ export function groupByDate(
405
+ files: readonly LibraryFile[],
406
+ dateOf: (file: LibraryFile) => string | null = libraryDate,
407
+ ): LibraryDateGroups {
353
408
  const byDay = new Map<string, LibraryFile[]>();
354
409
  const undated: LibraryFile[] = [];
355
410
  for (const file of files) {
356
- const date = libraryDate(file);
411
+ const date = dateOf(file);
357
412
  if (date === null) {
358
413
  undated.push(file);
359
414
  continue;
@@ -366,33 +421,38 @@ export function groupByDate(files: readonly LibraryFile[]): {
366
421
  }
367
422
  }
368
423
  const days = [...byDay.entries()]
369
- .map(([date, dayFiles]) => ({ date, files: dayFiles }))
424
+ .map(([date, dayFiles]): LibraryDay => ({ date, files: dayFiles }))
370
425
  .toSorted((a, b) => b.date.localeCompare(a.date));
371
426
  return { days, undated };
372
427
  }
373
428
 
374
- /** Board columns — one per category present, in the Library's own category order, then the rest. */
375
- export function groupByCategory(
429
+ /** The folder a file is in, project-relative: `pages/blog/a.md` → `pages/blog`. */
430
+ export function folderOf(path: string): string {
431
+ const slash = path.lastIndexOf("/");
432
+ return slash === -1 ? "." : path.slice(0, slash);
433
+ }
434
+
435
+ /**
436
+ * Board columns: one per folder the files are in, in path order.
437
+ *
438
+ * A collection is browsed one at a time, so a column per collection would be one column; the
439
+ * folders inside it (`pages/` and `pages/blog/`, a dated archive's years) are the grouping a
440
+ * collection already has on disk, and the one a Board can state without reading any file.
441
+ */
442
+ export function groupByFolder(
376
443
  files: readonly LibraryFile[],
377
444
  ): { group: string; files: LibraryFile[] }[] {
378
445
  const byGroup = new Map<string, LibraryFile[]>();
379
446
  for (const file of files) {
380
- const bucket = byGroup.get(file.category);
447
+ const folder = folderOf(file.path);
448
+ const bucket = byGroup.get(folder);
381
449
  if (bucket) {
382
450
  bucket.push(file);
383
451
  } else {
384
- byGroup.set(file.category, [file]);
452
+ byGroup.set(folder, [file]);
385
453
  }
386
454
  }
387
- const order = LIBRARY_CATEGORIES.map((c) => c.label);
388
455
  return [...byGroup.entries()]
389
456
  .map(([group, groupFiles]) => ({ files: groupFiles, group }))
390
- .toSorted((a, b) => {
391
- const ai = order.indexOf(a.group);
392
- const bi = order.indexOf(b.group);
393
- if (ai === bi) {
394
- return a.group.localeCompare(b.group);
395
- }
396
- return (ai === -1 ? order.length : ai) - (bi === -1 ? order.length : bi);
397
- });
457
+ .toSorted((a, b) => a.group.localeCompare(b.group));
398
458
  }