@jxsuite/studio 5.2.0 → 5.4.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 (398) hide show
  1. package/data/css-meta.json +28 -27
  2. package/dist/chunks/{cf-account-picker-h4dab9bq.js → cf-account-picker-3f08rry6.js} +21 -18
  3. package/dist/chunks/{cf-settings-adg74qsk.js → cf-settings-m79r7p5y.js} +4 -4
  4. package/dist/chunks/{components-5y78e05d.js → components-xm826zjw.js} +3 -3
  5. package/dist/chunks/{content-source-sgg1sv6n.js → content-source-jt7rbcbc.js} +22 -22
  6. package/dist/chunks/{convert-to-repeater-mf1cxgfn.js → convert-to-repeater-vg38bq99.js} +22 -22
  7. package/dist/chunks/{editor-3qhbg51x.js → editor-ddy019sn.js} +2 -2
  8. package/dist/chunks/entry-commands-64nb2a9a.js +42 -0
  9. package/dist/chunks/{extension-sections-c6zwzbre.js → extension-sections-r73an5s6.js} +31 -30
  10. package/dist/chunks/{file-ops-vrpq1jjk.js → file-ops-3xan8mnj.js} +21 -21
  11. package/dist/chunks/{files-msaf95y6.js → files-egsb0ry8.js} +30 -29
  12. package/dist/chunks/{format-host-f64fnesp.js → format-host-mym8qnd0.js} +3 -3
  13. package/dist/chunks/{fs-events-3y6y0nrm.js → fs-events-z2gg8qjt.js} +4 -4
  14. package/dist/chunks/{git-panel-bv5e22j0.js → git-panel-a05atk6q.js} +20 -20
  15. package/dist/chunks/{grid-view-1p6hsyjx.css → grid-view-3g1h2re8.css} +956 -139
  16. package/dist/chunks/{grid-view-paj67nr5.js → grid-view-qaqer9kr.js} +24 -24
  17. package/dist/chunks/{icons-yy10wk9r.js → icons-drxq9q10.js} +8 -2
  18. package/dist/chunks/{iframe-host-dh5np8vk.js → iframe-host-psetcv20.js} +11 -11
  19. package/dist/chunks/{index-n4j7qxyr.js → index-9yjae3hz.js} +4 -4
  20. package/dist/chunks/{javascript-4abzjcy9.css → javascript-bc9z461d.css} +688 -54
  21. package/dist/chunks/{javascript-xvrfrpkb.js → javascript-hr5sg57n.js} +2 -2
  22. package/dist/chunks/{jsonMode-vvmpmk34.css → jsonMode-qqd9nm1t.css} +1120 -303
  23. package/dist/chunks/{jsonMode-tyx2kj6p.js → jsonMode-zs88v0wr.js} +4 -4
  24. package/dist/chunks/{jx-validate-j0wxk72w.js → jx-validate-epp2z3s3.js} +2 -2
  25. package/dist/chunks/layers-panel-83a16ytx.js +41 -0
  26. package/dist/chunks/{layers-1vcfdbet.js → layers-s6mc01ry.js} +3 -3
  27. package/dist/chunks/{listbox-6v2ac08j.js → listbox-b7jxnhq1.js} +19 -3
  28. package/dist/chunks/{media-picker-p49nhqhs.js → media-picker-nhn6rv4w.js} +11 -11
  29. package/dist/chunks/{menu-qht48vnc.js → menu-8j4qxjrp.js} +4 -4
  30. package/dist/chunks/{monaco-binding-sw6en4dw.js → monaco-binding-e8d9wzyk.js} +3 -3
  31. package/dist/chunks/{monaco-buffer-pykwbm92.js → monaco-buffer-jaq1t9zj.js} +2 -2
  32. package/dist/chunks/{monaco-setup-8vbyqnhr.css → monaco-setup-ey9cjcm3.css} +954 -137
  33. package/dist/chunks/{monaco-setup-8r62fj6y.js → monaco-setup-gsjdysze.js} +7 -7
  34. package/dist/chunks/{platform-ts9cg1a4.js → platform-fnchmhy7.js} +5 -3
  35. package/dist/chunks/publish-panel-ak6hxfma.js +27 -0
  36. package/dist/chunks/quick-search-c63mkt3b.js +47 -0
  37. package/dist/chunks/{references-h69xp9zz.js → references-f7bdv3z5.js} +3 -3
  38. package/dist/chunks/right-panel-t5n8wttg.js +45 -0
  39. package/dist/chunks/{split-g7nm1rgb.js → split-4cz4b6ef.js} +14 -3
  40. package/dist/chunks/{studio-sar8g54p.js → studio-01269reb.js} +8 -8
  41. package/dist/chunks/{studio-rnyf3f8e.js → studio-0a4gncx0.js} +3 -3
  42. package/dist/chunks/{studio-e1f24eff.js → studio-0d4p4wxj.js} +6778 -2993
  43. package/dist/chunks/{studio-4wbb9ct0.js → studio-1tejxvba.js} +3006 -1855
  44. package/dist/chunks/{studio-p6pmwkvh.js → studio-3nprwbd9.js} +147 -28
  45. package/dist/chunks/{studio-4c041r8y.js → studio-40z39dme.js} +3 -3
  46. package/dist/chunks/{studio-68fydsrj.js → studio-482eeazk.js} +20 -20
  47. package/dist/chunks/{studio-y4f9fdge.js → studio-4998spet.js} +10 -9
  48. package/dist/chunks/{studio-nq5yf5mp.js → studio-557bmn0x.js} +2 -2
  49. package/dist/chunks/{studio-hdc2jt3z.js → studio-5w26wza5.js} +3 -3
  50. package/dist/chunks/{studio-6nzaktvy.js → studio-6pwn9j8c.js} +6 -3
  51. package/dist/chunks/{studio-wnsyffg1.js → studio-6vg0x5fz.js} +3 -2
  52. package/dist/chunks/{studio-vn5hske5.js → studio-7d3c1m59.js} +12 -5
  53. package/dist/chunks/{studio-28vs5k2y.js → studio-9vsvz7w7.js} +7 -7
  54. package/dist/chunks/{studio-t3adrr56.js → studio-9wm0xzpf.js} +19 -19
  55. package/dist/chunks/{studio-38emantv.js → studio-a5h5j33a.js} +19 -5
  56. package/dist/chunks/{studio-ympe0n7a.js → studio-ag3z6shb.js} +10 -4
  57. package/dist/chunks/studio-aj9drheq.js +177 -0
  58. package/dist/chunks/{studio-vt0tj32j.js → studio-apv9x70c.js} +189 -130
  59. package/dist/chunks/{studio-c04nzbby.js → studio-b9q3znz8.js} +2 -2
  60. package/dist/chunks/{studio-2mdbbc76.js → studio-bh47w0cy.js} +9 -10
  61. package/dist/chunks/{studio-ez11dmdh.js → studio-dgdm6vvt.js} +264 -52
  62. package/dist/chunks/{studio-5nz00bhh.js → studio-dwdcr2e8.js} +4 -4
  63. package/dist/chunks/{studio-nqgawfks.js → studio-fbcyz234.js} +146 -139
  64. package/dist/chunks/{studio-kcgff4r0.js → studio-fgmfksz8.js} +2 -2
  65. package/dist/chunks/{studio-x72j58vw.js → studio-fqpkpq1t.js} +7 -4
  66. package/dist/chunks/{studio-15f3kxqe.js → studio-fy320dfc.js} +62 -68
  67. package/dist/chunks/{studio-zjjde71a.js → studio-gjj4bbfx.js} +2 -2
  68. package/dist/chunks/{studio-66arbpc2.js → studio-jfhxy8h3.js} +16 -15
  69. package/dist/chunks/{studio-d0300636.js → studio-ks2zzth2.js} +17 -2
  70. package/dist/chunks/{studio-c07s5ckd.js → studio-kwewmhhq.js} +4 -4
  71. package/dist/chunks/{studio-01jeck2y.js → studio-m58xn8at.js} +26 -25
  72. package/dist/chunks/{studio-mpzwze9x.js → studio-mfkh1q8d.js} +17 -17
  73. package/dist/chunks/{studio-etvx9s2g.js → studio-mrh0a92f.js} +17 -17
  74. package/dist/chunks/{studio-qa7fzxan.js → studio-mt79tn56.js} +3 -3
  75. package/dist/chunks/{studio-hhskq2mr.js → studio-ne593z1j.js} +39 -32
  76. package/dist/chunks/{studio-h4nvnjvz.js → studio-ptfcxkz5.js} +418 -232
  77. package/dist/chunks/{studio-4xmjcrg3.js → studio-qxye31h7.js} +7 -7
  78. package/dist/chunks/{studio-a1pswps3.js → studio-rav5bpmp.js} +81 -59
  79. package/dist/chunks/{studio-ncn9e189.js → studio-rwmmbrth.js} +6 -6
  80. package/dist/chunks/{studio-en82c639.js → studio-sceg8ws0.js} +8 -8
  81. package/dist/chunks/{studio-wjpgxywa.js → studio-sjas5b3a.js} +19 -13
  82. package/dist/chunks/{studio-4r14yzyy.js → studio-vd67b66d.js} +3 -3
  83. package/dist/chunks/{studio-14d9tq4d.js → studio-w475cbf9.js} +10 -10
  84. package/dist/chunks/{studio-ctm7bhx5.js → studio-w7gpcvfj.js} +9 -9
  85. package/dist/chunks/{studio-9j6sfeba.js → studio-xrbfdxgk.js} +7 -7
  86. package/dist/chunks/{studio-x10fp4tp.js → studio-y49b6mjv.js} +35 -35
  87. package/dist/chunks/{studio-5t7ena5z.js → studio-ygvr9e4q.js} +10 -10
  88. package/dist/chunks/{studio-z2smx5ce.js → studio-yxmmjy2a.js} +9 -6
  89. package/dist/chunks/{tsMode-jy4m86rv.js → tsMode-ay4c78ne.js} +4 -4
  90. package/dist/chunks/{tsMode-hnxxb73h.css → tsMode-c72wyz27.css} +954 -137
  91. package/dist/chunks/{workspace-bnw54cha.js → workspace-b9k2frks.js} +5 -5
  92. package/dist/chunks/{ws-client-ny4zc51r.js → ws-client-erze4czt.js} +356 -20
  93. package/dist/codicon.ttf +0 -0
  94. package/dist/iframe-entry.js +20 -18
  95. package/dist/studio.css +956 -139
  96. package/dist/studio.js +1511 -851
  97. package/dist/workers/editor.worker.js +196 -107
  98. package/dist/workers/json.worker.js +196 -107
  99. package/dist/workers/ts.worker.js +196 -107
  100. package/package.json +18 -17
  101. package/src/about/about-modal.ts +4 -3
  102. package/src/browse/library-commands.ts +15 -13
  103. package/src/browse/library-pane.ts +2 -2
  104. package/src/canvas/canvas-render.ts +97 -83
  105. package/src/canvas/canvas-surface.ts +2 -2
  106. package/src/canvas/canvas-utils.ts +42 -32
  107. package/src/canvas/diff-toolbar.ts +21 -2
  108. package/src/canvas/diff-view.ts +30 -6
  109. package/src/canvas/iframe-entry.ts +2 -2
  110. package/src/canvas/iframe-host.ts +5 -5
  111. package/src/canvas/iframe-interaction.ts +7 -6
  112. package/src/canvas/iframe-overlay.ts +1 -1
  113. package/src/canvas/iframe-protocol.ts +6 -5
  114. package/src/canvas/iframe-render.ts +3 -3
  115. package/src/canvas/popover-state.ts +1 -1
  116. package/src/canvas/stage-scrollbar.ts +112 -0
  117. package/src/canvas/surface-registry.ts +9 -2
  118. package/src/collab/collab-commands.ts +8 -6
  119. package/src/collab/collab-session.ts +4 -4
  120. package/src/collab/collab-state.ts +4 -4
  121. package/src/collab/presence-chips.ts +3 -3
  122. package/src/commands/app-commands.ts +7 -7
  123. package/src/commands/budget.ts +17 -16
  124. package/src/commands/command-args.ts +10 -9
  125. package/src/commands/context.ts +20 -10
  126. package/src/commands/defaults.ts +30 -29
  127. package/src/commands/levels.ts +8 -6
  128. package/src/commands/live-context.ts +12 -10
  129. package/src/commands/reference.ts +5 -5
  130. package/src/commands/registry.ts +2 -2
  131. package/src/content/draft-state.ts +9 -8
  132. package/src/content/entry-commands.ts +16 -14
  133. package/src/content/entry-editor.ts +2 -2
  134. package/src/content/entry-fields.ts +1 -1
  135. package/src/editor/context-menu.ts +4 -4
  136. package/src/editor/convert-to-component.ts +6 -5
  137. package/src/editor/inline-edit.ts +3 -3
  138. package/src/editor/shortcuts.ts +88 -20
  139. package/src/editor/slash-menu.ts +11 -10
  140. package/src/files/elements.ts +4 -5
  141. package/src/files/file-ops.ts +1 -1
  142. package/src/files/files.ts +21 -17
  143. package/src/files/serialize-document.ts +1 -1
  144. package/src/format/convert-file.ts +5 -5
  145. package/src/github/github-auth-status.ts +107 -0
  146. package/src/github/github-auth.ts +18 -82
  147. package/src/github/github-publish.ts +7 -6
  148. package/src/grid/cell-editors.ts +8 -7
  149. package/src/grid/grid-layout.ts +1 -1
  150. package/src/grid/grid-open.ts +6 -5
  151. package/src/grid/grid-panel.ts +13 -12
  152. package/src/grid/redirects-grid.ts +14 -11
  153. package/src/grid/redirects.ts +10 -5
  154. package/src/grid/sources/content-source.ts +10 -9
  155. package/src/hosting/document.ts +28 -1
  156. package/src/hosting/stage.ts +15 -4
  157. package/src/i18n/i18n-commands.ts +9 -7
  158. package/src/new-project/location-fields.ts +16 -3
  159. package/src/new-project/new-project-modal.ts +23 -7
  160. package/src/page-params.ts +6 -6
  161. package/src/panels/activity-panel.ts +11 -10
  162. package/src/panels/ai-chat/chat-view.ts +27 -14
  163. package/src/panels/ai-chat/composer.ts +10 -3
  164. package/src/panels/ai-panel.ts +87 -29
  165. package/src/panels/block-action-bar.ts +59 -33
  166. package/src/panels/bottom-dock.ts +22 -22
  167. package/src/panels/chat-panel.ts +40 -5
  168. package/src/panels/data-explorer.ts +9 -9
  169. package/src/panels/data-grid.ts +1 -1
  170. package/src/panels/editors.ts +8 -8
  171. package/src/panels/elements-panel.ts +7 -8
  172. package/src/panels/empty-state.ts +1 -1
  173. package/src/panels/events-panel.ts +13 -12
  174. package/src/panels/formula-workspace.ts +8 -5
  175. package/src/panels/frontmatter-fields.ts +4 -1
  176. package/src/panels/frontmatter-panel.ts +18 -18
  177. package/src/panels/git-panel.ts +19 -13
  178. package/src/panels/head-panel.ts +9 -10
  179. package/src/panels/i18n-panel.ts +6 -4
  180. package/src/panels/imports-panel.ts +1 -1
  181. package/src/panels/jump-bar.ts +20 -18
  182. package/src/panels/layers-panel.ts +19 -17
  183. package/src/panels/left-panel.ts +3 -3
  184. package/src/panels/navigator-panels.ts +8 -8
  185. package/src/panels/overlays.ts +1 -1
  186. package/src/panels/pane-context.ts +56 -28
  187. package/src/panels/pane-grid.ts +9 -8
  188. package/src/panels/panel-registry.ts +47 -19
  189. package/src/panels/problems-panel.ts +11 -12
  190. package/src/panels/properties-panel.ts +21 -20
  191. package/src/panels/provenance.ts +3 -3
  192. package/src/panels/quick-search.ts +15 -11
  193. package/src/panels/right-panel.ts +4 -3
  194. package/src/panels/seo-modal.ts +5 -4
  195. package/src/panels/settings-menu.ts +9 -9
  196. package/src/panels/settings-pane.ts +3 -3
  197. package/src/panels/signals-panel.ts +16 -9
  198. package/src/panels/statement-editor.ts +12 -9
  199. package/src/panels/style-panel.ts +45 -41
  200. package/src/panels/stylebook-panel.ts +0 -1
  201. package/src/panels/tab-strip.ts +26 -23
  202. package/src/platform-errors.ts +2 -2
  203. package/src/platform.ts +44 -4
  204. package/src/platforms/cloud.ts +11 -1
  205. package/src/platforms/default-platform.ts +141 -4
  206. package/src/platforms/devserver.ts +23 -3
  207. package/src/publish/deploy-checklist.ts +11 -10
  208. package/src/publish/publish-commands.ts +9 -8
  209. package/src/services/a11y-report.ts +1 -1
  210. package/src/services/ai-ask.ts +39 -16
  211. package/src/services/ai-command-tools.ts +28 -14
  212. package/src/services/ai-import-tools.ts +43 -29
  213. package/src/services/ai-project-tools.ts +20 -38
  214. package/src/services/ai-settings.ts +55 -2
  215. package/src/services/ai-tools.ts +69 -58
  216. package/src/services/ai-write-report.ts +4 -4
  217. package/src/services/ai-writes.ts +74 -55
  218. package/src/services/automation.ts +12 -12
  219. package/src/services/clock.ts +2 -1
  220. package/src/services/connection.ts +2 -2
  221. package/src/services/context-manager.ts +69 -6
  222. package/src/services/directory-picker.ts +93 -27
  223. package/src/services/document-assistant.ts +86 -17
  224. package/src/services/gated-registry.ts +4 -3
  225. package/src/services/idle.ts +5 -4
  226. package/src/services/live-surfaces.ts +2 -1
  227. package/src/services/module-preloads.ts +67 -0
  228. package/src/services/notify.ts +9 -7
  229. package/src/services/popover-report.ts +3 -3
  230. package/src/services/preview-eval.ts +1 -1
  231. package/src/services/project-adoption.ts +34 -1
  232. package/src/services/project-path.ts +53 -0
  233. package/src/services/settings/kernel.ts +13 -2
  234. package/src/services/tool-executor.ts +135 -30
  235. package/src/services/tool-outcomes.ts +143 -0
  236. package/src/settings/contexts-section.ts +8 -8
  237. package/src/settings/contributed-section.ts +6 -6
  238. package/src/settings/css-vars-editor.ts +6 -5
  239. package/src/settings/extension-commands.ts +19 -18
  240. package/src/settings/extension-sections.ts +7 -7
  241. package/src/settings/extensions-section.ts +3 -3
  242. package/src/settings/general-settings.ts +21 -18
  243. package/src/settings/preferences-accounts.ts +3 -3
  244. package/src/settings/preferences-dialog.ts +9 -8
  245. package/src/settings/preferences-sections.ts +1 -1
  246. package/src/settings/project-sections.ts +2 -2
  247. package/src/settings/section-registry.ts +7 -6
  248. package/src/settings/settings-document.ts +41 -43
  249. package/src/shell/tree.ts +29 -0
  250. package/src/shell.ts +63 -55
  251. package/src/site-context.ts +1 -1
  252. package/src/store.ts +2 -2
  253. package/src/studio.ts +52 -28
  254. package/src/style/live-preview.ts +8 -8
  255. package/src/style/project-styles.ts +8 -9
  256. package/src/style/token-ref.ts +2 -2
  257. package/src/surfaces/about.json +6 -2
  258. package/src/surfaces/add-repo.json +2 -2
  259. package/src/surfaces/add-repo.ts +2 -2
  260. package/src/surfaces/ai-chat.json +14 -6
  261. package/src/surfaces/ai-chat.ts +4 -2
  262. package/src/surfaces/ai-credentials-form.json +53 -49
  263. package/src/surfaces/ai-credentials-form.ts +18 -4
  264. package/src/surfaces/ai-managed-connect.json +4 -4
  265. package/src/surfaces/block-action-bar.json +4 -4
  266. package/src/surfaces/block-action-bar.ts +3 -3
  267. package/src/surfaces/boot-failure.json +228 -0
  268. package/src/surfaces/boot-failure.ts +156 -0
  269. package/src/surfaces/bottom-dock.json +1 -1
  270. package/src/surfaces/canvas-stage.json +9 -40
  271. package/src/surfaces/canvas-stage.ts +9 -9
  272. package/src/surfaces/cf-account-picker.json +11 -8
  273. package/src/surfaces/commandbar.ts +11 -10
  274. package/src/surfaces/convert-repeater.ts +3 -2
  275. package/src/surfaces/dialog.json +7 -1
  276. package/src/surfaces/dialog.ts +2 -2
  277. package/src/surfaces/doc-header.json +6 -13
  278. package/src/surfaces/doc-header.ts +4 -5
  279. package/src/surfaces/entry-editor.json +1 -1
  280. package/src/surfaces/entry-editor.ts +2 -1
  281. package/src/surfaces/expression-editor.json +5 -5
  282. package/src/surfaces/files-panel.json +4 -3
  283. package/src/surfaces/files-panel.ts +1 -1
  284. package/src/surfaces/formula-palette.json +10 -9
  285. package/src/surfaces/formula-palette.ts +11 -7
  286. package/src/surfaces/git-panel.json +167 -109
  287. package/src/surfaces/git-panel.ts +2 -2
  288. package/src/surfaces/github-auth.json +2 -1
  289. package/src/surfaces/github-publish.ts +3 -3
  290. package/src/surfaces/grid-open.json +1 -1
  291. package/src/surfaces/grid-panel.json +2 -2
  292. package/src/surfaces/grid-views.json +1 -1
  293. package/src/surfaces/inspector-dock.json +2 -2
  294. package/src/surfaces/jump-bar.json +1 -1
  295. package/src/surfaces/jump-bar.ts +1 -1
  296. package/src/surfaces/library-pane.ts +2 -1
  297. package/src/surfaces/logic-panel.json +7 -7
  298. package/src/surfaces/logic-panel.ts +6 -4
  299. package/src/surfaces/logic-workspace.json +2 -2
  300. package/src/surfaces/logic-workspace.ts +2 -2
  301. package/src/surfaces/media-browser.ts +3 -3
  302. package/src/surfaces/media-pane.ts +2 -1
  303. package/src/surfaces/menu.ts +5 -5
  304. package/src/surfaces/new-project.json +1 -1
  305. package/src/surfaces/palette.json +8 -7
  306. package/src/surfaces/pane-context.json +86 -57
  307. package/src/surfaces/pane-context.ts +2 -1
  308. package/src/surfaces/pane-grid.json +3 -3
  309. package/src/surfaces/panel-activity.json +2 -1
  310. package/src/surfaces/panel-deploy-checklist.json +1 -1
  311. package/src/surfaces/panel-elements.ts +2 -1
  312. package/src/surfaces/panel-i18n.ts +2 -1
  313. package/src/surfaces/panel-outline.json +1 -1
  314. package/src/surfaces/panel-outline.ts +4 -3
  315. package/src/surfaces/panel-page.json +2 -2
  316. package/src/surfaces/panel-page.ts +4 -1
  317. package/src/surfaces/panel-problems.json +4 -3
  318. package/src/surfaces/panel-problems.ts +2 -2
  319. package/src/surfaces/panel-signals.json +23 -8
  320. package/src/surfaces/panel-signals.ts +5 -1
  321. package/src/surfaces/panel-stylebook-layers.json +1 -1
  322. package/src/surfaces/panel-stylebook-layers.ts +2 -2
  323. package/src/surfaces/preferences.json +21 -8
  324. package/src/surfaces/preferences.ts +9 -1
  325. package/src/surfaces/properties-panel.json +4 -4
  326. package/src/surfaces/properties-panel.ts +2 -2
  327. package/src/surfaces/publish.json +1 -1
  328. package/src/surfaces/publish.ts +2 -1
  329. package/src/surfaces/push-plan.json +4 -3
  330. package/src/surfaces/rail.json +2 -2
  331. package/src/surfaces/rail.ts +10 -4
  332. package/src/surfaces/reference-field.json +1 -1
  333. package/src/surfaces/schema-form.json +2 -2
  334. package/src/surfaces/schema-form.ts +1 -1
  335. package/src/surfaces/seo.json +1 -1
  336. package/src/surfaces/seo.ts +2 -2
  337. package/src/surfaces/settings-contributed.ts +2 -1
  338. package/src/surfaces/settings-css-vars.json +4 -4
  339. package/src/surfaces/settings-deploy.json +4 -4
  340. package/src/surfaces/settings-deploy.ts +2 -1
  341. package/src/surfaces/settings-extensions.json +6 -6
  342. package/src/surfaces/settings-extensions.ts +6 -2
  343. package/src/surfaces/settings-locales.json +4 -4
  344. package/src/surfaces/settings-overview.ts +2 -1
  345. package/src/surfaces/settings-pane.ts +3 -2
  346. package/src/surfaces/settings-rawjson.ts +1 -1
  347. package/src/surfaces/slash-menu.ts +4 -4
  348. package/src/surfaces/statements.json +3 -3
  349. package/src/surfaces/statusbar.ts +23 -23
  350. package/src/surfaces/style-panel.json +9 -5
  351. package/src/surfaces/style-panel.ts +3 -3
  352. package/src/surfaces/tab-strip.json +2 -2
  353. package/src/surfaces/target-line.json +1 -1
  354. package/src/surfaces/target-line.ts +12 -10
  355. package/src/surfaces/welcome.json +7 -2
  356. package/src/tabs/doc-op-apply.ts +5 -5
  357. package/src/tabs/patch-ops.ts +3 -3
  358. package/src/tabs/project-config.ts +10 -10
  359. package/src/tabs/selection.ts +1 -1
  360. package/src/tabs/tab.ts +13 -14
  361. package/src/tabs/transact.ts +18 -24
  362. package/src/types.ts +27 -3
  363. package/src/ui/ai-credentials-form.ts +74 -16
  364. package/src/ui/ai-managed-connect.ts +68 -19
  365. package/src/ui/color-selector.ts +1 -1
  366. package/src/ui/expression-editor.ts +3 -3
  367. package/src/ui/form-controls.ts +6 -5
  368. package/src/ui/formula-catalog.ts +4 -4
  369. package/src/ui/formula-chips.ts +2 -2
  370. package/src/ui/layers.ts +20 -18
  371. package/src/ui/panel-resize.ts +8 -28
  372. package/src/ui/popover-surface.ts +2 -2
  373. package/src/ui/progress-modal.ts +3 -3
  374. package/src/ui/regions.ts +14 -9
  375. package/src/ui/schema-form.ts +10 -9
  376. package/src/ui/timing.ts +9 -7
  377. package/src/ui/value-source.ts +4 -4
  378. package/src/ui/virtual-window.ts +58 -5
  379. package/src/utils/base64.ts +20 -1
  380. package/src/utils/canvas-media.ts +1 -1
  381. package/src/utils/studio-utils.ts +0 -31
  382. package/src/view.ts +4 -3
  383. package/src/workspace/pane-derive.ts +14 -13
  384. package/src/workspace/session.ts +7 -6
  385. package/src/workspace/workspace.ts +49 -39
  386. package/styles/canvas.css +1 -27
  387. package/styles/inspector.css +4 -3
  388. package/styles/overlays.css +1 -1
  389. package/styles/tokens.css +17 -1
  390. package/styles/tokens.json +6 -1
  391. package/dist/chunks/entry-commands-w9qsxa6q.js +0 -42
  392. package/dist/chunks/layers-panel-fksbdg4q.js +0 -40
  393. package/dist/chunks/publish-panel-vz23wwmg.js +0 -27
  394. package/dist/chunks/quick-search-e9rp74m8.js +0 -46
  395. package/dist/chunks/right-panel-j97t2yvy.js +0 -45
  396. package/dist/chunks/studio-727xh0e3.js +0 -76
  397. package/src/files/json-layout.ts +0 -474
  398. package/src/services/ai-turn-signal.ts +0 -70
@@ -42,9 +42,8 @@ export type LogicFieldKind = "control" | "text" | "select";
42
42
  /**
43
43
  * A bindable value as a first-class field row: a collection, a filter, a sort key, a `$switch`.
44
44
  *
45
- * These were the last second-class rows in the inspector (§12 P5 item 6) — a bare label and a
46
- * widget, with no set dot, no clear affordance and no error slot. Every field the tab has is one of
47
- * these now.
45
+ * These were the last second-class rows in the inspector — a bare label and a widget, with no set
46
+ * dot, no clear affordance and no error slot. Every field the tab has is one of these now.
48
47
  */
49
48
  export interface LogicFieldView {
50
49
  /** The slot's field key: the repeater's key, and what every callback names. */
@@ -161,7 +160,10 @@ export interface LogicView {
161
160
  /** `empty` or `ready` — no document, no selection and a stale one are all the first. */
162
161
  state: string;
163
162
  emptyMessage: string;
164
- /** What the reader can do about it. An empty state that teaches nothing offers none (§11.1). */
163
+ /**
164
+ * What the reader can do about it. An empty state that teaches nothing offers none
165
+ * (studio-ui-guidelines.md §11.1).
166
+ */
165
167
  emptyActions: LogicEmptyAction[];
166
168
  hasEmptyActions: boolean;
167
169
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://jxsuite.com/schema/v1",
3
3
  "$id": "StudioLogicWorkspace",
4
- "$description": "⑪ · Logic — the Bottom dock tab where a formula and a function body are edited BESIDE the page they compute. One tab, two surfaces, one header: `panels/formula-workspace.ts` decides which of them is open (a `$expression` or a Monaco body), what it is called and what its verbs are, and this draws both. The chip pipeline is a projection of `ui/formula-chips.ts`'s model — the expression tree read left to right — and a chip click reports its key back; nothing here unrolls a tree, reads a document or evaluates anything. Three ISLANDS, each an empty host this document draws and the flow fills (studio-ui-guidelines.md §9.4): `[part=\"code-host\"]` takes Monaco, `[part=\"editor-host\"]` takes the expression editor, which is a lit surface of its own and another conversion's to move, and one `[part=\"tree-host\"]` per data-rail entry takes the value tree, which is a mounted document of its own (`surfaces/panel-data.json`). The rail's trees had been empty since that tree became a document, because the lit takeover rendered a host nothing ever filled; announcing them is what fills them.",
4
+ "$description": "Logic — the Bottom dock tab where a formula and a function body are edited BESIDE the page they compute. One tab, two surfaces, one header: `panels/formula-workspace.ts` decides which of them is open (a `$expression` or a Monaco body), what it is called and what its verbs are, and this draws both. The chip pipeline is a projection of `ui/formula-chips.ts`'s model — the expression tree read left to right — and a chip click reports its key back; nothing here unrolls a tree, reads a document or evaluates anything. Three ISLANDS, each an empty host this document draws and the flow fills (studio-ui-guidelines.md §9.4): `[part=\"code-host\"]` takes Monaco, `[part=\"editor-host\"]` takes the expression editor, which is a lit surface of its own and another conversion's to move, and one `[part=\"tree-host\"]` per data-rail entry takes the value tree, which is a mounted document of its own (`surfaces/panel-data.json`). The rail's trees had been empty since that tree became a document, because the lit takeover rendered a host nothing ever filled; announcing them is what fills them.",
5
5
  "tagName": "div",
6
6
  "attributes": {
7
7
  "part": "workspace"
@@ -94,7 +94,7 @@
94
94
  "textOverflow": "ellipsis"
95
95
  },
96
96
  "& [part=\"badge\"]": {
97
- "$description": "The live value (spec §19.9). A resolved formula is arbitrary text — an object, a URL, a paragraph — so it ellipsizes inside the chip it annotates and never sets the chip's width.",
97
+ "$description": "The live value (spec.md §19.9). A resolved formula is arbitrary text — an object, a URL, a paragraph — so it ellipsizes inside the chip it annotates and never sets the chip's width.",
98
98
  "flex": "0 1 auto",
99
99
  "minWidth": "0",
100
100
  "maxWidth": "120px",
@@ -1,6 +1,6 @@
1
1
  /// <reference lib="dom" />
2
2
  /**
3
- * ⑪ · Logic — the Bottom dock tab, as a mounted document.
3
+ * Logic — the Bottom dock tab, as a mounted document.
4
4
  *
5
5
  * This is the adapter. `panels/formula-workspace.ts` is the flow — it reads which of the two
6
6
  * surfaces is open, resolves the expression at that document position, keeps the chip selection,
@@ -63,7 +63,7 @@ export interface LogicScopeEntryView {
63
63
  export interface LogicWorkspaceView {
64
64
  /** `empty` (nothing open in the tab) or `ready`. */
65
65
  state: string;
66
- /** What the tab is for, said when nothing is open in it (§11.1). */
66
+ /** What the tab is for, said when nothing is open in it (studio-ui-guidelines.md §11.1). */
67
67
  emptyMessage: string;
68
68
  /** Which body the ready state draws: `formula`, `code`, or `missing`. */
69
69
  surface: string;
@@ -10,9 +10,9 @@
10
10
  * **The platform owns dismissal.** The root is a `jx-popover`, so Escape, light dismissal, the top
11
11
  * layer and focus back to the invoker are its contract rather than three document listeners and a
12
12
  * `z-index` chosen from the layer the anchor happened to be in. That is not only tidier: an overlay
13
- * drawn into a layer div paints UNDERNEATH a modal `<dialog>` and is inert besides (`specs/ui.md`
14
- * §7), which is the whole reason `panels/seo-modal.ts` had to fork its own Browse onto the kit
15
- * menu, and a top-layer popover has no such problem.
13
+ * drawn into a layer div paints UNDERNEATH a modal `<dialog>` and is inert besides (ui.md §6),
14
+ * which is the whole reason `panels/seo-modal.ts` had to fork its own Browse onto the kit menu, and
15
+ * a top-layer popover has no such problem.
16
16
  *
17
17
  * **The filter takes the caret, and the adapter is what puts it there.** A `jx-popover` moves focus
18
18
  * into itself but has no opinion about which control; the panel is a search box over a list, so the
@@ -166,7 +166,8 @@ export function mountMediaSurface(
166
166
  let disposed = false;
167
167
  /* Nothing is called on an element here, so the mount is all there is to wait for: the DOCUMENT is
168
168
  what this surface renders, and the kit's Copy button settles its own template one
169
- `connectedCallback` later without anybody asking it to (§1.1, "await the element"). */
169
+ `connectedCallback` later without anybody asking it to (studio-ui-guidelines.md §1.1, "await
170
+ the element"). */
170
171
  const ready = mountSurface("media-pane", scope, host).then((surface) => {
171
172
  if (disposed) {
172
173
  surface.dispose();
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * The menu surface: a `jx-menu` of command-record projections, mounted into a popover layer slot.
3
3
  *
4
- * This is the first Studio surface rendered as a Jx document (specs/studio-ui-guidelines.md §6,
5
- * §9.3): `menu.json` is the markup, ARIA and style, and this adapter is the decisions — which
6
- * records, what they print, where the panel opens, what runs on select. The kit owns the menu
7
- * contract (roving focus, typeahead, submenus, light dismissal, Escape) through the platform's own
8
- * popover, so nothing here binds a key or a document listener.
4
+ * This is the first Studio surface rendered as a Jx document (studio-ui-guidelines.md §6, §9.3):
5
+ * `menu.json` is the markup, ARIA and style, and this adapter is the decisions — which records,
6
+ * what they print, where the panel opens, what runs on select. The kit owns the menu contract
7
+ * (roving focus, typeahead, submenus, light dismissal, Escape) through the platform's own popover,
8
+ * so nothing here binds a key or a document listener.
9
9
  *
10
10
  * Every menu opens in a `getLayerSlot("popover", id)` slot, which is what carries the
11
11
  * `overlay.menu:<id>` region the screenshot pipeline addresses, and is torn down when the popover
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://jxsuite.com/schema/v1",
3
3
  "$id": "StudioNewProject",
4
- "$description": "The New Project wizard: two steps in one dialog. Step 1 asks where the site comes from — a starter gallery that ends with one Start from scratch card, an Import of a site that already exists, or an Agent brief — and step 2 asks what it is called and where it is written. A `jx-dialog`, so the platform owns modality, Escape, focus restoration and the backdrop, which is what retired the fixed `.new-project-modal` card, the `<sp-underlay>` beside it, the `z-index: 1000` that card needed to climb back out from under its own scrim, and the hand-drawn header with its own close button. The footer is the dialog's too: Cancel, Back and the primary are `cancelLabel`, `secondaryLabel` and `confirmLabel`, so the wizard says which answers exist by naming them rather than by drawing three buttons per step. Nothing here knows what a starter is, which platform writes to a repository rather than a folder, what makes an AI gate open, or how a breakpoint policy is spelled — `new-project/new-project-modal.ts` keeps the flow, `new-project/import-tab.ts` the brief and `new-project/location-fields.ts` the destination, and all three hand over strings, flags and one discriminant per branch. The three AI controllers are islands: their own mounted documents, placed by the adapter into boxes this document renders empty (§9.4).",
4
+ "$description": "The New Project wizard: two steps in one dialog. Step 1 asks where the site comes from — a starter gallery that ends with one Start from scratch card, an Import of a site that already exists, or an Agent brief — and step 2 asks what it is called and where it is written. A `jx-dialog`, so the platform owns modality, Escape, focus restoration and the backdrop, which is what retired the fixed `.new-project-modal` card, the `<sp-underlay>` beside it, the `z-index: 1000` that card needed to climb back out from under its own scrim, and the hand-drawn header with its own close button. The footer is the dialog's too: Cancel, Back and the primary are `cancelLabel`, `secondaryLabel` and `confirmLabel`, so the wizard says which answers exist by naming them rather than by drawing three buttons per step. Nothing here knows what a starter is, which platform writes to a repository rather than a folder, what makes an AI gate open, or how a breakpoint policy is spelled — `new-project/new-project-modal.ts` keeps the flow, `new-project/import-tab.ts` the brief and `new-project/location-fields.ts` the destination, and all three hand over strings, flags and one discriminant per branch. The three AI controllers are islands: their own mounted documents, placed by the adapter into boxes this document renders empty (studio-ui-guidelines.md §9.4).",
5
5
  "tagName": "jx-dialog",
6
6
  "$props": {
7
7
  "headline": {
@@ -17,6 +17,9 @@
17
17
  "paddingTop": "60px",
18
18
  "background": "rgba(0, 0, 0, 0.4)"
19
19
  },
20
+ "& [part=\"overlay\"][hidden]": {
21
+ "display": "none"
22
+ },
20
23
  "& [part=\"panel\"]": {
21
24
  "width": "560px",
22
25
  "maxWidth": "calc(100vw - 32px)",
@@ -133,14 +136,12 @@
133
136
  "color": "var(--jx-fg-dim)"
134
137
  }
135
138
  },
136
- "$switch": {
137
- "$ref": "#/state/open"
138
- },
139
- "cases": {
140
- "true": {
139
+ "children": [
140
+ {
141
141
  "tagName": "div",
142
142
  "attributes": {
143
- "part": "overlay"
143
+ "part": "overlay",
144
+ "hidden": "${state.open ? null : ''}"
144
145
  },
145
146
  "onclick": {
146
147
  "$prototype": "Function",
@@ -531,5 +532,5 @@
531
532
  }
532
533
  ]
533
534
  }
534
- }
535
+ ]
535
536
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://jxsuite.com/schema/v1",
3
3
  "$id": "StudioPaneContext",
4
- "$description": "The pane's own chrome — region ⑦ (the context bar) and region ⑩ (the floating zoom pod), one mount per pane. It replaces `#tab-bar`, a 28px band styled identically to the tab strip above it that held five unrelated axes with no labels on any of them; the three axes here each say what they are, and the label is what stops the band re-accreting into an anonymous strip of chips. `panels/pane-context.ts` keeps every decision — which editor kinds a document declares, which canvas views it has, whether preview is a flag over them, what a lens may not write, which pane's stage a zoom verb lands on, and what a route param's candidate values are — and hands this document one projection of words, booleans and keyed rows. The bar and the banner share `[part=\"band\"]` so the adapter can MEASURE what the stage must clear: a banner's height is its wrapped text, and only layout knows how many lines that is.",
4
+ "$description": "The pane's own chrome — the pane context bar and the floating zoom pod, one mount per pane. It replaces `#tab-bar`, a 28px band styled identically to the tab strip above it that held five unrelated axes with no labels on any of them; the three axes here each say what they are, and the label is what stops the band re-accreting into an anonymous strip of chips. `panels/pane-context.ts` keeps every decision — which editor kinds a document declares, which canvas views it has, whether preview is a flag over them, what a lens may not write, which pane's stage a zoom verb lands on, and what a route param's candidate values are — and hands this document one projection of words, booleans and keyed rows. The bar and the banner share `[part=\"band\"]` so the adapter can MEASURE what the stage must clear: a banner's height is its wrapped text, and only layout knows how many lines that is.",
5
5
  "tagName": "div",
6
6
  "attributes": {
7
7
  "part": "chrome"
@@ -59,10 +59,14 @@
59
59
  "flexShrink": "0"
60
60
  },
61
61
  "& [part=\"preview-toggle\"]": {
62
- "$description": "Not a third radio, and it must not read as one: it says the canvas is inert. The margin separates the two axes the eye is being asked to read as separate; the accent fill is the kit's `emphasized`, which is what deleted the four Spectrum custom properties this rule used to carry.",
62
+ "$description": "Not a third radio, and it must not read as one: it says the canvas is inert. The margin separates the two axes the eye is being asked to read as separate; the accent fill is the kit's `emphasized`, which is what deleted the four Spectrum custom properties this rule used to carry. The toggle is `quiet: false`, so it rests as a framed button of its own beside the framed View switch, as the Spectrum button did; quiet, it read as a fourth loose word once the switch beside it drew its frame.",
63
63
  "flexShrink": "0",
64
64
  "marginInlineStart": "6px"
65
65
  },
66
+ "& jx-action-button[part=\"preview-toggle\"] > [part=\"control\"]": {
67
+ "$description": "The text padding the View switch's segments get from their group, which this toggle stands outside: the small size's 2px is for a glyph, and 6px is what the group gives a text segment. (0,3,1) outranks the kit's small padding at (0,3,0).",
68
+ "paddingInline": "6px"
69
+ },
66
70
  "& [part=\"context-trigger\"]": {
67
71
  "fontVariantNumeric": "tabular-nums"
68
72
  },
@@ -88,29 +92,47 @@
88
92
  "fontSize": "var(--jx-text-md)"
89
93
  },
90
94
  "& [part=\"pod\"]": {
91
- "$description": "Bottom-right of the pane, over the stage — a viewport control, which is not a document axis and so never belonged in a band beside one.",
95
+ "$description": "Bottom-right of the pane, over the stage — a viewport control, which is not a document axis and so never belonged in a band beside one. It is a ROW of two controls and draws no box of its own: a 1px border and a 6px radius round 2px/4px of padding framed the zoom group's own frame and the Fit select's own frame, a frame inside a frame and busier than any other group in the chrome. Each control draws itself and takes `--pod-lift` to stand off the document under it, which is what the pod's fill and border used to do for both at once, and the gap between them says they are two controls rather than one strip with a seam. The right inset ADDS `--stage-scrollbar-w` because the chrome layer spans the whole cell, scrollbar gutter included: a fixed 12px put the pod 3px into Edit's 15px track, painting over it and swallowing its clicks. CSS cannot measure a scrollbar and this document cannot see the scroller, so `canvas/stage-scrollbar.ts` measures the stage's own and writes the width on the cell, where this reads it by cascade. It is 0 wherever the stage does not scroll or the scrollbar is an overlay. Physical right on purpose: Studio's chrome is never mirrored.",
96
+ "--pod-lift": "0 2px 8px rgb(0 0 0 / 25%)",
92
97
  "alignSelf": "flex-end",
98
+ "display": "flex",
99
+ "alignItems": "center",
100
+ "gap": "var(--jx-space-2)",
93
101
  "pointerEvents": "auto",
94
- "margin": "0 var(--jx-space-4) var(--jx-space-4) 0",
95
- "padding": "var(--jx-space-1) var(--jx-space-2)",
96
- "border": "1px solid var(--border)",
97
- "borderRadius": "var(--jx-radius-md)",
98
- "background": "var(--bg)",
99
- "boxShadow": "0 2px 8px rgb(0 0 0 / 25%)"
102
+ "margin": "0 calc(var(--jx-space-4) + var(--stage-scrollbar-w, 0px)) var(--jx-space-4) 0"
103
+ },
104
+ "& [part=\"zoom-group\"]": {
105
+ "$description": "The segmented frame floats on its own now that the pod draws no box around it. The radius is the one the first and last segments already draw, so the shadow follows the shape of the strip instead of a rectangle around it — the host's box IS that strip, since the group has no padding and each member's -1px pulls its own host in by a pixel.",
106
+ "borderRadius": "var(--jx-radius-sm)",
107
+ "boxShadow": "var(--pod-lift)"
108
+ },
109
+ "& [part=\"pod\"] > [part=\"zoom-group\"][data-compact] > jx-action-button > [part=\"control\"]": {
110
+ "$description": "One resting ink across the pod. A compact group rests its unselected members on `--jx-fg-dim` and brightens the chosen one, which is how a segmented control says which segment is on — and nothing in this pod is ever chosen: the three are a viewport verb, a readout and a verb. So the dim ink said nothing here and made `100%` read as disabled beside the Fit select's value, which is the same kind of readout at `--jx-fg`. (0,5,1) over the group's own resting rule at (0,4,1); the group's hover is (0,6,1) and still wins, which now leaves it only the wash.",
111
+ "color": "var(--fg)"
100
112
  },
101
113
  "& [part=\"zoom-label\"]": {
102
- "minWidth": "48px",
103
- "fontFamily": "var(--font-mono)"
114
+ "$description": "A floor under the percentage, so the pod does not shift as the value changes length. The width is the host's and the face is the control's, below: the control sets its own font and sits inside the host at its content width, so this rule used to carry a mono face nothing inherited and to open a 6px hole in the segmented frame before the `+` segment (measured: a 48px host round a 41.8px control, drawn in Inter).",
115
+ "minWidth": "48px"
116
+ },
117
+ "& [part=\"zoom-label\"] > [part=\"control\"]": {
118
+ "$description": "The control fills its 48px host, closing the frame, and draws the percentage in the mono face with tabular digits so a changing value does not jitter. (0,3,0) outranks the kit control's own face at (0,2,0).",
119
+ "flex": "1",
120
+ "fontFamily": "var(--font-mono)",
121
+ "fontVariantNumeric": "tabular-nums"
104
122
  },
105
123
  "& [part=\"fit\"]": {
106
124
  "maxWidth": "120px"
107
125
  },
126
+ "& [part=\"fit\"] > [part=\"control\"]": {
127
+ "$description": "The pod's second control lifts off the document the way the first does, on the frame the kit's select already draws. On the control rather than the host, because the host is a column whose error region and help slot are the select's neighbours: the shadow has to follow the box that is painted.",
128
+ "boxShadow": "var(--pod-lift)"
129
+ },
108
130
  "& [part=\"popover\"]": {
109
131
  "$description": "Both panels take the pointer that `.pane-chrome` withholds. A popover is in the top layer while it shows, which changes where it PAINTS and not where it is in the tree, so it inherits `pointer-events: none` from the chrome layer exactly as the band does.",
110
132
  "pointerEvents": "auto"
111
133
  },
112
134
  "& [part=\"ctx\"]": {
113
- "$description": "One column of labelled groups over a footer that leaves for the definition site. This control only SELECTS (§2 principle 5) — nothing in it defines a breakpoint, a scheme or a feature query.",
135
+ "$description": "One column of labelled groups over a footer that leaves for the definition site. This control only SELECTS; the definitions live in Project Settings › Contexts (§6.2), and nothing in it defines a breakpoint, a scheme or a feature query.",
114
136
  "display": "flex",
115
137
  "flexDirection": "column",
116
138
  "gap": "10px",
@@ -129,11 +151,15 @@
129
151
  "letterSpacing": "0.04em",
130
152
  "color": "var(--fg-dim)"
131
153
  },
132
- "& [part=\"sizes\"]": {
133
- "flexWrap": "wrap"
154
+ "& [part=\"sizes\"], & [part=\"features\"]": {
155
+ "$description": "The two groups that WRAP, and the reason neither is a segmented control. A breakpoint or feature list is as long as the project makes it and this popover is a 240–340px column, so both fold onto a second line in any project with more than a few; a compact group cannot draw that — its seam is written in tree order, no selector can find the ends of a flex line, and it therefore refuses to wrap and would overflow the column instead (ui.md §5.4). Chips instead: each member draws its own rounded frame (`quiet: false`, since the group no longer frames it) and the chosen one takes the accent edge below. The gap is --jx-space-2 rather than the group's own 2px, which puts every small chip's hit area at the 24px floor on both axes instead of the 22px two overlapping extensions leave (§4.3).",
156
+ "flexWrap": "wrap",
157
+ "gap": "var(--jx-space-2)"
134
158
  },
135
- "& [part=\"features\"]": {
136
- "flexWrap": "wrap"
159
+ "& [part=\"sizes-item\"][data-selected] > [part=\"control\"], & [part=\"features-item\"][data-selected] > [part=\"control\"]": {
160
+ "$description": "A chosen chip reads the way a chosen segment does: the accent tint with an accent EDGE. A member's own selected state is a 15% tint over its neutral border, which among framed neighbours reads as a faint wash rather than as the one that is on — the measurement that gave the compact group its selected rule, restated here at the one place the group does not draw it. (0,4,0) over the member's own (0,3,0).",
161
+ "borderColor": "var(--jx-accent)",
162
+ "background": "var(--jx-accent-20)"
137
163
  },
138
164
  "& [part=\"fields\"]": {
139
165
  "$description": "The fields, stacked. They were a row on the bar capped at 140px; in the popover each takes the full column so a route value or a JSON test prop is readable while you type it.",
@@ -461,6 +487,7 @@
461
487
  },
462
488
  "$props": {
463
489
  "size": "sm",
490
+ "quiet": false,
464
491
  "toggles": true,
465
492
  "emphasized": true,
466
493
  "selected": {
@@ -799,55 +826,55 @@
799
826
  }
800
827
  ]
801
828
  }
802
- },
803
- {
804
- "tagName": "div",
829
+ }
830
+ ]
831
+ },
832
+ {
833
+ "tagName": "div",
834
+ "attributes": {
835
+ "part": "fit-slot",
836
+ "role": "none"
837
+ },
838
+ "style": {
839
+ "display": "contents"
840
+ },
841
+ "$switch": {
842
+ "$ref": "#/state/fitState"
843
+ },
844
+ "cases": {
845
+ "shown": {
846
+ "tagName": "jx-select",
805
847
  "attributes": {
806
- "part": "fit-slot",
807
- "role": "none"
808
- },
809
- "style": {
810
- "display": "contents"
848
+ "part": "fit"
811
849
  },
812
- "$switch": {
813
- "$ref": "#/state/fitState"
850
+ "$props": {
851
+ "label": "Fit",
852
+ "size": "sm",
853
+ "options": {
854
+ "$ref": "#/state/fitOptions"
855
+ },
856
+ "value": {
857
+ "$ref": "#/state/fitValue"
858
+ }
814
859
  },
815
- "cases": {
816
- "shown": {
817
- "tagName": "jx-select",
818
- "attributes": {
819
- "part": "fit"
820
- },
821
- "$props": {
822
- "label": "Fit",
823
- "size": "sm",
824
- "options": {
825
- "$ref": "#/state/fitOptions"
860
+ "onchange": {
861
+ "$prototype": "Function",
862
+ "body": [
863
+ {
864
+ "operator": "call",
865
+ "target": {
866
+ "$ref": "#/state/chooseFit"
826
867
  },
827
- "value": {
828
- "$ref": "#/state/fitValue"
829
- }
830
- },
831
- "onchange": {
832
- "$prototype": "Function",
833
- "body": [
868
+ "value": [
834
869
  {
835
- "operator": "call",
836
- "target": {
837
- "$ref": "#/state/chooseFit"
838
- },
839
- "value": [
840
- {
841
- "$ref": "event#/target/value"
842
- }
843
- ]
870
+ "$ref": "event#/target/value"
844
871
  }
845
872
  ]
846
873
  }
847
- }
874
+ ]
848
875
  }
849
876
  }
850
- ]
877
+ }
851
878
  }
852
879
  ]
853
880
  }
@@ -898,7 +925,7 @@
898
925
  },
899
926
  "$props": {
900
927
  "selects": "single",
901
- "compact": true,
928
+ "compact": false,
902
929
  "label": "Size"
903
930
  },
904
931
  "children": [
@@ -918,6 +945,7 @@
918
945
  },
919
946
  "$props": {
920
947
  "size": "sm",
948
+ "quiet": false,
921
949
  "checked": {
922
950
  "$ref": "$map/item/checked"
923
951
  },
@@ -1170,7 +1198,7 @@
1170
1198
  },
1171
1199
  "$props": {
1172
1200
  "selects": "multiple",
1173
- "compact": true,
1201
+ "compact": false,
1174
1202
  "label": "Features"
1175
1203
  },
1176
1204
  "children": [
@@ -1190,6 +1218,7 @@
1190
1218
  },
1191
1219
  "$props": {
1192
1220
  "size": "sm",
1221
+ "quiet": false,
1193
1222
  "toggles": true,
1194
1223
  "selected": {
1195
1224
  "$ref": "$map/item/selected"
@@ -1,6 +1,7 @@
1
1
  /// <reference lib="dom" />
2
2
  /**
3
- * The pane's chrome as a mounted document — regions ⑦ and ⑩, one mount per pane.
3
+ * The pane's chrome as a mounted document — the pane context bar and the floating zoom pod, one
4
+ * mount per pane.
4
5
  *
5
6
  * `panels/pane-context.ts` is the flow: which editor kinds a document declares, which canvas views
6
7
  * it has, whether preview is a flag over one of them, what a lens may never write, which pane's
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://jxsuite.com/schema/v1",
3
3
  "$id": "StudioPaneGrid",
4
- "$description": "The pane grid (studio.md §18.1): one cell per pane, with a splitter before every cell but the first. Every box here is EMPTY by design — the FIVE inside a cell are hosts other modules fill (`panels/tab-strip.ts` the strip, `panels/jump-bar.ts` the jump bar, `panels/pane-context.ts` the chrome layer, `canvas/canvas-render.ts` the stage, `panels/pane-grid.ts` itself the right-edge drop zone), and the stage is an ISLAND in the §9.4 sense: the canvas host mounts a cross-origin `<iframe>` into it, so nothing this document draws may ever go inside it. What the document owns is the STRUCTURE and the STYLE — the cell's own two-row grid, the three row-2 children that share its lower cell, and the splitter — which is `styles/shell.css`'s `.pane*` block and `styles/canvas.css`'s `.pane-stage` rule, carried here and keyed on `part`. Two things are load-bearing and easy to undo. (1) **A row that moves reloads an iframe**, so the keyed `$map` is not an optimisation: `workspace.panes[0]` is always the primary and `MAX_PANES` is 2, the key is the pane id, and the runtime's forward-cursor pass therefore never moves a kept row — gaining or losing the side pane leaves the primary's node, and the frame inside it, untouched. (2) **The splitter must sit BETWEEN two cells and inside neither**, so each row is a `display: contents` wrapper holding its own leading splitter and its cell: the wrapper generates no box, so the splitter and the two cells are the grid items of `#pane-grid` in DOM order, and a pointer landing on the splitter is in no cell at all. Every selector below is a `>` chain from the root, because a pane's stage hosts other surface documents and a bare `[part=\"row\"]` descendant rule would reach into them.",
4
+ "$description": "The pane grid (studio.md §18.1): one cell per pane, with a splitter before every cell but the first. Every box here is EMPTY by design — the FIVE inside a cell are hosts other modules fill (`panels/tab-strip.ts` the strip, `panels/jump-bar.ts` the jump bar, `panels/pane-context.ts` the chrome layer, `canvas/canvas-render.ts` the stage, `panels/pane-grid.ts` itself the right-edge drop zone), and the stage is an ISLAND in the studio-ui-guidelines.md §9.4 sense: the canvas host mounts a cross-origin `<iframe>` into it, so nothing this document draws may ever go inside it. What the document owns is the STRUCTURE and the STYLE — the cell's own two-row grid, the three row-2 children that share its lower cell, and the splitter — which is `styles/shell.css`'s `.pane*` block and `styles/canvas.css`'s `.pane-stage` rule, carried here and keyed on `part`. Two things are load-bearing and easy to undo. (1) **A row that moves reloads an iframe**, so the keyed `$map` is not an optimisation: `workspace.panes[0]` is always the primary and `MAX_PANES` is 2, the key is the pane id, and the runtime's forward-cursor pass therefore never moves a kept row — gaining or losing the side pane leaves the primary's node, and the frame inside it, untouched. (2) **The splitter must sit BETWEEN two cells and inside neither**, so each row is a `display: contents` wrapper holding its own leading splitter and its cell: the wrapper generates no box, so the splitter and the two cells are the grid items of `#pane-grid` in DOM order, and a pointer landing on the splitter is in no cell at all. Every selector below is a `>` chain from the root, because a pane's stage hosts other surface documents and a bare `[part=\"row\"]` descendant rule would reach into them.",
5
5
  "tagName": "div",
6
6
  "attributes": {
7
7
  "part": "grid",
@@ -45,7 +45,7 @@
45
45
  "display": "none"
46
46
  },
47
47
  "& > [part=\"row\"] > [part=\"pane\"] > [part=\"jump\"]": {
48
- "$description": "Region ⑥. Like the chrome layer below it this shares the pane's lower cell rather than owning a row, so the two bars stack OVER the stage instead of pushing it down. `align-self: start` is what keeps it the height of its own content instead of the height of the cell, so the bar never covers the stage it sits above.",
48
+ "$description": "The jump bar. Like the chrome layer below it this shares the pane's lower cell rather than owning a row, so the two bars stack OVER the stage instead of pushing it down. `align-self: start` is what keeps it the height of its own content instead of the height of the cell, so the bar never covers the stage it sits above.",
49
49
  "gridRow": "2",
50
50
  "gridColumn": "1",
51
51
  "alignSelf": "start",
@@ -55,7 +55,7 @@
55
55
  "maxWidth": "100%"
56
56
  },
57
57
  "& > [part=\"row\"] > [part=\"pane\"] > [part=\"chrome\"]": {
58
- "$description": "Regions ⑦ and ⑩. The layer itself is inert and only its children take the pointer; `surfaces/pane-context.json` owns what they look like. Offset by `--jump-bar-h` for the same reason the stage is: the jump bar is stacked over this same cell, and one projection per bar is what keeps \"no tab open\" costing no dead band.",
58
+ "$description": "The pane context bar and the floating zoom pod. The layer itself is inert and only its children take the pointer; `surfaces/pane-context.json` owns what they look like. Offset by `--jump-bar-h` for the same reason the stage is: the jump bar is stacked over this same cell, and one projection per bar is what keeps \"no tab open\" costing no dead band.",
59
59
  "gridRow": "2",
60
60
  "gridColumn": "1",
61
61
  "marginTop": "var(--jump-bar-h, 0px)",
@@ -154,7 +154,8 @@
154
154
  }
155
155
  },
156
156
  "& [part=\"log\"]": {
157
- "$description": "The captured output the progress modal used to show once and then lose. It scrolls inside the row rather than growing it, so one 400-line `bun install` failure does not become the whole panel.",
157
+ "$description": "The captured output the progress modal used to show once and then lose. It scrolls inside the row rather than growing it, so one 400-line `bun install` failure does not become the whole panel. It is selectable against the root's `user-select: none`, the one part of an activity row that is: the output is what a reader pastes into a bug report, and the row offers no copy action.",
158
+ "userSelect": "text",
158
159
  "maxHeight": "180px",
159
160
  "margin": "2px 0 0",
160
161
  "padding": "6px",
@@ -239,7 +239,7 @@
239
239
  "cases": {
240
240
  "true": {
241
241
  "tagName": "jx-button",
242
- "$description": "The recovery button wears the command's own title, so it reads as a verb rather than as a decoration, and a refused command is dimmed with the reason it names in its tooltip. A command the registry does not have, or whose `when` is false, draws NOTHING rather than a dead label — a surface may choose whether to show a command, never whether it exists (§12.4).",
242
+ "$description": "The recovery button wears the command's own title, so it reads as a verb rather than as a decoration, and a refused command is dimmed with the reason it names in its tooltip. A command the registry does not have, or whose `when` is false, draws NOTHING rather than a dead label — a surface may choose whether to show a command, never whether it exists (§13).",
243
243
  "$props": {
244
244
  "size": "sm",
245
245
  "disabled": {
@@ -148,7 +148,8 @@ export function mountElementsSurface(
148
148
  let disposed = false;
149
149
  /* Nothing is called on an element here, so the mount is all there is to wait for: the DOCUMENT is
150
150
  what this surface renders, and the kit elements inside it settle their own templates one
151
- `connectedCallback` later without anybody asking them to (§1.1, "await the element"). */
151
+ `connectedCallback` later without anybody asking them to (studio-ui-guidelines.md §1.1,
152
+ "await the element"). */
152
153
  const ready = mountSurface("panel-elements", scope, container).then((surface) => {
153
154
  if (disposed) {
154
155
  surface.dispose();
@@ -187,7 +187,8 @@ export function mountI18nSurface(
187
187
  let disposed = false;
188
188
  /* Nothing is called on the element, so the mount is all this has to wait for: the DOCUMENT is
189
189
  what this surface renders, and the kit elements inside it settle their own templates one
190
- `connectedCallback` later without anybody here asking them to (§1.1, "await the element"). */
190
+ `connectedCallback` later without anybody here asking them to (studio-ui-guidelines.md §1.1,
191
+ "await the element"). */
191
192
  void mountSurface("panel-i18n", scope, container).then((surface) => {
192
193
  if (disposed) {
193
194
  surface.dispose();
@@ -684,7 +684,7 @@
684
684
  ]
685
685
  },
686
686
  "empty": {
687
- "$description": "Drawn here rather than borrowed from `panels/empty-state.ts`, which is a lit template a document cannot call. What is kept is the pattern's rules (guidelines §11): one sentence saying what the region is for, then the one action that fills it.",
687
+ "$description": "Drawn here rather than borrowed from `panels/empty-state.ts`, which is a lit template a document cannot call. What is kept is the pattern's rules (studio-ui-guidelines.md §11): one sentence saying what the region is for, then the one action that fills it.",
688
688
  "tagName": "div",
689
689
  "attributes": {
690
690
  "part": "empty"
@@ -21,8 +21,8 @@
21
21
  * `role`, no `aria-*` and no key names — those were written out here and written out again in
22
22
  * `files-panel.ts`, one contract in two copies with nothing keeping them in agreement.
23
23
  *
24
- * **Three things reach the host through `onNodeCreated`** (guidelines §9.4), because each is a fact
25
- * about a node that only exists once it has been created:
24
+ * **Three things reach the host through `onNodeCreated`** (studio-ui-guidelines.md §9.4), because
25
+ * each is a fact about a node that only exists once it has been created:
26
26
  *
27
27
  * - The tree element, which is what the virtual window is measured against and what the scroll watch
28
28
  * binds to. Nothing about the window can be computed before it.
@@ -285,7 +285,8 @@ export function mountOutlineSurface(
285
285
  let disposed = false;
286
286
  /* Nothing is called on an element here, so the mount is all there is to wait for: the two islands
287
287
  announce themselves through `onNodeCreated` as they are created, which is one
288
- `connectedCallback` EARLIER than awaiting the element would be (guidelines §1.1). */
288
+ `connectedCallback` EARLIER than awaiting the element would be
289
+ (studio-ui-guidelines.md §1.1). */
289
290
  const ready = mountSurface("panel-outline", scope, container, {
290
291
  onNodeCreated: (element, _path, def) => {
291
292
  /* A text node carries no `part`, so narrowing and asking are the same question — asked once,
@@ -42,7 +42,7 @@
42
42
  "padding": "0 var(--jx-space-2)"
43
43
  },
44
44
  "& [part=\"row\"]": {
45
- "$description": "§4.1's standard form row, stacked: the label sits above a control that takes the whole width. `min-width: 0` is what keeps it honest in a 240px dock (§4.6) — a field refuses to shrink below its own min-content without it.",
45
+ "$description": "studio-ui-guidelines.md §4.1's standard form row, stacked: the label sits above a control that takes the whole width. `min-width: 0` is what keeps it honest in a 240px dock (studio-ui-guidelines.md §4.6) — a field refuses to shrink below its own min-content without it.",
46
46
  "display": "flex",
47
47
  "flexDirection": "column",
48
48
  "alignItems": "stretch",
@@ -58,7 +58,7 @@
58
58
  "color": "var(--fg-dim)"
59
59
  },
60
60
  "& [part=\"chip\"]": {
61
- "$description": "§4.2's set dot: a 6px accent dot, drawn only where the value is set on this document, that clears it when pressed. A real `button` — it is pressable, and it is the row's only keyboard route to clearing — stripped of the chrome a button brings so the row still reads as a label with a dot beside it.",
61
+ "$description": "studio-ui-guidelines.md §4.2's set dot: a 6px accent dot, drawn only where the value is set on this document, that clears it when pressed. A real `button` — it is pressable, and it is the row's only keyboard route to clearing — stripped of the chrome a button brings so the row still reads as a label with a dot beside it.",
62
62
  "width": "6px",
63
63
  "height": "6px",
64
64
  "padding": "0",
@@ -58,7 +58,10 @@ export interface PageRow extends Record<string, unknown> {
58
58
  label: string;
59
59
  /** Which control the row draws. `textarea` is a multiline text field, not a second element. */
60
60
  kind: "text" | "textarea" | "number" | "boolean" | "select" | "media";
61
- /** Whether the value is set on this document — §4.2's dot, and the row's only clear affordance. */
61
+ /**
62
+ * Whether the value is set on this document — studio-ui-guidelines.md §4.2's dot, and the row's
63
+ * only clear affordance.
64
+ */
62
65
  isSet: boolean;
63
66
  /** The dot's accessible name and tooltip, e.g. `Clear title`. */
64
67
  clearLabel: string;
@@ -113,7 +113,7 @@
113
113
  "overflowWrap": "anywhere"
114
114
  },
115
115
  "& [part=\"file-path\"]": {
116
- "$description": "The path is a control, not a label: it opens the file the problem is about, which is the click-through §7.1 asks for. Underlined on hover only — a permanently underlined path in a dense list reads as a paragraph of links. A plain button rather than a `jx-button`, for the reason the status bar's items are: what it has to look like is a line of text, and every fill, border and control height the kit draws would have to be taken back off again. Named `file-path` and not `path` because `jx-icon` puts `part=\"path\"` on the `<path>` of every glyph it draws, so `[part=\"path\"]` inside a row selects this button and both SVG paths beside it — a styling rule that reaches into the kit's own drawing, and a test or a devtools query that cannot tell them apart.",
116
+ "$description": "The path is a control, not a label: it opens the file the problem is about, which is the click-through §16.1 asks for. Underlined on hover only — a permanently underlined path in a dense list reads as a paragraph of links. A plain button rather than a `jx-button`, for the reason the status bar's items are: what it has to look like is a line of text, and every fill, border and control height the kit draws would have to be taken back off again. Named `file-path` and not `path` because `jx-icon` puts `part=\"path\"` on the `<path>` of every glyph it draws, so `[part=\"path\"]` inside a row selects this button and both SVG paths beside it — a styling rule that reaches into the kit's own drawing, and a test or a devtools query that cannot tell them apart.",
117
117
  "alignSelf": "flex-start",
118
118
  "maxWidth": "100%",
119
119
  "overflow": "hidden",
@@ -139,7 +139,8 @@
139
139
  }
140
140
  },
141
141
  "& [part=\"detail\"]": {
142
- "$description": "The captured log the progress modal used to own. It scrolls inside the row rather than growing it, so one 400-line `bun install` failure does not become the whole panel.",
142
+ "$description": "The captured log the progress modal used to own. It scrolls inside the row rather than growing it, so one 400-line `bun install` failure does not become the whole panel. It is the one part of a problem row that is selectable against the root's `user-select: none`: the log is what a reader pastes into a bug report, and the row offers no copy action.",
143
+ "userSelect": "text",
143
144
  "maxHeight": "180px",
144
145
  "margin": "var(--jx-space-1) 0 0",
145
146
  "padding": "6px",
@@ -171,7 +172,7 @@
171
172
  "flex": "none"
172
173
  },
173
174
  "& [part=\"empty\"]": {
174
- "$description": "The teaching empty state, drawn here rather than borrowed from `panels/empty-state.ts`: that helper is a lit template, and a document cannot call one. What is kept is the pattern's rules (§11) — one sentence saying what the region is FOR, then where its content comes from. It offers no action, because the action that fills this region is a failure and nothing here should invite one.",
175
+ "$description": "The teaching empty state, drawn here rather than borrowed from `panels/empty-state.ts`: that helper is a lit template, and a document cannot call one. What is kept is the pattern's rules (studio-ui-guidelines.md §11) — one sentence saying what the region is FOR, then where its content comes from. It offers no action, because the action that fills this region is a failure and nothing here should invite one.",
175
176
  "display": "flex",
176
177
  "flexDirection": "column",
177
178
  "alignItems": "center",
@@ -109,8 +109,8 @@ function project(scope: ProblemsScope, values: ProblemsValues): void {
109
109
  *
110
110
  * Nothing is called on the elements, so the mount is all this has to wait for: the DOCUMENT is what
111
111
  * this surface renders, and the kit elements inside it settle their own templates one
112
- * `connectedCallback` later without anybody here asking them to (guidelines §1.1, "await the
113
- * element").
112
+ * `connectedCallback` later without anybody here asking them to (studio-ui-guidelines.md §1.1,
113
+ * "await the element").
114
114
  */
115
115
  export function mountProblemsSurface(
116
116
  container: HTMLElement,