@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
@@ -41,6 +41,7 @@ import { createGridController, getGridController } from "./grid-controller";
41
41
  import { createCsvFileSource } from "./sources/csv-file-source";
42
42
  import { loadedGridEngine, loadGridEngine } from "./grid-lazy";
43
43
  import { parseGridTabId } from "./grid-source";
44
+ import { clearGridReveal, pendingGridReveal } from "./grid-reveal";
44
45
  import { mountGridPanelSurface } from "../surfaces/grid-panel";
45
46
  import { openGridViewsSurface } from "../surfaces/grid-views";
46
47
  import { openGridReplaceSurface } from "../surfaces/grid-replace";
@@ -56,6 +57,7 @@ import {
56
57
  saveViewAs,
57
58
  } from "./grid-layout";
58
59
  import { argsSchema, stringArg, stringProperty } from "../commands/command-args";
60
+ import type { CommandArgValues } from "../commands/command-args";
59
61
  import type { EffectScope } from "@vue/reactivity";
60
62
  import type { GridController } from "./grid-controller";
61
63
  import type { GridLayout, GridSortSpec } from "./grid-layout";
@@ -69,7 +71,7 @@ import type {
69
71
  GridPanelView,
70
72
  } from "../surfaces/grid-panel";
71
73
  import type { GridViewsSurfaceHandle, GridViewsView } from "../surfaces/grid-views";
72
- import type { GridReplaceSurfaceHandle } from "../surfaces/grid-replace";
74
+ import type { PopoverSurfaceHandle } from "../ui/popover-surface";
73
75
 
74
76
  interface ActiveGridPanel {
75
77
  /** The pane whose stage this grid is drawn on. */
@@ -85,7 +87,7 @@ interface ActiveGridPanel {
85
87
  /** Where that panel was opened, so a re-projection cannot move it back to the origin. */
86
88
  viewsAt: { x: number; y: number };
87
89
  /** Find & replace while it is open. */
88
- replace: GridReplaceSurfaceHandle | null;
90
+ replace: PopoverSurfaceHandle | null;
89
91
  /**
90
92
  * Rebuild the engine over the same controller.
91
93
  *
@@ -614,15 +616,66 @@ export function renderGridMode(surface: CanvasSurface, tab: Tab) {
614
616
  }
615
617
  restored = true;
616
618
  const layout = loadGridLayout(engine.source.id);
617
- void engine.setSort(layout?.sort ?? null);
618
- engine.setGrouping(layout?.groupBy ?? null);
619
+ restoreStoredOrder(engine, layout);
619
620
  view.setSearch(layout?.filter ?? "");
620
621
  });
621
622
  }
623
+ revealRequested(engine, panel, tab.documentPath);
622
624
  });
623
625
  });
624
626
  }
625
627
 
628
+ /**
629
+ * Put the stored sort and grouping back on a freshly built engine, asking the controller only for
630
+ * what differs from the order it already holds.
631
+ *
632
+ * The controller outlives the panel: leaving the grid's workspace and coming back rebuilds the
633
+ * table but keeps the controller, so on every return after the first the stored order IS the
634
+ * controller's order. Asking for it anyway was not free. Each of `setSort` and `setGrouping`
635
+ * re-projects the rows into the view, and a view still building parks that as a refresh it runs the
636
+ * moment it is built, so every open rendered its rows twice (the second time measuring every row's
637
+ * height again); a remote-sorting source re-queried its backend for the same rows on top. An
638
+ * explicit change (a saved view applied, a header in the Views popover) still goes straight to the
639
+ * controller, so re-asking for the order you are looking at keeps its meaning there.
640
+ */
641
+ export function restoreStoredOrder(engine: GridController, layout: GridLayout | null): void {
642
+ const sort = layout?.sort ?? null;
643
+ const { query, grouping } = engine.state;
644
+ const sortHeld =
645
+ sort === null
646
+ ? query.orderBy === undefined
647
+ : query.orderBy === sort.field && query.dir === sort.dir;
648
+ if (!sortHeld) {
649
+ void engine.setSort(sort);
650
+ }
651
+ const groupBy = layout?.groupBy ?? null;
652
+ if (grouping !== groupBy) {
653
+ engine.setGrouping(groupBy);
654
+ }
655
+ }
656
+
657
+ /**
658
+ * Land on the row a record's opener asked for (`grid-reveal.ts`), once the engine and the rows
659
+ * exist. The position counts the file's data rows as loaded, so it names a row whatever order a
660
+ * saved view sorts them into. The request is taken either way: a row that is gone is not revealed
661
+ * later by surprise.
662
+ */
663
+ function revealRequested(
664
+ engine: GridController,
665
+ panel: ActiveGridPanel,
666
+ path: string | null | undefined,
667
+ ): void {
668
+ const position = pendingGridReveal(path);
669
+ if (position === undefined || !path || !panel.view || engine.state.loading) {
670
+ return;
671
+ }
672
+ clearGridReveal(path);
673
+ const row = engine.state.rows[position];
674
+ if (row) {
675
+ void panel.view.revealRow(row.key);
676
+ }
677
+ }
678
+
626
679
  /** The frame a tab with no grid source draws: one sentence, and no controls to press. */
627
680
  function missingView(): GridPanelView {
628
681
  return {
@@ -692,6 +745,12 @@ function requireSurface(commandId: string) {
692
745
  return surface;
693
746
  }
694
747
 
748
+ /** A saved view, addressed by the grid it was saved for. */
749
+ interface SavedViewRef {
750
+ gridId: string;
751
+ name: string;
752
+ }
753
+
695
754
  /**
696
755
  * Saved views, as commands.
697
756
  *
@@ -703,10 +762,10 @@ function requireSurface(commandId: string) {
703
762
  * @returns {AnyCommand[]}
704
763
  */
705
764
  export function gridViewCommands(): AnyCommand[] {
706
- const viewNameArg = (commandId: string, args: unknown): { gridId: string; name: string } => {
765
+ const viewNameArg = (commandId: string, args: CommandArgValues): SavedViewRef => {
707
766
  const { controller } = requireSurface(commandId);
708
767
  const gridId = controller.source.id;
709
- const name = stringArg(commandId, args as Record<string, unknown>, "name");
768
+ const name = stringArg(commandId, args, "name");
710
769
  const known = listSavedViews(gridId).map((view) => view.name);
711
770
  if (!known.includes(name)) {
712
771
  throw new RangeError(
@@ -0,0 +1,34 @@
1
+ /**
2
+ * The row a file's grid should land on when it opens: a file-backed collection's record.
3
+ *
4
+ * A collection whose `source` names one file (`./content/projects.csv`) is written in that file's
5
+ * grid, so opening one of its records in the Content home opens the file (`specs/studio.md` §22.5).
6
+ * Opening the whole table and leaving the reader to find the row they clicked is not opening the
7
+ * record, so the opener names the record's position here and the grid selects that row and scrolls
8
+ * it into view once its rows have loaded.
9
+ *
10
+ * Reactive and keyed by the file's path, so a request reaches a grid that is already on screen as
11
+ * well as one still loading: the grid panel's one effect reads it, applies it and takes it.
12
+ *
13
+ * @docs studio/projects/browse
14
+ */
15
+
16
+ import { reactive } from "../reactivity";
17
+
18
+ /** File path → the position of the row to reveal, among the file's data rows from 0. */
19
+ const pending = reactive(new Map<string, number>());
20
+
21
+ /** Ask the grid of `path` to reveal the row at `position` (its place among the data rows, from 0). */
22
+ export function requestGridReveal(path: string, position: number): void {
23
+ pending.set(path, position);
24
+ }
25
+
26
+ /** The row the grid of `path` is asked to reveal, or `undefined`. Reading it tracks it. */
27
+ export function pendingGridReveal(path: string | null | undefined): number | undefined {
28
+ return path ? pending.get(path) : undefined;
29
+ }
30
+
31
+ /** Drop the request for `path` once the grid has acted on it. */
32
+ export function clearGridReveal(path: string): void {
33
+ pending.delete(path);
34
+ }
@@ -6,6 +6,7 @@
6
6
  * pending edits; they never see the grid engine. Grid tabs over non-file sources are "virtual" —
7
7
  * their tab id is a `grid://` URI rather than a document path.
8
8
  */
9
+ import { isNonNullObject } from "@jxsuite/schema/guards";
9
10
  import type { JsonSchema } from "../ui/schema-form";
10
11
 
11
12
  /** A single cell value. JSON-shaped so batches serialize cleanly. */
@@ -126,14 +127,7 @@ export function cellValuesEqual(a: GridCellValue, b: GridCellValue): boolean {
126
127
  if (Array.isArray(a) && Array.isArray(b)) {
127
128
  return a.length === b.length && a.every((v, i) => v === b[i]);
128
129
  }
129
- if (
130
- a !== null &&
131
- b !== null &&
132
- typeof a === "object" &&
133
- typeof b === "object" &&
134
- !Array.isArray(a) &&
135
- !Array.isArray(b)
136
- ) {
130
+ if (isNonNullObject(a) && isNonNullObject(b) && !Array.isArray(a) && !Array.isArray(b)) {
137
131
  return a.$ref === b.$ref;
138
132
  }
139
133
  return false;
@@ -144,18 +138,14 @@ export function cellValuesEqual(a: GridCellValue, b: GridCellValue): boolean {
144
138
  const GRID_SCHEME = "grid://";
145
139
 
146
140
  /**
147
- * The virtual sources a tab id can name.
148
- *
149
- * `library` is the odd one and deliberately so: the Library is a source over this same contract
150
- * (`browse/library-source.ts`) but its tab's editor kind is `library`, not `grid` — Table is one of
151
- * its five layouts rather than its identity. It lives in this id space because "which virtual tab
152
- * is this?" has exactly one answer per window and there is no second scheme worth inventing.
153
- * Category and layout are VIEW state and are deliberately absent from the id: a Library that
154
- * changed identity when you clicked "Pages" would open a second tab per filter.
141
+ * Placeholder document for grid tabs: the grid never reads it, and save routes to the controller.
142
+ * Every tab takes its own `structuredClone` of it.
155
143
  */
144
+ export const GRID_STUB_DOCUMENT = { children: [], tagName: "div" };
145
+
146
+ /** The virtual sources a grid tab id can name. */
156
147
  export type GridTabRef =
157
148
  | { kind: "pages" }
158
- | { kind: "library" }
159
149
  | { kind: "collection"; name: string }
160
150
  | { kind: "data"; connection: string; table: string };
161
151
 
@@ -165,9 +155,6 @@ export function makeGridTabId(ref: GridTabRef): string {
165
155
  case "pages": {
166
156
  return `${GRID_SCHEME}pages`;
167
157
  }
168
- case "library": {
169
- return `${GRID_SCHEME}library`;
170
- }
171
158
  case "collection": {
172
159
  return `${GRID_SCHEME}collection/${encodeURIComponent(ref.name)}`;
173
160
  }
@@ -191,9 +178,6 @@ export function parseGridTabId(id: string): GridTabRef | null {
191
178
  if (parts[0] === "pages" && parts.length === 1) {
192
179
  return { kind: "pages" };
193
180
  }
194
- if (parts[0] === "library" && parts.length === 1) {
195
- return { kind: "library" };
196
- }
197
181
  if (parts[0] === "collection" && parts.length === 2 && parts[1]) {
198
182
  return { kind: "collection", name: decodeURIComponent(parts[1]) };
199
183
  }
@@ -208,11 +192,8 @@ export function parseGridTabId(id: string): GridTabRef | null {
208
192
  }
209
193
 
210
194
  /**
211
- * Short human label for a virtual tab ("posts · grid", "users @ main · grid", "Pages · grid").
212
- *
213
- * The Library is just "Library": the `· grid` suffix distinguishes a grid over a source from the
214
- * document tab of the same name, and the Library has no document tab to be confused with — nor is a
215
- * grid what it is, only what one of its layouts draws.
195
+ * Short human label for a virtual tab ("posts · grid", "users @ main · grid", "Pages · grid"). The
196
+ * `· grid` suffix distinguishes a grid over a source from the document tab of the same name.
216
197
  */
217
198
  export function gridTabLabel(id: string): string | null {
218
199
  const ref = parseGridTabId(id);
@@ -223,9 +204,6 @@ export function gridTabLabel(id: string): string | null {
223
204
  case "pages": {
224
205
  return "Pages · grid";
225
206
  }
226
- case "library": {
227
- return "Library";
228
- }
229
207
  case "collection": {
230
208
  return `${ref.name} · grid`;
231
209
  }
@@ -37,6 +37,7 @@ import type {
37
37
  ColumnComponent,
38
38
  ColumnDefinition,
39
39
  RowComponent,
40
+ RowData,
40
41
  } from "tabulator-tables";
41
42
  import type { GridCellValue, GridColumn } from "./grid-source";
42
43
  import type { GridController } from "./grid-controller";
@@ -51,6 +52,12 @@ export interface GridView {
51
52
  getSelectedRowKeys: () => string[];
52
53
  /** Local text filter across all columns (empty clears). */
53
54
  setSearch: (term: string) => void;
55
+ /**
56
+ * Select one row's cells and scroll it into view, once the table is built.
57
+ *
58
+ * @returns False when no row the table shows carries the key (filtered out, or gone).
59
+ */
60
+ revealRow: (rowKey: string) => Promise<boolean>;
54
61
  destroy: () => void;
55
62
  }
56
63
 
@@ -89,7 +96,7 @@ function makeHost(className: string): HTMLElement {
89
96
  return host;
90
97
  }
91
98
 
92
- function sorterForColumn(column: GridColumn): ColumnDefinition["sorter"] {
99
+ function sorterForColumn(column: GridColumn): ColumnDefinition<GridCellValue>["sorter"] {
93
100
  switch (column.kind) {
94
101
  case "number": {
95
102
  return "number";
@@ -98,8 +105,7 @@ function sorterForColumn(column: GridColumn): ColumnDefinition["sorter"] {
98
105
  return "boolean";
99
106
  }
100
107
  case "array": {
101
- return (a: unknown, b: unknown) =>
102
- cellToText(a as GridCellValue).localeCompare(cellToText(b as GridCellValue));
108
+ return (a: GridCellValue, b: GridCellValue) => cellToText(a).localeCompare(cellToText(b));
103
109
  }
104
110
  default: {
105
111
  return "string";
@@ -119,9 +125,9 @@ export function createGridView(host: HTMLElement, controller: GridController): G
119
125
  let built = false;
120
126
  let pendingRefresh = false;
121
127
 
122
- const rowKeyOf = (row: RowComponent) => String(row.getData()[ROW_KEY_FIELD] ?? "");
128
+ const rowKeyOf = (row: RowComponent<GridCellValue>) => String(row.getData()[ROW_KEY_FIELD] ?? "");
123
129
 
124
- const paintRow = (row: RowComponent) => {
130
+ const paintRow = (row: RowComponent<GridCellValue>) => {
125
131
  const rowState = buffer.rowState(rowKeyOf(row));
126
132
  const el = row.getElement();
127
133
  el.classList.toggle("jx-grid-row--pending-delete", rowState === "pending-delete");
@@ -129,7 +135,7 @@ export function createGridView(host: HTMLElement, controller: GridController): G
129
135
  el.classList.toggle("jx-grid-row--stale", rowState === "stale");
130
136
  };
131
137
 
132
- const paintCell = (cell: CellComponent) => {
138
+ const paintCell = (cell: CellComponent<GridCellValue>) => {
133
139
  const cellState = buffer.cellState(rowKeyOf(cell.getRow()), cell.getField());
134
140
  const el = cell.getElement();
135
141
  el.classList.toggle("jx-grid-cell--dirty", cellState === "dirty");
@@ -147,10 +153,11 @@ export function createGridView(host: HTMLElement, controller: GridController): G
147
153
  (column.editable || (column.insertOnly === true && buffer.isInsertKey(rowKey))) &&
148
154
  buffer.rowState(rowKey) !== "pending-delete";
149
155
 
150
- const columnDefs: ColumnDefinition[] = columns.map((column) => {
156
+ const columnDefs: ColumnDefinition<GridCellValue>[] = columns.map((column) => {
151
157
  const baseFormatter = formatterForColumn(column, makeHost);
152
158
  return {
153
- editable: (cell: CellComponent) => cellEditable(column, rowKeyOf(cell.getRow())),
159
+ editable: (cell: CellComponent<GridCellValue>) =>
160
+ cellEditable(column, rowKeyOf(cell.getRow())),
154
161
  // Image/reference cells edit through an anchored popover (dblclick), not an editor session.
155
162
  editor: hasPopoverEditor(column) ? undefined : editorForColumn(column, makeHost),
156
163
  field: column.field,
@@ -215,12 +222,17 @@ export function createGridView(host: HTMLElement, controller: GridController): G
215
222
 
216
223
  controller.bindView({ refreshData });
217
224
 
218
- table.on("tableBuilt", () => {
219
- built = true;
220
- if (pendingRefresh) {
221
- pendingRefresh = false;
222
- refreshData();
223
- }
225
+ /* Settles once the table is built: a reveal asked for before then waits for it, because the
226
+ engine has no rows to find, and its default range would replace the one the reveal drew. */
227
+ const whenBuilt = new Promise<void>((resolve) => {
228
+ table.on("tableBuilt", () => {
229
+ built = true;
230
+ if (pendingRefresh) {
231
+ pendingRefresh = false;
232
+ refreshData();
233
+ }
234
+ resolve();
235
+ });
224
236
  });
225
237
 
226
238
  /*
@@ -254,7 +266,7 @@ export function createGridView(host: HTMLElement, controller: GridController): G
254
266
  };
255
267
  const unregisterProbe = registerGridProbe(probe);
256
268
 
257
- table.on("cellEdited", (cell: CellComponent) => {
269
+ table.on("cellEdited", (cell: CellComponent<GridCellValue>) => {
258
270
  if (suppress) {
259
271
  return;
260
272
  }
@@ -267,7 +279,7 @@ export function createGridView(host: HTMLElement, controller: GridController): G
267
279
  const value = coerceCellInput(cell.getValue(), column);
268
280
  buffer.setCell(rowKey, field, value);
269
281
  // Normalize what the table shows to the typed value (e.g. pasted "42" in a number column).
270
- if (!cellValuesEqual(value, cell.getValue() as GridCellValue)) {
282
+ if (!cellValuesEqual(value, cell.getValue())) {
271
283
  suppress = true;
272
284
  try {
273
285
  cell.setValue(value, true);
@@ -287,7 +299,7 @@ export function createGridView(host: HTMLElement, controller: GridController): G
287
299
  saveGridLayout(gridId, { order: ordered.map((c) => c.getField()) });
288
300
  });
289
301
 
290
- table.on("cellDblClick", (_event: unknown, cell: CellComponent) => {
302
+ table.on("cellDblClick", (_event: MouseEvent, cell: CellComponent<GridCellValue>) => {
291
303
  const column = columnByField.get(cell.getField());
292
304
  const rowKey = rowKeyOf(cell.getRow());
293
305
  if (!column || !hasPopoverEditor(column) || !cellEditable(column, rowKey)) {
@@ -383,6 +395,20 @@ export function createGridView(host: HTMLElement, controller: GridController): G
383
395
 
384
396
  refreshData,
385
397
 
398
+ async revealRow(rowKey: string) {
399
+ await whenBuilt;
400
+ const row = table.getRow(rowKey);
401
+ const cells = row ? row.getCells() : [];
402
+ const [first] = cells;
403
+ const last = cells.at(-1);
404
+ if (!first || !last) {
405
+ return false;
406
+ }
407
+ table.addRange(first, last);
408
+ await table.scrollToRow(rowKey, "center", false).catch(() => {});
409
+ return true;
410
+ },
411
+
386
412
  setSearch(term: string) {
387
413
  const query = term.trim().toLowerCase();
388
414
  if (query === "") {
@@ -390,12 +416,8 @@ export function createGridView(host: HTMLElement, controller: GridController): G
390
416
  return;
391
417
  }
392
418
  const fields = columns.map((column) => column.field);
393
- table.setFilter((data: Record<string, unknown>) =>
394
- fields.some((field) =>
395
- cellToText(data[field] as GridCellValue)
396
- .toLowerCase()
397
- .includes(query),
398
- ),
419
+ table.setFilter((data: RowData<GridCellValue>) =>
420
+ fields.some((field) => cellToText(data[field]).toLowerCase().includes(query)),
399
421
  );
400
422
  },
401
423
  };
@@ -41,6 +41,7 @@ import {
41
41
  validateRedirects,
42
42
  } from "./redirects";
43
43
  import { optionalStringArg, stringProperty } from "../commands/command-args";
44
+ import { GRID_STUB_DOCUMENT } from "./grid-source";
44
45
  import type { RedirectConfig, RedirectRule, RedirectTarget } from "./redirects";
45
46
  import type {
46
47
  CommitResult,
@@ -67,8 +68,10 @@ export const REDIRECTS_TAB_ID = "grid://redirects";
67
68
  /** Who the Problems list attributes a redirect finding to. Also the key it clears them by. */
68
69
  export const REDIRECTS_PROBLEM_SOURCE = "Redirects";
69
70
 
70
- /** Placeholder document for the virtual tab — the grid never reads it; save routes to the source. */
71
- const GRID_STUB_DOCUMENT = { children: [], tagName: "div" };
71
+ /** The one key a redirect commit patches; `undefined` removes `redirects` from project.json. */
72
+ interface RedirectsPatch {
73
+ redirects: RedirectConfig | undefined;
74
+ }
72
75
 
73
76
  /** Extensions the router treats as pages. Anything else under `pages/` is an asset, not a route. */
74
77
  const PAGE_EXTENSIONS = [".json", ".md", ".html"];
@@ -120,7 +123,7 @@ export function redirectRow(rule: RedirectRule, index: number): GridRow {
120
123
 
121
124
  /** The live redirects map, straight off the configuration document. */
122
125
  function currentConfig(): RedirectConfig | undefined {
123
- return projectState?.projectConfig?.redirects as RedirectConfig | undefined;
126
+ return projectState?.projectConfig?.redirects;
124
127
  }
125
128
 
126
129
  /**
@@ -133,7 +136,10 @@ function parseTarget(raw: string): RedirectTarget {
133
136
  return REWRITE;
134
137
  }
135
138
  const value = Number(trimmed);
136
- return Number.isInteger(value) ? (value as RedirectTarget) : (trimmed as RedirectTarget);
139
+ /* SAFETY: deliberately unchecked, per the doc above. Every rule built from cells reaches
140
+ `ruleErrors` in `commit()`, which tests `status` against REDIRECT_TARGETS and refuses the whole
141
+ batch before `configFromRules` can write an unrecognised target to project.json. */
142
+ return (Number.isInteger(value) ? value : trimmed) as RedirectTarget;
137
143
  }
138
144
 
139
145
  /** A cell bag back to a rule. An unrecognised target is refused by {@link ruleErrors}. */
@@ -327,9 +333,12 @@ export function createRedirectsSource(): GridSource {
327
333
  // `undefined` CLEARS the key (see `commitProjectConfig`): an empty table should leave no
328
334
  // `"redirects": {}` behind. The local type spells the undefined out, which
329
335
  // `exactOptionalPropertyTypes` will not let `Partial<ProjectConfig>` do.
330
- const patch: { redirects: RedirectConfig | undefined } = {
336
+ const patch: RedirectsPatch = {
331
337
  redirects: next.length > 0 ? configFromRules(next) : undefined,
332
338
  };
339
+ /* SAFETY: `commitProjectConfig` spreads the patch onto the document and documents an own
340
+ `undefined` as "clear this key"; the only other value is a RedirectConfig, which is
341
+ structurally ProjectConfig["redirects"]. Only the spelling of "absent" differs. */
333
342
  const commit = await commitProjectConfig(patch as Partial<ProjectConfig>);
334
343
  if (!commit.ok) {
335
344
  // `commitProjectConfig` already filed the Problem; repeating it would list one failure
@@ -26,6 +26,7 @@
26
26
  */
27
27
 
28
28
  import { REDIRECT_STATUSES } from "@jxsuite/schema/defs";
29
+ import { isString } from "@jxsuite/schema/guards";
29
30
  import { parseCsv } from "./csv-codec";
30
31
 
31
32
  /** One redirect rule, flattened out of `project.json`'s two accepted spellings. */
@@ -128,17 +129,17 @@ export function routePattern(route: string): string {
128
129
  /** Flatten `project.json`'s redirects map into rules, in declaration order. */
129
130
  export function rulesFromConfig(config: RedirectConfig | undefined): RedirectRule[] {
130
131
  return Object.entries(config ?? {}).map(([source, target]) => {
131
- if (typeof target === "string") {
132
+ if (isString(target)) {
132
133
  return { destination: target, source, status: DEFAULT_REDIRECT_STATUS };
133
134
  }
134
135
  if ("rewrite" in target) {
135
136
  return { destination: target.destination, source, status: REWRITE };
136
137
  }
137
- return {
138
- destination: target.destination,
139
- source,
140
- status: (target.status ?? DEFAULT_REDIRECT_STATUS) as RedirectTarget,
141
- };
138
+ /* SAFETY: project.json's schema declares `status` as `enum: [...REDIRECT_STATUSES]`, the same
139
+ constant RedirectTarget is built from. A hand-edited file that breaks it is still caught:
140
+ every rule passes the grid's `ruleErrors` status check before anything is written back. */
141
+ const status = (target.status ?? DEFAULT_REDIRECT_STATUS) as RedirectTarget;
142
+ return { destination: target.destination, source, status };
142
143
  });
143
144
  }
144
145
 
@@ -151,7 +152,7 @@ export function rulesFromConfig(config: RedirectConfig | undefined): RedirectRul
151
152
  * level down. A later duplicate source wins, which is what a JSON object means anyway; the grid
152
153
  * refuses duplicates before they get here.
153
154
  */
154
- export function configFromRules(rules: readonly RedirectRule[]): RedirectConfig {
155
+ export function configFromRules(rules: readonly RedirectRule[]) {
155
156
  const config: RedirectConfig = {};
156
157
  for (const rule of rules) {
157
158
  if (rule.status === REWRITE) {
@@ -189,11 +190,14 @@ function ruleFor(rules: readonly RedirectRule[], path: string): RedirectRule | u
189
190
  );
190
191
  }
191
192
 
193
+ /** The path a chain of rules walks, and whether it came back to a source it already visited. */
194
+ interface RedirectWalk {
195
+ path: string[];
196
+ looped: boolean;
197
+ }
198
+
192
199
  /** Follow destinations from a rule until they stop resolving. Returns the path walked. */
193
- function walk(
194
- rules: readonly RedirectRule[],
195
- start: RedirectRule,
196
- ): { path: string[]; looped: boolean } {
200
+ function walk(rules: readonly RedirectRule[], start: RedirectRule): RedirectWalk {
197
201
  const path = [start.source];
198
202
  const seen = new Set([normalizePath(start.source)]);
199
203
  let current = start;
@@ -309,9 +313,7 @@ function parseStatus(token: string | undefined): RedirectTarget | null {
309
313
  return REWRITE;
310
314
  }
311
315
  const value = Number(raw);
312
- return (REDIRECT_STATUSES as readonly number[]).includes(value)
313
- ? (value as RedirectTarget)
314
- : null;
316
+ return REDIRECT_STATUSES.find((status) => status === value) ?? null;
315
317
  }
316
318
 
317
319
  /** Netlify/Cloudflare `_redirects`: `source destination [status]`, `#` comments, blank lines. */
@@ -8,6 +8,14 @@
8
8
  * parser extension's `coerceCSVRows` (currency-stripped numbers, `"true"` booleans, comma-split
9
9
  * arrays) so grid edits round-trip identically to the runtime content loader.
10
10
  */
11
+ import {
12
+ isBoolean,
13
+ isJsonObject,
14
+ isNonNullObject,
15
+ isNumber,
16
+ isString,
17
+ } from "@jxsuite/schema/guards";
18
+ import type { ContentTypeSchema, JsonValue } from "@jxsuite/schema/types";
11
19
  import type { GridCellValue, GridColumn, GridColumnKind } from "./grid-source";
12
20
  import type { JsonSchema } from "../ui/schema-form";
13
21
  import { isMediaFormat } from "../utils/studio-utils";
@@ -93,17 +101,17 @@ export interface ColumnsFromSchemaOptions {
93
101
  * required properties in declaration order, then the rest in declaration order.
94
102
  */
95
103
  export function columnsFromSchema(
96
- schema: { properties?: Record<string, unknown>; required?: string[] } | null | undefined,
104
+ schema: ContentTypeSchema | null | undefined,
97
105
  opts: ColumnsFromSchemaOptions = {},
98
106
  ): GridColumn[] {
99
- const props = Object.entries(schema?.properties ?? {}) as [string, PropSchema][];
107
+ const props: [string, PropSchema][] = Object.entries(schema?.properties ?? {});
100
108
  const required = new Set(schema?.required);
101
109
  const readonly = new Set(opts.readonlyFields);
102
110
 
103
111
  const columns = props.map(([field, prop]): GridColumn => {
104
112
  const kind = readonly.has(field) ? "readonly" : kindForProp(prop);
105
113
  const enumLen = Array.isArray(prop.enum)
106
- ? Math.max(...(prop.enum as unknown[]).map((v) => String(v).length), 4)
114
+ ? Math.max(...prop.enum.map((v) => String(v).length), 4)
107
115
  : 0;
108
116
  return {
109
117
  editable: kind !== "readonly",
@@ -144,9 +152,10 @@ export function inferColumnsFromRows(
144
152
  }
145
153
 
146
154
  return fields.map((field): GridColumn => {
147
- const values = sample
148
- .map((row) => row[field])
149
- .filter((v): v is Exclude<GridCellValue, null> => v !== null && v !== undefined && v !== "");
155
+ const values = sample.flatMap((row) => {
156
+ const value = row[field];
157
+ return value === null || value === undefined || value === "" ? [] : [value];
158
+ });
150
159
  const kind = inferKind(values);
151
160
  const maxLen = Math.max(...values.map((v) => cellToText(v).length), field.length, 4);
152
161
  return {
@@ -167,14 +176,11 @@ function inferKind(values: Exclude<GridCellValue, null>[]): GridColumnKind {
167
176
  return "array";
168
177
  }
169
178
  const texts = values.map(String);
170
- if (
171
- values.every((v) => typeof v === "boolean") ||
172
- texts.every((t) => /^(true|false)$/i.test(t))
173
- ) {
179
+ if (values.every((v) => isBoolean(v)) || texts.every((t) => /^(true|false)$/i.test(t))) {
174
180
  return "boolean";
175
181
  }
176
182
  if (
177
- values.every((v) => typeof v === "number") ||
183
+ values.every((v) => isNumber(v)) ||
178
184
  texts.every((t) => t.trim() !== "" && !Number.isNaN(Number(t.replaceAll(/[$€£¥,\s]/g, ""))))
179
185
  ) {
180
186
  return "number";
@@ -194,13 +200,13 @@ function inferKind(values: Exclude<GridCellValue, null>[]): GridColumnKind {
194
200
  * Coerce editor/clipboard input to the column's typed value. Empty input clears to null. Number and
195
201
  * array semantics mirror the parser extension's coerceCSVRows.
196
202
  */
197
- export function coerceCellInput(raw: unknown, col: GridColumn): GridCellValue {
203
+ export function coerceCellInput(raw: JsonValue | undefined, col: GridColumn): GridCellValue {
198
204
  if (raw === null || raw === undefined) {
199
205
  return null;
200
206
  }
201
207
  switch (col.kind) {
202
208
  case "number": {
203
- if (typeof raw === "number") {
209
+ if (isNumber(raw)) {
204
210
  return Number.isNaN(raw) ? null : raw;
205
211
  }
206
212
  const cleaned = String(raw)
@@ -213,7 +219,7 @@ export function coerceCellInput(raw: unknown, col: GridColumn): GridCellValue {
213
219
  return Number.isNaN(n) ? null : n;
214
220
  }
215
221
  case "boolean": {
216
- if (typeof raw === "boolean") {
222
+ if (isBoolean(raw)) {
217
223
  return raw;
218
224
  }
219
225
  return String(raw).trim().toLowerCase() === "true";
@@ -233,9 +239,9 @@ export function coerceCellInput(raw: unknown, col: GridColumn): GridCellValue {
233
239
  case "reference": {
234
240
  // Relationship VALUES are plain target-entry ids ("jane-doe") — the $ref lives on the
235
241
  // Schema property, not in the data (specs/relationships.md; parser resolveContentTypeRefs).
236
- if (typeof raw === "object" && raw !== null && "$ref" in raw) {
237
- const ref = (raw as { $ref: unknown }).$ref;
238
- return typeof ref === "string" && ref !== "" ? ref : null;
242
+ if (isJsonObject(raw) && "$ref" in raw) {
243
+ const ref = raw.$ref;
244
+ return isString(ref) && ref !== "" ? ref : null;
239
245
  }
240
246
  const text = String(raw).trim();
241
247
  return text === "" ? null : text;
@@ -248,14 +254,14 @@ export function coerceCellInput(raw: unknown, col: GridColumn): GridCellValue {
248
254
  }
249
255
 
250
256
  /** Plain-text projection of a cell value — display, clipboard, and CSV share it. */
251
- export function cellToText(value: GridCellValue): string {
257
+ export function cellToText(value: GridCellValue | undefined): string {
252
258
  if (value === null || value === undefined) {
253
259
  return "";
254
260
  }
255
261
  if (Array.isArray(value)) {
256
262
  return value.join(", ");
257
263
  }
258
- if (typeof value === "object") {
264
+ if (isNonNullObject(value)) {
259
265
  return value.$ref;
260
266
  }
261
267
  return String(value);