@jxsuite/studio 6.1.2 → 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 (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
@@ -40,6 +40,40 @@ export const PROJECT_STYLES_TITLE = "Project Styles";
40
40
  */
41
41
  export const PROJECT_STYLES_VIEW: CanvasMode = "stylebook";
42
42
 
43
+ /**
44
+ * The editor the Variables view draws under: the CSS custom properties of `project.json`'s root
45
+ * style block (§7.1). A Studio-side editor mode like `media` or `entry`, not a canvas render, so it
46
+ * is not a member of the iframe protocol's `CANVAS_MODES` and nothing in the frame bundle reads
47
+ * it.
48
+ */
49
+ export const PROJECT_VARIABLES_VIEW = "tokens";
50
+
51
+ /** The Code editor's mode over the same document. */
52
+ const PROJECT_SOURCE_VIEW = "source";
53
+
54
+ /**
55
+ * The Styles workspace's three views of the `project.json` tab, by the names `styles.open` takes,
56
+ * in the order the pane's Editor control offers them: the element defaults (keyed by tag name), the
57
+ * custom properties, and the file as text. One map, so the argument enum, the tab's mode list and
58
+ * the editor labels cannot disagree about which mode a view is.
59
+ */
60
+ export const STYLES_VIEW_MODES = {
61
+ elements: PROJECT_STYLES_VIEW,
62
+ variables: PROJECT_VARIABLES_VIEW,
63
+ code: PROJECT_SOURCE_VIEW,
64
+ } as const;
65
+
66
+ /** A view `styles.open` can be asked for. */
67
+ export type StylesView = keyof typeof STYLES_VIEW_MODES;
68
+
69
+ /** Every view name, in the Editor control's order. */
70
+ export const STYLES_VIEWS: readonly StylesView[] = ["elements", "variables", "code"];
71
+
72
+ /** The `project.json` tab's modes, in that same order. */
73
+ export const STYLES_TAB_MODES: readonly string[] = STYLES_VIEWS.map(
74
+ (view) => STYLES_VIEW_MODES[view],
75
+ );
76
+
43
77
  // ─── Token groups ────────────────────────────────────────────────────────────
44
78
 
45
79
  /** The four buckets the token editor lists, in display order. */
@@ -0,0 +1,89 @@
1
+ /**
2
+ * What each project component's Project Styles card is drawn with.
3
+ *
4
+ * The catalogue drew every component as a bare instance with only its declared defaults, and a
5
+ * component is rarely drawable that way: the museum starter's `<mu-exhibition-card>` formats a
6
+ * `date` that defaults to `""`, so its card stayed empty and the canvas logged "was not rendered:
7
+ * RangeError: Invalid time value" for it on every paint (`spec.md` §16.4). The Site panel's
8
+ * previews already know where a component's sample props live (`browse/component-examples.ts`), so
9
+ * a card asks the same three sources, in the same order, and draws:
10
+ *
11
+ * - `props`: an instance given its sample props, when the definition renders with them;
12
+ * - `row`: the first row of a list that draws it, when it is only ever used as a list row;
13
+ * - `bare`: the bare instance, when it renders with its defaults and nothing better was found;
14
+ * - `none`: no live instance at all (the catalogue's placeholder box), when it renders with none of
15
+ * the above, because an instance that throws draws nothing and reports an error nobody can fix.
16
+ *
17
+ * Answers are cached per component registry: the registry is replaced whenever the project's
18
+ * components are re-read, so a changed definition is asked again.
19
+ *
20
+ * @docs studio/design/stylebook
21
+ */
22
+
23
+ import { componentExampleProps, componentSampleRow } from "../browse/component-examples";
24
+ import type { SampleRow } from "../browse/component-examples";
25
+ import { readDefinition, rendersWith } from "../browse/library-preview";
26
+ import { defineComponent } from "../panels/component-preview";
27
+ import type { ComponentEntry } from "../files/components";
28
+ import type { JsonValue } from "@jxsuite/schema/types";
29
+
30
+ /** How one component card is drawn; see the module comment. */
31
+ export type StylebookSpecimen =
32
+ | { kind: "props"; props: Record<string, JsonValue> }
33
+ | { kind: "row"; sample: SampleRow }
34
+ | { kind: "bare" }
35
+ | { kind: "none" };
36
+
37
+ /** The specimens of the components a catalogue draws, by tag name. */
38
+ export type StylebookSpecimens = ReadonlyMap<string, StylebookSpecimen>;
39
+
40
+ const cache = new WeakMap<readonly ComponentEntry[], Map<string, Promise<StylebookSpecimen>>>();
41
+
42
+ /** One component's specimen. A component that is not a project JSON definition is drawn bare. */
43
+ export async function componentSpecimen(component: ComponentEntry): Promise<StylebookSpecimen> {
44
+ const { path } = component;
45
+ if (component.source === "npm" || !path?.endsWith(".json")) {
46
+ return { kind: "bare" };
47
+ }
48
+ const definition = await readDefinition(path);
49
+ if (!definition) {
50
+ return { kind: "bare" };
51
+ }
52
+ const props = await componentExampleProps(definition, path);
53
+ if (props.size > 0 && (await rendersWith(definition, path, props))) {
54
+ return { kind: "props", props: Object.fromEntries(props) };
55
+ }
56
+ const sample = await componentSampleRow(definition, path);
57
+ if (sample && (await defineComponent(component))) {
58
+ return { kind: "row", sample };
59
+ }
60
+ return (await rendersWith(definition, path, new Map())) ? { kind: "bare" } : { kind: "none" };
61
+ }
62
+
63
+ /**
64
+ * The specimens of every component in `registry`, asked once per registry and component. A
65
+ * component whose answer cannot be found is drawn bare, as it was before specimens existed.
66
+ */
67
+ export async function loadStylebookSpecimens(
68
+ registry: readonly ComponentEntry[],
69
+ ask: (component: ComponentEntry) => Promise<StylebookSpecimen> = componentSpecimen,
70
+ ): Promise<StylebookSpecimens> {
71
+ let answers = cache.get(registry);
72
+ if (!answers) {
73
+ answers = new Map();
74
+ cache.set(registry, answers);
75
+ }
76
+ const known = answers;
77
+ const entries = await Promise.all(
78
+ registry.map(async (component): Promise<[string, StylebookSpecimen]> => {
79
+ const key = component.path ?? component.tagName;
80
+ let answer = known.get(key);
81
+ if (!answer) {
82
+ answer = ask(component).catch((): StylebookSpecimen => ({ kind: "bare" }));
83
+ known.set(key, answer);
84
+ }
85
+ return [component.tagName, await answer];
86
+ }),
87
+ );
88
+ return new Map(entries);
89
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * What a tab is styling while it draws the Styles workspace's Elements view: a TAG, not a node.
3
+ *
4
+ * The Elements view is a catalogue of specimens, and picking one moves `shell.stylebook.selection`
5
+ * (`selectStylebookTag`), never the tab's document selection: an `h1` specimen is not a node of
6
+ * `project.json`, so there is no path that names it. Every place that answers "what am I pointed
7
+ * at" (the status bar's selection field, the command bar's selection segment, the Inspector's
8
+ * header) asks this first, and falls back to the document selection only when it says null. Before
9
+ * they shared it, two of the three read the document selection alone, and the Outline's row click
10
+ * parked that on the root, so `h1 · Base` was being edited under a header and a path that both said
11
+ * `div`.
12
+ *
13
+ * The answer is null outside the Elements view, which is the whole condition the status bar always
14
+ * had: the stylebook selection outlives a workspace switch (coming back to Styles finds `h1` still
15
+ * picked), but a Content page, the Variables view or the Publish home is not editing `h1`.
16
+ */
17
+
18
+ import { shell } from "../shell";
19
+ import { PROJECT_STYLES_VIEW } from "./project-styles";
20
+
21
+ import type { Tab } from "../tabs/tab";
22
+
23
+ /** The tag the tab's Elements view is styling, or null when the tab is not styling a tag. */
24
+ export function stylebookTarget(tab: Tab | null | undefined): string | null {
25
+ return tab?.session.ui.canvasMode === PROJECT_STYLES_VIEW ? shell.stylebook.selection : null;
26
+ }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * What a Project Styles tag rule inherits, and from where.
3
+ *
4
+ * `project.json`'s style compiles its flat properties to `body` and each bare tag key to a global
5
+ * rule (`compileStyles`, via `site/site-build.ts`), so an `h1` with no `fontFamily` of its own is
6
+ * set in whatever `body` says, and a `th` under `table` takes `table`'s colour first. The Style
7
+ * panel's own walk (`computeInheritedSources`) only follows ONE coordinate across contexts, which
8
+ * is right for a page element (its ancestors are other nodes, edited elsewhere) and wrong here:
9
+ * every ancestor of a tag rule is in this same file. Without this, an unset inherited row showed
10
+ * the CSS initial value as its placeholder, so Font Family on `h1` read "depends on user agent"
11
+ * while the specimen beside it was drawn in the project's body font.
12
+ *
13
+ * Only properties CSS inherits are walked ({@link INHERITED_PROPERTIES}); `margin` on `body` is not
14
+ * a value an `h1` has.
15
+ *
16
+ * @docs studio/design/stylebook
17
+ */
18
+
19
+ import { getNestedStyle, isNumber, isString } from "@jxsuite/schema/guards";
20
+ import type { JxStyle } from "@jxsuite/schema/types";
21
+
22
+ /**
23
+ * The properties the Style panel draws (`data/css-meta.json`) that CSS defines as inherited.
24
+ *
25
+ * A list rather than a lookup because the panel bundle carries no CSS property database: the test
26
+ * beside this module holds it to `@webref/css` in both directions, so a property is here exactly
27
+ * when the panel draws it and the specification says `Inherited: yes`.
28
+ */
29
+ export const INHERITED_PROPERTIES: ReadonlySet<string> = new Set([
30
+ "color",
31
+ "cursor",
32
+ "fontFamily",
33
+ "fontSize",
34
+ "fontStyle",
35
+ "fontVariant",
36
+ "fontWeight",
37
+ "letterSpacing",
38
+ "lineHeight",
39
+ "listStyleType",
40
+ "pointerEvents",
41
+ "textAlign",
42
+ "textShadow",
43
+ "textTransform",
44
+ "visibility",
45
+ "wordBreak",
46
+ "wordSpacing",
47
+ ]);
48
+
49
+ /** One inherited value and the rule that supplies it: `body`, or an ancestor tag in the path. */
50
+ export interface TagAncestorSource {
51
+ value: string | number;
52
+ donor: string;
53
+ }
54
+
55
+ /** The declarations of `block` that CSS inherits, layered over `into` as coming from `donor`. */
56
+ function layerInherited(
57
+ into: Map<string, TagAncestorSource>,
58
+ block: JxStyle | undefined,
59
+ donor: string,
60
+ ): void {
61
+ for (const [prop, value] of Object.entries(block ?? {})) {
62
+ if (INHERITED_PROPERTIES.has(prop) && (isString(value) || isNumber(value))) {
63
+ into.set(prop, { donor, value });
64
+ }
65
+ }
66
+ }
67
+
68
+ /** The style a tag path addresses (`table th` → `style.table.th`), or undefined when absent. */
69
+ function tagBlock(style: JxStyle | undefined, path: readonly string[]): JxStyle | undefined {
70
+ let block = style;
71
+ for (const tag of path) {
72
+ block = getNestedStyle(block, tag);
73
+ }
74
+ return block;
75
+ }
76
+
77
+ /**
78
+ * What the tag at `tagPath` inherits from the rules above it, nearest donor winning: `body` (the
79
+ * flat properties), then each ancestor tag in the path. In a context (`media`, a breakpoint or a
80
+ * scheme block's name without its `@`), each donor's block in that context is layered over its
81
+ * base, which is the order the compiled stylesheet applies them in.
82
+ */
83
+ export function tagAncestorSources(
84
+ style: JxStyle,
85
+ tagPath: string,
86
+ media: string | null,
87
+ ): Record<string, TagAncestorSource> {
88
+ const path = tagPath.split(" ").filter(Boolean);
89
+ const contextStyle = media ? getNestedStyle(style, `@${media}`) : undefined;
90
+ const sources = new Map<string, TagAncestorSource>();
91
+ /* `body` is spelled two ways and both compile to the one rule: the flat properties, and a `body`
92
+ tag key. The tag key is later in the sheet, so it is layered second. */
93
+ const ancestors: string[][] = [[], ...(path[0] === "body" ? [] : [["body"]])];
94
+ for (let depth = 1; depth < path.length; depth += 1) {
95
+ ancestors.push(path.slice(0, depth));
96
+ }
97
+ for (const ancestor of ancestors) {
98
+ const donor = ancestor.at(-1) ?? "body";
99
+ layerInherited(sources, tagBlock(style, ancestor), donor);
100
+ if (contextStyle) {
101
+ layerInherited(sources, tagBlock(contextStyle, ancestor), donor);
102
+ }
103
+ }
104
+ return Object.fromEntries(sources);
105
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Where the Variables view should point next: one custom property, or one group of them.
3
+ *
4
+ * The Styles panel (`panels/styles-panel.ts`) lists every CSS custom property and every group, and
5
+ * choosing one shows it in the Variables view (`style/variables-view.ts`). The panel does not own
6
+ * the pane, so it does not call into the view: it files a REQUEST here and the view, which watches
7
+ * {@link variablesFocus}, scrolls the row into view and puts the keyboard on it. A request made
8
+ * while the view is not on screen yet (the pane was in Elements) is served when the view mounts,
9
+ * once: {@link VariablesFocusRequest.served} is what tells a new request from one already served.
10
+ *
11
+ * The property the view MARKS is `shell.stylebook.variable`, written here too, so the panel and the
12
+ * editor mark the same row.
13
+ *
14
+ * @docs studio/design/tokens
15
+ */
16
+
17
+ import { shallowRef } from "../reactivity";
18
+ import { shell } from "../shell";
19
+ import type { TokenGroupId } from "./project-styles";
20
+
21
+ /** What the Variables view is asked to bring on screen. */
22
+ export type VariablesFocus =
23
+ /** One custom property, `--accent`: its row is scrolled to and its value field focused. */
24
+ | { kind: "variable"; name: string }
25
+ /**
26
+ * One group (Colors, Fonts, …): its heading is scrolled to, and with `add` its Add row's name
27
+ * field is focused, which is how "Add variable" reaches the editor's own add flow.
28
+ */
29
+ | { kind: "group"; group: TokenGroupId; add: boolean };
30
+
31
+ /**
32
+ * One request. `served` is set by the view that brought it on screen, so a second view (another
33
+ * pane, or the same pane drawn again) does not move the keyboard for a click it has already
34
+ * answered. A plain field on a SHALLOW ref's value: serving a request is not a change anybody
35
+ * watches.
36
+ */
37
+ export interface VariablesFocusRequest {
38
+ focus: VariablesFocus | null;
39
+ served: boolean;
40
+ }
41
+
42
+ /** The latest request. Every assignment is a new request; nothing asked yet is a served `null`. */
43
+ export const variablesFocus = shallowRef<VariablesFocusRequest>({ focus: null, served: true });
44
+
45
+ /**
46
+ * Ask the Variables view to bring a property or a group on screen. Choosing the property already
47
+ * chosen asks again, which brings it back after the author scrolled away.
48
+ *
49
+ * @param {VariablesFocus} focus
50
+ */
51
+ export function requestVariablesFocus(focus: VariablesFocus): void {
52
+ if (focus.kind === "variable") {
53
+ shell.stylebook.variable = focus.name;
54
+ }
55
+ variablesFocus.value = { focus, served: false };
56
+ }
57
+
58
+ /** Forget any request not yet served: a project switch, whose views are not this request's. */
59
+ export function resetVariablesFocus(): void {
60
+ variablesFocus.value = { focus: null, served: true };
61
+ }
@@ -0,0 +1,235 @@
1
+ /// <reference lib="dom" />
2
+ /**
3
+ * The Variables view: the Styles workspace's editor for the project's CSS custom properties
4
+ * (studio.md §7.1).
5
+ *
6
+ * It is the `tokens` editor of the `project.json` tab, beside Elements (the `stylebook` specimens)
7
+ * and Code (`source`), so the pane's Editor control switches between the three over one document,
8
+ * one history and one dirty flag. What it draws is the CSS Variables editor that used to be a
9
+ * Project Settings section (`settings/css-vars-editor.ts`), unchanged, inside a frame of its own
10
+ * (`surfaces/styles-variables.json`) that says what a variable is, when an edit reaches the file
11
+ * and where colour schemes are declared.
12
+ *
13
+ * **Saving is stated, not implied.** The editor commits every edit through the configuration
14
+ * chokepoint as it is made (`updateSiteConfig` → `commitProjectConfig`), which writes the whole
15
+ * document and leaves the tab clean, while an edit in the Elements view is a transaction on the tab
16
+ * that waits for ⌘S. Both models are kept; what is not allowed is the author learning the
17
+ * difference from the Save button, so the view says it in words ({@link VARIABLES_SAVING}).
18
+ *
19
+ * **One configuration object.** Before the editor draws, the open `project.json` tab is made the
20
+ * configuration document of record (`projectConfigDocument`), so the object the editor mutates is
21
+ * the tab's own and an element style edit made a moment ago in Elements is not a rival the commit
22
+ * would refuse (`tabs/project-config.ts`).
23
+ *
24
+ * **It follows the document.** An edit that reaches the tab another way (an undo, the Code view, an
25
+ * element style edit that wrote a custom property) re-projects the editor, and choosing a variable
26
+ * or a group in the Styles panel (`style/variables-focus.ts`) points the editor at it.
27
+ *
28
+ * Mounted per pane, keyed by pane id, for the reason `media/media-pane.ts` gives: two panes can
29
+ * each show a view at once.
30
+ *
31
+ * @docs studio/design/tokens
32
+ */
33
+
34
+ import { effect, effectScope, pauseTracking, resetTracking } from "../reactivity";
35
+ import { projectState } from "../store";
36
+ import { shell } from "../shell";
37
+ import { runActiveReported } from "../commands/run-reported";
38
+ import { projectConfigDocument } from "../tabs/project-config";
39
+ import { PROJECT_CONFIG_PATH } from "../tabs/tab";
40
+ import { paneRegion } from "../ui/regions";
41
+ import { focusCssVar, focusCssVarGroup, renderCssVarsEditor } from "../settings/css-vars-editor";
42
+ import { variablesFocus } from "./variables-focus";
43
+ import type { VariablesFocus } from "./variables-focus";
44
+ import { mountVariablesSurface } from "../surfaces/styles-variables";
45
+ import type { VariablesSurfaceHandle, VariablesView } from "../surfaces/styles-variables";
46
+ import type { Tab } from "../tabs/tab";
47
+ import type { CanvasSurface } from "../canvas/canvas-surface";
48
+
49
+ /** The view's heading: the name its Editor control row gives it too. */
50
+ export const VARIABLES_TITLE = "Variables";
51
+
52
+ /** What a variable is, in the words of the platform feature it is. */
53
+ export const VARIABLES_LEDE =
54
+ "Your site's CSS custom properties, kept in the root style block of project.json. Every page " +
55
+ "and component can use one in any style value as var(--name).";
56
+
57
+ /**
58
+ * When an edit here reaches the file, which is not when an Elements edit does.
59
+ *
60
+ * Three sentences, each one rule, with the exception named AS an exception. It was one sentence
61
+ * saying a change is saved as you make it and the next saying Save writes the value, which a reader
62
+ * took as the view contradicting itself rather than as undo being the case that waits.
63
+ */
64
+ export const VARIABLES_SAVING =
65
+ "Each change here is written to project.json as you make it, so there is nothing to save " +
66
+ "afterwards. The write also saves any Elements change still waiting for Save, because both " +
67
+ "live in that file. Undo is the exception: an undone change waits for Save like any other edit.";
68
+
69
+ /** Where color schemes and breakpoints are declared, which is not here. */
70
+ export const VARIABLES_SCHEMES =
71
+ "To give a variable another value in a color scheme or at a breakpoint, use Add override " +
72
+ "under its row. The schemes and breakpoints themselves are declared in Project settings, " +
73
+ "under Contexts.";
74
+
75
+ /** What the view draws in `paneId`. Pure: every word is a constant. */
76
+ export function variablesView(paneId: string): VariablesView {
77
+ return {
78
+ lede: VARIABLES_LEDE,
79
+ // The label every door to Contexts wears: the pane context bar's footer and the Colors group's notice.
80
+ manageLabel: "Manage contexts…",
81
+ region: paneRegion(paneId, "variables"),
82
+ saving: VARIABLES_SAVING,
83
+ schemes: VARIABLES_SCHEMES,
84
+ title: VARIABLES_TITLE,
85
+ };
86
+ }
87
+
88
+ // ─── Mounting ────────────────────────────────────────────────────────────────
89
+
90
+ interface ActiveVariablesView {
91
+ paneId: string;
92
+ tabId: string;
93
+ wrap: HTMLElement;
94
+ surface: VariablesSurfaceHandle;
95
+ scope: { stop: () => void; run: <T>(fn: () => T) => T | undefined };
96
+ }
97
+
98
+ const _active = new Map<string, ActiveVariablesView>();
99
+
100
+ /** Whether this tab's view is already mounted in this pane and still in the document. */
101
+ export function variablesViewMounted(paneId: string, tab: Tab): boolean {
102
+ const view = _active.get(paneId);
103
+ return (
104
+ view !== undefined && view.tabId === tab.id && view.wrap.isConnected && view.surface.attached()
105
+ );
106
+ }
107
+
108
+ /** Tear one pane's view down (mode change, tab switch, project close). Idempotent. */
109
+ export function detachVariablesView(paneId: string): void {
110
+ const view = _active.get(paneId);
111
+ if (!view) {
112
+ return;
113
+ }
114
+ view.scope.stop();
115
+ view.surface.dispose();
116
+ _active.delete(paneId);
117
+ }
118
+
119
+ /** Open Project Settings on Contexts. A refusal is filed under this view's workspace. */
120
+ function manageContexts(): void {
121
+ void runActiveReported("settings.open", { section: "contexts" }, "Styles");
122
+ }
123
+
124
+ /**
125
+ * Make the open `project.json` tab the configuration document, so the object the editor mutates in
126
+ * place is the tab's own. A no-op with no project, and for any other document.
127
+ */
128
+ function bindConfiguration(tab: Tab): void {
129
+ if (projectState && tab.documentPath === PROJECT_CONFIG_PATH) {
130
+ projectConfigDocument();
131
+ }
132
+ }
133
+
134
+ /** Bring what a request names on screen in `host`, the editor island. */
135
+ function serve(host: HTMLElement, focus: VariablesFocus | null): void {
136
+ if (focus?.kind === "group") {
137
+ focusCssVarGroup(host, focus.group, { add: focus.add });
138
+ return;
139
+ }
140
+ focusCssVar(host, focus?.name ?? shell.stylebook.variable);
141
+ }
142
+
143
+ /** Serve the latest request in `host` if no view has served it yet. Whether it did. */
144
+ function serveLatest(host: HTMLElement): boolean {
145
+ const request = variablesFocus.value;
146
+ if (request.served) {
147
+ return false;
148
+ }
149
+ request.served = true;
150
+ serve(host, request.focus);
151
+ return true;
152
+ }
153
+
154
+ /** Run `fn` without the calling effect tracking what it reads. */
155
+ function untracked(fn: () => void): void {
156
+ pauseTracking();
157
+ try {
158
+ fn();
159
+ } finally {
160
+ resetTracking();
161
+ }
162
+ }
163
+
164
+ /**
165
+ * Draw the Variables view into a pane's stage.
166
+ *
167
+ * @param {CanvasSurface} surface
168
+ * @param {Tab} tab The `project.json` tab, in its `tokens` editor
169
+ */
170
+ export function renderVariablesMode(surface: CanvasSurface, tab: Tab): void {
171
+ const { paneId, wrap } = surface;
172
+ if (variablesViewMounted(paneId, tab)) {
173
+ return;
174
+ }
175
+ detachVariablesView(paneId);
176
+ bindConfiguration(tab);
177
+
178
+ /** The editor island, once the document has created it. */
179
+ let editorHost: HTMLElement | null = null;
180
+
181
+ const mounted = mountVariablesSurface(
182
+ wrap,
183
+ variablesView(paneId),
184
+ { manageContexts },
185
+ {
186
+ editorSlot: (host) => {
187
+ editorHost = host;
188
+ renderCssVarsEditor(host);
189
+ /* A request the Styles panel made while the pane was in another view (a variable or a
190
+ group chosen from Elements) is served now, once. Otherwise the marked property is only
191
+ MARKED: arriving at the view is not a request to move the keyboard. */
192
+ if (!serveLatest(host) && shell.stylebook.variable !== null) {
193
+ focusCssVar(host, shell.stylebook.variable, { reveal: false });
194
+ }
195
+ },
196
+ },
197
+ );
198
+ const scope = effectScope();
199
+ _active.set(paneId, { paneId, scope, surface: mounted, tabId: tab.id, wrap });
200
+
201
+ scope.run(() => {
202
+ /* What the editor shows, read off the TAB so an undo, a Code edit or a transaction that
203
+ replaced the root re-projects it. Serialised, because a property nested in an `@` block is
204
+ a change the editor draws and a shallow read would not see. */
205
+ let seen: string | null = null;
206
+ effect(() => {
207
+ const { document } = tab.doc;
208
+ const key = JSON.stringify([document.style ?? null, document.$media ?? null]);
209
+ if (key === seen) {
210
+ return;
211
+ }
212
+ const first = seen === null;
213
+ seen = key;
214
+ const host = editorHost;
215
+ if (!first && host) {
216
+ untracked(() => {
217
+ bindConfiguration(tab);
218
+ renderCssVarsEditor(host);
219
+ });
220
+ }
221
+ });
222
+ /* The Styles panel's variable rows, group headings and "Add variable". Every request is a new
223
+ value, so choosing the same property again, after scrolling away from it, brings it back
224
+ again. */
225
+ effect(() => {
226
+ void variablesFocus.value;
227
+ const host = editorHost;
228
+ if (host) {
229
+ untracked(() => {
230
+ serveLatest(host);
231
+ });
232
+ }
233
+ });
234
+ });
235
+ }