@jxsuite/studio 4.1.0 → 5.1.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 (612) hide show
  1. package/README.md +1 -1
  2. package/data/elements-meta.json +5 -15
  3. package/data/html-meta.json +51 -6
  4. package/dist/chunks/{2020-n6tfwnda.js → 2020-g79n01v9.js} +14 -14
  5. package/dist/chunks/action-group-sp6tna8v.js +118 -0
  6. package/dist/chunks/adapter-nj7tnjfn.js +13 -0
  7. package/dist/chunks/cf-account-picker-qwkm9zrf.js +495 -0
  8. package/dist/chunks/cf-settings-71bv5zn9.js +20 -0
  9. package/dist/chunks/color-area-v17df7b8.js +154 -0
  10. package/dist/chunks/color-field-anwybnkn.js +208 -0
  11. package/dist/chunks/color-slider-44ez96fc.js +79 -0
  12. package/dist/chunks/color-xgg3kfw7.js +35 -0
  13. package/dist/chunks/combobox-5e7jev23.js +236 -0
  14. package/dist/chunks/components-vj72gqtq.js +20 -0
  15. package/dist/chunks/content-source-5mex4x1h.js +46 -0
  16. package/dist/chunks/convert-to-repeater-n64h8znc.js +639 -0
  17. package/dist/chunks/dialog-s890b918.js +85 -0
  18. package/dist/chunks/editor-3qhbg51x.js +35 -0
  19. package/dist/chunks/entry-commands-234hjnqw.js +42 -0
  20. package/dist/chunks/extension-sections-3hpcambp.js +651 -0
  21. package/dist/chunks/file-ops-8yhd83xr.js +47 -0
  22. package/dist/chunks/files-hnxqxtsg.js +72 -0
  23. package/dist/chunks/format-host-779sfp2n.js +40 -0
  24. package/dist/chunks/fs-events-b88z7g4h.js +18 -0
  25. package/dist/chunks/git-panel-xwj8fpab.js +49 -0
  26. package/dist/chunks/icons-yy10wk9r.js +402 -0
  27. package/dist/chunks/iframe-entry-15g3n6xv.js +114 -0
  28. package/dist/chunks/iframe-entry-b27vq81n.js +203 -0
  29. package/dist/chunks/iframe-entry-nbyxee1y.js +154 -0
  30. package/dist/chunks/iframe-host-syr0f9sb.js +115 -0
  31. package/dist/chunks/{index-wcnt3r9g.js → index-mdmyx6s2.js} +11 -11
  32. package/dist/chunks/index-n4j7qxyr.js +109 -0
  33. package/dist/chunks/{javascript-q8kpmfah.js → javascript-xvrfrpkb.js} +8 -9
  34. package/dist/chunks/{jsonMode-dkr040ga.js → jsonMode-tyx2kj6p.js} +526 -527
  35. package/dist/chunks/jx-validate-j0wxk72w.js +15 -0
  36. package/dist/chunks/layers-ff81wthn.js +30 -0
  37. package/dist/chunks/layers-panel-pnnghw12.js +40 -0
  38. package/dist/chunks/listbox-6v2ac08j.js +44 -0
  39. package/dist/chunks/lit-html-m244w9nh.js +17 -0
  40. package/dist/chunks/media-picker-cqhhxhhe.js +33 -0
  41. package/dist/chunks/menu-9p2w46gj.js +15 -0
  42. package/dist/chunks/menu-q99sy9rf.js +285 -0
  43. package/dist/chunks/{monaco-binding-rj6xpx9y.js → monaco-binding-sw6en4dw.js} +12 -15
  44. package/dist/chunks/monaco-buffer-bhy3hb6m.js +24 -0
  45. package/dist/chunks/{monaco-setup-vx9bhp1d.js → monaco-setup-8r62fj6y.js} +27 -37
  46. package/dist/chunks/notify-628t0anh.js +21 -0
  47. package/dist/chunks/number-field-5cndyft8.js +72 -0
  48. package/dist/chunks/parse-0zx14y15.js +10 -0
  49. package/dist/chunks/platform-ts9cg1a4.js +15 -0
  50. package/dist/chunks/popover-47z3ytva.js +25 -0
  51. package/dist/chunks/publish-panel-5zt840sy.js +27 -0
  52. package/dist/chunks/quick-search-3748564r.js +45 -0
  53. package/dist/chunks/references-qvvxej7h.js +26 -0
  54. package/dist/chunks/right-panel-eccz92qt.js +45 -0
  55. package/dist/chunks/section-registry-5pq32t0q.js +25 -0
  56. package/dist/chunks/select-2r16ez41.js +49 -0
  57. package/dist/chunks/split-g7nm1rgb.js +191 -0
  58. package/dist/chunks/studio-0hqbpbd0.js +62 -0
  59. package/dist/chunks/{studio-kryvsw6j.js → studio-1k325pwf.js} +48 -48
  60. package/dist/chunks/{studio-b55y6ewx.js → studio-1knfqgy7.js} +58 -58
  61. package/dist/chunks/{studio-2b946z26.js → studio-1z1kcjv4.js} +3628 -6095
  62. package/dist/chunks/studio-3773086z.js +111 -0
  63. package/dist/chunks/{studio-4r1pv6zf.js → studio-38emantv.js} +22 -5
  64. package/dist/chunks/{studio-x813zp48.js → studio-3rz5md06.js} +30 -30
  65. package/dist/chunks/{studio-ynxwkrzd.js → studio-4wbb9ct0.js} +1953 -1785
  66. package/dist/chunks/studio-5te5tqng.js +81 -0
  67. package/dist/chunks/studio-5wt9nvhd.js +4763 -0
  68. package/dist/chunks/{studio-p4ngc046.js → studio-6ewqv390.js} +9 -9
  69. package/dist/chunks/{studio-9ab8gqsm.js → studio-6nzaktvy.js} +7 -7
  70. package/dist/chunks/studio-6xa21ej9.js +28 -0
  71. package/dist/chunks/{studio-5ehhackm.js → studio-727xh0e3.js} +19 -19
  72. package/dist/chunks/{studio-gcye7qka.js → studio-7e11jpa9.js} +21 -21
  73. package/dist/chunks/{studio-q7v10cg2.js → studio-7r42c6ca.js} +17 -7
  74. package/dist/chunks/studio-7xnmgv66.js +13615 -0
  75. package/dist/chunks/studio-8scdew0e.js +258 -0
  76. package/dist/chunks/{studio-fbf92ckf.js → studio-93zafjcm.js} +275 -163
  77. package/dist/chunks/{studio-dg7zyt5x.js → studio-98b3z07n.js} +1 -1
  78. package/dist/chunks/studio-a79k90n9.js +1162 -0
  79. package/dist/chunks/studio-aj37eer3.js +422 -0
  80. package/dist/chunks/studio-b0k5tqgp.js +2432 -0
  81. package/dist/chunks/studio-b4s9eykd.js +2811 -0
  82. package/dist/chunks/{studio-f3wqjtk5.js → studio-d0300636.js} +5076 -18
  83. package/dist/chunks/{studio-b9b6t1dg.js → studio-e1f24eff.js} +5664 -5666
  84. package/dist/chunks/studio-e1pgga3k.js +839 -0
  85. package/dist/chunks/{studio-g1wdche0.js → studio-esrxgwh6.js} +80 -80
  86. package/dist/chunks/{studio-q43a5y9h.js → studio-g3jevyjt.js} +16 -16
  87. package/dist/chunks/studio-gb13095a.js +2806 -0
  88. package/dist/chunks/{studio-3n4ndrzh.js → studio-h4nvnjvz.js} +303 -303
  89. package/dist/chunks/{studio-dm19q43r.js → studio-hhvs4sdg.js} +10 -10
  90. package/dist/chunks/{studio-x4qkdat5.js → studio-js8nv53n.js} +1749 -2481
  91. package/dist/chunks/{studio-qjy2z9bv.js → studio-jxp12rnj.js} +32 -137
  92. package/dist/chunks/{studio-trxrabqf.js → studio-k75n7vhp.js} +527 -283
  93. package/dist/chunks/{studio-q9jd1a60.js → studio-kcgff4r0.js} +15 -18
  94. package/dist/chunks/studio-kkqkcp3d.js +17668 -0
  95. package/dist/chunks/studio-mhhyamxf.js +763 -0
  96. package/dist/chunks/{studio-cft9r4r7.js → studio-nq5yf5mp.js} +22 -22
  97. package/dist/chunks/{studio-685s0ytq.js → studio-nqgawfks.js} +572 -572
  98. package/dist/chunks/studio-nzzpvzx9.js +185 -0
  99. package/dist/chunks/{studio-xrapxwwc.js → studio-p1dw8wfw.js} +55 -29
  100. package/dist/chunks/{studio-3bqpr0zh.js → studio-pxbgypmg.js} +299 -110
  101. package/dist/chunks/studio-q0a3yk4n.js +33 -0
  102. package/dist/chunks/{studio-wcy8trfx.js → studio-q3x06vmj.js} +23 -22
  103. package/dist/chunks/{studio-6yw4y3my.js → studio-qhhm6hbt.js} +8 -8
  104. package/dist/chunks/studio-qk4bfsq2.js +362 -0
  105. package/dist/chunks/{studio-msd847zn.js → studio-qk90fgqm.js} +361 -90
  106. package/dist/chunks/{studio-jkftxyvz.js → studio-r6nvacqs.js} +5861 -2154
  107. package/dist/chunks/{studio-53n8bp04.js → studio-r6xmmtfh.js} +1 -1
  108. package/dist/chunks/{studio-tvgyw9xw.js → studio-rnyf3f8e.js} +83 -250
  109. package/dist/chunks/studio-rs76k67r.js +12 -0
  110. package/dist/chunks/studio-sbjyc8bt.js +954 -0
  111. package/dist/chunks/{studio-1wagb550.js → studio-syg2tadj.js} +11 -11
  112. package/dist/chunks/{studio-t5wqwzdh.js → studio-tjjk7jvk.js} +1 -1
  113. package/dist/chunks/studio-tqgryxwg.js +1171 -0
  114. package/dist/chunks/studio-try13h8c.js +8448 -0
  115. package/dist/chunks/studio-vfq8qpjt.js +1219 -0
  116. package/dist/chunks/studio-vhv5tgxm.js +51 -0
  117. package/dist/chunks/{studio-ahn3pdgx.js → studio-vw7mzp6z.js} +52 -38
  118. package/dist/chunks/studio-wqpngpsk.js +174 -0
  119. package/dist/chunks/studio-wqz6dggm.js +1356 -0
  120. package/dist/chunks/{studio-92ab2jqe.js → studio-y9zedyjn.js} +14 -14
  121. package/dist/chunks/studio-yxa81f45.js +12 -0
  122. package/dist/chunks/studio-zdn2g6dt.js +148 -0
  123. package/dist/chunks/swatch-group-t0n6h2rn.js +139 -0
  124. package/dist/chunks/tabs-wbp1cdws.js +156 -0
  125. package/dist/chunks/textfield-abk6qyee.js +73 -0
  126. package/dist/chunks/toast-780pvfbv.js +27 -0
  127. package/dist/chunks/toast-host-3sqv46sn.js +116 -0
  128. package/dist/chunks/toolbar-xbh5bhtr.js +194 -0
  129. package/dist/chunks/tooltip-eptb614w.js +369 -0
  130. package/dist/chunks/tree-a73p0pqm.js +367 -0
  131. package/dist/chunks/{tsMode-76kr53q0.js → tsMode-jy4m86rv.js} +83 -85
  132. package/dist/chunks/workspace-t55jdjbx.js +69 -0
  133. package/dist/chunks/{ws-client-6shc5rze.js → ws-client-ny4zc51r.js} +20 -22
  134. package/dist/iframe-entry.js +1873 -673
  135. package/dist/studio.js +52757 -36535
  136. package/dist/workers/editor.worker.js +1040 -1085
  137. package/dist/workers/json.worker.js +1946 -1991
  138. package/dist/workers/ts.worker.js +4960 -5005
  139. package/index.html +1 -0
  140. package/package.json +18 -52
  141. package/src/about/about-modal.ts +72 -123
  142. package/src/browse/library-commands.ts +20 -49
  143. package/src/browse/library-layouts.ts +87 -218
  144. package/src/browse/library-pane.ts +406 -438
  145. package/src/canvas/canvas-helpers.ts +0 -49
  146. package/src/canvas/canvas-live-render.ts +25 -2
  147. package/src/canvas/canvas-render.ts +666 -231
  148. package/src/canvas/canvas-surface.ts +0 -1
  149. package/src/canvas/canvas-utils.ts +333 -113
  150. package/src/canvas/dialog-path.ts +76 -0
  151. package/src/canvas/dialog-state.ts +67 -0
  152. package/src/canvas/diff-marks.ts +252 -0
  153. package/src/canvas/diff-toolbar.ts +349 -0
  154. package/src/canvas/diff-view.ts +123 -0
  155. package/src/canvas/edit-width-drag.ts +187 -0
  156. package/src/canvas/edit-width.ts +150 -0
  157. package/src/canvas/iframe-entry.ts +125 -8
  158. package/src/canvas/iframe-host.ts +271 -15
  159. package/src/canvas/iframe-interaction.ts +133 -13
  160. package/src/canvas/iframe-patch.ts +7 -1
  161. package/src/canvas/iframe-position.ts +5 -6
  162. package/src/canvas/iframe-protocol.ts +106 -5
  163. package/src/canvas/iframe-render.ts +373 -5
  164. package/src/canvas/iframe-slash.ts +2 -2
  165. package/src/canvas/iframe-subtree.ts +5 -8
  166. package/src/canvas/path-mapping.ts +25 -3
  167. package/src/canvas/popover-path.ts +106 -0
  168. package/src/canvas/popover-state.ts +155 -0
  169. package/src/canvas/surface-registry.ts +21 -10
  170. package/src/collab/presence-chips.ts +51 -73
  171. package/src/commands/app-commands.ts +10 -0
  172. package/src/commands/budget.ts +12 -0
  173. package/src/commands/command-args.ts +404 -6
  174. package/src/commands/defaults.ts +44 -14
  175. package/src/commands/live-context.ts +11 -5
  176. package/src/commands/reference.ts +12 -2
  177. package/src/commands/registry.ts +177 -10
  178. package/src/commands/run-reported.ts +120 -0
  179. package/src/content/entry-commands.ts +16 -23
  180. package/src/content/entry-editor.ts +144 -101
  181. package/src/editor/canvas-slash-bridge.ts +2 -2
  182. package/src/editor/context-menu.ts +49 -200
  183. package/src/editor/convert-to-component.ts +42 -82
  184. package/src/editor/convert-to-repeater.ts +132 -173
  185. package/src/editor/inline-edit.ts +11 -0
  186. package/src/editor/shortcuts.ts +76 -49
  187. package/src/editor/slash-menu.ts +150 -157
  188. package/src/files/components.ts +39 -0
  189. package/src/files/file-ops.ts +117 -11
  190. package/src/files/files.ts +944 -660
  191. package/src/files/json-layout.ts +474 -0
  192. package/src/files/serialize-document.ts +8 -1
  193. package/src/format/convert-file.ts +16 -10
  194. package/src/format/format-host.ts +50 -1
  195. package/src/github/github-auth.ts +71 -29
  196. package/src/github/github-publish.ts +57 -65
  197. package/src/grid/cell-editors.ts +46 -4
  198. package/src/grid/cell-popovers.ts +65 -62
  199. package/src/grid/grid-open.ts +86 -64
  200. package/src/grid/grid-panel.ts +390 -469
  201. package/src/grid/redirects-grid.ts +40 -44
  202. package/src/hosting/layout.ts +2 -0
  203. package/src/i18n/i18n-commands.ts +137 -62
  204. package/src/media/media-pane.ts +83 -133
  205. package/src/new-project/add-repo-modal.ts +125 -176
  206. package/src/new-project/import-tab.ts +181 -252
  207. package/src/new-project/location-fields.ts +93 -160
  208. package/src/new-project/new-project-modal.ts +376 -367
  209. package/src/packages/jxsuite-update.ts +76 -18
  210. package/src/packages/pull-package-sync.ts +5 -1
  211. package/src/panels/activity-panel.ts +137 -104
  212. package/src/panels/ai-chat/chat-markdown.ts +15 -13
  213. package/src/panels/ai-chat/chat-view.ts +307 -472
  214. package/src/panels/ai-chat/composer.ts +175 -163
  215. package/src/panels/ai-chat/sessions-view.ts +31 -62
  216. package/src/panels/ai-panel.ts +213 -185
  217. package/src/panels/block-action-bar.ts +444 -645
  218. package/src/panels/bottom-dock.ts +112 -47
  219. package/src/panels/chat-panel.ts +19 -14
  220. package/src/panels/data-explorer.ts +141 -102
  221. package/src/panels/data-grid.ts +183 -150
  222. package/src/panels/dnd.ts +75 -20
  223. package/src/panels/editors.ts +26 -19
  224. package/src/panels/elements-panel.ts +243 -186
  225. package/src/panels/empty-state.ts +26 -42
  226. package/src/panels/events-panel.ts +950 -729
  227. package/src/panels/formula-workspace.ts +434 -207
  228. package/src/panels/frontmatter-fields.ts +185 -153
  229. package/src/panels/frontmatter-panel.ts +411 -187
  230. package/src/panels/git-diff-open.ts +148 -0
  231. package/src/panels/git-panel.ts +679 -605
  232. package/src/panels/head-panel.ts +617 -435
  233. package/src/panels/i18n-panel.ts +148 -135
  234. package/src/panels/imports-panel.ts +388 -414
  235. package/src/panels/jump-bar.ts +175 -147
  236. package/src/panels/layers-panel.ts +785 -671
  237. package/src/panels/left-panel.ts +166 -94
  238. package/src/panels/navigator-panels.ts +1 -1
  239. package/src/panels/pane-context.ts +529 -677
  240. package/src/panels/pane-grid.ts +265 -241
  241. package/src/panels/panel-registry.ts +15 -4
  242. package/src/panels/problems-panel.ts +181 -99
  243. package/src/panels/properties-panel.ts +1525 -966
  244. package/src/panels/provenance.ts +31 -113
  245. package/src/panels/quick-search.ts +223 -184
  246. package/src/panels/right-panel.ts +135 -169
  247. package/src/panels/seo-modal.ts +346 -167
  248. package/src/panels/settings-menu.ts +114 -661
  249. package/src/panels/settings-pane.ts +102 -86
  250. package/src/panels/signals-panel.ts +1318 -1172
  251. package/src/panels/statement-editor.ts +556 -428
  252. package/src/panels/style-panel.ts +1367 -630
  253. package/src/panels/style-utils.ts +36 -32
  254. package/src/panels/stylebook-doc.ts +30 -73
  255. package/src/panels/stylebook-layers-panel.ts +202 -109
  256. package/src/panels/stylebook-panel.ts +124 -88
  257. package/src/panels/tab-strip.ts +386 -288
  258. package/src/platforms/cloud.ts +106 -16
  259. package/src/platforms/devserver.ts +13 -0
  260. package/src/publish/deploy-checklist.ts +124 -78
  261. package/src/publish/publish-commands.ts +4 -12
  262. package/src/publish/publish-panel.ts +134 -328
  263. package/src/services/a11y-report.ts +100 -43
  264. package/src/services/ai-command-tools.ts +538 -0
  265. package/src/services/ai-project-tools.ts +8 -2
  266. package/src/services/ai-session-store.ts +6 -0
  267. package/src/services/ai-system-prompt.ts +112 -24
  268. package/src/services/ai-tools.ts +36 -212
  269. package/src/services/ai-write-report.ts +174 -0
  270. package/src/services/document-assistant.ts +59 -8
  271. package/src/services/idle.ts +16 -14
  272. package/src/services/live-surfaces.ts +237 -0
  273. package/src/services/model-uri.ts +75 -0
  274. package/src/services/notify.ts +63 -6
  275. package/src/services/popover-report.ts +325 -0
  276. package/src/services/surface-registry.ts +56 -0
  277. package/src/services/tool-executor.ts +6 -0
  278. package/src/settings/contexts-section.ts +301 -299
  279. package/src/settings/contributed-section.ts +361 -222
  280. package/src/settings/css-vars-editor.ts +320 -325
  281. package/src/settings/defs-editor.ts +572 -535
  282. package/src/settings/dependencies-editor.ts +79 -107
  283. package/src/settings/extension-commands.ts +379 -0
  284. package/src/settings/extension-rows.ts +113 -0
  285. package/src/settings/extensions-section.ts +287 -0
  286. package/src/settings/general-settings.ts +130 -181
  287. package/src/settings/head-editor.ts +10 -305
  288. package/src/settings/locales-section.ts +146 -196
  289. package/src/settings/preferences-accounts.ts +1 -1
  290. package/src/settings/preferences-dialog.ts +350 -330
  291. package/src/settings/project-sections.ts +108 -181
  292. package/src/settings/schema-field-ui.ts +11 -399
  293. package/src/settings/section-registry.ts +8 -1
  294. package/src/settings/settings-document.ts +31 -29
  295. package/src/shell/tree.ts +42 -87
  296. package/src/shell.ts +48 -36
  297. package/src/studio.ts +104 -69
  298. package/src/style/token-ref.ts +0 -39
  299. package/src/surfaces/about.json +263 -0
  300. package/src/surfaces/about.ts +163 -0
  301. package/src/surfaces/add-repo.json +486 -0
  302. package/src/surfaces/add-repo.ts +236 -0
  303. package/src/surfaces/ai-chat.json +2185 -0
  304. package/src/surfaces/ai-chat.ts +549 -0
  305. package/src/surfaces/ai-credentials-form.json +332 -0
  306. package/src/surfaces/ai-credentials-form.ts +151 -0
  307. package/src/surfaces/ai-managed-connect.json +108 -0
  308. package/src/surfaces/ai-managed-connect.ts +123 -0
  309. package/src/surfaces/ai-model-picker.json +114 -0
  310. package/src/surfaces/ai-model-picker.ts +139 -0
  311. package/src/surfaces/block-action-bar.json +640 -0
  312. package/src/surfaces/block-action-bar.ts +368 -0
  313. package/src/surfaces/bottom-dock.json +154 -0
  314. package/src/surfaces/bottom-dock.ts +125 -0
  315. package/src/surfaces/canvas-stage.json +444 -0
  316. package/src/surfaces/canvas-stage.ts +253 -0
  317. package/src/surfaces/cf-account-picker.json +300 -0
  318. package/src/surfaces/cf-account-picker.ts +214 -0
  319. package/src/surfaces/commandbar.json +985 -0
  320. package/src/{panels/toolbar.ts → surfaces/commandbar.ts} +417 -391
  321. package/src/surfaces/convert-repeater.json +309 -0
  322. package/src/surfaces/convert-repeater.ts +276 -0
  323. package/src/surfaces/data-actions.json +157 -0
  324. package/src/surfaces/data-actions.ts +115 -0
  325. package/src/surfaces/dialog.json +289 -0
  326. package/src/surfaces/dialog.ts +343 -0
  327. package/src/surfaces/diff-toolbar.json +266 -0
  328. package/src/surfaces/diff-toolbar.ts +139 -0
  329. package/src/surfaces/doc-header.json +739 -0
  330. package/src/surfaces/doc-header.ts +223 -0
  331. package/src/surfaces/empty-state.json +152 -0
  332. package/src/surfaces/empty-state.ts +173 -0
  333. package/src/surfaces/entry-editor.json +281 -0
  334. package/src/surfaces/entry-editor.ts +191 -0
  335. package/src/surfaces/expression-editor.json +977 -0
  336. package/src/surfaces/expression-editor.ts +266 -0
  337. package/src/surfaces/files-panel.json +592 -0
  338. package/src/surfaces/files-panel.ts +301 -0
  339. package/src/surfaces/formula-palette.json +364 -0
  340. package/src/surfaces/formula-palette.ts +340 -0
  341. package/src/surfaces/git-panel.json +1822 -0
  342. package/src/surfaces/git-panel.ts +272 -0
  343. package/src/surfaces/github-auth.json +112 -0
  344. package/src/surfaces/github-auth.ts +139 -0
  345. package/src/surfaces/github-publish.json +206 -0
  346. package/src/surfaces/github-publish.ts +169 -0
  347. package/src/surfaces/grid-cell.json +218 -0
  348. package/src/surfaces/grid-cell.ts +120 -0
  349. package/src/surfaces/grid-open.json +147 -0
  350. package/src/surfaces/grid-open.ts +87 -0
  351. package/src/surfaces/grid-panel.json +706 -0
  352. package/src/surfaces/grid-panel.ts +206 -0
  353. package/src/surfaces/grid-replace.json +179 -0
  354. package/src/surfaces/grid-replace.ts +89 -0
  355. package/src/surfaces/grid-views.json +446 -0
  356. package/src/surfaces/grid-views.ts +172 -0
  357. package/src/surfaces/inspector-dock.json +187 -0
  358. package/src/surfaces/inspector-dock.ts +161 -0
  359. package/src/surfaces/jump-bar.json +243 -0
  360. package/src/surfaces/jump-bar.ts +129 -0
  361. package/src/surfaces/jxsuite-update.json +146 -0
  362. package/src/surfaces/jxsuite-update.ts +149 -0
  363. package/src/surfaces/library-pane.json +1509 -0
  364. package/src/surfaces/library-pane.ts +363 -0
  365. package/src/surfaces/logic-panel.json +1949 -0
  366. package/src/surfaces/logic-panel.ts +369 -0
  367. package/src/surfaces/logic-workspace.json +685 -0
  368. package/src/surfaces/logic-workspace.ts +238 -0
  369. package/src/surfaces/media-browser.json +303 -0
  370. package/src/surfaces/media-browser.ts +145 -0
  371. package/src/surfaces/media-field.json +163 -0
  372. package/src/surfaces/media-field.ts +116 -0
  373. package/src/surfaces/media-pane.json +513 -0
  374. package/src/surfaces/media-pane.ts +197 -0
  375. package/src/surfaces/menu.json +232 -0
  376. package/src/surfaces/menu.ts +375 -0
  377. package/src/surfaces/navigator-dock.json +113 -0
  378. package/src/surfaces/navigator-dock.ts +130 -0
  379. package/src/surfaces/new-project.json +1654 -0
  380. package/src/surfaces/new-project.ts +411 -0
  381. package/src/surfaces/palette.json +535 -0
  382. package/src/surfaces/pane-context.json +1497 -0
  383. package/src/surfaces/pane-context.ts +513 -0
  384. package/src/surfaces/pane-grid.json +188 -0
  385. package/src/surfaces/pane-grid.ts +250 -0
  386. package/src/surfaces/panel-activity.json +563 -0
  387. package/src/surfaces/panel-activity.ts +187 -0
  388. package/src/surfaces/panel-data.json +141 -0
  389. package/src/surfaces/panel-data.ts +156 -0
  390. package/src/surfaces/panel-deploy-checklist.json +283 -0
  391. package/src/surfaces/panel-deploy-checklist.ts +175 -0
  392. package/src/surfaces/panel-elements.json +367 -0
  393. package/src/surfaces/panel-elements.ts +175 -0
  394. package/src/surfaces/panel-i18n.json +569 -0
  395. package/src/surfaces/panel-i18n.ts +212 -0
  396. package/src/surfaces/panel-imports.json +780 -0
  397. package/src/surfaces/panel-imports.ts +209 -0
  398. package/src/surfaces/panel-outline.json +734 -0
  399. package/src/surfaces/panel-outline.ts +326 -0
  400. package/src/surfaces/panel-page.json +1017 -0
  401. package/src/surfaces/panel-page.ts +240 -0
  402. package/src/surfaces/panel-problems.json +497 -0
  403. package/src/surfaces/panel-problems.ts +157 -0
  404. package/src/surfaces/panel-signals.json +1973 -0
  405. package/src/surfaces/panel-signals.ts +436 -0
  406. package/src/surfaces/panel-stylebook-layers.json +317 -0
  407. package/src/surfaces/panel-stylebook-layers.ts +155 -0
  408. package/src/surfaces/preferences.json +850 -0
  409. package/src/surfaces/preferences.ts +332 -0
  410. package/src/surfaces/progress-modal.json +110 -0
  411. package/src/surfaces/progress-modal.ts +150 -0
  412. package/src/surfaces/properties-panel.json +1578 -0
  413. package/src/surfaces/properties-panel.ts +337 -0
  414. package/src/surfaces/publish.json +945 -0
  415. package/src/surfaces/publish.ts +392 -0
  416. package/src/surfaces/push-plan.json +110 -0
  417. package/src/surfaces/push-plan.ts +87 -0
  418. package/src/surfaces/rail.json +255 -0
  419. package/src/surfaces/rail.ts +206 -0
  420. package/src/surfaces/reference-field.json +191 -0
  421. package/src/surfaces/reference-field.ts +168 -0
  422. package/src/surfaces/schema-builder.json +1011 -0
  423. package/src/surfaces/schema-builder.ts +181 -0
  424. package/src/surfaces/schema-form.json +1013 -0
  425. package/src/surfaces/schema-form.ts +287 -0
  426. package/src/surfaces/secret-field.json +60 -0
  427. package/src/surfaces/secret-field.ts +146 -0
  428. package/src/surfaces/seo.json +932 -0
  429. package/src/surfaces/seo.ts +334 -0
  430. package/src/surfaces/settings-contexts.json +538 -0
  431. package/src/surfaces/settings-contexts.ts +196 -0
  432. package/src/surfaces/settings-contributed.json +489 -0
  433. package/src/surfaces/settings-contributed.ts +199 -0
  434. package/src/surfaces/settings-css-vars.json +820 -0
  435. package/src/surfaces/settings-css-vars.ts +199 -0
  436. package/src/surfaces/settings-defs.json +1363 -0
  437. package/src/surfaces/settings-defs.ts +232 -0
  438. package/src/surfaces/settings-deploy.json +108 -0
  439. package/src/surfaces/settings-deploy.ts +135 -0
  440. package/src/surfaces/settings-extensions.json +486 -0
  441. package/src/surfaces/settings-extensions.ts +201 -0
  442. package/src/surfaces/settings-head.json +779 -0
  443. package/src/surfaces/settings-head.ts +397 -0
  444. package/src/surfaces/settings-locales.json +420 -0
  445. package/src/surfaces/settings-locales.ts +137 -0
  446. package/src/surfaces/settings-overview.json +423 -0
  447. package/src/surfaces/settings-overview.ts +218 -0
  448. package/src/surfaces/settings-packages.json +549 -0
  449. package/src/surfaces/settings-packages.ts +158 -0
  450. package/src/surfaces/settings-pane.json +147 -0
  451. package/src/surfaces/settings-pane.ts +150 -0
  452. package/src/surfaces/settings-rawjson.json +104 -0
  453. package/src/surfaces/settings-rawjson.ts +107 -0
  454. package/src/surfaces/shell.json +99 -0
  455. package/src/surfaces/shell.ts +30 -0
  456. package/src/surfaces/slash-menu.json +180 -0
  457. package/src/surfaces/slash-menu.ts +272 -0
  458. package/src/surfaces/statements.json +607 -0
  459. package/src/surfaces/statements.ts +238 -0
  460. package/src/surfaces/statusbar.json +94 -0
  461. package/src/{panels → surfaces}/statusbar.ts +164 -90
  462. package/src/surfaces/style-panel.json +1643 -0
  463. package/src/surfaces/style-panel.ts +338 -0
  464. package/src/surfaces/stylebook-chrome.json +122 -0
  465. package/src/surfaces/stylebook-chrome.ts +122 -0
  466. package/src/surfaces/tab-strip.json +448 -0
  467. package/src/surfaces/tab-strip.ts +200 -0
  468. package/src/surfaces/target-line.json +419 -0
  469. package/src/surfaces/target-line.ts +349 -0
  470. package/src/surfaces/toasts.json +189 -0
  471. package/src/surfaces/welcome.json +571 -0
  472. package/src/surfaces/welcome.ts +338 -0
  473. package/src/tabs/project-config.ts +111 -21
  474. package/src/tabs/tab.ts +52 -1
  475. package/src/types.ts +22 -0
  476. package/src/ui/ai-credentials-form.ts +104 -100
  477. package/src/ui/ai-managed-connect.ts +54 -36
  478. package/src/ui/ai-model-picker.ts +75 -47
  479. package/src/ui/cf-account-picker.ts +76 -141
  480. package/src/ui/color-selector.ts +80 -301
  481. package/src/ui/dynamic-slot.ts +43 -283
  482. package/src/ui/expression-editor.ts +797 -576
  483. package/src/ui/field-input.ts +8 -181
  484. package/src/ui/form-controls.ts +838 -366
  485. package/src/ui/formula-chips.ts +80 -85
  486. package/src/ui/kit.ts +33 -0
  487. package/src/ui/layers.ts +296 -593
  488. package/src/ui/media-picker.ts +203 -284
  489. package/src/ui/panel-resize.ts +251 -64
  490. package/src/ui/popover-surface.ts +153 -0
  491. package/src/ui/progress-modal.ts +22 -60
  492. package/src/ui/regions.ts +13 -7
  493. package/src/ui/schema-form.ts +906 -440
  494. package/src/ui/surface.ts +122 -0
  495. package/src/ui/unit-selector.ts +15 -131
  496. package/src/ui/value-source.ts +14 -0
  497. package/src/ui/virtual-window.ts +88 -9
  498. package/src/utils/canvas-media.ts +72 -0
  499. package/src/utils/edit-display.ts +7 -2
  500. package/src/utils/element-selectors.ts +69 -0
  501. package/src/utils/link-target.ts +2 -2
  502. package/src/utils/studio-utils.ts +0 -10
  503. package/src/view.ts +15 -0
  504. package/src/workspace/pane-derive.ts +36 -14
  505. package/src/workspace/workspace.ts +75 -6
  506. package/styles/canvas.css +72 -467
  507. package/styles/forced-colors.css +48 -82
  508. package/styles/forced-colors.json +41 -0
  509. package/styles/inspector.css +2 -1301
  510. package/styles/overlays.css +96 -2823
  511. package/styles/panels.css +6 -1423
  512. package/styles/shell-frame.css +272 -0
  513. package/styles/shell-frame.json +227 -0
  514. package/styles/shell.css +0 -1568
  515. package/styles/tokens.css +65 -136
  516. package/styles/tokens.json +84 -0
  517. package/dist/chunks/Overlay.dev-etqjwyf9.js +0 -23
  518. package/dist/chunks/adapter-jkcyhgtr.js +0 -14
  519. package/dist/chunks/cf-account-picker-en86v7x7.js +0 -163
  520. package/dist/chunks/cf-settings-45fgyx8y.js +0 -21
  521. package/dist/chunks/components-zmx10t62.js +0 -21
  522. package/dist/chunks/content-source-48xg86wj.js +0 -49
  523. package/dist/chunks/convert-to-repeater-43tfn7cs.js +0 -268
  524. package/dist/chunks/editor-cptq5jp1.js +0 -37
  525. package/dist/chunks/entry-commands-e63f1xc0.js +0 -46
  526. package/dist/chunks/extension-sections-txv08xxg.js +0 -311
  527. package/dist/chunks/file-ops-wbh4hhsx.js +0 -48
  528. package/dist/chunks/files-3kfkwhk4.js +0 -93
  529. package/dist/chunks/flow-qbfgrpeh.js +0 -634
  530. package/dist/chunks/focus-trap.esm-9t2drp0g.js +0 -1025
  531. package/dist/chunks/focus-visible-6eg70z18.js +0 -167
  532. package/dist/chunks/format-host-w16q81tf.js +0 -43
  533. package/dist/chunks/fs-events-hrrg328g.js +0 -21
  534. package/dist/chunks/git-panel-532whr1y.js +0 -59
  535. package/dist/chunks/index-zqxmqxmh.js +0 -109
  536. package/dist/chunks/jx-validate-8er6gbxy.js +0 -19
  537. package/dist/chunks/layers-panel-07hm7g5j.js +0 -67
  538. package/dist/chunks/layers-q75tj2mf.js +0 -45
  539. package/dist/chunks/lit-html-j055mkh8.js +0 -22
  540. package/dist/chunks/monaco-buffer-dqw0xxpx.js +0 -25
  541. package/dist/chunks/notify-yjm79n4s.js +0 -30
  542. package/dist/chunks/parse-24d0gay3.js +0 -19
  543. package/dist/chunks/platform-ba1j1gbh.js +0 -16
  544. package/dist/chunks/publish-panel-v9st96ja.js +0 -29
  545. package/dist/chunks/quick-search-zccjp6gv.js +0 -66
  546. package/dist/chunks/references-3qx8fkyp.js +0 -29
  547. package/dist/chunks/right-panel-vm3b6kwy.js +0 -46
  548. package/dist/chunks/section-registry-sx1ykvkw.js +0 -30
  549. package/dist/chunks/sp-overlay.dev-qgvhnxf4.js +0 -18
  550. package/dist/chunks/sp-popover.dev-n2etmqdp.js +0 -9
  551. package/dist/chunks/sp-progress-circle.dev-hryhj0es.js +0 -15
  552. package/dist/chunks/sp-tooltip.dev-4sastdnw.js +0 -15
  553. package/dist/chunks/sp-tray.dev-tkbscm06.js +0 -199
  554. package/dist/chunks/studio-0a5qrh01.js +0 -3
  555. package/dist/chunks/studio-0bq6eh7v.js +0 -12
  556. package/dist/chunks/studio-18j3bmcz.js +0 -14
  557. package/dist/chunks/studio-1ngbejft.js +0 -181
  558. package/dist/chunks/studio-4b5z1x43.js +0 -424
  559. package/dist/chunks/studio-4n2b5gzb.js +0 -357
  560. package/dist/chunks/studio-4rzyrtjz.js +0 -426
  561. package/dist/chunks/studio-5fx3g9jg.js +0 -4325
  562. package/dist/chunks/studio-5myknm0a.js +0 -1903
  563. package/dist/chunks/studio-7afd21nw.js +0 -67
  564. package/dist/chunks/studio-7nte2hj4.js +0 -613
  565. package/dist/chunks/studio-8jpzqk5s.js +0 -128
  566. package/dist/chunks/studio-8q517dfr.js +0 -24
  567. package/dist/chunks/studio-950k0dx6.js +0 -6939
  568. package/dist/chunks/studio-9n4mrmnb.js +0 -184
  569. package/dist/chunks/studio-a0tswy0w.js +0 -58
  570. package/dist/chunks/studio-ahnzd9rg.js +0 -23
  571. package/dist/chunks/studio-bgxt93ga.js +0 -62
  572. package/dist/chunks/studio-cmb03bg5.js +0 -13890
  573. package/dist/chunks/studio-d1ks410h.js +0 -175
  574. package/dist/chunks/studio-ef49pnzx.js +0 -387
  575. package/dist/chunks/studio-eqq1w638.js +0 -113
  576. package/dist/chunks/studio-ew0djmhg.js +0 -341
  577. package/dist/chunks/studio-gfgb8pe6.js +0 -1652
  578. package/dist/chunks/studio-h4rxscfc.js +0 -10
  579. package/dist/chunks/studio-jc994dnr.js +0 -1066
  580. package/dist/chunks/studio-kyh9avvv.js +0 -28
  581. package/dist/chunks/studio-m3hwn7y1.js +0 -120
  582. package/dist/chunks/studio-mtfnaqs9.js +0 -659
  583. package/dist/chunks/studio-n6j9t10q.js +0 -318
  584. package/dist/chunks/studio-n8b9wqwy.js +0 -291
  585. package/dist/chunks/studio-qcy05dp8.js +0 -1743
  586. package/dist/chunks/studio-qq6jym04.js +0 -53
  587. package/dist/chunks/studio-rdx8jcxy.js +0 -83
  588. package/dist/chunks/studio-rn9ta2mz.js +0 -111
  589. package/dist/chunks/studio-t7qb9db8.js +0 -665
  590. package/dist/chunks/studio-tmc5emrw.js +0 -8
  591. package/dist/chunks/studio-z6nw2ek2.js +0 -18
  592. package/dist/chunks/studio-zczps70q.js +0 -378
  593. package/dist/chunks/studio-zqazsct2.js +0 -1823
  594. package/dist/chunks/workspace-fjx52ryv.js +0 -89
  595. package/src/panels/activity-bar.ts +0 -251
  596. package/src/panels/panel-scheduler.ts +0 -219
  597. package/src/panels/style-inputs.ts +0 -237
  598. package/src/panels/target-line.ts +0 -274
  599. package/src/panels/welcome-screen.ts +0 -346
  600. package/src/ui/button-group.ts +0 -102
  601. package/src/ui/choice-field.ts +0 -72
  602. package/src/ui/field-row.ts +0 -249
  603. package/src/ui/formula-palette.ts +0 -213
  604. package/src/ui/icons.ts +0 -52
  605. package/src/ui/jx-theme.ts +0 -130
  606. package/src/ui/spectrum.ts +0 -340
  607. package/src/ui/value-selector.ts +0 -174
  608. package/src/ui/widgets.ts +0 -172
  609. /package/dist/chunks/{javascript-s56a8dpk.css → javascript-4abzjcy9.css} +0 -0
  610. /package/dist/chunks/{jsonMode-zr9sw0c7.css → jsonMode-vvmpmk34.css} +0 -0
  611. /package/dist/chunks/{monaco-setup-pav68602.css → monaco-setup-8vbyqnhr.css} +0 -0
  612. /package/dist/chunks/{tsMode-ef187txx.css → tsMode-hnxxb73h.css} +0 -0
@@ -8,6 +8,12 @@
8
8
  * so the catalogue, the canvas and this form all read the same vocabulary; this module is the form
9
9
  * over it.
10
10
  *
11
+ * **The markup left.** The section is the `settings-css-vars` surface
12
+ * (`surfaces/settings-css-vars.json`), mounted by `surfaces/settings-css-vars.ts`; what is here is
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.
16
+ *
11
17
  * Three things it does NOT do, each on purpose:
12
18
  *
13
19
  * - **It does not define a context.** Breakpoints and colour schemes are declared once, in Project
@@ -20,27 +26,33 @@
20
26
  * change" true of the specimen canvas as well as the page one.
21
27
  */
22
28
 
23
- import { html, render as litRender, nothing } from "lit-html";
24
- import { ref } from "lit-html/directives/ref.js";
25
- import { classMap } from "lit-html/directives/class-map.js";
26
29
  import { errorMessage } from "@jxsuite/schema/parse";
27
30
  import { notify } from "../services/notify";
28
31
  import { projectState } from "../store";
29
32
  import { getEffectiveMedia, updateSiteConfig } from "../site-context";
30
33
  import {
34
+ TOKEN_GROUPS,
31
35
  addableContexts,
32
36
  groupTokens,
33
37
  listTokenContexts,
34
38
  readTokenOverride,
39
+ tokenLabel,
35
40
  writeTokenOverride,
36
41
  } from "../style/project-styles";
37
- import { renderTokenChip, resolveTokenValue, tokenRefName } from "../style/token-ref";
42
+ import { resolveTokenValue, toTokenRef, tokenRefName } from "../style/token-ref";
38
43
  import { pushProjectStylesToCanvas } from "../style/live-preview";
44
+ import { renderCssVarsSurface } from "../surfaces/settings-css-vars";
39
45
  import { friendlyNameToVar } from "../utils/studio-utils";
40
46
 
41
- import type { JxStyle } from "@jxsuite/schema/types";
47
+ import type { JxStyle, ProjectConfig } from "@jxsuite/schema/types";
42
48
  import type { ProjectToken, TokenContext, TokenGroup, TokenGroupId } from "../style/project-styles";
43
- import type { TemplateResult } from "lit-html";
49
+ import type {
50
+ CssVarsActions,
51
+ CssVarsView,
52
+ GroupView,
53
+ OverrideRowView,
54
+ TokenRowView,
55
+ } from "../surfaces/settings-css-vars";
44
56
 
45
57
  /**
46
58
  * What each group's add row hints with — an example friendly name and an example value. These are
@@ -60,379 +72,362 @@ const COLOR_INPUT_FALLBACK = "#3b82f6";
60
72
  /** The same, for an override row: a scheme override is usually a darker value than the base. */
61
73
  const OVERRIDE_INPUT_FALLBACK = "#111111";
62
74
 
63
- /** What one token row needs from the surrounding form — bound once per render, not per row. */
64
- interface TokenFormCtx {
65
- /** The project's root style, mutated in place and persisted through {@link updateSiteConfig}. */
66
- rootStyle: JxStyle;
67
- /** Every declared rendering context, schemes first ({@link listTokenContexts}). */
68
- contexts: TokenContext[];
69
- /** Commit the current style without re-rendering the form. */
70
- save: () => void;
71
- /** Commit and re-render — for anything that changes which rows exist. */
72
- commit: () => void;
73
- }
75
+ /** The picker's own first row: what it reads while nothing has been picked. */
76
+ const ADD_OVERRIDE_ROW = { label: "Add override…", value: "" };
74
77
 
75
78
  /**
76
- * Render the token editor into a container.
79
+ * The add row being typed into, per group, and the last write that failed.
77
80
  *
78
- * @param {HTMLElement} container
81
+ * Keyed by container so two mounted copies (and two tests) never share either — the same shape
82
+ * `general-settings.ts` and `locales-section.ts` use, and for the same reason: this section saves
83
+ * on change, so a silent rejection reads as "my edit just vanished". The pending add row is here
84
+ * rather than in the document because typing must survive the section being redrawn from outside;
85
+ * its predecessor held the two values in the DOM through `ref()`, which meant every redraw emptied
86
+ * them and the reader lost half a token name to a nav click they did not make.
79
87
  */
80
- export function renderCssVarsEditor(container: HTMLElement) {
81
- const config = projectState?.projectConfig || {};
82
- const rootStyle = (config.style || {}) as JxStyle;
83
- const contexts = listTokenContexts(getEffectiveMedia(config.$media));
84
- const hasScheme = contexts.some((c) => c.kind === "scheme");
85
-
86
- const save = () => {
87
- void updateSiteConfig({ style: { ...rootStyle } });
88
- pushProjectStylesToCanvas();
89
- };
90
-
91
- const commit = () => {
92
- save();
93
- renderCssVarsEditor(container);
94
- };
95
-
96
- const ctx: TokenFormCtx = { commit, contexts, rootStyle, save };
97
-
98
- const addVar = (prefix: string, friendlyName: string, val: string) => {
99
- const varName = friendlyNameToVar(friendlyName, prefix);
100
- if (!varName || !val) {
101
- return;
102
- }
103
- rootStyle[varName] = val;
104
- commit();
105
- };
88
+ interface Form {
89
+ add: Partial<Record<TokenGroupId, { name: string; value: string }>>;
90
+ error: string;
91
+ }
106
92
 
107
- /*
108
- * Without a declared scheme query there is nothing to override, so this section can only point at
109
- * the place a scheme is DEFINED. It used to define one itself — a button here appended
110
- * `'--dark': '(prefers-color-scheme: dark)'` to `$media` without ever using the word breakpoint,
111
- * which made this form the fourth and least discoverable definition site for a map whose other
112
- * three lived in the wizard, Overview and Properties › Media. The lazy import breaks the
113
- * css-vars-editor ↔ section-registry cycle.
114
- */
115
- const manageContexts = () => {
116
- void import("./section-registry")
117
- .then(({ setSettingsSection }) => setSettingsSection("contexts"))
118
- .catch((error: unknown) => {
119
- notify.error(`Could not open Settings › Contexts — ${errorMessage(error)}`, {
120
- source: "Settings",
121
- });
122
- });
123
- };
93
+ const forms = new WeakMap<HTMLElement, Form>();
124
94
 
125
- const tpl = html`
126
- <div class="settings-section">
127
- <h3 class="settings-section-title">CSS Variables</h3>
128
- ${groupTokens(rootStyle).map(({ group, tokens }) =>
129
- group.id === "other" && tokens.length === 0
130
- ? nothing
131
- : renderGroup(group, tokens, ctx, hasScheme, addVar, manageContexts),
132
- )}
133
- </div>
134
- `;
95
+ /** This container's form, minted on first sight. */
96
+ function form(container: HTMLElement): Form {
97
+ let state = forms.get(container);
98
+ if (!state) {
99
+ state = { add: {}, error: "" };
100
+ forms.set(container, state);
101
+ }
102
+ return state;
103
+ }
135
104
 
136
- litRender(tpl, container);
105
+ /** This container's pending add row for one group, minted on first sight. */
106
+ function pending(container: HTMLElement, group: TokenGroupId): { name: string; value: string } {
107
+ const { add } = form(container);
108
+ return (add[group] ??= { name: "", value: "" });
137
109
  }
138
110
 
139
- /**
140
- * One group: its heading, its token rows, its add row, and — for Colors with no scheme declared —
141
- * the sentence that says where a scheme comes from.
142
- *
143
- * @param {TokenGroup} group
144
- * @param {ProjectToken[]} tokens
145
- * @param {TokenFormCtx} ctx
146
- * @param {boolean} hasScheme
147
- * @param {(prefix: string, friendlyName: string, val: string) => void} addVar
148
- * @param {() => void} manageContexts
149
- */
150
- function renderGroup(
151
- group: TokenGroup,
152
- tokens: ProjectToken[],
153
- ctx: TokenFormCtx,
154
- hasScheme: boolean,
155
- addVar: (prefix: string, friendlyName: string, val: string) => void,
156
- manageContexts: () => void,
157
- ): TemplateResult {
158
- return html`
159
- <div class="css-vars-group">
160
- <h4 class="css-vars-group-title">${group.title}</h4>
161
- ${tokens.map((token) => renderTokenRow(token, group, ctx))} ${renderAddRow(group, addVar)}
162
- ${
163
- group.id === "color" && !hasScheme
164
- ? html`
165
- <p class="settings-field-desc">
166
- No colour scheme is defined yet, so these tokens have one value each.
167
- <sp-action-button
168
- size="s"
169
- quiet
170
- title="Define a colour scheme in Project Settings › Contexts"
171
- @click=${manageContexts}
172
- >
173
- Manage contexts…
174
- </sp-action-button>
175
- </p>
176
- `
177
- : nothing
178
- }
179
- </div>
180
- `;
111
+ /** The live project configuration, or an empty one before a project is open. */
112
+ function config(): ProjectConfig {
113
+ return (projectState?.projectConfig || {}) as ProjectConfig;
181
114
  }
182
115
 
183
116
  /**
184
- * One token: its swatch (colours only), its name, its value field, the chip it wears when that
185
- * value follows another token, its delete button — then its font preview and its overrides.
117
+ * The project's root style block, mutated IN PLACE and then persisted whole.
186
118
  *
187
- * @param {ProjectToken} token
188
- * @param {TokenGroup} group
189
- * @param {TokenFormCtx} ctx
119
+ * The `{}` fallback is a throwaway for a project that declares no styles at all: the first token
120
+ * added to one reaches disk through the patch below and comes back on the refresh that follows the
121
+ * write, because there is no object here for it to have been written into.
190
122
  */
191
- function renderTokenRow(token: ProjectToken, group: TokenGroup, ctx: TokenFormCtx): TemplateResult {
192
- const { rootStyle } = ctx;
193
- const isColor = group.id === "color";
194
- const refName = tokenRefName(token.value);
195
- const resolved = resolveTokenValue(rootStyle, token.value);
196
-
197
- const updateVar = (val: string) => {
198
- rootStyle[token.name] = val;
199
- ctx.save();
200
- };
201
- const deleteVar = () => {
202
- delete rootStyle[token.name];
203
- ctx.commit();
204
- };
123
+ function style(): JxStyle {
124
+ return (config().style || {}) as JxStyle;
125
+ }
205
126
 
206
- return html`
207
- <div class="css-var-row">
208
- ${isColor ? renderSwatch(resolved, COLOR_INPUT_FALLBACK, updateVar) : nothing}
209
- <span class="css-var-name">${token.label}</span>
210
- <sp-textfield
211
- size="s"
212
- .value=${String(token.value)}
213
- @change=${(e: Event) => updateVar((e.target as HTMLInputElement).value)}
214
- style=${valueFieldStyle(group)}
215
- ></sp-textfield>
216
- ${refName ? renderTokenChip(refName, resolved, { swatch: isColor }) : nothing}
217
- <sp-action-button quiet size="s" title="Delete ${token.label}" @click=${deleteVar}>
218
- <sp-icon-delete slot="icon"></sp-icon-delete>
219
- </sp-action-button>
220
- </div>
221
- ${
222
- group.id === "font"
223
- ? html`<div class="css-var-font-preview" style="font-family:${String(token.value)}">
224
- The quick brown fox jumps over the lazy dog
225
- </div>`
226
- : nothing
227
- }
228
- ${renderOverrides(token, group, ctx)}
229
- `;
127
+ /** Every rendering context this project declares, schemes first. */
128
+ function contexts(): TokenContext[] {
129
+ return listTokenContexts(getEffectiveMedia(config().$media));
230
130
  }
231
131
 
232
132
  /**
233
- * How wide the value field is — colours and sizes are short values beside a swatch or a unit, fonts
234
- * and free-form tokens are long ones. The predecessor said the same thing four times.
133
+ * Push the mutated style at the canvases, show it, and write it — in that order.
235
134
  *
236
- * @param {TokenGroup} group
135
+ * The canvas and the form are updated synchronously because the edit is already true of the model;
136
+ * the write is awaited only so that its REJECTION has somewhere to land. The predecessor dropped it
137
+ * with a bare `void`, so a read-only `project.json` took every edit and kept none of them without
138
+ * ever saying so.
139
+ *
140
+ * @param {HTMLElement} container
237
141
  */
238
- function valueFieldStyle(group: TokenGroup): string {
239
- if (group.id === "color") {
240
- return "flex:1;max-width:160px";
241
- }
242
- if (group.id === "size") {
243
- return "max-width:120px";
142
+ function commit(container: HTMLElement): void {
143
+ pushProjectStylesToCanvas();
144
+ refresh(container);
145
+ void persist(container);
146
+ }
147
+
148
+ /** @param {HTMLElement} container */
149
+ async function persist(container: HTMLElement): Promise<void> {
150
+ try {
151
+ await updateSiteConfig({ style: { ...style() } });
152
+ form(container).error = "";
153
+ } catch (error) {
154
+ form(container).error = `Could not save project.json — ${errorMessage(error)}`;
244
155
  }
245
- return "flex:1";
156
+ refresh(container);
157
+ }
158
+
159
+ // ─── Projection ──────────────────────────────────────────────────────────────
160
+
161
+ /** The colour a well is painted, and the colour the native input under it opens on. */
162
+ function well(
163
+ resolved: string | number | undefined,
164
+ fallback: string,
165
+ ): { swatchBg: string; swatchInput: string } {
166
+ const swatchBg = resolved === undefined ? "transparent" : String(resolved);
167
+ return { swatchBg, swatchInput: swatchBg.startsWith("#") ? swatchBg : fallback };
246
168
  }
247
169
 
248
170
  /**
249
- * The colour well: a background showing the value the token RESOLVES to (so an alias token is not a
250
- * blank square) over a native colour input.
171
+ * One override row: what this token is in one context, and what an edit to it names.
172
+ *
173
+ * The row carries its token AND its context because the document's inner `$map` shadows the outer
174
+ * one — a row cannot ask which token it hangs under, so it is told.
251
175
  *
252
- * @param {string | number | undefined} resolved
253
- * @param {string} fallback — what the native input shows when the value is not a hex literal
254
- * @param {(val: string) => void} onInput
176
+ * @param {ProjectToken} token
177
+ * @param {TokenContext} context
178
+ * @param {boolean} isColor
179
+ * @param {JxStyle} rootStyle
180
+ * @returns {OverrideRowView}
255
181
  */
256
- function renderSwatch(
257
- resolved: string | number | undefined,
258
- fallback: string,
259
- onInput: (val: string) => void,
260
- ): TemplateResult {
261
- const shown = resolved === undefined ? "transparent" : String(resolved);
262
- return html`
263
- <div class="css-var-swatch" style="background:${shown}">
264
- <input
265
- type="color"
266
- .value=${shown.startsWith("#") ? shown : fallback}
267
- @input=${(e: Event) => onInput((e.target as HTMLInputElement).value)}
268
- />
269
- </div>
270
- `;
182
+ function overrideRow(
183
+ token: ProjectToken,
184
+ context: TokenContext,
185
+ isColor: boolean,
186
+ rootStyle: JxStyle,
187
+ ): OverrideRowView {
188
+ const current = readTokenOverride(rootStyle, context, token.name);
189
+ return {
190
+ ctx: context.name,
191
+ fieldLabel: `${token.label} in ${context.label}`,
192
+ id: `${token.name} ${context.name}`,
193
+ kind: context.kind,
194
+ label: context.label,
195
+ swatchLabel: `${token.label} in ${context.label}`,
196
+ swatchState: isColor ? "swatch" : "none",
197
+ token: token.name,
198
+ value: current === undefined ? "" : String(current),
199
+ ...well(resolveTokenValue(rootStyle, current), OVERRIDE_INPUT_FALLBACK),
200
+ };
271
201
  }
272
202
 
273
203
  /**
274
- * A token's per-context values: one row per context it is overridden in, plus — for a colour, once
275
- * a scheme exists — a row per scheme whether or not it carries a value, because "what is this
276
- * colour in dark mode" is a question a palette is always answering. Then the add affordance.
204
+ * One token row: its value, the chip it wears when that value follows another token, its font
205
+ * preview, its per-context values and the contexts it could still be given one in.
277
206
  *
278
- * The add affordance is the change. Before it, a row appeared only for a token that already had an
279
- * `@media` block, so the first override for any token could only be written by hand in
280
- * `project.json` — the form could edit an override it could not create.
207
+ * A colour's scheme rows are shown whether or not they carry a value, because "what is this colour
208
+ * in dark mode" is a question a palette is always answering. A token with no value is offered no
209
+ * picker: writing an empty override is how one is CLEARED, so the affordance would be inert.
281
210
  *
282
211
  * @param {ProjectToken} token
283
212
  * @param {TokenGroup} group
284
- * @param {TokenFormCtx} ctx
213
+ * @param {JxStyle} rootStyle
214
+ * @param {TokenContext[]} declared
215
+ * @returns {TokenRowView}
285
216
  */
286
- function renderOverrides(
217
+ function tokenRow(
287
218
  token: ProjectToken,
288
219
  group: TokenGroup,
289
- ctx: TokenFormCtx,
290
- ): TemplateResult | typeof nothing {
291
- const { contexts, rootStyle } = ctx;
220
+ rootStyle: JxStyle,
221
+ declared: TokenContext[],
222
+ ): TokenRowView {
292
223
  const isColor = group.id === "color";
293
- const shown = contexts.filter(
224
+ const value = String(token.value);
225
+ const resolved = resolveTokenValue(rootStyle, token.value);
226
+ const refName = tokenRefName(token.value);
227
+ const shown = declared.filter(
294
228
  (context) =>
295
229
  (isColor && context.kind === "scheme") ||
296
230
  readTokenOverride(rootStyle, context, token.name) !== undefined,
297
231
  );
298
- /*
299
- * A token with no value has nothing to give a context, so the picker is not offered rather than
300
- * offered and silently inert — writing an empty override is how one is CLEARED.
301
- */
302
- const addable =
303
- String(token.value) === "" ? [] : addableContexts(rootStyle, contexts, token.name, shown);
232
+ const addable = value === "" ? [] : addableContexts(rootStyle, declared, token.name, shown);
233
+ return {
234
+ addLabel: `Add an override for ${token.label}`,
235
+ addOptions: [ADD_OVERRIDE_ROW, ...addable.map((c) => ({ label: c.label, value: c.name }))],
236
+ addPick: "",
237
+ addState: addable.length === 0 ? "none" : "shown",
238
+ chipLabel: refName === null ? "" : tokenLabel(refName),
239
+ chipState: refName === null ? "none" : isColor && resolved !== undefined ? "swatch" : "plain",
240
+ chipSwatch: resolved === undefined ? "" : String(resolved),
241
+ chipTitle:
242
+ refName === null
243
+ ? ""
244
+ : `${toTokenRef(refName)} → ${resolved === undefined ? "unresolved" : String(resolved)}`,
245
+ label: token.label,
246
+ name: token.name,
247
+ overrides: shown.map((context) => overrideRow(token, context, isColor, rootStyle)),
248
+ overrideState: shown.length === 0 && addable.length === 0 ? "none" : "shown",
249
+ previewFont: group.id === "font" ? value : "",
250
+ previewState: group.id === "font" ? "font" : "none",
251
+ removeLabel: `Delete ${token.label}`,
252
+ swatchLabel: `${token.label} colour`,
253
+ swatchState: isColor ? "swatch" : "none",
254
+ value,
255
+ ...well(isColor ? resolved : undefined, COLOR_INPUT_FALLBACK),
256
+ };
257
+ }
304
258
 
305
- if (shown.length === 0 && addable.length === 0) {
306
- return nothing;
259
+ /**
260
+ * What the section shows right now.
261
+ *
262
+ * Read from `config()` at the moment of drawing rather than carried from the last one:
263
+ * `projectState` is a plain module binding replaced wholesale on a project switch, and an extension
264
+ * or the raw JSON editor can write `style` between two of these.
265
+ *
266
+ * @param {HTMLElement} container
267
+ * @returns {CssVarsView}
268
+ */
269
+ function view(container: HTMLElement): CssVarsView {
270
+ const rootStyle = style();
271
+ const declared = contexts();
272
+ const hasScheme = declared.some((context) => context.kind === "scheme");
273
+ const groups: GroupView[] = [];
274
+ for (const { group, tokens } of groupTokens(rootStyle)) {
275
+ /* A bucket named "Other" over an empty list teaches nothing (§2 principle 6). Every other
276
+ group keeps its heading and its add row, because an empty one is where a palette starts. */
277
+ if (group.id === "other" && tokens.length === 0) {
278
+ continue;
279
+ }
280
+ const draft = pending(container, group.id);
281
+ groups.push({
282
+ addLabel: `Add a ${group.title} variable`,
283
+ addName: draft.name,
284
+ addValue: draft.value,
285
+ id: group.id,
286
+ nameHint: ADD_ROW_HINTS[group.id].name,
287
+ nameLabel: `New ${group.title} name`,
288
+ noticeState: group.id === "color" && !hasScheme ? "shown" : "none",
289
+ title: group.title,
290
+ tokens: tokens.map((token) => tokenRow(token, group, rootStyle, declared)),
291
+ valueHint: ADD_ROW_HINTS[group.id].value,
292
+ valueLabel: `New ${group.title} value`,
293
+ });
307
294
  }
295
+ return { error: form(container).error, groups };
296
+ }
308
297
 
309
- const setOverride = (context: TokenContext, val: string) => {
310
- writeTokenOverride(rootStyle, context, token.name, val);
311
- ctx.commit();
312
- };
298
+ /** Re-read the file and the form, and let the surface reconcile. */
299
+ function refresh(container: HTMLElement): void {
300
+ renderCssVarsSurface(container, view(container), actions(container));
301
+ }
302
+
303
+ // ─── Writes ──────────────────────────────────────────────────────────────────
304
+
305
+ /** The group a token can be added to, by id. */
306
+ function groupOf(id: string): TokenGroup | undefined {
307
+ return TOKEN_GROUPS.find((group) => group.id === id);
308
+ }
313
309
 
314
- return html`
315
- <div class="css-var-media-overrides">
316
- ${shown.map((context) => renderOverrideRow(token, context, isColor, rootStyle, setOverride))}
317
- ${
318
- addable.length === 0
319
- ? nothing
320
- : html`
321
- <div class="css-var-override-add">
322
- <sp-picker
323
- size="s"
324
- quiet
325
- label="Add override"
326
- placeholder="Add override…"
327
- title="Give ${token.label} a different value in one rendering context"
328
- @change=${(e: Event) => {
329
- const name = (e.target as HTMLInputElement).value;
330
- const context = addable.find((c) => c.name === name);
331
- if (context) {
332
- setOverride(context, String(token.value));
333
- }
334
- }}
335
- >
336
- ${addable.map(
337
- (context) =>
338
- html`<sp-menu-item value=${context.name}>${context.label}</sp-menu-item>`,
339
- )}
340
- </sp-picker>
341
- </div>
342
- `
343
- }
344
- </div>
345
- `;
310
+ /** Add the group's pending token, if it names one this project can take. */
311
+ function addToken(container: HTMLElement, groupId: string): void {
312
+ const group = groupOf(groupId);
313
+ if (!group) {
314
+ return;
315
+ }
316
+ const draft = pending(container, group.id);
317
+ const varName = friendlyNameToVar(draft.name, group.prefix);
318
+ if (!varName || !draft.value) {
319
+ return;
320
+ }
321
+ style()[varName] = draft.value;
322
+ draft.name = "";
323
+ draft.value = "";
324
+ commit(container);
346
325
  }
347
326
 
348
327
  /**
349
- * One override row. Empty means "inherits the base value", and clearing a row removes the override
350
- * (and the block, once it empties) — one write path for a scheme and a breakpoint alike.
328
+ * Give a token a value in a context it has none in, seeded from its base value.
351
329
  *
352
- * @param {ProjectToken} token
353
- * @param {TokenContext} context
354
- * @param {boolean} isColor
355
- * @param {JxStyle} rootStyle
356
- * @param {(context: TokenContext, val: string) => void} setOverride
330
+ * A name the picker did not offer is ignored rather than written: the control's first row is the
331
+ * placeholder, whose value is the empty string, and a context that already carries an override is
332
+ * not a context this can create one in.
333
+ *
334
+ * @param {HTMLElement} container
335
+ * @param {string} token
336
+ * @param {string} ctx
357
337
  */
358
- function renderOverrideRow(
359
- token: ProjectToken,
360
- context: TokenContext,
361
- isColor: boolean,
362
- rootStyle: JxStyle,
363
- setOverride: (context: TokenContext, val: string) => void,
364
- ): TemplateResult {
365
- const current = readTokenOverride(rootStyle, context, token.name);
366
- return html`
367
- <div
368
- class=${classMap({
369
- "css-var-media-row": true,
370
- "css-var-scheme-row": context.kind === "scheme",
371
- })}
372
- >
373
- <span class="css-var-media-label">${context.label}</span>
374
- ${
375
- isColor
376
- ? renderSwatch(resolveTokenValue(rootStyle, current), OVERRIDE_INPUT_FALLBACK, (val) =>
377
- setOverride(context, val),
378
- )
379
- : nothing
380
- }
381
- <sp-textfield
382
- size="s"
383
- placeholder="inherits"
384
- .value=${current === undefined ? "" : String(current)}
385
- @change=${(e: Event) => setOverride(context, (e.target as HTMLInputElement).value)}
386
- style=${isColor ? "flex:1;max-width:160px" : "max-width:120px"}
387
- ></sp-textfield>
388
- </div>
389
- `;
338
+ function addOverride(container: HTMLElement, token: string, ctx: string): void {
339
+ const rootStyle = style();
340
+ const context = contexts().find((c) => c.name === ctx);
341
+ if (!context || readTokenOverride(rootStyle, context, token) !== undefined) {
342
+ refresh(container);
343
+ return;
344
+ }
345
+ const base = rootStyle[token];
346
+ if (typeof base !== "string" && typeof base !== "number") {
347
+ return;
348
+ }
349
+ writeTokenOverride(rootStyle, context, token, String(base));
350
+ commit(container);
390
351
  }
391
352
 
392
353
  /**
393
- * The group's "add a token" row: a friendly name, a value, and the button that slugs the one into a
394
- * variable name under the group's prefix.
354
+ * What the reader may do, bound to one container.
395
355
  *
396
- * @param {TokenGroup} group
397
- * @param {(prefix: string, friendlyName: string, val: string) => void} addVar
356
+ * Memoized per container so the surface is handed the same functions every time: they are read
357
+ * once, when it mounts, and a fresh set on every refresh would be a scope write that says nothing.
398
358
  */
399
- function renderAddRow(
400
- group: TokenGroup,
401
- addVar: (prefix: string, friendlyName: string, val: string) => void,
402
- ): TemplateResult {
403
- let nameEl: HTMLInputElement | null = null;
404
- let valEl: HTMLInputElement | null = null;
405
- const hint = ADD_ROW_HINTS[group.id];
359
+ const bound = new WeakMap<HTMLElement, CssVarsActions>();
360
+
361
+ function actions(container: HTMLElement): CssVarsActions {
362
+ let acts = bound.get(container);
363
+ if (!acts) {
364
+ acts = {
365
+ addOverride: (token: string, ctx: string) => {
366
+ addOverride(container, token, ctx);
367
+ },
368
+ addToken: (groupId: string) => {
369
+ addToken(container, groupId);
370
+ },
371
+ /*
372
+ * Without a declared scheme query there is nothing to override, so this section can only
373
+ * point at the place a scheme is DEFINED. It used to define one itself — a button here
374
+ * appended `'--dark': '(prefers-color-scheme: dark)'` to `$media` without ever using the word
375
+ * breakpoint, which made this form the fourth and least discoverable definition site for a
376
+ * map whose other three lived in the wizard, Overview and Properties › Media. The lazy import
377
+ * breaks the css-vars-editor ↔ section-registry cycle.
378
+ */
379
+ manageContexts: () => {
380
+ void import("./section-registry")
381
+ .then(({ setSettingsSection }) => setSettingsSection("contexts"))
382
+ .catch((error: unknown) => {
383
+ notify.error(`Could not open Settings › Contexts — ${errorMessage(error)}`, {
384
+ source: "Settings",
385
+ });
386
+ });
387
+ },
388
+ removeToken: (name: string) => {
389
+ delete style()[name];
390
+ commit(container);
391
+ },
392
+ /*
393
+ * Recorded, and nothing redrawn. The field already holds what the reader typed — a refresh
394
+ * here would re-derive every group, every token and every override row to write each control
395
+ * the value it already has, once per keystroke. What the record buys is the redraw the reader
396
+ * did NOT ask for: a nav click, an extension registering, a write landing. The projection
397
+ * reads it, so the half-typed name comes back rather than being emptied, which is what the
398
+ * predecessor's `ref()` into the DOM could never do.
399
+ */
400
+ setAddName: (groupId: string, value: string) => {
401
+ pending(container, groupId as TokenGroupId).name = value;
402
+ },
403
+ setAddValue: (groupId: string, value: string) => {
404
+ pending(container, groupId as TokenGroupId).value = value;
405
+ },
406
+ setOverride: (token: string, ctx: string, value: string) => {
407
+ const context = contexts().find((c) => c.name === ctx);
408
+ if (!context) {
409
+ return;
410
+ }
411
+ /* The block is recreated on demand, so a caller holding a stale row still writes to the
412
+ right place — and an emptied block is removed rather than left as `"@--dark": {}`. */
413
+ writeTokenOverride(style(), context, token, value);
414
+ commit(container);
415
+ },
416
+ setToken: (name: string, value: string) => {
417
+ style()[name] = value;
418
+ commit(container);
419
+ },
420
+ };
421
+ bound.set(container, acts);
422
+ }
423
+ return acts;
424
+ }
406
425
 
407
- return html`
408
- <div class="css-var-add-row">
409
- <sp-textfield
410
- size="s"
411
- placeholder=${hint.name}
412
- ${ref((el) => {
413
- if (el) {
414
- nameEl = el as HTMLInputElement;
415
- }
416
- })}
417
- ></sp-textfield>
418
- <sp-textfield
419
- size="s"
420
- placeholder=${hint.value}
421
- ${ref((el) => {
422
- if (el) {
423
- valEl = el as HTMLInputElement;
424
- }
425
- })}
426
- ></sp-textfield>
427
- <sp-action-button
428
- size="s"
429
- @click=${() => {
430
- if (nameEl && valEl) {
431
- addVar(group.prefix, nameEl.value, valEl.value);
432
- }
433
- }}
434
- >Add</sp-action-button
435
- >
436
- </div>
437
- `;
426
+ /**
427
+ * The project's design tokens, grouped, with their per-context values.
428
+ *
429
+ * @param {HTMLElement} container
430
+ */
431
+ export function renderCssVarsEditor(container: HTMLElement): void {
432
+ refresh(container);
438
433
  }