@jxsuite/studio 6.1.2 → 8.0.1

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 (522) hide show
  1. package/README.md +5 -5
  2. package/dist/chunks/2020-5wtzce5g.js +4 -0
  3. package/dist/chunks/adapter-5tphg7xe.js +4 -0
  4. package/dist/chunks/add-new-flow-psym14sn.js +4 -0
  5. package/dist/chunks/cf-account-picker-haqazq5r.js +4 -0
  6. package/dist/chunks/cf-settings-h2wrh6hq.js +4 -0
  7. package/dist/chunks/{color-area-0fj8a4ga.js → color-area-6rbra5dy.js} +2 -2
  8. package/dist/chunks/{color-field-xch8kx2g.js → color-field-gy56c94g.js} +3 -3
  9. package/dist/chunks/color-m7r1vk54.js +4 -0
  10. package/dist/chunks/{color-slider-jxd8v350.js → color-slider-sqqdyf6c.js} +2 -2
  11. package/dist/chunks/{combobox-p0efwjke.js → combobox-72h32ejk.js} +3 -3
  12. package/dist/chunks/components-r22xca09.js +4 -0
  13. package/dist/chunks/content-source-mmppmcyg.js +4 -0
  14. package/dist/chunks/convert-to-repeater-he70fc2b.js +4 -0
  15. package/dist/chunks/editor-ccd9jwsa.js +4 -0
  16. package/dist/chunks/entry-commands-6qxz9e8p.js +4 -0
  17. package/dist/chunks/extension-sections-0egb88dm.js +4 -0
  18. package/dist/chunks/file-ops-qnab36ek.js +4 -0
  19. package/dist/chunks/files-rcn56qvm.js +4 -0
  20. package/dist/chunks/format-host-yxz0kjjs.js +4 -0
  21. package/dist/chunks/fs-events-d1qxq4z4.js +4 -0
  22. package/dist/chunks/grid-open-4z1g062t.js +4 -0
  23. package/dist/chunks/{grid-view-d2wq9ezg.js → grid-view-qg1b5eqx.js} +25 -25
  24. package/dist/chunks/{icons-pnfz478q.js → icons-63bjtbs7.js} +2 -2
  25. package/dist/chunks/{iframe-entry-jdcktez8.js → iframe-entry-2zggzajv.js} +4 -4
  26. package/dist/chunks/{iframe-entry-zap785cw.js → iframe-entry-76j8vwwx.js} +4 -4
  27. package/dist/chunks/iframe-entry-99nr5zfb.js +5 -0
  28. package/dist/chunks/{iframe-entry-x0ygf2yr.js → iframe-entry-pkgmcgp0.js} +4 -4
  29. package/dist/chunks/iframe-host-ssv7kyj0.js +4 -0
  30. package/dist/chunks/{index-zpjmzqfk.js → index-32eqzv1k.js} +3 -3
  31. package/dist/chunks/index-f0jn7nnp.js +4 -0
  32. package/dist/chunks/{javascript-m54mnwp6.js → javascript-pjp734q4.js} +3 -3
  33. package/dist/chunks/jsonMode-njkvsa02.js +13 -0
  34. package/dist/chunks/jx-validate-ttasrbh7.js +4 -0
  35. package/dist/chunks/layers-bgyr11tr.js +4 -0
  36. package/dist/chunks/layers-panel-7ez66zeq.js +4 -0
  37. package/dist/chunks/{listbox-e74qjyq6.js → listbox-c421cf8c.js} +2 -2
  38. package/dist/chunks/lit-html-v9gh687x.js +4 -0
  39. package/dist/chunks/media-library-sq468wts.js +4 -0
  40. package/dist/chunks/media-picker-shfe59pt.js +4 -0
  41. package/dist/chunks/{menu-n6yzswmy.js → menu-bdpzbfvs.js} +2 -2
  42. package/dist/chunks/{monaco-binding-7gx83x3r.js → monaco-binding-vq1hgnn0.js} +3 -3
  43. package/dist/chunks/monaco-buffer-3afgwvbp.js +4 -0
  44. package/dist/chunks/monaco-setup-xrd2cbkp.js +4 -0
  45. package/dist/chunks/notify-kzrjr3fv.js +4 -0
  46. package/dist/chunks/parse-v77xtwv7.js +4 -0
  47. package/dist/chunks/platform-7v4rtd7m.js +4 -0
  48. package/dist/chunks/popover-b89sfej7.js +4 -0
  49. package/dist/chunks/publish-panel-2z9gw8ee.js +4 -0
  50. package/dist/chunks/publish-quick-qx2455cj.js +4 -0
  51. package/dist/chunks/publish-workspace-wrc1dgwx.js +4 -0
  52. package/dist/chunks/quick-search-n0t0eqxb.js +4 -0
  53. package/dist/chunks/references-9547rg5s.js +4 -0
  54. package/dist/chunks/right-panel-wsgnr9pn.js +4 -0
  55. package/dist/chunks/source-control-kwktr9y6.js +4 -0
  56. package/dist/chunks/{split-n2gfpm5m.js → split-c9zfdgxf.js} +2 -2
  57. package/dist/chunks/studio-03ct6yfv.js +9 -0
  58. package/dist/chunks/studio-07rcfje3.js +5 -0
  59. package/dist/chunks/studio-3e54qh39.js +7 -0
  60. package/dist/chunks/studio-3exxhz5g.js +5 -0
  61. package/dist/chunks/studio-3q40e3rj.js +5 -0
  62. package/dist/chunks/studio-3qeh9t0h.js +6 -0
  63. package/dist/chunks/studio-3qqjeep5.js +6 -0
  64. package/dist/chunks/studio-43sd2mam.js +4 -0
  65. package/dist/chunks/studio-4hp8pkyt.js +5 -0
  66. package/dist/chunks/studio-58xg6j2q.js +9 -0
  67. package/dist/chunks/studio-5g0rprdt.js +7 -0
  68. package/dist/chunks/{studio-2j1cb95x.js → studio-6m380wp7.js} +4 -4
  69. package/dist/chunks/studio-80jyh1xh.js +4 -0
  70. package/dist/chunks/studio-83mk4bgg.js +9 -0
  71. package/dist/chunks/{studio-v0jzqdjm.js → studio-881z1xrx.js} +4 -4
  72. package/dist/chunks/studio-8m0y2qe7.js +5 -0
  73. package/dist/chunks/{studio-d81xfh1g.js → studio-8tr6cfrc.js} +4 -4
  74. package/dist/chunks/studio-8vcvfs7r.js +6 -0
  75. package/dist/chunks/studio-9tmebf0s.js +5 -0
  76. package/dist/chunks/studio-a2bvaptz.js +5 -0
  77. package/dist/chunks/studio-b7y5mr30.js +5 -0
  78. package/dist/chunks/studio-bavb31r0.js +5 -0
  79. package/dist/chunks/{studio-dgz8d0c1.js → studio-bbe4c90a.js} +4 -4
  80. package/dist/chunks/studio-c05wdnt3.js +5 -0
  81. package/dist/chunks/studio-ccv2svc6.js +5 -0
  82. package/dist/chunks/studio-d5grtb9e.js +16 -0
  83. package/dist/chunks/studio-df0baea9.js +5 -0
  84. package/dist/chunks/studio-dgk4dqtx.js +7 -0
  85. package/dist/chunks/studio-e1g64q43.js +5 -0
  86. package/dist/chunks/studio-ed1hp6zf.js +6 -0
  87. package/dist/chunks/studio-ed3xx40h.js +7 -0
  88. package/dist/chunks/studio-f14e1zdj.js +5 -0
  89. package/dist/chunks/studio-fbhxxc5f.js +5 -0
  90. package/dist/chunks/studio-fyh0jc96.js +5 -0
  91. package/dist/chunks/studio-gcxk20n7.js +5 -0
  92. package/dist/chunks/studio-jaaz8ce9.js +5 -0
  93. package/dist/chunks/{studio-90pq9km1.js → studio-jcnsdaep.js} +4 -4
  94. package/dist/chunks/studio-jsgf2q5k.js +7 -0
  95. package/dist/chunks/{studio-0q988f9w.js → studio-k3xxbagr.js} +3 -3
  96. package/dist/chunks/{studio-5ve6bbep.js → studio-k7evxqh4.js} +4 -4
  97. package/dist/chunks/studio-kt3pjkwd.js +5 -0
  98. package/dist/chunks/studio-m8g16bgz.js +5 -0
  99. package/dist/chunks/studio-mn0476ag.js +5 -0
  100. package/dist/chunks/studio-mx1smyq0.js +5 -0
  101. package/dist/chunks/studio-n0c5h6mf.js +5 -0
  102. package/dist/chunks/{studio-485046te.js → studio-nh6d342n.js} +7 -7
  103. package/dist/chunks/studio-nqxqf8p2.js +4 -0
  104. package/dist/chunks/studio-p4nrkvqr.js +5 -0
  105. package/dist/chunks/{studio-1fxkaaea.js → studio-pbxa5fpc.js} +4 -4
  106. package/dist/chunks/studio-pgmvdv7z.js +7 -0
  107. package/dist/chunks/studio-ph84avkf.js +5 -0
  108. package/dist/chunks/{studio-tq0rtfwj.js → studio-q0mvbaq6.js} +4 -4
  109. package/dist/chunks/studio-q0tccd43.js +5 -0
  110. package/dist/chunks/studio-q7rtx6zq.js +14 -0
  111. package/dist/chunks/{studio-a3g98wjr.js → studio-qgh13jtz.js} +4 -4
  112. package/dist/chunks/studio-qmn1xc24.js +5 -0
  113. package/dist/chunks/studio-qwdqwkj0.js +5 -0
  114. package/dist/chunks/studio-r5qy30vx.js +5 -0
  115. package/dist/chunks/studio-rj9eamf8.js +5 -0
  116. package/dist/chunks/studio-rptgsk96.js +5 -0
  117. package/dist/chunks/studio-rthyg42z.js +928 -0
  118. package/dist/chunks/studio-s19tp1xr.js +5 -0
  119. package/dist/chunks/studio-s32578pn.js +5 -0
  120. package/dist/chunks/studio-svb7yyve.js +5 -0
  121. package/dist/chunks/studio-syreb644.js +5 -0
  122. package/dist/chunks/studio-tf9jryb1.js +10 -0
  123. package/dist/chunks/studio-tfkznv39.js +5 -0
  124. package/dist/chunks/studio-tft6r105.js +5 -0
  125. package/dist/chunks/studio-txf2kysx.js +5 -0
  126. package/dist/chunks/studio-v8867ddv.js +12 -0
  127. package/dist/chunks/studio-vxq7fcvv.js +5 -0
  128. package/dist/chunks/studio-w4rz9hdk.js +5 -0
  129. package/dist/chunks/studio-wbcjbhy1.js +9 -0
  130. package/dist/chunks/studio-wc649wss.js +5 -0
  131. package/dist/chunks/studio-wys23mxz.js +5 -0
  132. package/dist/chunks/studio-x1x167jh.js +5 -0
  133. package/dist/chunks/studio-x9hsze61.js +5 -0
  134. package/dist/chunks/studio-y0n7yxea.js +9 -0
  135. package/dist/chunks/studio-y3ahhdpx.js +5 -0
  136. package/dist/chunks/studio-z97c48fk.js +5 -0
  137. package/dist/chunks/studio-zat62m0c.js +5 -0
  138. package/dist/chunks/studio-zcd2e7yz.js +5 -0
  139. package/dist/chunks/studio-zz9qe3rw.js +64 -0
  140. package/dist/chunks/toast-1gv0h53h.js +4 -0
  141. package/dist/chunks/{toast-host-ke5z4ng7.js → toast-host-1yg5ar8d.js} +3 -3
  142. package/dist/chunks/{tooltip-5v8ngwj2.js → tooltip-yypz28gq.js} +3 -3
  143. package/dist/chunks/{tree-mdq3v5cw.js → tree-9xa4hm7n.js} +2 -2
  144. package/dist/chunks/tsMode-epyfz1hv.js +14 -0
  145. package/dist/chunks/workspace-dz7nxfhv.js +4 -0
  146. package/dist/chunks/workspace-home-xsd7hkjw.js +4 -0
  147. package/dist/chunks/{ws-client-nze0k6mv.js → ws-client-bv552sfx.js} +3 -3
  148. package/dist/iframe-entry.js +20 -16
  149. package/dist/manifest.json +77 -63
  150. package/dist/studio.js +103 -104
  151. package/dist/workers/ts.worker.js +3 -3
  152. package/package.json +12 -11
  153. package/src/browse/component-examples.ts +272 -0
  154. package/src/browse/library-commands.ts +64 -104
  155. package/src/browse/library-layouts.ts +263 -49
  156. package/src/browse/library-model.ts +181 -133
  157. package/src/browse/library-pane.ts +738 -446
  158. package/src/browse/library-preview.ts +149 -19
  159. package/src/browse/library-source.ts +308 -41
  160. package/src/browse/preview-root.ts +78 -0
  161. package/src/browse/preview-style.ts +155 -0
  162. package/src/canvas/asset-refs.ts +16 -1
  163. package/src/canvas/canvas-live-render.ts +222 -30
  164. package/src/canvas/canvas-origin.ts +37 -12
  165. package/src/canvas/canvas-page-context.ts +112 -0
  166. package/src/canvas/canvas-render.ts +113 -107
  167. package/src/canvas/canvas-utils.ts +57 -12
  168. package/src/canvas/iframe-drop.ts +107 -0
  169. package/src/canvas/iframe-entry.ts +24 -12
  170. package/src/canvas/iframe-host.ts +134 -62
  171. package/src/canvas/iframe-keys.ts +11 -0
  172. package/src/canvas/iframe-patch.ts +8 -7
  173. package/src/canvas/iframe-protocol.ts +24 -5
  174. package/src/canvas/iframe-render.ts +48 -1
  175. package/src/canvas/iframe-subtree.ts +5 -2
  176. package/src/canvas/npm-modules.ts +22 -0
  177. package/src/canvas/preview-navigate.ts +16 -0
  178. package/src/canvas/repeater-sources.ts +200 -0
  179. package/src/canvas/stage-scrollbar.ts +5 -1
  180. package/src/canvas/surface-registry.ts +6 -0
  181. package/src/commands/app-commands.ts +16 -6
  182. package/src/commands/budget.ts +10 -8
  183. package/src/commands/context.ts +35 -10
  184. package/src/commands/defaults.ts +69 -45
  185. package/src/commands/keymap.ts +9 -0
  186. package/src/commands/levels.ts +11 -5
  187. package/src/commands/live-context.ts +2 -0
  188. package/src/commands/registry.ts +10 -1
  189. package/src/content/collection-match.ts +6 -5
  190. package/src/content/collection-pages.ts +412 -0
  191. package/src/content/content-collections.ts +270 -0
  192. package/src/content/entry-commands.ts +51 -60
  193. package/src/content/entry-editor.ts +111 -18
  194. package/src/content/entry-fields.ts +13 -1
  195. package/src/content/entry-inspector.ts +225 -0
  196. package/src/content/entry-model.ts +17 -3
  197. package/src/content/entry-open.ts +80 -0
  198. package/src/content/entry-summaries.ts +440 -0
  199. package/src/content/file-record-ids.ts +80 -0
  200. package/src/content/file-records.ts +125 -0
  201. package/src/content/page-summaries.ts +129 -0
  202. package/src/content/record-entry.ts +201 -0
  203. package/src/content/writing-banner.ts +177 -0
  204. package/src/create/add-new-commands.ts +185 -0
  205. package/src/create/add-new-flow.ts +1116 -0
  206. package/src/create/add-new.ts +1014 -0
  207. package/src/create/element-name.ts +121 -0
  208. package/src/editor/convert-to-component.ts +67 -43
  209. package/src/editor/file-drop-action.ts +9 -1
  210. package/src/editor/inline-edit-apply.ts +44 -0
  211. package/src/editor/inline-edit.ts +10 -0
  212. package/src/editor/insert-component.ts +91 -0
  213. package/src/editor/insert-zone-action.ts +13 -4
  214. package/src/editor/shortcuts.ts +44 -22
  215. package/src/editor/slash-menu.ts +51 -8
  216. package/src/files/components.ts +74 -10
  217. package/src/files/file-ops.ts +15 -5
  218. package/src/files/files.ts +164 -150
  219. package/src/files/fs-events.ts +18 -7
  220. package/src/files/media-meta.ts +95 -1
  221. package/src/files/media-types.ts +55 -0
  222. package/src/files/media-upload.ts +209 -52
  223. package/src/files/new-file-name.ts +156 -0
  224. package/src/files/serialize-document.ts +13 -3
  225. package/src/format/format-host.ts +15 -0
  226. package/src/github/github-auth.ts +2 -2
  227. package/src/github/github-publish.ts +4 -3
  228. package/src/grid/grid-controller.ts +5 -1
  229. package/src/grid/grid-open.ts +0 -27
  230. package/src/grid/grid-panel.ts +54 -2
  231. package/src/grid/grid-reveal.ts +34 -0
  232. package/src/grid/grid-source.ts +3 -25
  233. package/src/grid/grid-view.ts +31 -6
  234. package/src/grid/sources/content-source.ts +75 -7
  235. package/src/grid/tabulator-tables.d.ts +6 -0
  236. package/src/hosting/document.ts +2 -2
  237. package/src/i18n/i18n-commands.ts +2 -1
  238. package/src/media/media-commands.ts +181 -0
  239. package/src/media/media-library-model.ts +232 -0
  240. package/src/media/media-library.ts +1283 -0
  241. package/src/media/media-pane.ts +47 -19
  242. package/src/packages/pull-package-sync.ts +1 -1
  243. package/src/panels/activity-panel.ts +21 -5
  244. package/src/panels/ai-chat/chat-markdown.ts +8 -8
  245. package/src/panels/block-action-bar.ts +11 -11
  246. package/src/panels/canvas-dnd-bridge.ts +5 -2
  247. package/src/panels/chat-panel.ts +6 -6
  248. package/src/panels/collections-panel.ts +306 -0
  249. package/src/panels/component-preview.ts +35 -13
  250. package/src/panels/data-explorer.ts +1 -1
  251. package/src/panels/data-grid.ts +4 -0
  252. package/src/panels/dnd.ts +17 -30
  253. package/src/panels/elements-panel.ts +9 -2
  254. package/src/panels/empty-state.ts +2 -2
  255. package/src/panels/formula-workspace.ts +2 -3
  256. package/src/panels/frontmatter-fields.ts +9 -9
  257. package/src/panels/git-diff-open.ts +9 -5
  258. package/src/panels/head-panel.ts +369 -103
  259. package/src/panels/i18n-panel.ts +11 -10
  260. package/src/panels/imports-panel.ts +2 -0
  261. package/src/panels/jump-bar.ts +27 -2
  262. package/src/panels/layers-panel.ts +36 -30
  263. package/src/panels/left-panel.ts +22 -8
  264. package/src/panels/navigator-panels.ts +23 -11
  265. package/src/panels/pane-context.ts +111 -29
  266. package/src/panels/pane-grid.ts +6 -6
  267. package/src/panels/panel-registry.ts +14 -9
  268. package/src/panels/properties-panel.ts +7 -3
  269. package/src/panels/right-panel.ts +199 -43
  270. package/src/panels/seo-modal.ts +41 -108
  271. package/src/panels/settings-menu.ts +52 -50
  272. package/src/panels/settings-pane.ts +268 -162
  273. package/src/panels/signals-panel.ts +3 -4
  274. package/src/panels/site-model.ts +367 -0
  275. package/src/panels/site-panel.ts +638 -0
  276. package/src/panels/style-panel.ts +37 -3
  277. package/src/panels/stylebook-doc.ts +142 -10
  278. package/src/panels/stylebook-layers-panel.ts +39 -80
  279. package/src/panels/stylebook-panel.ts +47 -10
  280. package/src/panels/styles-panel.ts +327 -0
  281. package/src/panels/tab-strip.ts +109 -25
  282. package/src/platform.ts +1 -1
  283. package/src/platforms/cloud.ts +28 -1
  284. package/src/platforms/default-platform.ts +4 -4
  285. package/src/platforms/devserver.ts +51 -25
  286. package/src/publish/deploy-checklist.ts +12 -7
  287. package/src/publish/pages-service.ts +38 -14
  288. package/src/publish/publish-changes.ts +491 -0
  289. package/src/publish/publish-commands.ts +83 -18
  290. package/src/publish/publish-ids.ts +49 -0
  291. package/src/publish/publish-quick.ts +148 -0
  292. package/src/publish/publish-workspace.ts +926 -0
  293. package/src/publish/source-control.ts +907 -0
  294. package/src/services/automation.ts +16 -20
  295. package/src/services/cf-settings.ts +4 -4
  296. package/src/services/connection.ts +2 -2
  297. package/src/services/directory-picker.ts +2 -2
  298. package/src/services/references.ts +0 -0
  299. package/src/services/render-critic.ts +21 -2
  300. package/src/services/settings/definitions.ts +25 -14
  301. package/src/settings/contributed-section.ts +49 -10
  302. package/src/settings/css-vars-editor.ts +93 -27
  303. package/src/settings/developer-panels.ts +43 -0
  304. package/src/settings/extension-sections.ts +20 -2
  305. package/src/settings/general-settings.ts +91 -21
  306. package/src/settings/preferences-dialog.ts +8 -1
  307. package/src/settings/project-sections.ts +27 -10
  308. package/src/settings/schema-field-ui.ts +3 -1
  309. package/src/settings/section-registry.ts +116 -11
  310. package/src/settings/settings-dialog.ts +192 -0
  311. package/src/settings/settings-document.ts +182 -162
  312. package/src/shell.ts +467 -431
  313. package/src/site-context.ts +64 -10
  314. package/src/state.ts +28 -9
  315. package/src/studio.ts +194 -41
  316. package/src/style/project-styles.ts +34 -0
  317. package/src/style/stylebook-specimens.ts +89 -0
  318. package/src/style/stylebook-target.ts +26 -0
  319. package/src/style/tag-inheritance.ts +105 -0
  320. package/src/style/variables-focus.ts +61 -0
  321. package/src/style/variables-view.ts +235 -0
  322. package/src/surfaces/add-new.json +1482 -0
  323. package/src/surfaces/add-new.ts +325 -0
  324. package/src/surfaces/ai-chat.ts +2 -2
  325. package/src/surfaces/boot-failure.json +4 -3
  326. package/src/surfaces/bottom-dock.json +1 -1
  327. package/src/surfaces/canvas-stage.json +30 -19
  328. package/src/surfaces/canvas-stage.ts +5 -5
  329. package/src/surfaces/collections-panel.json +615 -0
  330. package/src/surfaces/collections-panel.ts +168 -0
  331. package/src/surfaces/commandbar.json +241 -96
  332. package/src/surfaces/commandbar.ts +134 -99
  333. package/src/surfaces/empty-state.json +1 -1
  334. package/src/surfaces/entry-editor.json +136 -0
  335. package/src/surfaces/entry-editor.ts +21 -0
  336. package/src/surfaces/entry-inspector.json +371 -0
  337. package/src/surfaces/entry-inspector.ts +143 -0
  338. package/src/surfaces/inspector-dock.json +162 -14
  339. package/src/surfaces/inspector-dock.ts +46 -19
  340. package/src/surfaces/library-pane.json +670 -437
  341. package/src/surfaces/library-pane.ts +94 -59
  342. package/src/surfaces/media-browser.json +62 -6
  343. package/src/surfaces/media-browser.ts +15 -1
  344. package/src/surfaces/media-field.json +1 -1
  345. package/src/surfaces/media-library.json +1586 -0
  346. package/src/surfaces/media-library.ts +282 -0
  347. package/src/surfaces/media-pick-dialog.json +71 -0
  348. package/src/surfaces/media-pick-dialog.ts +132 -0
  349. package/src/surfaces/menu.ts +18 -0
  350. package/src/surfaces/pane-context.json +144 -77
  351. package/src/surfaces/pane-context.ts +24 -0
  352. package/src/surfaces/panel-deploy-checklist.json +12 -6
  353. package/src/surfaces/panel-deploy-checklist.ts +3 -1
  354. package/src/surfaces/panel-page.json +72 -2
  355. package/src/surfaces/panel-page.ts +38 -7
  356. package/src/surfaces/panel-signals.json +1 -1
  357. package/src/surfaces/panel-signals.ts +5 -5
  358. package/src/surfaces/panel-stylebook-layers.json +71 -204
  359. package/src/surfaces/panel-stylebook-layers.ts +0 -21
  360. package/src/surfaces/preferences.json +120 -48
  361. package/src/surfaces/preferences.ts +8 -0
  362. package/src/surfaces/publish-quick.json +428 -0
  363. package/src/surfaces/publish-quick.ts +165 -0
  364. package/src/surfaces/publish-workspace.json +2892 -0
  365. package/src/surfaces/publish-workspace.ts +391 -0
  366. package/src/surfaces/rail.json +1 -159
  367. package/src/surfaces/rail.ts +18 -75
  368. package/src/surfaces/schema-form.json +10 -2
  369. package/src/surfaces/schema-form.ts +2 -0
  370. package/src/surfaces/seo.json +1 -1
  371. package/src/surfaces/settings-contributed.json +5 -5
  372. package/src/surfaces/settings-contributed.ts +18 -2
  373. package/src/surfaces/settings-css-vars.json +44 -36
  374. package/src/surfaces/settings-css-vars.ts +77 -4
  375. package/src/surfaces/settings-deploy.json +2 -15
  376. package/src/surfaces/settings-deploy.ts +1 -1
  377. package/src/surfaces/settings-dialog.json +51 -0
  378. package/src/surfaces/settings-dialog.ts +169 -0
  379. package/src/surfaces/settings-overview.json +3 -3
  380. package/src/surfaces/settings-overview.ts +9 -2
  381. package/src/surfaces/settings-pane.json +269 -46
  382. package/src/surfaces/settings-pane.ts +85 -24
  383. package/src/surfaces/shell.json +2 -1
  384. package/src/surfaces/site-panel.json +1029 -0
  385. package/src/surfaces/site-panel.ts +233 -0
  386. package/src/surfaces/slash-menu.json +63 -21
  387. package/src/surfaces/slash-menu.ts +23 -0
  388. package/src/surfaces/statusbar.ts +39 -15
  389. package/src/surfaces/styles-panel.json +735 -0
  390. package/src/surfaces/styles-panel.ts +195 -0
  391. package/src/surfaces/styles-variables.json +149 -0
  392. package/src/surfaces/styles-variables.ts +145 -0
  393. package/src/surfaces/tab-strip.json +4 -4
  394. package/src/surfaces/welcome.ts +1 -1
  395. package/src/surfaces/writing-banner.json +94 -0
  396. package/src/surfaces/writing-banner.ts +80 -0
  397. package/src/tabs/bare-repeaters.ts +101 -0
  398. package/src/tabs/tab.ts +47 -7
  399. package/src/types.ts +21 -26
  400. package/src/ui/form-controls.ts +47 -8
  401. package/src/ui/layers.ts +13 -0
  402. package/src/ui/media-picker.ts +284 -40
  403. package/src/ui/regions.ts +7 -6
  404. package/src/ui/schema-form.ts +259 -27
  405. package/src/ui/virtual-window.ts +26 -1
  406. package/src/utils/base64.ts +3 -3
  407. package/src/utils/edit-display.ts +322 -67
  408. package/src/utils/local-day.ts +18 -0
  409. package/src/workspace/pane-derive.ts +4 -4
  410. package/src/workspace/session.ts +28 -7
  411. package/src/workspace/tab-workspace.ts +137 -0
  412. package/src/workspace/workspace-back.ts +189 -0
  413. package/src/workspace/workspace-home.ts +133 -0
  414. package/src/workspace/workspace-ids.ts +129 -0
  415. package/src/workspace/workspace-switch.ts +372 -0
  416. package/src/workspace/workspace.ts +125 -11
  417. package/styles/shell-frame.css +30 -7
  418. package/styles/shell-frame.json +15 -3
  419. package/dist/chunks/2020-f2gkpy8d.js +0 -4
  420. package/dist/chunks/adapter-4912g339.js +0 -4
  421. package/dist/chunks/cf-account-picker-wccaenh6.js +0 -4
  422. package/dist/chunks/cf-settings-br6105tr.js +0 -4
  423. package/dist/chunks/color-28ksk2qm.js +0 -4
  424. package/dist/chunks/components-db68vsn7.js +0 -4
  425. package/dist/chunks/content-source-1449qesq.js +0 -4
  426. package/dist/chunks/convert-to-repeater-5h457egj.js +0 -4
  427. package/dist/chunks/editor-x9jn86a7.js +0 -4
  428. package/dist/chunks/entry-commands-may24cpt.js +0 -4
  429. package/dist/chunks/extension-sections-pvr14vxr.js +0 -4
  430. package/dist/chunks/file-ops-x9v54pcj.js +0 -4
  431. package/dist/chunks/files-j3knqf0s.js +0 -4
  432. package/dist/chunks/format-host-tyre2trb.js +0 -4
  433. package/dist/chunks/fs-events-64ma9htc.js +0 -4
  434. package/dist/chunks/git-panel-84ps5dex.js +0 -4
  435. package/dist/chunks/iframe-entry-fvbk89gm.js +0 -5
  436. package/dist/chunks/iframe-host-ck6vejt5.js +0 -4
  437. package/dist/chunks/index-b8xw3vy9.js +0 -4
  438. package/dist/chunks/jsonMode-w15cmrcm.js +0 -13
  439. package/dist/chunks/jx-validate-at3zn8wa.js +0 -4
  440. package/dist/chunks/layers-h4xp1pss.js +0 -4
  441. package/dist/chunks/layers-panel-m5hw1d7g.js +0 -4
  442. package/dist/chunks/lit-html-8t8t3dnr.js +0 -4
  443. package/dist/chunks/media-picker-2cweexc5.js +0 -4
  444. package/dist/chunks/menu-ynw13y0s.js +0 -4
  445. package/dist/chunks/monaco-buffer-qzxn567r.js +0 -4
  446. package/dist/chunks/monaco-setup-gxf6656g.js +0 -4
  447. package/dist/chunks/notify-cj5zbrs2.js +0 -4
  448. package/dist/chunks/parse-b7ddhr8m.js +0 -4
  449. package/dist/chunks/platform-3dfws9js.js +0 -4
  450. package/dist/chunks/popover-jt2gxmzs.js +0 -4
  451. package/dist/chunks/publish-panel-1gvxbj21.js +0 -4
  452. package/dist/chunks/quick-search-0dajrwqg.js +0 -4
  453. package/dist/chunks/references-49qgt404.js +0 -4
  454. package/dist/chunks/right-panel-jm1bwe53.js +0 -4
  455. package/dist/chunks/section-registry-6kwc4fky.js +0 -4
  456. package/dist/chunks/studio-0rt52vpq.js +0 -5
  457. package/dist/chunks/studio-18vgbhs5.js +0 -5
  458. package/dist/chunks/studio-24mccdrj.js +0 -5
  459. package/dist/chunks/studio-2eh507zk.js +0 -9
  460. package/dist/chunks/studio-2hcbccfv.js +0 -5
  461. package/dist/chunks/studio-2jbs3rxv.js +0 -5
  462. package/dist/chunks/studio-4h8k4dw9.js +0 -5
  463. package/dist/chunks/studio-5f6n18kx.js +0 -5
  464. package/dist/chunks/studio-5gthpky6.js +0 -5
  465. package/dist/chunks/studio-6ep3js6b.js +0 -9
  466. package/dist/chunks/studio-6wkmf3wz.js +0 -9
  467. package/dist/chunks/studio-841rf3cg.js +0 -5
  468. package/dist/chunks/studio-8gmwgheg.js +0 -5
  469. package/dist/chunks/studio-8qm0ep50.js +0 -5
  470. package/dist/chunks/studio-924p1tm1.js +0 -6
  471. package/dist/chunks/studio-a3shpz9y.js +0 -5
  472. package/dist/chunks/studio-amsbaaar.js +0 -6
  473. package/dist/chunks/studio-at5spjbc.js +0 -7
  474. package/dist/chunks/studio-b2xv945e.js +0 -5
  475. package/dist/chunks/studio-bn5nkafw.js +0 -5
  476. package/dist/chunks/studio-bw6q5xjf.js +0 -9
  477. package/dist/chunks/studio-c7q0t9x1.js +0 -5
  478. package/dist/chunks/studio-camnhc96.js +0 -6
  479. package/dist/chunks/studio-cffqvnzd.js +0 -5
  480. package/dist/chunks/studio-efvfrsf8.js +0 -5
  481. package/dist/chunks/studio-er30bpcx.js +0 -5
  482. package/dist/chunks/studio-ezscgr64.js +0 -5
  483. package/dist/chunks/studio-ffrrncvz.js +0 -5
  484. package/dist/chunks/studio-fpphgn8y.js +0 -10
  485. package/dist/chunks/studio-j1kvhdjk.js +0 -4
  486. package/dist/chunks/studio-j430n16g.js +0 -7
  487. package/dist/chunks/studio-jjkg84nj.js +0 -5
  488. package/dist/chunks/studio-m0q32ars.js +0 -4
  489. package/dist/chunks/studio-m6bdst11.js +0 -5
  490. package/dist/chunks/studio-nv2cptd4.js +0 -64
  491. package/dist/chunks/studio-nwfrc98n.js +0 -5
  492. package/dist/chunks/studio-p1wgvp7r.js +0 -5
  493. package/dist/chunks/studio-pag2wncm.js +0 -5
  494. package/dist/chunks/studio-qvanvzfd.js +0 -5
  495. package/dist/chunks/studio-qwa64kt7.js +0 -5
  496. package/dist/chunks/studio-rk1zc4x3.js +0 -928
  497. package/dist/chunks/studio-se2r3ptc.js +0 -5
  498. package/dist/chunks/studio-sg2a0dh0.js +0 -5
  499. package/dist/chunks/studio-tjzjhe68.js +0 -5
  500. package/dist/chunks/studio-v2w7q8r1.js +0 -7
  501. package/dist/chunks/studio-v5vjq1h0.js +0 -4
  502. package/dist/chunks/studio-v8aga3vp.js +0 -14
  503. package/dist/chunks/studio-vfcdrfmv.js +0 -5
  504. package/dist/chunks/studio-vmfkgdjf.js +0 -5
  505. package/dist/chunks/studio-wt1816jj.js +0 -5
  506. package/dist/chunks/studio-wz73q5kq.js +0 -4
  507. package/dist/chunks/studio-y04qtxvp.js +0 -7
  508. package/dist/chunks/studio-y21g8zzg.js +0 -5
  509. package/dist/chunks/studio-y64hrt8p.js +0 -12
  510. package/dist/chunks/studio-ynn90f58.js +0 -16
  511. package/dist/chunks/studio-yxz682sx.js +0 -5
  512. package/dist/chunks/studio-zp7snvkq.js +0 -5
  513. package/dist/chunks/studio-zq4z6tm6.js +0 -5
  514. package/dist/chunks/toast-c9fn075p.js +0 -4
  515. package/dist/chunks/tsMode-sf49ee9x.js +0 -14
  516. package/dist/chunks/workspace-jtfahpee.js +0 -4
  517. package/src/panels/frontmatter-panel.ts +0 -711
  518. package/src/panels/git-panel.ts +0 -1108
  519. package/src/surfaces/doc-header.json +0 -776
  520. package/src/surfaces/doc-header.ts +0 -222
  521. package/src/surfaces/git-panel.json +0 -1880
  522. package/src/surfaces/git-panel.ts +0 -264
@@ -92,13 +92,14 @@ export function isScriptable(command: AnyCommand): boolean {
92
92
  // ─── The registry-gap declaration ─────────────────────────────────────────────
93
93
 
94
94
  /**
95
- * How a manifest id the registry does not declare is going to stop existing.
95
+ * Why a manifest id the registry does not declare will never be one.
96
96
  *
97
- * - `command` — a thing a user does, so it becomes a registry record. The value names who lands it.
98
- * - `seed` — a remote's state, addressed through {@link AutomationApi.seed}.
99
- * - `refused` — §13.5 says the app will never provide it; the manifest step is deleted.
97
+ * There were three fates. `command` (a thing a user does, so it becomes a registry record) emptied
98
+ * when `media.browse` landed in `media/media-commands.ts`, the last of them; `seed` (a remote's
99
+ * state) is answered from {@link seedIds}. What is left is `refused`: §13.5 says the app will never
100
+ * provide it, and the manifest step is deleted.
100
101
  */
101
- export type GapDisposition = "command" | "seed" | "refused";
102
+ export type GapDisposition = "refused";
102
103
 
103
104
  export interface ManifestId {
104
105
  disposition: GapDisposition;
@@ -117,17 +118,16 @@ export interface ManifestId {
117
118
  * — only to explain, when the registry refuses an id, which of the three fates that id has.
118
119
  *
119
120
  * This is a countdown, in the idiom of the checker's own `TOGGLE_DEBT`: it may only shrink. It went
120
- * 39 → 8 when the manifest converted, and 8 → 7 when `element.insertData` became `insert.data`
121
- * (`canvas/canvas-render.ts`). What left: every `seed` entry, now read off {@link seedIds} and
121
+ * 39 → 8 when the manifest converted, 8 → 7 when `element.insertData` became `insert.data`
122
+ * (`canvas/canvas-render.ts`), and down to five when `media.browse` became a record of its own
123
+ * (`media/media-commands.ts`). What left: every `seed` entry, now read off {@link seedIds} and
122
124
  * answered from the live registry rather than from a hand-kept list; every `toggle*` entry, which
123
- * {@link TOGGLE_ID} refuses before this map is ever consulted; and every `command` entry whose
124
- * record has since landed.
125
+ * {@link TOGGLE_ID} refuses before this map is ever consulted; and every `command` entry, each of
126
+ * whose records has landed.
125
127
  *
126
- * What is left is two kinds. Two `command` entries are the manifest's real registry gaps — each
127
- * reached today by an `input` step clicking a hand-stamped region, and each of those steps carries
128
- * an `unstable` hatch naming the phase that lands the record, so this map and that hatch count are
129
- * the same debt. Five `refused` entries are NOT a countdown: they are §13.5's normative refusals,
130
- * and they stay so that a caller reaching for one gets the reason instead of "unknown command".
128
+ * What is left is one kind, and it is NOT a countdown: five `refused` entries, §13.5's normative
129
+ * refusals, which stay so that a caller reaching for one gets the reason instead of "unknown
130
+ * command".
131
131
  */
132
132
  export const AUTOMATION_COMMANDS = {
133
133
  "file.contextMenu": {
@@ -138,14 +138,13 @@ export const AUTOMATION_COMMANDS = {
138
138
  disposition: "refused",
139
139
  note: "matched RENDERED TEXT, which R1 of scripts/screenshots/README.md forbids; a row is addressed by its data-jx-path",
140
140
  },
141
- "media.browse": { disposition: "command", note: "media.browse, site-architecture.md §9.4" },
142
141
  "project.showWelcome": {
143
142
  disposition: "refused",
144
143
  note: "cold start is a startup profile (?profile=fresh), not an action",
145
144
  },
146
145
  "settings.setSection": {
147
146
  disposition: "refused",
148
- note: 'mirrored the section registry\'s LABELS; say settings.open { section: "cssVars" }',
147
+ note: 'mirrored the section registry\'s LABELS; say settings.open { section: "contexts" }',
149
148
  },
150
149
  "view.setStatus": {
151
150
  disposition: "refused",
@@ -414,11 +413,8 @@ function unknownCommandMessage(
414
413
  return `"${id}" is a seed, not a command — call seed("${id}", …)`;
415
414
  }
416
415
  const gap = COMMAND_GAPS.get(id);
417
- if (gap?.disposition === "refused") {
418
- return `"${id}" is refused by spec §13.5: ${gap.note}`;
419
- }
420
416
  if (gap) {
421
- return `"${id}" has no command record yet (${gap.note}) — __jxAutomation.run projects the registry and nothing else`;
417
+ return `"${id}" is refused by spec §13.5: ${gap.note}`;
422
418
  }
423
419
  const known = registry
424
420
  .list()
@@ -1,12 +1,12 @@
1
1
  /// <reference lib="dom" />
2
2
  /**
3
3
  * Cf-settings — the Cloudflare publish connection on platforms without a hosted OAuth broker (dev
4
- * server, desktop). The API token is stored like the AI key, over `settings/kernel.ts`. It only ever
5
- * leaves the machine to the same-origin `/__studio/cf/proxy`, which forwards it as a bearer to
4
+ * server, desktop). The API token is stored like the AI key, over `settings/kernel.ts`. It only
5
+ * ever leaves the machine to the same-origin `/__studio/cf/proxy`, which forwards it as a bearer to
6
6
  * api.cloudflare.com (not CORS-enabled, hence the proxy).
7
7
  *
8
- * As with the AI provider, a blank value is a VALUE: {@link clearCfConnection} is the deletion path,
9
- * so nothing can revoke a connection by rendering an empty field into a setter.
8
+ * As with the AI provider, a blank value is a VALUE: {@link clearCfConnection} is the deletion
9
+ * path, so nothing can revoke a connection by rendering an empty field into a setter.
10
10
  *
11
11
  * @license MIT
12
12
  */
@@ -14,8 +14,8 @@
14
14
  * does not stay on the Problems list (§16.1's second and third rules: a record is retired when what
15
15
  * it names is fixed, and a repeat is not a new row).
16
16
  *
17
- * A platform without `subscribeConnection` — the dev server, electrobun — installs nothing. There
18
- * is no connection to lose there, and a notice about one would be a lie.
17
+ * A platform without `subscribeConnection` — the dev server — installs nothing. There is no
18
+ * connection to lose there, and a notice about one would be a lie.
19
19
  *
20
20
  * @docs studio/interface/problems-and-progress
21
21
  */
@@ -25,8 +25,8 @@
25
25
  * cancel, and Browse… a button that silently did nothing.
26
26
  *
27
27
  * Only the plain dev-server browser session needs this. Every packaged build has a real native
28
- * dialog that returns a path directly and keeps it — electrobun's `Utils.openFileDialog`, and the
29
- * NixOS chromium build's XDG desktop portal.
28
+ * dialog that returns a path directly and keeps it — the Electron app's native folder dialog, and
29
+ * the NixOS chromium build's XDG desktop portal.
30
30
  *
31
31
  * @docs studio/projects/create
32
32
  */
Binary file
@@ -13,8 +13,16 @@
13
13
  * @license MIT
14
14
  */
15
15
 
16
- import { buildScope, renderNode, runScoped, setSkipServerFunctions } from "@jxsuite/runtime";
16
+ import {
17
+ buildScope,
18
+ renderNode,
19
+ runScoped,
20
+ setResolveToken,
21
+ setSkipServerFunctions,
22
+ setTemplateErrorHandler,
23
+ } from "@jxsuite/runtime";
17
24
  import type { JxDocument } from "@jxsuite/schema/types";
25
+ import { hostResolveToken } from "../canvas/canvas-origin";
18
26
 
19
27
  /**
20
28
  * Translate a render-time error into an actionable message the model can fix.
@@ -52,8 +60,17 @@ export async function renderCheck(
52
60
  doc: JxDocument,
53
61
  ): Promise<{ ok: true } | { ok: false; error: string }> {
54
62
  let stopRender: (() => void) | null = null;
63
+ /* A binding that throws no longer unwinds the render (spec.md §6.1) — it renders empty and waits
64
+ for its data — so the throw is collected here instead. The first one is the verdict: a page
65
+ whose template can never evaluate is exactly what this check exists to refuse. */
66
+ const bindingErrors: Error[] = [];
67
+ setTemplateErrorHandler((error) => {
68
+ bindingErrors.push(error);
69
+ });
55
70
  try {
56
71
  setSkipServerFunctions(true);
72
+ // The desktop dev proxy refuses a class resolve without the token the canvas carries.
73
+ setResolveToken(hostResolveToken());
57
74
 
58
75
  const state = await buildScope(doc, {});
59
76
 
@@ -63,10 +80,12 @@ export async function renderCheck(
63
80
  });
64
81
  stopRender = stop;
65
82
 
66
- return { ok: true };
83
+ const [first] = bindingErrors;
84
+ return first ? { ok: false, error: translateRenderError(first) } : { ok: true };
67
85
  } catch (error) {
68
86
  return { ok: false, error: translateRenderError(error) };
69
87
  } finally {
88
+ setTemplateErrorHandler(null);
70
89
  // Dispose all effects created synchronously by renderNode via the RUNTIME's runScoped — scope
71
90
  // Collection is per @vue/reactivity module instance, so a studio effectScope here would collect
72
91
  // Nothing. Effects from the async buildScope (prototype/computed setup) still escape the scope;
@@ -2,23 +2,23 @@
2
2
  * The settings registry — every application setting Studio holds, declared once.
3
3
  *
4
4
  * Before this table the answer to "which settings roam, and what is each one's default" lived in
5
- * four places: a `PERSISTED_SETTINGS_KEYS` array, a private `const` per key in each `*-settings.ts`,
6
- * a bespoke getter/setter pair beside it, and whatever the getter's `||` happened to fall back to.
7
- * Adding a roaming setting meant editing all four and hoping; the key strings themselves were
8
- * duplicated between the array and the module that owned them.
5
+ * four places: a `PERSISTED_SETTINGS_KEYS` array, a private `const` per key in each
6
+ * `*-settings.ts`, a bespoke getter/setter pair beside it, and whatever the getter's `||` happened
7
+ * to fall back to. Adding a roaming setting meant editing all four and hoping; the key strings
8
+ * themselves were duplicated between the array and the module that owned them.
9
9
  *
10
10
  * Two properties of this table are load-bearing rather than tidy:
11
11
  *
12
- * 1. **Scope is declared, not inferred.** {@link USER_SETTINGS} is DERIVED from it, so a setting
13
- * roams because it says `scope: "user"` — not because someone remembered to add its key to a
14
- * second list. `device` is the honest name for the rest: panel geometry and a palette's MRU
15
- * describe *this window*, and a user with two windows open wants them to differ.
16
- * 2. **A default is not a value.** The default is what a *reader* sees when nothing is stored; it
17
- * is never itself stored. `getModel()` used to mask unset as `"gpt-4o"` with `||`, a form
18
- * prefilled from it, and Save wrote the mask back — which is how an install whose owner had
19
- * configured an entirely different provider was left holding `jx.ai.model: "gpt-4o"` and
20
- * nothing else. {@link readSetting} and {@link readStoredSetting} in `kernel.ts` are two
21
- * functions for exactly this reason.
12
+ * 1. **Scope is declared, not inferred.** {@link USER_SETTINGS} is DERIVED from it, so a setting roams
13
+ * because it says `scope: "user"` — not because someone remembered to add its key to a second
14
+ * list. `device` is the honest name for the rest: panel geometry and a palette's MRU describe
15
+ * _this window_, and a user with two windows open wants them to differ.
16
+ * 2. **A default is not a value.** The default is what a _reader_ sees when nothing is stored; it is
17
+ * never itself stored. `getModel()` used to mask unset as `"gpt-4o"` with `||`, a form prefilled
18
+ * from it, and Save wrote the mask back — which is how an install whose owner had configured an
19
+ * entirely different provider was left holding `jx.ai.model: "gpt-4o"` and nothing else.
20
+ * {@link readSetting} and {@link readStoredSetting} in `kernel.ts` are two functions for exactly
21
+ * this reason.
22
22
  *
23
23
  * @license MIT
24
24
  */
@@ -144,6 +144,17 @@ export const SETTINGS = {
144
144
  normalize: trimmed,
145
145
  scope: "user",
146
146
  },
147
+ /**
148
+ * Whether the Design rail draws the developer panels — Files and Packages (`specs/studio.md`
149
+ * §5.1). Unset, the default, keeps them off the rail; `settings/developer-panels.ts` reads it.
150
+ * Roams, for the reason `showIgnoredFiles` does: it is a way of working, not a window's.
151
+ */
152
+ developerPanels: {
153
+ default: "",
154
+ key: "jx.panels.developer",
155
+ normalize: trimmed,
156
+ scope: "user",
157
+ },
147
158
  cfAccountId: {
148
159
  default: "",
149
160
  key: "jx.cf.accountId",
@@ -49,8 +49,7 @@ import { resolveContextPointer } from "../services/context-resolver";
49
49
  import { deriveSecretEnvName } from "../services/data-service";
50
50
  import { validateProjectConfig } from "../services/jx-validate";
51
51
  import { notify } from "../services/notify";
52
- import { paneRegion } from "../ui/regions";
53
- import { paneOfContainer } from "../canvas/canvas-surface";
52
+ import { SETTINGS_DIALOG_REGION } from "../surfaces/settings-dialog";
54
53
  import { mountContributedSurface } from "../surfaces/settings-contributed";
55
54
 
56
55
  import type { JsonSchema, SchemaFormContext } from "../ui/schema-form";
@@ -77,6 +76,12 @@ export interface SettingsContribution {
77
76
  | {
78
77
  ui?: Record<string, { control?: string; enum?: unknown }> | undefined;
79
78
  newEntry?: JsonObject | undefined;
79
+ /**
80
+ * What ONE entry of a map section is called, singular and lowercase ("content type",
81
+ * "table"), so the column offers "New content type" rather than "New Entry", a word that
82
+ * means a collection's item everywhere else in Studio. Defaults to "entry".
83
+ */
84
+ noun?: string | undefined;
80
85
  }
81
86
  | undefined;
82
87
  };
@@ -365,10 +370,17 @@ function sectionValue(key: string): JsonObject | null {
365
370
 
366
371
  // ─── Per-container mount ──────────────────────────────────────────────────────
367
372
 
368
- /* There is no `paneOfContainer` here. It moved to `canvas/canvas-surface.ts`, beside the other
369
- "which pane is this about" answers, because it is not a settings idea: any stage content handed
370
- only a host needs it, and `settings/general-settings.ts` and `settings/project-sections.ts` are
371
- two more that do — both write a canvas mode, and both used to write the FOCUSED pane's. */
373
+ /**
374
+ * A region under the settings dialog, which is where a contributed section is drawn (§17.1): its
375
+ * entry rows and its entry editor are named under `overlay.dialog:settings`, so a shot can crop one
376
+ * without a selector.
377
+ *
378
+ * @param {string} part
379
+ * @returns {string}
380
+ */
381
+ function sectionRegion(part: string): string {
382
+ return `${SETTINGS_DIALOG_REGION}/${part}`;
383
+ }
372
384
 
373
385
  /** One mounted section: its document, its two island hosts, and what it was last asked to draw. */
374
386
  interface SectionMount {
@@ -412,14 +424,39 @@ function say(record: SectionMount, value: string): void {
412
424
 
413
425
  // ─── Projection ───────────────────────────────────────────────────────────────
414
426
 
427
+ /** The default name for one entry of a map section, when the contribution names none. */
428
+ const DEFAULT_ENTRY_NOUN = "entry";
429
+
430
+ /** The map column's words for one entry: the four places a map section names it. */
431
+ export interface EntryWords {
432
+ newLabel: string;
433
+ newFieldLabel: string;
434
+ newPlaceholder: string;
435
+ emptyText: string;
436
+ }
437
+
438
+ /** The map column's words, from what the contribution calls one entry. */
439
+ export function entryWords(noun?: string): EntryWords {
440
+ const word = noun?.trim().toLowerCase() || DEFAULT_ENTRY_NOUN;
441
+ const capitalised = `${word.charAt(0).toUpperCase()}${word.slice(1)}`;
442
+ // "an entry", "a table": the article English reads before the word's first sound, by its letter.
443
+ const article = /^[aeiou]/u.test(word) ? "an" : "a";
444
+ return {
445
+ emptyText: `Select ${article} ${word} or create one`,
446
+ newFieldLabel: `${capitalised} name`,
447
+ newLabel: `New ${word}`,
448
+ newPlaceholder: `${slugify(word)}-name`,
449
+ };
450
+ }
451
+
415
452
  /** What the document draws right now, read from the store and this module's own state. */
416
453
  function project(record: SectionMount): ContributedView {
417
- const { container, contribution, opts } = record;
454
+ const { contribution, opts } = record;
418
455
  const sectionKey = contribution.key;
419
456
  const title = contribution.title ?? sectionKey;
420
457
  const actionsState = opts.actions ? "slot" : "none";
421
- const paneId = paneOfContainer(container);
422
- const editorRegion = paneRegion(paneId, "editor");
458
+ const editorRegion = sectionRegion("editor");
459
+ const words = entryWords(contribution.settings.entry?.noun);
423
460
 
424
461
  if ((contribution.settings.layout ?? "form") !== "map") {
425
462
  return {
@@ -432,6 +469,7 @@ function project(record: SectionMount): ContributedView {
432
469
  newName: "",
433
470
  newState: "closed",
434
471
  title,
472
+ ...words,
435
473
  };
436
474
  }
437
475
 
@@ -445,7 +483,7 @@ function project(record: SectionMount): ContributedView {
445
483
  editorState: editing ? "editing" : "empty",
446
484
  entries: Object.keys(entries).map((name) => ({
447
485
  key: name,
448
- region: paneRegion(paneId, `entry:${name}`),
486
+ region: sectionRegion(`entry:${name}`),
449
487
  selected: name === selected,
450
488
  })),
451
489
  entryName: record.echo ?? (editing ? selected : ""),
@@ -453,6 +491,7 @@ function project(record: SectionMount): ContributedView {
453
491
  newName: newEntryNames.get(sectionKey) ?? "",
454
492
  newState: newEntryOpen.has(sectionKey) ? "open" : "closed",
455
493
  title,
494
+ ...words,
456
495
  };
457
496
  }
458
497
 
@@ -11,8 +11,16 @@
11
11
  * **The markup left.** The section is the `settings-css-vars` surface
12
12
  * (`surfaces/settings-css-vars.json`), mounted by `surfaces/settings-css-vars.ts`; what is here is
13
13
  * the part that was always this module's — what a row shows, what an edit writes, and what a failed
14
- * write says. `renderCssVarsEditor` is unchanged as a contract: the registry hands a container to a
15
- * `render`, and this one mounts a document into it instead of rendering lit.
14
+ * write says. `renderCssVarsEditor` is unchanged as a contract: it is handed a container and mounts
15
+ * a document into it instead of rendering lit.
16
+ *
17
+ * **Its host is the Styles workspace's Variables view** (`style/variables-view.ts`, §7.1), the
18
+ * `tokens` editor of the `project.json` tab. It was Project Settings › CSS Variables, and its
19
+ * persistence did not change with the move: an edit is committed through the configuration
20
+ * chokepoint (`updateSiteConfig` → `commitProjectConfig`) as it is made, which writes the whole
21
+ * document, so an element style edit the Elements view left unsaved on the same tab is written too
22
+ * and the tab comes back clean. The view says so in as many words, rather than letting the Save
23
+ * button's state be the first the author hears of it.
16
24
  *
17
25
  * Three things it does NOT do, each on purpose:
18
26
  *
@@ -28,7 +36,7 @@
28
36
 
29
37
  import { isNumber, isString } from "@jxsuite/schema/guards";
30
38
  import { errorMessage } from "@jxsuite/schema/parse";
31
- import { notify } from "../services/notify";
39
+ import { runActiveReported } from "../commands/run-reported";
32
40
  import { projectState } from "../store";
33
41
  import { getEffectiveMedia, updateSiteConfig } from "../site-context";
34
42
  import {
@@ -37,12 +45,15 @@ import {
37
45
  groupTokens,
38
46
  listTokenContexts,
39
47
  readTokenOverride,
40
- tokenLabel,
41
48
  writeTokenOverride,
42
49
  } from "../style/project-styles";
43
50
  import { resolveTokenValue, toTokenRef, tokenRefName } from "../style/token-ref";
44
51
  import { pushProjectStylesToCanvas } from "../style/live-preview";
45
- import { renderCssVarsSurface } from "../surfaces/settings-css-vars";
52
+ import {
53
+ renderCssVarsSurface,
54
+ revealCssVarsGroup,
55
+ revealCssVarsToken,
56
+ } from "../surfaces/settings-css-vars";
46
57
  import { friendlyNameToVar } from "../utils/studio-utils";
47
58
 
48
59
  import type { JxStyle, ProjectConfig } from "@jxsuite/schema/types";
@@ -89,6 +100,8 @@ const ADD_OVERRIDE_ROW = { label: "Add override…", value: "" };
89
100
  interface Form {
90
101
  add: Partial<Record<TokenGroupId, { name: string; value: string }>>;
91
102
  error: string;
103
+ /** The token the Outline pointed this editor at ({@link focusCssVar}), or `null`. */
104
+ current: string | null;
92
105
  }
93
106
 
94
107
  const forms = new WeakMap<HTMLElement, Form>();
@@ -97,7 +110,7 @@ const forms = new WeakMap<HTMLElement, Form>();
97
110
  function form(container: HTMLElement): Form {
98
111
  let state = forms.get(container);
99
112
  if (!state) {
100
- state = { add: {}, error: "" };
113
+ state = { add: {}, current: null, error: "" };
101
114
  forms.set(container, state);
102
115
  }
103
116
  return state;
@@ -197,11 +210,11 @@ function overrideRow(
197
210
  const current = readTokenOverride(rootStyle, context, token.name);
198
211
  return {
199
212
  ctx: context.name,
200
- fieldLabel: `${token.label} in ${context.label}`,
213
+ fieldLabel: `${token.name} in ${context.label}`,
201
214
  id: `${token.name} ${context.name}`,
202
215
  kind: context.kind,
203
216
  label: context.label,
204
- swatchLabel: `${token.label} in ${context.label}`,
217
+ swatchLabel: `${token.name} in ${context.label}`,
205
218
  swatchState: isColor ? "swatch" : "none",
206
219
  token: token.name,
207
220
  value: current === undefined ? "" : String(current),
@@ -217,6 +230,10 @@ function overrideRow(
217
230
  * in dark mode" is a question a palette is always answering. A token with no value is offered no
218
231
  * picker: writing an empty override is how one is CLEARED, so the affordance would be inert.
219
232
  *
233
+ * A row is NAMED by its custom property, `--color-accent`, never by a friendly rewording of it: the
234
+ * Outline beside the view lists the same `--name`, a `var()` reference spells it, and it is what
235
+ * CSS reads. The same goes for a reference chip, which names the property the value follows.
236
+ *
220
237
  * @param {ProjectToken} token
221
238
  * @param {TokenGroup} group
222
239
  * @param {JxStyle} rootStyle
@@ -228,6 +245,7 @@ function tokenRow(
228
245
  group: TokenGroup,
229
246
  rootStyle: JxStyle,
230
247
  declared: TokenContext[],
248
+ current: string | null,
231
249
  ): TokenRowView {
232
250
  const isColor = group.id === "color";
233
251
  const value = String(token.value);
@@ -240,25 +258,26 @@ function tokenRow(
240
258
  );
241
259
  const addable = value === "" ? [] : addableContexts(rootStyle, declared, token.name, shown);
242
260
  return {
243
- addLabel: `Add an override for ${token.label}`,
261
+ addLabel: `Add an override for ${token.name}`,
244
262
  addOptions: [ADD_OVERRIDE_ROW, ...addable.map((c) => ({ label: c.label, value: c.name }))],
245
263
  addPick: "",
246
264
  addState: addable.length === 0 ? "none" : "shown",
247
- chipLabel: refName === null ? "" : tokenLabel(refName),
265
+ chipLabel: refName ?? "",
248
266
  chipState: refName === null ? "none" : isColor && resolved !== undefined ? "swatch" : "plain",
249
267
  chipSwatch: resolved === undefined ? "" : String(resolved),
250
268
  chipTitle:
251
269
  refName === null
252
270
  ? ""
253
271
  : `${toTokenRef(refName)} → ${resolved === undefined ? "unresolved" : String(resolved)}`,
254
- label: token.label,
272
+ current: token.name === current,
273
+ label: token.name,
255
274
  name: token.name,
256
275
  overrides: shown.map((context) => overrideRow(token, context, isColor, rootStyle)),
257
276
  overrideState: shown.length === 0 && addable.length === 0 ? "none" : "shown",
258
277
  previewFont: group.id === "font" ? value : "",
259
278
  previewState: group.id === "font" ? "font" : "none",
260
- removeLabel: `Delete ${token.label}`,
261
- swatchLabel: `${token.label} colour`,
279
+ removeLabel: `Delete ${token.name}`,
280
+ swatchLabel: `${token.name} color`,
262
281
  swatchState: isColor ? "swatch" : "none",
263
282
  value,
264
283
  ...well(isColor ? resolved : undefined, COLOR_INPUT_FALLBACK),
@@ -297,7 +316,9 @@ function view(container: HTMLElement): CssVarsView {
297
316
  nameLabel: `New ${group.title} name`,
298
317
  noticeState: group.id === "color" && !hasScheme ? "shown" : "none",
299
318
  title: group.title,
300
- tokens: tokens.map((token) => tokenRow(token, group, rootStyle, declared)),
319
+ tokens: tokens.map((token) =>
320
+ tokenRow(token, group, rootStyle, declared, form(container).current),
321
+ ),
301
322
  valueHint: ADD_ROW_HINTS[group.id].value,
302
323
  valueLabel: `New ${group.title} value`,
303
324
  });
@@ -360,16 +381,17 @@ function addOverride(container: HTMLElement, token: string, ctx: string): void {
360
381
  commit(container);
361
382
  }
362
383
 
363
- /** Switch Settings to the Contexts section, saying so when the section registry will not load. */
364
- async function openContextsSection(): Promise<void> {
365
- try {
366
- const { setSettingsSection } = await import("./section-registry");
367
- setSettingsSection("contexts");
368
- } catch (error) {
369
- notify.error(`Could not open Settings › Contexts — ${errorMessage(error)}`, {
370
- source: "Settings",
371
- });
372
- }
384
+ /**
385
+ * Open Project Settings on Contexts, where the color schemes and breakpoints this editor overrides
386
+ * per token are defined.
387
+ *
388
+ * Through the command rather than by writing the registry's section: the editor is hosted outside
389
+ * Settings (the Styles workspace's Variables view), so selecting a section of a dialog that is not
390
+ * open would change nothing the reader can see. A refusal is filed under "Styles", the workspace
391
+ * the editor lives in, as the Variables view's own button files it.
392
+ */
393
+ function openContextsSection(): void {
394
+ void runActiveReported("settings.open", { section: "contexts" }, "Styles");
373
395
  }
374
396
 
375
397
  /**
@@ -395,11 +417,11 @@ function actions(container: HTMLElement): CssVarsActions {
395
417
  * point at the place a scheme is DEFINED. It used to define one itself — a button here
396
418
  * appended `'--dark': '(prefers-color-scheme: dark)'` to `$media` without ever using the word
397
419
  * breakpoint, which made this form the fourth and least discoverable definition site for a
398
- * map whose other three lived in the wizard, Overview and Properties › Media. The lazy import
399
- * breaks the css-vars-editor ↔ section-registry cycle.
420
+ * map whose other three lived in the wizard, Overview and Properties › Media. It goes there
421
+ * through `settings.open`, so the dialog opens on Contexts however this editor is hosted.
400
422
  */
401
423
  manageContexts: () => {
402
- void openContextsSection();
424
+ openContextsSection();
403
425
  },
404
426
  removeToken: (name: string) => {
405
427
  delete style()[name];
@@ -453,3 +475,47 @@ function actions(container: HTMLElement): CssVarsActions {
453
475
  export function renderCssVarsEditor(container: HTMLElement): void {
454
476
  refresh(container);
455
477
  }
478
+
479
+ /**
480
+ * Point the editor at one token: mark its row, scroll it into view and put the keyboard on its
481
+ * value. What a variable row in the Styles workspace's Outline asks for.
482
+ *
483
+ * A name this project does not declare is still recorded (it may be about to be added, or the
484
+ * Outline may be ahead of a write), and simply marks nothing. The flow only marks the row; bringing
485
+ * it on screen is the surface's (`revealCssVarsToken`), because only the adapter knows where the
486
+ * row it draws is.
487
+ *
488
+ * @param {HTMLElement} container
489
+ * @param {string | null} name A custom property, `--accent`, or `null` to mark none
490
+ * @param {{ reveal?: boolean }} [options] `reveal: false` marks the row without moving the keyboard
491
+ * or the scroll position
492
+ */
493
+ export function focusCssVar(
494
+ container: HTMLElement,
495
+ name: string | null,
496
+ options: { reveal?: boolean } = {},
497
+ ): void {
498
+ form(container).current = name;
499
+ refresh(container);
500
+ if (name === null || options.reveal === false) {
501
+ return;
502
+ }
503
+ revealCssVarsToken(container, name);
504
+ }
505
+
506
+ /**
507
+ * Point the editor at one group: bring its heading on screen, and with `add` put the keyboard on
508
+ * its Add row, the editor's own way of adding a variable. What a group heading and "Add variable"
509
+ * in the Styles workspace's Styles panel ask for.
510
+ *
511
+ * @param {HTMLElement} container
512
+ * @param {TokenGroupId} group
513
+ * @param {{ add?: boolean }} [options] `add: true` focuses the Add row's name field
514
+ */
515
+ export function focusCssVarGroup(
516
+ container: HTMLElement,
517
+ group: TokenGroupId,
518
+ options: { add?: boolean } = {},
519
+ ): void {
520
+ revealCssVarsGroup(container, group, options.add === true);
521
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * The **Show developer panels** preference (`specs/studio.md` §5.1, §15).
3
+ *
4
+ * Off by default. A site author works in pages, templates, components and media, and the Site panel
5
+ * lists those by what they are; the Files tree and the Packages list are where a developer looks,
6
+ * so they are off the Design rail until the author asks for them. With the switch off both panels
7
+ * are still reachable by `view.setActivity` and the palette: the switch hides two rail buttons, not
8
+ * two capabilities.
9
+ *
10
+ * The value roams like the theme does (`SETTINGS.developerPanels`, scope `user`), and it is read
11
+ * through a REACTIVE mirror rather than straight from the kernel: the rail derives its groups
12
+ * inside an effect, and a kernel read is not tracked, so a flip in Preferences (or in another
13
+ * window) would otherwise leave the rail drawing the old answer until something unrelated repainted
14
+ * it.
15
+ *
16
+ * @docs studio/interface
17
+ */
18
+
19
+ import { reactive } from "../reactivity";
20
+ import { SETTINGS } from "../services/settings/definitions";
21
+ import { onSettingsChanged, readStoredSetting, setSetting } from "../services/settings/kernel";
22
+
23
+ /** The stored spelling of "on". Anything else, including unset, is off. */
24
+ const ON = "true";
25
+
26
+ const _state = reactive({ on: readStoredSetting(SETTINGS.developerPanels) === ON });
27
+
28
+ onSettingsChanged((keys) => {
29
+ if (keys.includes(SETTINGS.developerPanels.key)) {
30
+ _state.on = readStoredSetting(SETTINGS.developerPanels) === ON;
31
+ }
32
+ });
33
+
34
+ /** Whether the developer panels (Files, Packages) are on the rail. Tracked when read in an effect. */
35
+ export function developerPanelsShown(): boolean {
36
+ return _state.on;
37
+ }
38
+
39
+ /** Put the developer panels on the rail, or take them off. Persisted and roaming. */
40
+ export function setDeveloperPanelsShown(show: boolean): void {
41
+ _state.on = show;
42
+ setSetting(SETTINGS.developerPanels, show ? ON : "");
43
+ }