@jxsuite/studio 5.3.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 (389) hide show
  1. package/data/css-meta.json +28 -27
  2. package/dist/chunks/{cf-account-picker-nwnwdm6p.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-4rzvmp0m.js → content-source-jt7rbcbc.js} +22 -22
  6. package/dist/chunks/{convert-to-repeater-jxsv62v7.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-2mrptyek.js → extension-sections-r73an5s6.js} +30 -29
  10. package/dist/chunks/{file-ops-knfqshrm.js → file-ops-3xan8mnj.js} +21 -21
  11. package/dist/chunks/{files-y6fr4he9.js → files-egsb0ry8.js} +28 -28
  12. package/dist/chunks/{format-host-1k4qrcqd.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-2rkrsjva.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-a7b87n2c.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-scpw01h8.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/layers-panel-83a16ytx.js +41 -0
  25. package/dist/chunks/{layers-jnvdbqva.js → layers-s6mc01ry.js} +3 -3
  26. package/dist/chunks/{media-picker-f66nav16.js → media-picker-nhn6rv4w.js} +11 -11
  27. package/dist/chunks/{menu-1dfhry4s.js → menu-8j4qxjrp.js} +4 -4
  28. package/dist/chunks/{monaco-binding-sw6en4dw.js → monaco-binding-e8d9wzyk.js} +3 -3
  29. package/dist/chunks/{monaco-buffer-pykwbm92.js → monaco-buffer-jaq1t9zj.js} +2 -2
  30. package/dist/chunks/{monaco-setup-8vbyqnhr.css → monaco-setup-ey9cjcm3.css} +954 -137
  31. package/dist/chunks/{monaco-setup-km6abc6q.js → monaco-setup-gsjdysze.js} +6 -6
  32. package/dist/chunks/{platform-ts9cg1a4.js → platform-fnchmhy7.js} +5 -3
  33. package/dist/chunks/publish-panel-ak6hxfma.js +27 -0
  34. package/dist/chunks/quick-search-c63mkt3b.js +47 -0
  35. package/dist/chunks/{references-h69xp9zz.js → references-f7bdv3z5.js} +3 -3
  36. package/dist/chunks/right-panel-t5n8wttg.js +45 -0
  37. package/dist/chunks/{studio-ze46gzjh.js → studio-01269reb.js} +7 -7
  38. package/dist/chunks/{studio-rnyf3f8e.js → studio-0a4gncx0.js} +3 -3
  39. package/dist/chunks/{studio-e1f24eff.js → studio-0d4p4wxj.js} +6778 -2993
  40. package/dist/chunks/{studio-4wbb9ct0.js → studio-1tejxvba.js} +3006 -1855
  41. package/dist/chunks/{studio-d1n2bykn.js → studio-3nprwbd9.js} +117 -25
  42. package/dist/chunks/{studio-4c041r8y.js → studio-40z39dme.js} +3 -3
  43. package/dist/chunks/{studio-151w0xnh.js → studio-482eeazk.js} +20 -20
  44. package/dist/chunks/{studio-cgprcdxn.js → studio-4998spet.js} +10 -9
  45. package/dist/chunks/{studio-nq5yf5mp.js → studio-557bmn0x.js} +2 -2
  46. package/dist/chunks/{studio-rtskkm43.js → studio-5w26wza5.js} +3 -3
  47. package/dist/chunks/{studio-6nzaktvy.js → studio-6pwn9j8c.js} +6 -3
  48. package/dist/chunks/{studio-wnsyffg1.js → studio-6vg0x5fz.js} +3 -2
  49. package/dist/chunks/{studio-vn5hske5.js → studio-7d3c1m59.js} +12 -5
  50. package/dist/chunks/{studio-6gryj0sg.js → studio-9vsvz7w7.js} +6 -6
  51. package/dist/chunks/{studio-50wfwy44.js → studio-9wm0xzpf.js} +19 -19
  52. package/dist/chunks/{studio-0j7r7s9g.js → studio-ag3z6shb.js} +10 -4
  53. package/dist/chunks/studio-aj9drheq.js +177 -0
  54. package/dist/chunks/{studio-xajk70w0.js → studio-apv9x70c.js} +189 -130
  55. package/dist/chunks/{studio-c04nzbby.js → studio-b9q3znz8.js} +2 -2
  56. package/dist/chunks/{studio-nfx354t1.js → studio-bh47w0cy.js} +9 -10
  57. package/dist/chunks/{studio-gk2twyh4.js → studio-dgdm6vvt.js} +264 -52
  58. package/dist/chunks/{studio-gtfq1dkz.js → studio-dwdcr2e8.js} +4 -4
  59. package/dist/chunks/{studio-nqgawfks.js → studio-fbcyz234.js} +146 -139
  60. package/dist/chunks/{studio-27q131j3.js → studio-fqpkpq1t.js} +7 -4
  61. package/dist/chunks/{studio-c0qgc3tn.js → studio-fy320dfc.js} +62 -68
  62. package/dist/chunks/{studio-zjjde71a.js → studio-gjj4bbfx.js} +2 -2
  63. package/dist/chunks/{studio-g33v4fe9.js → studio-jfhxy8h3.js} +7 -7
  64. package/dist/chunks/{studio-ab87phj1.js → studio-kwewmhhq.js} +4 -4
  65. package/dist/chunks/{studio-7rrb1esn.js → studio-m58xn8at.js} +25 -24
  66. package/dist/chunks/{studio-fzjx96t2.js → studio-mfkh1q8d.js} +17 -17
  67. package/dist/chunks/{studio-drg8qj9k.js → studio-mrh0a92f.js} +17 -17
  68. package/dist/chunks/{studio-jt27ta6x.js → studio-mt79tn56.js} +3 -3
  69. package/dist/chunks/{studio-b66rsh78.js → studio-ne593z1j.js} +38 -31
  70. package/dist/chunks/{studio-h4nvnjvz.js → studio-ptfcxkz5.js} +418 -232
  71. package/dist/chunks/{studio-dd1qqkry.js → studio-qxye31h7.js} +7 -7
  72. package/dist/chunks/{studio-ye9drbk8.js → studio-rav5bpmp.js} +73 -52
  73. package/dist/chunks/{studio-6kvgrkrp.js → studio-rwmmbrth.js} +6 -6
  74. package/dist/chunks/{studio-b7xacrwe.js → studio-sceg8ws0.js} +8 -8
  75. package/dist/chunks/{studio-msc1ee1m.js → studio-sjas5b3a.js} +19 -13
  76. package/dist/chunks/{studio-a65w20ex.js → studio-vd67b66d.js} +3 -3
  77. package/dist/chunks/{studio-7144epdr.js → studio-w475cbf9.js} +10 -10
  78. package/dist/chunks/{studio-4f3psrk1.js → studio-w7gpcvfj.js} +9 -9
  79. package/dist/chunks/{studio-nsgw7dbk.js → studio-xrbfdxgk.js} +7 -7
  80. package/dist/chunks/{studio-ke09tn9k.js → studio-y49b6mjv.js} +35 -35
  81. package/dist/chunks/{studio-j0w60gft.js → studio-ygvr9e4q.js} +10 -10
  82. package/dist/chunks/{studio-z2smx5ce.js → studio-yxmmjy2a.js} +9 -6
  83. package/dist/chunks/{tsMode-jy4m86rv.js → tsMode-ay4c78ne.js} +4 -4
  84. package/dist/chunks/{tsMode-hnxxb73h.css → tsMode-c72wyz27.css} +954 -137
  85. package/dist/chunks/{workspace-np10mayv.js → workspace-b9k2frks.js} +5 -5
  86. package/dist/chunks/{ws-client-ny4zc51r.js → ws-client-erze4czt.js} +356 -20
  87. package/dist/codicon.ttf +0 -0
  88. package/dist/iframe-entry.js +18 -16
  89. package/dist/studio.css +956 -139
  90. package/dist/studio.js +1453 -830
  91. package/dist/workers/editor.worker.js +196 -107
  92. package/dist/workers/json.worker.js +196 -107
  93. package/dist/workers/ts.worker.js +196 -107
  94. package/package.json +15 -14
  95. package/src/about/about-modal.ts +4 -3
  96. package/src/browse/library-commands.ts +15 -13
  97. package/src/browse/library-pane.ts +2 -2
  98. package/src/canvas/canvas-render.ts +97 -83
  99. package/src/canvas/canvas-surface.ts +2 -2
  100. package/src/canvas/canvas-utils.ts +42 -32
  101. package/src/canvas/diff-toolbar.ts +21 -2
  102. package/src/canvas/diff-view.ts +30 -6
  103. package/src/canvas/iframe-entry.ts +2 -2
  104. package/src/canvas/iframe-host.ts +5 -5
  105. package/src/canvas/iframe-interaction.ts +7 -6
  106. package/src/canvas/iframe-overlay.ts +1 -1
  107. package/src/canvas/iframe-protocol.ts +6 -5
  108. package/src/canvas/iframe-render.ts +3 -3
  109. package/src/canvas/popover-state.ts +1 -1
  110. package/src/canvas/stage-scrollbar.ts +112 -0
  111. package/src/canvas/surface-registry.ts +9 -2
  112. package/src/collab/collab-commands.ts +8 -6
  113. package/src/collab/collab-session.ts +4 -4
  114. package/src/collab/collab-state.ts +4 -4
  115. package/src/collab/presence-chips.ts +3 -3
  116. package/src/commands/app-commands.ts +7 -7
  117. package/src/commands/budget.ts +17 -16
  118. package/src/commands/command-args.ts +10 -9
  119. package/src/commands/context.ts +20 -10
  120. package/src/commands/defaults.ts +30 -29
  121. package/src/commands/levels.ts +8 -6
  122. package/src/commands/live-context.ts +12 -10
  123. package/src/commands/reference.ts +5 -5
  124. package/src/commands/registry.ts +2 -2
  125. package/src/content/draft-state.ts +9 -8
  126. package/src/content/entry-commands.ts +16 -14
  127. package/src/content/entry-editor.ts +2 -2
  128. package/src/content/entry-fields.ts +1 -1
  129. package/src/editor/context-menu.ts +4 -4
  130. package/src/editor/convert-to-component.ts +6 -5
  131. package/src/editor/inline-edit.ts +3 -3
  132. package/src/editor/shortcuts.ts +88 -20
  133. package/src/editor/slash-menu.ts +11 -10
  134. package/src/files/elements.ts +4 -5
  135. package/src/files/file-ops.ts +1 -1
  136. package/src/files/files.ts +21 -17
  137. package/src/files/serialize-document.ts +1 -1
  138. package/src/format/convert-file.ts +5 -5
  139. package/src/github/github-auth-status.ts +107 -0
  140. package/src/github/github-auth.ts +18 -82
  141. package/src/github/github-publish.ts +7 -6
  142. package/src/grid/cell-editors.ts +8 -7
  143. package/src/grid/grid-layout.ts +1 -1
  144. package/src/grid/grid-open.ts +6 -5
  145. package/src/grid/grid-panel.ts +13 -12
  146. package/src/grid/redirects-grid.ts +14 -11
  147. package/src/grid/redirects.ts +10 -5
  148. package/src/grid/sources/content-source.ts +10 -9
  149. package/src/hosting/document.ts +28 -1
  150. package/src/hosting/stage.ts +15 -4
  151. package/src/i18n/i18n-commands.ts +9 -7
  152. package/src/new-project/location-fields.ts +16 -3
  153. package/src/new-project/new-project-modal.ts +23 -7
  154. package/src/page-params.ts +6 -6
  155. package/src/panels/activity-panel.ts +11 -10
  156. package/src/panels/ai-chat/chat-view.ts +27 -14
  157. package/src/panels/ai-chat/composer.ts +10 -3
  158. package/src/panels/ai-panel.ts +87 -29
  159. package/src/panels/block-action-bar.ts +59 -33
  160. package/src/panels/bottom-dock.ts +22 -22
  161. package/src/panels/data-explorer.ts +9 -9
  162. package/src/panels/data-grid.ts +1 -1
  163. package/src/panels/editors.ts +8 -8
  164. package/src/panels/elements-panel.ts +7 -8
  165. package/src/panels/empty-state.ts +1 -1
  166. package/src/panels/events-panel.ts +13 -12
  167. package/src/panels/formula-workspace.ts +8 -5
  168. package/src/panels/frontmatter-fields.ts +4 -1
  169. package/src/panels/frontmatter-panel.ts +18 -18
  170. package/src/panels/git-panel.ts +19 -13
  171. package/src/panels/head-panel.ts +9 -10
  172. package/src/panels/i18n-panel.ts +6 -4
  173. package/src/panels/imports-panel.ts +1 -1
  174. package/src/panels/jump-bar.ts +20 -18
  175. package/src/panels/layers-panel.ts +19 -17
  176. package/src/panels/left-panel.ts +3 -3
  177. package/src/panels/navigator-panels.ts +8 -8
  178. package/src/panels/overlays.ts +1 -1
  179. package/src/panels/pane-context.ts +56 -28
  180. package/src/panels/pane-grid.ts +9 -8
  181. package/src/panels/panel-registry.ts +47 -19
  182. package/src/panels/problems-panel.ts +11 -12
  183. package/src/panels/properties-panel.ts +21 -20
  184. package/src/panels/provenance.ts +3 -3
  185. package/src/panels/quick-search.ts +15 -11
  186. package/src/panels/right-panel.ts +4 -3
  187. package/src/panels/seo-modal.ts +5 -4
  188. package/src/panels/settings-menu.ts +9 -9
  189. package/src/panels/settings-pane.ts +3 -3
  190. package/src/panels/signals-panel.ts +16 -9
  191. package/src/panels/statement-editor.ts +12 -9
  192. package/src/panels/style-panel.ts +45 -41
  193. package/src/panels/stylebook-panel.ts +0 -1
  194. package/src/panels/tab-strip.ts +26 -23
  195. package/src/platform-errors.ts +2 -2
  196. package/src/platform.ts +44 -4
  197. package/src/platforms/cloud.ts +11 -1
  198. package/src/platforms/default-platform.ts +141 -4
  199. package/src/platforms/devserver.ts +23 -3
  200. package/src/publish/deploy-checklist.ts +11 -10
  201. package/src/publish/publish-commands.ts +9 -8
  202. package/src/services/a11y-report.ts +1 -1
  203. package/src/services/ai-ask.ts +39 -16
  204. package/src/services/ai-command-tools.ts +28 -14
  205. package/src/services/ai-import-tools.ts +43 -29
  206. package/src/services/ai-project-tools.ts +20 -38
  207. package/src/services/ai-settings.ts +55 -2
  208. package/src/services/ai-tools.ts +69 -58
  209. package/src/services/ai-write-report.ts +4 -4
  210. package/src/services/ai-writes.ts +74 -55
  211. package/src/services/automation.ts +12 -12
  212. package/src/services/clock.ts +2 -1
  213. package/src/services/connection.ts +2 -2
  214. package/src/services/context-manager.ts +69 -6
  215. package/src/services/directory-picker.ts +93 -27
  216. package/src/services/document-assistant.ts +86 -17
  217. package/src/services/gated-registry.ts +4 -3
  218. package/src/services/idle.ts +5 -4
  219. package/src/services/live-surfaces.ts +2 -1
  220. package/src/services/notify.ts +9 -7
  221. package/src/services/popover-report.ts +3 -3
  222. package/src/services/preview-eval.ts +1 -1
  223. package/src/services/project-adoption.ts +34 -1
  224. package/src/services/project-path.ts +53 -0
  225. package/src/services/settings/kernel.ts +13 -2
  226. package/src/services/tool-executor.ts +135 -30
  227. package/src/services/tool-outcomes.ts +143 -0
  228. package/src/settings/contexts-section.ts +8 -8
  229. package/src/settings/contributed-section.ts +6 -6
  230. package/src/settings/css-vars-editor.ts +6 -5
  231. package/src/settings/extension-commands.ts +19 -18
  232. package/src/settings/extension-sections.ts +7 -7
  233. package/src/settings/extensions-section.ts +3 -3
  234. package/src/settings/general-settings.ts +21 -18
  235. package/src/settings/preferences-accounts.ts +3 -3
  236. package/src/settings/preferences-dialog.ts +9 -8
  237. package/src/settings/preferences-sections.ts +1 -1
  238. package/src/settings/project-sections.ts +2 -2
  239. package/src/settings/section-registry.ts +7 -6
  240. package/src/settings/settings-document.ts +41 -43
  241. package/src/shell/tree.ts +29 -0
  242. package/src/shell.ts +63 -55
  243. package/src/site-context.ts +1 -1
  244. package/src/store.ts +2 -2
  245. package/src/studio.ts +46 -28
  246. package/src/style/live-preview.ts +8 -8
  247. package/src/style/project-styles.ts +8 -9
  248. package/src/style/token-ref.ts +2 -2
  249. package/src/surfaces/about.json +6 -2
  250. package/src/surfaces/add-repo.json +2 -2
  251. package/src/surfaces/add-repo.ts +2 -2
  252. package/src/surfaces/ai-chat.json +14 -6
  253. package/src/surfaces/ai-chat.ts +4 -2
  254. package/src/surfaces/ai-credentials-form.json +53 -49
  255. package/src/surfaces/ai-credentials-form.ts +18 -4
  256. package/src/surfaces/ai-managed-connect.json +4 -4
  257. package/src/surfaces/block-action-bar.json +4 -4
  258. package/src/surfaces/block-action-bar.ts +3 -3
  259. package/src/surfaces/boot-failure.json +228 -0
  260. package/src/surfaces/boot-failure.ts +156 -0
  261. package/src/surfaces/bottom-dock.json +1 -1
  262. package/src/surfaces/canvas-stage.json +9 -40
  263. package/src/surfaces/canvas-stage.ts +9 -9
  264. package/src/surfaces/cf-account-picker.json +11 -8
  265. package/src/surfaces/commandbar.ts +11 -10
  266. package/src/surfaces/convert-repeater.ts +3 -2
  267. package/src/surfaces/dialog.json +7 -1
  268. package/src/surfaces/dialog.ts +2 -2
  269. package/src/surfaces/doc-header.json +6 -13
  270. package/src/surfaces/doc-header.ts +4 -5
  271. package/src/surfaces/entry-editor.json +1 -1
  272. package/src/surfaces/entry-editor.ts +2 -1
  273. package/src/surfaces/expression-editor.json +5 -5
  274. package/src/surfaces/files-panel.json +4 -3
  275. package/src/surfaces/files-panel.ts +1 -1
  276. package/src/surfaces/formula-palette.json +2 -2
  277. package/src/surfaces/formula-palette.ts +1 -1
  278. package/src/surfaces/git-panel.json +167 -109
  279. package/src/surfaces/git-panel.ts +2 -2
  280. package/src/surfaces/github-auth.json +2 -1
  281. package/src/surfaces/github-publish.ts +3 -3
  282. package/src/surfaces/grid-open.json +1 -1
  283. package/src/surfaces/grid-panel.json +2 -2
  284. package/src/surfaces/grid-views.json +1 -1
  285. package/src/surfaces/inspector-dock.json +2 -2
  286. package/src/surfaces/jump-bar.json +1 -1
  287. package/src/surfaces/jump-bar.ts +1 -1
  288. package/src/surfaces/library-pane.ts +2 -1
  289. package/src/surfaces/logic-panel.json +7 -7
  290. package/src/surfaces/logic-panel.ts +6 -4
  291. package/src/surfaces/logic-workspace.json +2 -2
  292. package/src/surfaces/logic-workspace.ts +2 -2
  293. package/src/surfaces/media-browser.ts +3 -3
  294. package/src/surfaces/media-pane.ts +2 -1
  295. package/src/surfaces/menu.ts +5 -5
  296. package/src/surfaces/new-project.json +1 -1
  297. package/src/surfaces/pane-context.json +86 -57
  298. package/src/surfaces/pane-context.ts +2 -1
  299. package/src/surfaces/pane-grid.json +3 -3
  300. package/src/surfaces/panel-activity.json +2 -1
  301. package/src/surfaces/panel-deploy-checklist.json +1 -1
  302. package/src/surfaces/panel-elements.ts +2 -1
  303. package/src/surfaces/panel-i18n.ts +2 -1
  304. package/src/surfaces/panel-outline.json +1 -1
  305. package/src/surfaces/panel-outline.ts +4 -3
  306. package/src/surfaces/panel-page.json +2 -2
  307. package/src/surfaces/panel-page.ts +4 -1
  308. package/src/surfaces/panel-problems.json +4 -3
  309. package/src/surfaces/panel-problems.ts +2 -2
  310. package/src/surfaces/panel-signals.json +23 -8
  311. package/src/surfaces/panel-signals.ts +5 -1
  312. package/src/surfaces/panel-stylebook-layers.json +1 -1
  313. package/src/surfaces/panel-stylebook-layers.ts +2 -2
  314. package/src/surfaces/preferences.json +21 -8
  315. package/src/surfaces/preferences.ts +9 -1
  316. package/src/surfaces/properties-panel.json +4 -4
  317. package/src/surfaces/properties-panel.ts +2 -2
  318. package/src/surfaces/publish.json +1 -1
  319. package/src/surfaces/publish.ts +2 -1
  320. package/src/surfaces/push-plan.json +4 -3
  321. package/src/surfaces/rail.json +2 -2
  322. package/src/surfaces/rail.ts +10 -4
  323. package/src/surfaces/reference-field.json +1 -1
  324. package/src/surfaces/schema-form.json +2 -2
  325. package/src/surfaces/schema-form.ts +1 -1
  326. package/src/surfaces/seo.json +1 -1
  327. package/src/surfaces/seo.ts +2 -2
  328. package/src/surfaces/settings-contributed.ts +2 -1
  329. package/src/surfaces/settings-css-vars.json +4 -4
  330. package/src/surfaces/settings-deploy.json +4 -4
  331. package/src/surfaces/settings-deploy.ts +2 -1
  332. package/src/surfaces/settings-extensions.json +6 -6
  333. package/src/surfaces/settings-extensions.ts +6 -2
  334. package/src/surfaces/settings-locales.json +4 -4
  335. package/src/surfaces/settings-overview.ts +2 -1
  336. package/src/surfaces/settings-pane.ts +3 -2
  337. package/src/surfaces/settings-rawjson.ts +1 -1
  338. package/src/surfaces/slash-menu.ts +4 -4
  339. package/src/surfaces/statements.json +3 -3
  340. package/src/surfaces/statusbar.ts +23 -23
  341. package/src/surfaces/style-panel.json +9 -5
  342. package/src/surfaces/style-panel.ts +3 -3
  343. package/src/surfaces/tab-strip.json +2 -2
  344. package/src/surfaces/target-line.json +1 -1
  345. package/src/surfaces/target-line.ts +12 -10
  346. package/src/surfaces/welcome.json +7 -2
  347. package/src/tabs/doc-op-apply.ts +5 -5
  348. package/src/tabs/patch-ops.ts +3 -3
  349. package/src/tabs/project-config.ts +10 -10
  350. package/src/tabs/selection.ts +1 -1
  351. package/src/tabs/tab.ts +13 -14
  352. package/src/tabs/transact.ts +18 -24
  353. package/src/types.ts +27 -3
  354. package/src/ui/ai-credentials-form.ts +74 -16
  355. package/src/ui/ai-managed-connect.ts +68 -19
  356. package/src/ui/color-selector.ts +1 -1
  357. package/src/ui/expression-editor.ts +3 -3
  358. package/src/ui/form-controls.ts +6 -5
  359. package/src/ui/formula-catalog.ts +4 -4
  360. package/src/ui/formula-chips.ts +2 -2
  361. package/src/ui/layers.ts +20 -18
  362. package/src/ui/panel-resize.ts +5 -5
  363. package/src/ui/popover-surface.ts +2 -2
  364. package/src/ui/progress-modal.ts +3 -3
  365. package/src/ui/regions.ts +14 -9
  366. package/src/ui/schema-form.ts +10 -9
  367. package/src/ui/timing.ts +9 -7
  368. package/src/ui/value-source.ts +4 -4
  369. package/src/ui/virtual-window.ts +1 -1
  370. package/src/utils/base64.ts +20 -1
  371. package/src/utils/canvas-media.ts +1 -1
  372. package/src/utils/studio-utils.ts +0 -31
  373. package/src/view.ts +4 -3
  374. package/src/workspace/pane-derive.ts +14 -13
  375. package/src/workspace/session.ts +7 -6
  376. package/src/workspace/workspace.ts +49 -39
  377. package/styles/canvas.css +1 -27
  378. package/styles/inspector.css +4 -3
  379. package/styles/overlays.css +1 -1
  380. package/styles/tokens.css +17 -1
  381. package/styles/tokens.json +6 -1
  382. package/dist/chunks/entry-commands-1wnsqn5d.js +0 -42
  383. package/dist/chunks/layers-panel-73gfkcga.js +0 -41
  384. package/dist/chunks/publish-panel-z1zd2da1.js +0 -27
  385. package/dist/chunks/quick-search-zdv7h8ht.js +0 -47
  386. package/dist/chunks/right-panel-889vbnm5.js +0 -45
  387. package/dist/chunks/studio-727xh0e3.js +0 -76
  388. package/src/files/json-layout.ts +0 -474
  389. package/src/services/ai-turn-signal.ts +0 -70
@@ -20,8 +20,8 @@
20
20
  "fontSize": "var(--jx-text-md)",
21
21
  "color": "var(--fg-dim)"
22
22
  },
23
- "& [part=\"error\"]": {
24
- "$description": "A write that failed, said under the section title rather than pinned to a control: settings save on change, so a silent rejection would read as \"my edit just vanished\", and the whole file failed rather than one field.",
23
+ "& [part=\"section-error\"]": {
24
+ "$description": "A write that failed, said under the section title rather than pinned to a control: settings save on change, so a silent rejection would read as \"my edit just vanished\", and the whole file failed rather than one field. It is `section-error` rather than `error` because the tag field's refusal IS the kit's own `[part=\"error\"]` sentence, in this same light-DOM tree: a rule on that name gave the tag field's refusal this margin and size, and reached the two pickers' empty regions as well.",
25
25
  "margin": "6px 0 0",
26
26
  "fontSize": "var(--jx-text-md)",
27
27
  "color": "var(--danger)"
@@ -95,7 +95,7 @@
95
95
  {
96
96
  "tagName": "div",
97
97
  "attributes": {
98
- "part": "error-slot",
98
+ "part": "section-error-slot",
99
99
  "role": "none"
100
100
  },
101
101
  "$switch": {
@@ -105,7 +105,7 @@
105
105
  "true": {
106
106
  "tagName": "p",
107
107
  "attributes": {
108
- "part": "error",
108
+ "part": "section-error",
109
109
  "role": "alert"
110
110
  },
111
111
  "textContent": "${state.error}"
@@ -188,7 +188,8 @@ export function mountOverviewSurface(
188
188
  let disposed = false;
189
189
  /* Nothing is called on the element, so the mount is all this has to wait for: the DOCUMENT is
190
190
  what this surface renders, and the kit elements inside it settle their own templates one
191
- `connectedCallback` later without anybody here asking them to (§1.1, "await the element"). */
191
+ `connectedCallback` later without anybody here asking them to (studio-ui-guidelines.md §1.1,
192
+ "await the element"). */
192
193
  void mountSurface("settings-overview", scope, container).then((surface) => {
193
194
  if (disposed) {
194
195
  surface.dispose();
@@ -8,8 +8,9 @@
8
8
  * **One island, and the sections are why.** A settings section is handed a container and renders
9
9
  * into it — some of them still with lit, some by mounting a document of their own — so the body
10
10
  * cannot be part of this document's subtree. It draws an empty `[part="body"]`, announces it
11
- * through `onNodeCreated` as it is created, and the flow renders into it (studio-ui-guidelines.md
12
- * §9.4). Nothing here queries for it by a selector this package also renders.
11
+ * through `onNodeCreated` as it is created, and the flow renders into it: the island seam of
12
+ * studio-ui-guidelines.md §9.4. Nothing here queries for it by a selector this package also
13
+ * renders.
13
14
  *
14
15
  * @docs studio/projects/settings
15
16
  */
@@ -77,7 +77,7 @@ export function mountRawJsonSurface(
77
77
  let disposed = false;
78
78
  /* Nothing is called on the element, so the mount is all this has to wait for: the DOCUMENT is
79
79
  what this surface renders, and `jx-button` settles its own template one `connectedCallback`
80
- later without anybody here asking it to (§1.1, "await the element"). */
80
+ later without anybody here asking it to (studio-ui-guidelines.md §1.1, "await the element"). */
81
81
  void mountSurface("settings-rawjson", scope, container).then((surface) => {
82
82
  if (disposed) {
83
83
  surface.dispose();
@@ -6,10 +6,10 @@
6
6
  * which commands are on offer, what the filter matches, which row is active and what a pick does.
7
7
  *
8
8
  * **It is a listbox, and it is deliberately not `surfaces/menu.json`.** Every other Studio menu is
9
- * that surface, and the rule is that a second list of actions is a defect (§12.5) — but the two
10
- * differ on the one thing a menu cannot give up. `jx-menu` owns the keyboard: showing it moves the
11
- * caret onto its first row, which is the whole point of a roving-focus menu. This panel filters a
12
- * caret that is somewhere else — inside the canvas's `contenteditable`, and usually inside the
9
+ * that surface, and studio-ui-guidelines.md §12.5 makes a second list of actions a defect — but the
10
+ * two differ on the one thing a menu cannot give up. `jx-menu` owns the keyboard: showing it moves
11
+ * the caret onto its first row, which is the whole point of a roving-focus menu. This panel filters
12
+ * a caret that is somewhere else — inside the canvas's `contenteditable`, and usually inside the
13
13
  * canvas IFRAME — and every character typed after the `/` has to keep landing there, so the panel
14
14
  * that takes the keyboard is the panel that ends the interaction it exists to serve. What is left
15
15
  * once focus is off the table is a combobox popup: `role="listbox"`, an active row marked with
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://jxsuite.com/schema/v1",
3
3
  "$id": "StudioStatements",
4
- "$description": "The statement editor (spec §20): a Function entry's `body: JxStatement[]` edited as STRUCTURE rather than as text. The rows arrive FLAT. A statement tree nests to any depth — an `if` holds two lanes, a `$switch` holds one per case plus a default, and either may hold another of both — while a document's one repeater is `$prototype: \"Array\"` over a list, so `panels/statement-editor.ts` walks the tree once and hands over rows that already carry their own indent; recursion is a property of the walk, exactly as it is for the Data panel's value tree. Four kinds of row come out of that walk: a statement CARD (its header, and the fields that statement is made of), a LANE header naming a branch, the ADD control that ends every lane, and an ACTION that grows the statement itself (`+ Add else`, `+ Add case`). Two hosts draw this — the Navigator's State panel and the Inspector's Logic tab — and neither is named here: the region is stamped on the host, because a shared control cannot know where it is. An operand is an ISLAND: the document renders `[part=\"control-host\"]` and nothing inside it, and the flow fills it with the expression editor (studio-ui-guidelines.md §9.4).",
4
+ "$description": "The statement editor (spec.md §20): a Function entry's `body: JxStatement[]` edited as STRUCTURE rather than as text. The rows arrive FLAT. A statement tree nests to any depth — an `if` holds two lanes, a `$switch` holds one per case plus a default, and either may hold another of both — while a document's one repeater is `$prototype: \"Array\"` over a list, so `panels/statement-editor.ts` walks the tree once and hands over rows that already carry their own indent; recursion is a property of the walk, exactly as it is for the Data panel's value tree. Four kinds of row come out of that walk: a statement CARD (its header, and the fields that statement is made of), a LANE header naming a branch, the ADD control that ends every lane, and an ACTION that grows the statement itself (`+ Add else`, `+ Add case`). Two hosts draw this — the Navigator's State panel and the Inspector's Logic tab — and neither is named here: the region is stamped on the host, because a shared control cannot know where it is. An operand is an ISLAND: the document renders `[part=\"control-host\"]` and nothing inside it, and the flow fills it with the expression editor (studio-ui-guidelines.md §9.4).",
5
5
  "tagName": "div",
6
6
  "attributes": {
7
7
  "part": "statements"
@@ -218,7 +218,7 @@
218
218
  "$ref": "$map/item/key"
219
219
  },
220
220
  "map": {
221
- "$description": "One operand of the statement. Every field is `span` — the Inspector is 280px and the guidelines' standard row is vertically stacked (§4.1) — and every field carries `data-prop`, which is what `inspector/field:<prop>` addresses. The key is `<row>::<prop>`, self-contained because this `$map` shadows the row's own `$map.item`.",
221
+ "$description": "One operand of the statement. Every field is `span` — the Inspector is 280px and the standard row is vertically stacked (studio-ui-guidelines.md §4.1) — and every field carries `data-prop`, which is what `inspector/field:<prop>` addresses. The key is `<row>::<prop>`, self-contained because this `$map` shadows the row's own `$map.item`.",
222
222
  "tagName": "jx-field",
223
223
  "attributes": {
224
224
  "part": "field",
@@ -500,7 +500,7 @@
500
500
  ]
501
501
  },
502
502
  "add": {
503
- "$description": "The end of every lane. It opens the kit's menu rather than being a picker of its own: a select that has to snap back to its placeholder after each pick is a control fighting the runtime's skip-an-equal-write, and §12.5 asks for one list of actions rather than a second.",
503
+ "$description": "The end of every lane. It opens the kit's menu rather than being a picker of its own: a select that has to snap back to its placeholder after each pick is a control fighting the runtime's skip-an-equal-write, and studio-ui-guidelines.md §12.5 asks for one list of actions rather than a second.",
504
504
  "tagName": "div",
505
505
  "attributes": {
506
506
  "part": "add",
@@ -1,24 +1,24 @@
1
1
  /// <reference lib="dom" />
2
2
  /**
3
- * ⑫ The status bar — ambient state, in scope order, and nothing else.
3
+ * The status bar — ambient state, in scope order, and nothing else.
4
4
  *
5
5
  * What this replaces: a bar built by `innerHTML` string concatenation with a three-character
6
6
  * escaper, carrying whatever the last of 78 `statusMessage()` calls had said, for three seconds.
7
7
  * Transient messages have left entirely for the toast host (`ui/layers.ts`) and the Problems list
8
8
  * (`services/notify.ts`); what remains here is state that is TRUE for as long as it is shown.
9
9
  *
10
- * **Three fixed fields, in the shell's own left-to-right level order** (plan §3.2 ⑫), so the bar
11
- * restates the containment model on every glance:
10
+ * **Three fixed fields, in the shell's own left-to-right level order** (§16.2), so the bar restates
11
+ * the containment model on every glance:
12
12
  *
13
13
  * ```text
14
14
  * PROJECT ‖ DOCUMENT ‖ SELECTION
15
15
  * name · branch ↑n↓n · problems ‖ path · view · save state ‖ count · style rule
16
16
  * ```
17
17
  *
18
- * The SELECTION field held an ancestor breadcrumb until region ⑥ landed. The trail is an ADDRESS,
19
- * not ambient state, and it now lives once — in the jump bar (`panels/jump-bar.ts`), which merged
20
- * it with the pane context bar's document-stack chain. What is left here is the count and the
21
- * Stylebook's rule, neither of which is a path.
18
+ * The SELECTION field held an ancestor breadcrumb until the jump bar landed. The trail is an
19
+ * ADDRESS, not ambient state, and it now lives once — in the jump bar (`panels/jump-bar.ts`), which
20
+ * merged it with the pane context bar's document-stack chain. What is left here is the count and
21
+ * the Stylebook's rule, neither of which is a path.
22
22
  *
23
23
  * `statusbar/project`, `statusbar/document` and `statusbar/selection` are three placements the
24
24
  * level × placement matrix already declares, each admitting exactly one level — so the bar's
@@ -31,12 +31,12 @@
31
31
  *
32
32
  * **Every interactive item is a command.** There are no click handlers in this file: an item names
33
33
  * a command id, and renders as a button only when the registry has that command and its `when`
34
- * holds. That is what lets an item that has no command yet — the peers count, whose `Collaborate:`
35
- * family lands with P4.8 — sit in the template today and start rendering the day it is registered,
36
- * with no edit here. The three readouts that are NOT buttons are marked: the view name (its control
37
- * is the pane context bar ⑦; a second mode picker in 24px would be the chrome duplication §2
38
- * principle 9 exists to prevent), the save wording once a document IS saved, and the stylebook
39
- * selector.
34
+ * holds. That is what let an item with no command yet — the peers count, before the `Collaborate:`
35
+ * family was registered — sit in the template and start rendering the day its command arrived, with
36
+ * no edit here. The three readouts that are NOT buttons are marked: the view name (its control is
37
+ * the pane context bar; a second mode picker in 24px would be the chrome duplication
38
+ * studio-ui-guidelines.md §12.2's budget exists to prevent), the save wording once a document IS
39
+ * saved, and the stylebook selector.
40
40
  *
41
41
  * The bar is the `statusbar` surface (`surfaces/statusbar.json`): this module is the projection —
42
42
  * three fields of items, each item a button with a command or a readout without — and the surface
@@ -186,7 +186,7 @@ function projectField(
186
186
  return { id, items: live, region };
187
187
  }
188
188
 
189
- // ─── ⑫a PROJECT ──────────────────────────────────────────────────────────────
189
+ // ─── PROJECT ─────────────────────────────────────────────────────────────────
190
190
 
191
191
  /** `↑2↓1`, or "" when the branch is level with its upstream. */
192
192
  export function aheadBehindLabel(ahead: number, behind: number): string {
@@ -203,15 +203,15 @@ function projectField_(registry: CommandRegistry | null): ProjectedField | null
203
203
  project
204
204
  ? { command: "project.openRecent", label: project.name }
205
205
  : { command: "project.open", label: "No project" },
206
- /* WHICH branch, when there is one — and deliberately no "not tracked" twin, though plan §12 P1
207
- workstream 9's "repo state becomes a persistent status-bar field" reads like a request for
208
- one. An untracked project already states itself in this field, one item along:
206
+ /* WHICH branch, when there is one — and deliberately no "not tracked" twin, though the shell
207
+ redesign's "repo state becomes a persistent status-bar field" reads like a request for one.
208
+ An untracked project already states itself in this field, one item along:
209
209
  `deployStatusItem()`'s first link is `repo`, whose label is "Track this project with git" and
210
210
  whose command is `git.init`. A second item beside it would carry no fact the first does not
211
211
  — "Not tracked" and "Track this project with git" answer the same question with the same verb
212
- — and adjacent duplicate chrome is what §2 principle 9 forbids. `tests/statusbar.test.ts`
213
- pins the pairing from both ends, so deleting the checklist's repo step fails there rather
214
- than quietly taking the state off the bar. */
212
+ — and adjacent duplicate chrome is what the chrome budget (studio-ui-guidelines.md §12.2)
213
+ forbids. `tests/statusbar.test.ts` pins the pairing from both ends, so deleting the
214
+ checklist's repo step fails there rather than quietly taking the state off the bar. */
215
215
  status?.isRepo === true && status.branch
216
216
  ? {
217
217
  command: "panel.focus.git",
@@ -248,7 +248,7 @@ function projectField_(registry: CommandRegistry | null): ProjectedField | null
248
248
  ]);
249
249
  }
250
250
 
251
- // ─── ⑫b DOCUMENT ─────────────────────────────────────────────────────────────
251
+ // ─── DOCUMENT ────────────────────────────────────────────────────────────────
252
252
 
253
253
  /**
254
254
  * What the pane is showing, in the words the pane context bar uses.
@@ -307,13 +307,13 @@ function documentField(registry: CommandRegistry | null): ProjectedField | null
307
307
  ]);
308
308
  }
309
309
 
310
- // ─── ⑫c SELECTION ────────────────────────────────────────────────────────────
310
+ // ─── SELECTION ───────────────────────────────────────────────────────────────
311
311
 
312
312
  /**
313
313
  * What is selected — the COUNT, and nothing that is an address.
314
314
  *
315
315
  * This field used to carry a clickable ancestor trail, one `selection.set` per crumb. That trail
316
- * has moved whole to the jump bar (⑥, `panels/jump-bar.ts`), which is region ⑥'s entire reason to
316
+ * has moved whole to the jump bar (`panels/jump-bar.ts`), which is the jump bar's entire reason to
317
317
  * exist: Studio had two half-breadcrumbs — that one, and the pane context bar's document-stack
318
318
  * chain — and neither ever rendered the whole address. Leaving a copy here would have made three.
319
319
  *
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://jxsuite.com/schema/v1",
3
3
  "$id": "StudioStylePanel",
4
- "$description": "The Inspector's Style tab: the Target Line's host, one filter, then the CSS property accordion — every row saying where its value came from (§6.2), every section heading tallying what is set inside it. Nothing here knows what CSS is. `panels/style-panel.ts` resolves the compound coordinate (selection, breakpoint, scheme layer, nested selector), reads css-meta, decides which of seven controls a property gets, works out its provenance and what a commit writes; this document draws the answer and decides nothing. That split is what lets the tab stop going through `panels/panel-scheduler.ts`: the focus guard existed because a lit repaint of the whole panel could take the field a reader was typing into, and a document is one runtime effect per bound property with an equal write skipped.",
4
+ "$description": "The Inspector's Style tab: the Target Line's host, one filter, then the CSS property accordion — every row saying where its value came from (§6.7), every section heading tallying what is set inside it. Nothing here knows what CSS is. `panels/style-panel.ts` resolves the compound coordinate (selection, breakpoint, scheme layer, nested selector), reads css-meta, decides which of seven controls a property gets, works out its provenance and what a commit writes; this document draws the answer and decides nothing. That split is what lets the tab stop going through `panels/panel-scheduler.ts`: the focus guard existed because a lit repaint of the whole panel could take the field a reader was typing into, and a document is one runtime effect per bound property with an equal write skipped.",
5
5
  "tagName": "div",
6
6
  "attributes": {
7
7
  "part": "panel"
@@ -14,7 +14,7 @@
14
14
  "fontFamily": "var(--jx-font-sans)",
15
15
  "color": "var(--jx-fg)",
16
16
  "& [part=\"empty\"]": {
17
- "$description": "The one empty-state pattern (`panels/empty-state.ts`), drawn here because a document cannot render a lit helper. Its rules are what is kept (§11): one sentence saying what the region is FOR, then the action that fills it.",
17
+ "$description": "The one empty-state pattern (`panels/empty-state.ts`), drawn here because a document cannot render a lit helper. Its rules are what is kept (studio-ui-guidelines.md §11): one sentence saying what the region is FOR, then the action that fills it.",
18
18
  "display": "flex",
19
19
  "flexDirection": "column",
20
20
  "alignItems": "center",
@@ -106,7 +106,7 @@
106
106
  "minInlineSize": "0"
107
107
  },
108
108
  "& [part=\"chip-slot\"] > [part=\"chip\"]": {
109
- "$description": "One vocabulary, five states (§6.2). `default` draws nothing at all — absence IS the ghost — which is why there is no rule for it: the document never makes the node. `set` is the 6px accent disc `.set-dot` has always been; the two that carry information wear their donor's name in a bordered pill, and `mixed` is neutral on purpose because it says nothing about WHERE a value came from, only that the selection disagrees.",
109
+ "$description": "One vocabulary, five states (§6.7). `default` draws nothing at all — absence IS the ghost — which is why there is no rule for it: the document never makes the node. `set` is the 6px accent disc `.set-dot` has always been; the two that carry information wear their donor's name in a bordered pill, and `mixed` is neutral on purpose because it says nothing about WHERE a value came from, only that the selection disagrees.",
110
110
  "display": "inline-flex",
111
111
  "alignItems": "center",
112
112
  "flexShrink": "0",
@@ -190,7 +190,7 @@
190
190
  "background": "var(--jx-handler)"
191
191
  },
192
192
  "& [part=\"source\"]": {
193
- "$description": "The Value Source chip (§6.3): quiet while the value is a literal, accent-tinted the moment it is produced from something else. A CSS declaration has exactly two rungs — `JxStyle` admits no `$ref` — so the picker it opens is two rows, and that is derived from the schema rather than written here.",
193
+ "$description": "The Value Source chip (§6.6): quiet while the value is a literal, accent-tinted the moment it is produced from something else. A CSS declaration has exactly two rungs — `JxStyle` admits no `$ref` — so the picker it opens is two rows, and that is derived from the schema rather than written here.",
194
194
  "flex": "none",
195
195
  "color": "var(--jx-fg-dim)"
196
196
  },
@@ -881,7 +881,7 @@
881
881
  }
882
882
  },
883
883
  "group": {
884
- "$description": "The dual-mode control: a number beside its unit. Type what you mean, or take a unit from the list — and the list is the kit MENU rather than a second popup of this document's own (§12.5), because every row of it is a verb: a unit re-attaches to the number the field holds. A keyword row, whose list commits a value, is the `keywords` case instead — and so is the font row now, because a font is chosen by looking and a menu row cannot draw itself in its own face.",
884
+ "$description": "The dual-mode control: a number beside its unit. Type what you mean, or take a unit from the list — and the list is the kit MENU rather than a second popup of this document's own (studio-ui-guidelines.md §12.5), because every row of it is a verb: a unit re-attaches to the number the field holds. A keyword row, whose list commits a value, is the `keywords` case instead — and so is the font row now, because a font is chosen by looking and a menu row cannot draw itself in its own face.",
885
885
  "tagName": "div",
886
886
  "attributes": {
887
887
  "part": "group"
@@ -1070,7 +1070,11 @@
1070
1070
  },
1071
1071
  "children": [
1072
1072
  {
1073
+ "$description": "The abbreviation, for a value with no glyph, and HIDDEN rather than empty on a button that has one. The kit's `[part=\"label\"]` is `display: contents`, so an empty span is still a flex item in the control, and the control's 4px gap sits between the glyph and nothing: every icon button in the tab drew 26px wide with its glyph pushed 2px off centre, instead of 22px and centred. Hidden, it takes no box, and the button's name and tooltip are the value either way.",
1073
1074
  "tagName": "span",
1075
+ "attributes": {
1076
+ "hidden": "${$map.item.text ? null : ''}"
1077
+ },
1074
1078
  "textContent": "${$map.item.text}"
1075
1079
  }
1076
1080
  ]
@@ -104,9 +104,9 @@ export interface StyleButtonView extends Record<string, unknown> {
104
104
  value: string;
105
105
  /** The accessible name and tooltip. */
106
106
  title: string;
107
- /** A kit glyph name, or the empty string where the kit has none for this value. */
107
+ /** A kit manifest name, css-meta's `$icons` entry verbatim, or `""` where the value has none. */
108
108
  icon: string;
109
- /** The abbreviation drawn when there is no glyph. Empty when there is one. */
109
+ /** The abbreviation drawn when there is no glyph. Empty when there is one, and its span hidden. */
110
110
  text: string;
111
111
  selected: boolean;
112
112
  }
@@ -138,7 +138,7 @@ export interface StyleRowView extends Record<string, unknown> {
138
138
  chipState: string;
139
139
  chipText: string;
140
140
  chipTitle: string;
141
- /** The Value Source chip (§6.3). Absent on a child, a custom pair and a nested rule. */
141
+ /** The Value Source chip (§6.6). Absent on a child, a custom pair and a nested rule. */
142
142
  hasSource: boolean;
143
143
  sourceState: string;
144
144
  sourceLabel: string;
@@ -101,7 +101,7 @@
101
101
  "lineHeight": "1"
102
102
  },
103
103
  "& [part=\"pill\"]": {
104
- "$description": "`.entry-pill` — the draft pill (§7.6), in `jx-tab`'s status slot. It is ON THE CHIP and not only inside the entry editor because the mistake it prevents, publishing something you believed was private, is made while glancing at a row of tabs. \"Published\" is deliberately as visible as \"Draft\": a state you can only see one half of is a state you cannot check. The two Spectrum colours it used to name are `--jx-signal` against `--jx-bg`, which flips with the theme where a fixed yellow and a fixed black did not.",
104
+ "$description": "`.entry-pill` — the draft pill (site-architecture.md §7.6), in `jx-tab`'s status slot. It is ON THE CHIP and not only inside the entry editor because the mistake it prevents, publishing something you believed was private, is made while glancing at a row of tabs. \"Published\" is deliberately as visible as \"Draft\": a state you can only see one half of is a state you cannot check. The two Spectrum colours it used to name are `--jx-signal` against `--jx-bg`, which flips with the theme where a fixed yellow and a fixed black did not.",
105
105
  "padding": "0 5px",
106
106
  "borderRadius": "var(--radius)",
107
107
  "background": "var(--bg)",
@@ -334,7 +334,7 @@
334
334
  "textContent": "${$map.item.pill}"
335
335
  },
336
336
  {
337
- "$description": "The pin, in the actions slot. `title` is the whole accessible name (§10): the glyph is hidden, so a matching `aria-label` would announce it twice. `tabindex` follows the tab's own selectedness, exactly as the close button's does — the strip is ONE stop in the tab order, and a control inside every chip that took the platform's default would make fifteen.",
337
+ "$description": "The pin, in the actions slot. `title` is the whole accessible name (studio-ui-guidelines.md §10): the glyph is hidden, so a matching `aria-label` would announce it twice. `tabindex` follows the tab's own selectedness, exactly as the close button's does — the strip is ONE stop in the tab order, and a control inside every chip that took the platform's default would make fifteen.",
338
338
  "tagName": "button",
339
339
  "attributes": {
340
340
  "slot": "actions",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://jxsuite.com/schema/v1",
3
3
  "$id": "StudioTargetLine",
4
- "$description": "The Style tab's edit target, as one sentence (plan §6.1): element · breakpoint · scheme variant · selector, then the chip that states how wide the blast radius is. Every word of the sentence is a control, because a sentence you cannot act on is a caption and the panel already had one of those. The breakpoint and scheme segments ROUTE to where those axes are defined rather than offering a third list to pick from — the Style tab owns the selector axis and nothing else — so the selector is the one segment with a menu, and that menu is the kit's. The project-scope warning band is not decoration: entering Stylebook converts every edit from `this element` to `every element of this tag`, and the band states that before the first keystroke.",
4
+ "$description": "The Style tab's edit target, as one sentence (§6.2): element · breakpoint · scheme variant · selector, then the chip that states how wide the blast radius is. Every word of the sentence is a control, because a sentence you cannot act on is a caption and the panel already had one of those. The breakpoint and scheme segments ROUTE to where those axes are defined rather than offering a third list to pick from — the Style tab owns the selector axis and nothing else — so the selector is the one segment with a menu, and that menu is the kit's. The project-scope warning band is not decoration: entering Stylebook converts every edit from `this element` to `every element of this tag`, and the band states that before the first keystroke.",
5
5
  "tagName": "div",
6
6
  "attributes": {
7
7
  "part": "target"
@@ -1,9 +1,9 @@
1
1
  /// <reference lib="dom" />
2
2
  /**
3
- * The Target Line — the Style tab's compound edit target, as one sentence (plan §6.1).
3
+ * The Target Line — the Style tab's compound edit target, as one sentence (§6.2).
4
4
  *
5
5
  * ```text
6
- * ⌖ h1 · @md · :hover · dark variant [ all <h1> in this document ]
6
+ * ⌖ h1 · Base · dark variant · :hover [ all <h1> in this document ]
7
7
  * ```
8
8
  *
9
9
  * `style-panel.ts` has always computed this tuple exactly: it is the per-field key
@@ -18,10 +18,10 @@
18
18
  * 1. **Every segment is a control.** A sentence you cannot act on is a caption, and the panel already
19
19
  * had one of those.
20
20
  * 2. **The Style tab does not own the breakpoint or the scheme.** Those axes are SELECTED on the pane
21
- * context bar (region ⑦) and DEFINED in Project Settings › Contexts — §2 principle 5. The
22
- * breakpoint and scheme segments therefore state the resolved value and route to the definition
23
- * site; they do not offer a third list to pick from. The selector segment is the one axis this
24
- * tab owns, so it is the one segment with a menu.
21
+ * context bar and DEFINED in Project Settings › Contexts (§6.2). The breakpoint and scheme
22
+ * segments therefore state the resolved value and route to the definition site; they do not
23
+ * offer a third list to pick from. The selector segment is the one axis this tab owns, so it is
24
+ * the one segment with a menu.
25
25
  * 3. **The scope chip is what makes Stylebook safe.** Entering Stylebook silently discards the element
26
26
  * selection and converts every subsequent edit from "this element" to "every element of this
27
27
  * tag" — with one line of text, after the fact, as the only signal. The chip states the blast
@@ -35,8 +35,9 @@
35
35
  * panel renders an EMPTY host for it and hands this module the model; the document owns the markup,
36
36
  * the ARIA and every value in the style, and this module owns the decisions — what each word says,
37
37
  * what pressing one does, and what the selector menu offers. That menu is the KIT's
38
- * (`surfaces/menu.ts`), because a list of choices is what that surface already is (§12.5), which is
39
- * also how the roving caret, typeahead and Escape arrive here without a line of keyboard code.
38
+ * (`surfaces/menu.ts`), because a list of choices is what that surface already is
39
+ * (studio-ui-guidelines.md §12.5), which is also how the roving caret, typeahead and Escape arrive
40
+ * here without a line of keyboard code.
40
41
  *
41
42
  * @docs studio/design/states-and-selectors
42
43
  */
@@ -78,7 +79,7 @@ export interface TargetSelector {
78
79
  /** Which options the element already declares — marked in the menu. */
79
80
  declared: Set<string>;
80
81
  onSelect: (selector: string | null) => void;
81
- /** Opens the Add Nested Selector dialog (`showPromptDialog`, ui-guidelines §8.7). */
82
+ /** Opens the Add Nested Selector dialog (`showPromptDialog`, studio-ui-guidelines.md §8.7). */
82
83
  onAddCustom: () => void;
83
84
  }
84
85
 
@@ -277,7 +278,8 @@ const ADD_SELECTOR_VALUE = "__add_custom__";
277
278
  *
278
279
  * The one command in this file, and it addresses a CONTROL rather than a state — which is why it
279
280
  * refuses out loud instead of doing nothing: a manifest that hands a CSS selector to a synthetic
280
- * mouse would silently photograph the wrong panel (§13).
281
+ * mouse would silently photograph the wrong panel (the shot contract,
282
+ * `scripts/screenshots/README.md`).
281
283
  *
282
284
  * @throws {RangeError} When the Style tab is not rendered.
283
285
  */
@@ -47,10 +47,15 @@
47
47
  "letterSpacing": "0.3px"
48
48
  },
49
49
  "& [part=\"section-header\"]": {
50
+ "$description": "`center`, not `baseline`: `Clear all` is a small kit button, and a small kit control is layout-contained so its outset hit area adds nothing to a scrolling ancestor's overflow, which leaves it with no baseline to export. A baseline row synthesised one from the button's bottom edge, which stood the header 33px tall with the title 10px under the button's label. The gap under the header is the HEADER's, because centring aligns MARGIN boxes: while the h2 kept its own 8px block-end margin its margin box was 26px, exactly the header's height, so `center` had nothing to move and left the h2 flush at the top with the button centred 3.6px below its baseline — a fix that measured right and still looked wrong. With the margin moved out, the two boxes are the only things in the line and they centre on each other.",
50
51
  "display": "flex",
51
- "alignItems": "baseline",
52
+ "alignItems": "center",
52
53
  "justifyContent": "space-between",
53
- "gap": "var(--jx-space-4)"
54
+ "gap": "var(--jx-space-4)",
55
+ "marginBottom": "var(--jx-space-3)"
56
+ },
57
+ "& [part=\"section-header\"] [part=\"section-title\"]": {
58
+ "marginBlockEnd": "0"
54
59
  },
55
60
  "& [part=\"actions\"]": {
56
61
  "display": "flex",
@@ -4,10 +4,10 @@
4
4
  * from live editing: history replay in the parent ({@link file://./transact.ts}) and the iframe
5
5
  * canvas's non-reactive shadow doc (the patch source-of-truth across the cross-origin bridge).
6
6
  *
7
- * The implementation is the canonical one in `@jxsuite/collab/ops` (yjs-free, so the slim
8
- * canvas-iframe bundle imports it without dragging yjs in); this module re-exports it so both sides
9
- * of the frame boundary — and the collab bridge — replay ops through one code path.
7
+ * The implementation is the canonical one in `@jxsuite/schema/doc-ops` (it imports types only, so
8
+ * the slim canvas-iframe bundle takes it without dragging yjs in); this module re-exports it so
9
+ * both sides of the frame boundary and the collab bridge replay ops through one code path.
10
10
  */
11
11
 
12
- export { applyDocOpToDoc, childArray, cloneValue } from "@jxsuite/collab/ops";
13
- export type { JxDocOp } from "@jxsuite/collab/ops";
12
+ export { applyDocOpToDoc, childArray, cloneValue, inverseOf } from "@jxsuite/schema/doc-ops";
13
+ export type { JxDocOp } from "@jxsuite/schema/doc-ops";
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  // oxlint-disable-next-line unicorn/prefer-export-from -- JxDocOpPair is also used locally (TransactionRecord)
9
- import type { JxDocOpPair } from "@jxsuite/collab/ops";
9
+ import type { JxDocOpPair } from "@jxsuite/schema/doc-ops";
10
10
  import type { JxPath } from "../state";
11
11
  import type { Tab } from "./tab.js";
12
12
 
@@ -34,10 +34,10 @@ export type JxPatchOp =
34
34
  * Value-carrying document mutation, replayable in either direction. Mutators record a
35
35
  * forward/inverse pair per change; history applies them for surgical undo/redo and for
36
36
  * materializing states from checkpoints — without whole-document snapshots per edit. The definition
37
- * is canonical in `@jxsuite/collab/ops` (the collab bridge mirrors the same ops into a shared
37
+ * is canonical in `@jxsuite/schema/doc-ops` (the collab bridge mirrors the same ops into a shared
38
38
  * Y.Doc); re-exported here so studio call sites keep their import path.
39
39
  */
40
- export type { JxDocOp } from "@jxsuite/collab/ops";
40
+ export type { JxDocOp } from "@jxsuite/schema/doc-ops";
41
41
  export type { JxDocOpPair };
42
42
 
43
43
  /**
@@ -33,14 +33,14 @@
33
33
  * from the other side: a config that reached disk without passing through here (the assistant's
34
34
  * `write_file`) is put INTO the document rather than left beside it as a rival.
35
35
  *
36
- * **One serialisation.** {@link serializeProjectConfig} is `files/json-layout.ts`'s serializer over
37
- * the layout the file was read in — byte-for-byte what `files/serialize-document.ts`'s native-JSON
38
- * branch writes, so a ⌘S on the open tab and a settings edit produce the same file. The predecessor
39
- * had `null, 2` in `site-context.ts` and `"\t"` in both `settings/contributed-section.ts` and
40
- * `settings/defs-editor.ts`, so a settings edit re-indented the entire file — every `project.json`
41
- * in this repository is on disk with two spaces. It was then `JSON.stringify(config, null, 2)`,
42
- * which agreed with the tab's save and disagreed with the formatter: a one-field edit re-laid every
43
- * short array in the file (issue 308).
36
+ * **One serialisation.** {@link serializeProjectConfig} is `@jxsuite/schema/json-layout`'s
37
+ * serializer over the layout the file was read in — byte-for-byte what
38
+ * `files/serialize-document.ts`'s native-JSON branch writes, so a ⌘S on the open tab and a settings
39
+ * edit produce the same file. The predecessor had `null, 2` in `site-context.ts` and `"\t"` in both
40
+ * `settings/contributed-section.ts` and `settings/defs-editor.ts`, so a settings edit re-indented
41
+ * the entire file — every `project.json` in this repository is on disk with two spaces. It was then
42
+ * `JSON.stringify(config, null, 2)`, which agreed with the tab's save and disagreed with the
43
+ * formatter: a one-field edit re-laid every short array in the file (issue 308).
44
44
  *
45
45
  * **A no-op edit writes nothing.** A form that re-commits the value it already holds — and every
46
46
  * one of these surfaces has such a path — used to rewrite the whole file. A commit now compares the
@@ -67,8 +67,8 @@ import { requireProjectState, setProjectState } from "../state";
67
67
  import { setWorkspaceProject, workspace } from "../workspace/workspace";
68
68
  import { PROJECT_CONFIG_PATH, createTab, disposeTab } from "./tab";
69
69
  import { transactDoc } from "./transact";
70
- import { deriveJsonLayout, parseJsonDocument, serializeJson } from "../files/json-layout";
71
- import type { JsonLayout } from "../files/json-layout";
70
+ import { deriveJsonLayout, parseJsonDocument, serializeJson } from "@jxsuite/schema/json-layout";
71
+ import type { JsonLayout } from "@jxsuite/schema/json-layout";
72
72
 
73
73
  import type { Tab } from "./tab";
74
74
  import type { ProjectConfig } from "@jxsuite/schema/types";
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The selection SET — one vocabulary for `session.selection`, now that it is `JxPath[]` (§6.5).
2
+ * The selection SET — one vocabulary for `session.selection`, now that it is `JxPath[]` (§6.7).
3
3
  *
4
4
  * ## The invariant this module exists to hold
5
5
  *
package/src/tabs/tab.ts CHANGED
@@ -8,7 +8,7 @@ import { editorKindForMode } from "../commands/context";
8
8
  import type { EditorKind } from "../commands/context";
9
9
  import type { JxMutableNode } from "@jxsuite/schema/types";
10
10
  import type { JxDocOp, JxFmOp } from "./patch-ops";
11
- import type { JsonLayout } from "../files/json-layout";
11
+ import type { JsonLayout } from "@jxsuite/schema/json-layout";
12
12
 
13
13
  /**
14
14
  * The project's configuration file, project-relative.
@@ -70,13 +70,13 @@ export interface TabUi {
70
70
  featureToggles: Record<string, boolean>;
71
71
  /**
72
72
  * Canvas color-scheme preview: follow the OS ("auto") or force a scheme. Drives the
73
- * data-color-scheme attribute on the canvas iframe root (spec §9.5) and, in the style sidebar,
73
+ * data-color-scheme attribute on the canvas iframe root (spec.md §9.5) and, in the style sidebar,
74
74
  * which scheme layer edits target.
75
75
  */
76
76
  previewColorScheme: "auto" | "light" | "dark";
77
77
  /**
78
- * The locale this pane renders AS — the artboard's `lang` and `dir` (§13.4), never which file is
79
- * open.
78
+ * The locale this pane renders AS — the artboard's `lang` and `dir` (site-architecture.md §13.4),
79
+ * never which file is open.
80
80
  *
81
81
  * Jx has no message catalogue: a translation is a different file in a different directory, so
82
82
  * "show this page in French" is a navigation and belongs to the locale preset. This axis is the
@@ -187,8 +187,8 @@ export interface Tab {
187
187
  handlersSource: string | null;
188
188
  dirty: boolean;
189
189
  /**
190
- * The layout the document's JSON file was written in (`files/json-layout.ts`), or null for a
191
- * document with no JSON source — a format-class file, a new document, a stub.
190
+ * The layout the document's JSON file was written in (`@jxsuite/schema/json-layout`), or null
191
+ * for a document with no JSON source — a format-class file, a new document, a stub.
192
192
  *
193
193
  * On the document record because it is a fact about the FILE the document came from, and it
194
194
  * lives exactly as long as that fact does: every edit leaves it alone (the pointers it is keyed
@@ -201,7 +201,7 @@ export interface Tab {
201
201
  };
202
202
  session: {
203
203
  /**
204
- * The selected document paths, in the order the user built them (§6.5).
204
+ * The selected document paths, in the order the user built them (§6.7).
205
205
  *
206
206
  * `[]` is "nothing selected" — there is no `null` state, because "no selection" and "a
207
207
  * selection of nothing" were never two different things. `selection[0]` is the anchor a
@@ -419,11 +419,9 @@ function inferDocumentMode(documentPath: string | null | undefined, sourceFormat
419
419
  }
420
420
 
421
421
  // ─── Editor kinds ─────────────────────────────────────────────────────────────
422
- // §4.2's first axis. `canvasMode` conflates two orthogonal questions — WHICH EDITOR is open, and
423
- // (for the Canvas editor only) WHICH VIEW of it. The pane context bar labels them separately, and
424
- // The pane model needs the first one on its own: the second pane is capped to non-Canvas kinds
425
- // Until P8's `canvas-patcher` fan-out lands, because a second live `@jxsuite/runtime` host is the
426
- // Expensive part.
422
+ // The pane context bar's Editor axis (docs/studio/interface/tabs.md). `canvasMode` conflates two
423
+ // Orthogonal questions — WHICH EDITOR is open, and (for the Canvas editor only) WHICH VIEW of it.
424
+ // The pane context bar labels them separately, so the first is answered here on its own.
427
425
  //
428
426
  // The mode → kind map itself is `commands/context.ts`'s `editorKindForMode`. It was duplicated
429
427
  // Here, and the copy that drifted is what let a settings document resolve into the canvas key
@@ -442,7 +440,8 @@ export function editorKindOf(tab: Tab): EditorKind {
442
440
 
443
441
  /**
444
442
  * Every editor kind this document supports, in the format's own mode order and deduplicated — the
445
- * dropdown's entries, so it can never contain a permanently dead one (§4.2).
443
+ * dropdown's entries, so it can never contain a permanently dead one
444
+ * (docs/studio/interface/tabs.md, "The pane context bar").
446
445
  *
447
446
  * `preview` contributes nothing: it is a Canvas VIEW, and the kind it would add is already there.
448
447
  *
@@ -482,7 +481,7 @@ export function modeForEditorKind(tab: Tab, kind: EditorKind): string | undefine
482
481
  // ─── There is no sub-document stack ───────────────────────────────────────────
483
482
  // A tab held one, and it was scaffolding for a navigation model the tab model replaced. `studio.md`
484
483
  // §14.3 justified it for exactly two cases and both moved: a function body opens in the Bottom
485
- // Dock's Logic tab (P8), and a `$map` template is a subtree of its parent document, selected in
484
+ // Dock's Logic tab (§16.3), and a `$map` template is a subtree of its parent document, selected in
486
485
  // Place on the canvas rather than loaded as a document of its own. Everything with a file of its
487
486
  // Own — a component, a layout — opens a REAL TAB with an `openedFrom` relationship (§14.1–2):
488
487
  // {@link TabOrigin}, above, which nothing pops and nothing restores from.