@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
@@ -15,7 +15,7 @@
15
15
  "fontSize": "var(--jx-text-md)",
16
16
  "color": "var(--fg)",
17
17
  "& [part=\"empty\"]": {
18
- "$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 (§11): one sentence saying what the region is for, then the action that fills it.",
18
+ "$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 action that fills it.",
19
19
  "display": "flex",
20
20
  "flex": "1",
21
21
  "flexDirection": "column",
@@ -37,18 +37,30 @@
37
37
  "gap": "var(--jx-space-2)"
38
38
  },
39
39
  "& [part=\"sync-bar\"]": {
40
+ "$description": "A wrapping row (studio-ui-guidelines.md §4.6), and it has exactly two items: `sync-head` (Refresh and the status, which never split) and what answers the status (the Fetch/Pull/Push group, or Create GitHub repository with no remote). It was a single line whose only shrinkable item was the status text, so a narrow Navigator never moved a button: it broke \"3 behind / Last updated 09:04 AM\" into a column one word wide (25px at the 160px floor) and painted \"(no\" under Create GitHub repository at the default 240px. Now the second item drops to a line of its own when the two no longer fit, and where that happens is decided by the status text's own width (a count, a locale's clock), never by a breakpoint. The row gap is the smaller step so a wrapped bar reads as one block.",
40
41
  "display": "flex",
42
+ "flexWrap": "wrap",
41
43
  "alignItems": "center",
42
- "gap": "var(--jx-space-4)",
44
+ "gap": "var(--jx-space-3) var(--jx-space-4)",
43
45
  "padding": "var(--jx-space-4)",
44
46
  "borderBottom": "1px solid var(--border)"
45
47
  },
46
- "& [part=\"sync-bar\"][data-remote=\"none\"]": {
48
+ "& [part=\"sync-bar\"][data-remote=\"none\"], & [part=\"sync-bar\"][data-remote=\"none\"] > [part=\"sync-head\"]": {
49
+ "$description": "The no-remote bar keeps its tighter 8px between Refresh and the sentence, and on both axes: the head carries that gap now that Refresh and the text sit in it rather than in the bar.",
47
50
  "gap": "var(--jx-space-3)"
48
51
  },
52
+ "& [part=\"sync-head\"]": {
53
+ "$description": "Refresh and the status, as one item of the bar, so wrapping never leaves the icon alone on a line above its text. `flex: 1 1 auto` makes its basis the status text's own width, which is the wrap threshold; with `min-width: 0` it can then shrink below that when it is alone on a line, and the status wraps as a sentence rather than word by word.",
54
+ "display": "flex",
55
+ "flex": "1 1 auto",
56
+ "alignItems": "center",
57
+ "gap": "var(--jx-space-4)",
58
+ "minWidth": "0"
59
+ },
49
60
  "& [part=\"sync-text\"]": {
61
+ "$description": "`1 1 auto` rather than `1`: the head's basis decides whether the verbs fit beside it, and it should be the status text's own width. An auto basis says that directly; the `0%` basis of `flex: 1` only reaches the same answer through how an engine treats a percentage while it measures.",
50
62
  "display": "flex",
51
- "flex": "1",
63
+ "flex": "1 1 auto",
52
64
  "flexDirection": "column",
53
65
  "gap": "1px",
54
66
  "minWidth": "0"
@@ -63,17 +75,28 @@
63
75
  "color": "var(--fg-dim)"
64
76
  },
65
77
  "& [part=\"sync-actions\"]": {
78
+ "$description": "The verbs never shrink: they are what moves. `margin-left: auto` keeps them at the inline end whether they share the status's line or sit on one of their own.",
66
79
  "display": "flex",
67
80
  "flex": "none",
68
81
  "marginLeft": "auto"
69
82
  },
70
83
  "& [part=\"branch-row\"]": {
84
+ "$description": "A wrapping row (studio-ui-guidelines.md §4.6) of two items, `branch-head` and the picker. It was a single line with the picker capped at 40% of it, so a long branch name was cut twice (\"chor…\" beside \"cho…\") and a narrow Navigator word-stacked \"Active / branch\". Now the picker drops below the name when the two no longer fit, at a width the name decides.",
71
85
  "display": "flex",
86
+ "flexWrap": "wrap",
72
87
  "alignItems": "center",
73
- "gap": "var(--jx-space-4)",
88
+ "gap": "var(--jx-space-3) var(--jx-space-4)",
74
89
  "padding": "10px var(--jx-space-4)",
75
90
  "borderBottom": "1px solid var(--border)"
76
91
  },
92
+ "& [part=\"branch-head\"]": {
93
+ "$description": "The branch icon and the name, as one item so the icon is never alone on a line. The 999:1 grow ratio against the picker gives nearly all spare room to the name while the two share a line, so the picker stays the width of the branch it shows; once the picker wraps, it is alone and takes the whole line. A third item in this row needs its own flex decision.",
94
+ "display": "flex",
95
+ "flex": "999 1 auto",
96
+ "alignItems": "center",
97
+ "gap": "var(--jx-space-4)",
98
+ "minWidth": "0"
99
+ },
77
100
  "& [part=\"branch-icon\"]": {
78
101
  "$description": "The hand-drawn 18px branch SVG this panel carried is the kit's `git-branch` glyph — the same key `PanelRecord.icon` already names for this panel's rail button, so the two drawings cannot drift.",
79
102
  "flex": "none",
@@ -82,7 +105,7 @@
82
105
  },
83
106
  "& [part=\"branch-text\"]": {
84
107
  "display": "flex",
85
- "flex": "1",
108
+ "flex": "1 1 auto",
86
109
  "flexDirection": "column",
87
110
  "gap": "1px",
88
111
  "minWidth": "0"
@@ -100,8 +123,17 @@
100
123
  "whiteSpace": "nowrap"
101
124
  },
102
125
  "& [part=\"branch-picker\"]": {
103
- "flex": "none",
104
- "maxWidth": "40%"
126
+ "$description": "Sized by the branch it shows while it shares the name's line, and the full width of the row once it wraps below it, which is where a long branch name finally reads whole. `min-width: 0` is the kit's own default, restated because studio-ui-guidelines.md §4.6 asks it of every flex child: when even a line of its own is narrower than the name, the picker shrinks and the kit's preview ellipsizes.",
127
+ "flex": "1 1 auto",
128
+ "minWidth": "0"
129
+ },
130
+ "& [part=\"tab\"]": {
131
+ "$description": "The sub-tabs may shrink below their labels. A flex item's automatic minimum is its content, and a tab's label is nowrap, so \"Local Changes (3)\" and \"History\" held 179px against the 159px the Navigator has at its 160px floor and scrolled the whole panel sideways; the kit's label ellipsis could never engage. `inspector-dock.json` makes the same call for its tabs. It is a surface decision and not a kit default because the document tab strip deliberately scrolls instead.",
132
+ "minWidth": "0"
133
+ },
134
+ "& [part=\"create-repository\"] > [part=\"control\"], & [part=\"init\"] > [part=\"control\"], & [part=\"clone\"] > [part=\"control\"], & [part=\"commit-button\"] > [part=\"control\"]": {
135
+ "$description": "The panel's labelled buttons wrap their words at the Navigator's floor instead of overflowing it. The kit's control is nowrap, which is right for a toolbar and made each label a floor of its own: \"Create GitHub repository\" held 165px in a 135px sync bar, \"Clone Git Repository\" and \"Initialize Repository\" held 141px and 135px in the empty state's 127px, and \"Commit and sync\" beside its menu had about a pixel to spare in the commit form's 135px. Nothing changes where the label fits, because a nowrap label and a wrapping one have the same max-content width. This reaches into the kit's `control` part as `commandbar.json` does for its primary button.",
136
+ "whiteSpace": "normal"
105
137
  },
106
138
  "& [part=\"commit\"]": {
107
139
  "display": "flex",
@@ -270,7 +302,8 @@
270
302
  "fontSize": "var(--jx-text-sm)",
271
303
  "textAlign": "center"
272
304
  },
273
- "& [part=\"error\"]": {
305
+ "& [part=\"failure\"]": {
306
+ "$description": "The panel's own refusal banner. It is `failure` rather than `error` because the branch picker and the commit field each draw a permanent, empty `[part=\"error\"]` of their own inside this same light-DOM tree: under that name this padding, rule and wash drew a 16×13 box over both fields' top-left corners that took the click, and dressed either field's real refusal sentence as a banner.",
274
307
  "margin": "0",
275
308
  "padding": "6px var(--jx-space-3)",
276
309
  "borderBottom": "1px solid var(--border)",
@@ -279,7 +312,7 @@
279
312
  "fontSize": "var(--jx-text-sm)"
280
313
  },
281
314
  "@(forced-colors: active)": {
282
- "& [part=\"error\"]": {
315
+ "& [part=\"failure\"]": {
283
316
  "$description": "The wash behind the banner collapses into the page when every author colour is replaced, so the border is what is left to mark it.",
284
317
  "border": "1px solid CanvasText",
285
318
  "color": "CanvasText"
@@ -510,80 +543,89 @@
510
543
  "data-remote": "yes"
511
544
  },
512
545
  "children": [
513
- {
514
- "tagName": "jx-action-button",
515
- "attributes": {
516
- "part": "refresh",
517
- "data-action": "refresh"
518
- },
519
- "$props": {
520
- "icon": "arrows-clockwise",
521
- "size": "sm",
522
- "quiet": true,
523
- "label": "Refresh",
524
- "hint": "Refresh",
525
- "disabled": {
526
- "$ref": "#/state/busy"
527
- }
528
- },
529
- "onclick": {
530
- "$prototype": "Function",
531
- "body": [
532
- {
533
- "operator": "call",
534
- "target": {
535
- "$ref": "#/state/refresh"
536
- },
537
- "value": []
538
- }
539
- ]
540
- }
541
- },
542
546
  {
543
547
  "tagName": "div",
544
548
  "attributes": {
545
- "part": "sync-text"
549
+ "part": "sync-head"
546
550
  },
547
551
  "children": [
548
552
  {
549
- "tagName": "span",
553
+ "tagName": "jx-action-button",
550
554
  "attributes": {
551
- "part": "sync-label"
555
+ "part": "refresh",
556
+ "data-action": "refresh"
552
557
  },
553
- "textContent": "${state.syncLabel}"
558
+ "$props": {
559
+ "icon": "arrows-clockwise",
560
+ "size": "sm",
561
+ "quiet": true,
562
+ "label": "Refresh",
563
+ "hint": "Refresh",
564
+ "disabled": {
565
+ "$ref": "#/state/busy"
566
+ }
567
+ },
568
+ "onclick": {
569
+ "$prototype": "Function",
570
+ "body": [
571
+ {
572
+ "operator": "call",
573
+ "target": {
574
+ "$ref": "#/state/refresh"
575
+ },
576
+ "value": []
577
+ }
578
+ ]
579
+ }
554
580
  },
555
581
  {
556
- "tagName": "span",
582
+ "tagName": "div",
557
583
  "attributes": {
558
- "part": "updated-slot",
559
- "role": "none"
584
+ "part": "sync-text"
560
585
  },
561
- "style": {
562
- "display": "contents"
563
- },
564
- "$switch": {
565
- "$ref": "#/state/hasLastUpdated"
566
- },
567
- "cases": {
568
- "true": {
586
+ "children": [
587
+ {
569
588
  "tagName": "span",
570
589
  "attributes": {
571
- "part": "sync-time"
590
+ "part": "sync-label"
572
591
  },
573
- "textContent": "${state.lastUpdated}"
592
+ "textContent": "${state.syncLabel}"
593
+ },
594
+ {
595
+ "tagName": "span",
596
+ "attributes": {
597
+ "part": "updated-slot",
598
+ "role": "none"
599
+ },
600
+ "style": {
601
+ "display": "contents"
602
+ },
603
+ "$switch": {
604
+ "$ref": "#/state/hasLastUpdated"
605
+ },
606
+ "cases": {
607
+ "true": {
608
+ "tagName": "span",
609
+ "attributes": {
610
+ "part": "sync-time"
611
+ },
612
+ "textContent": "${state.lastUpdated}"
613
+ }
614
+ }
574
615
  }
575
- }
616
+ ]
576
617
  }
577
618
  ]
578
619
  },
579
620
  {
621
+ "$description": "Three quiet tools, so NOT compact. A compact group draws every member's frame and fill whatever its quiet says, so the `quiet: true` each verb below writes would have been silently framed into a segmented control; Spectrum's group here was quiet and never compact, which is what compact=false and the 2px gap between the verbs restore.",
580
622
  "tagName": "jx-action-group",
581
623
  "attributes": {
582
624
  "part": "sync-actions"
583
625
  },
584
626
  "$props": {
585
627
  "label": "Remote actions",
586
- "compact": true
628
+ "compact": false
587
629
  },
588
630
  "children": [
589
631
  {
@@ -692,47 +734,55 @@
692
734
  "data-remote": "none"
693
735
  },
694
736
  "children": [
695
- {
696
- "tagName": "jx-action-button",
697
- "attributes": {
698
- "part": "refresh",
699
- "data-action": "refresh"
700
- },
701
- "$props": {
702
- "icon": "arrows-clockwise",
703
- "size": "sm",
704
- "quiet": true,
705
- "label": "Refresh",
706
- "hint": "Refresh",
707
- "disabled": {
708
- "$ref": "#/state/busy"
709
- }
710
- },
711
- "onclick": {
712
- "$prototype": "Function",
713
- "body": [
714
- {
715
- "operator": "call",
716
- "target": {
717
- "$ref": "#/state/refresh"
718
- },
719
- "value": []
720
- }
721
- ]
722
- }
723
- },
724
737
  {
725
738
  "tagName": "div",
726
739
  "attributes": {
727
- "part": "sync-text"
740
+ "part": "sync-head"
728
741
  },
729
742
  "children": [
730
743
  {
731
- "tagName": "span",
744
+ "tagName": "jx-action-button",
745
+ "attributes": {
746
+ "part": "refresh",
747
+ "data-action": "refresh"
748
+ },
749
+ "$props": {
750
+ "icon": "arrows-clockwise",
751
+ "size": "sm",
752
+ "quiet": true,
753
+ "label": "Refresh",
754
+ "hint": "Refresh",
755
+ "disabled": {
756
+ "$ref": "#/state/busy"
757
+ }
758
+ },
759
+ "onclick": {
760
+ "$prototype": "Function",
761
+ "body": [
762
+ {
763
+ "operator": "call",
764
+ "target": {
765
+ "$ref": "#/state/refresh"
766
+ },
767
+ "value": []
768
+ }
769
+ ]
770
+ }
771
+ },
772
+ {
773
+ "tagName": "div",
732
774
  "attributes": {
733
- "part": "sync-label"
775
+ "part": "sync-text"
734
776
  },
735
- "textContent": "Local only (no remote)"
777
+ "children": [
778
+ {
779
+ "tagName": "span",
780
+ "attributes": {
781
+ "part": "sync-label"
782
+ },
783
+ "textContent": "Local only (no remote)"
784
+ }
785
+ ]
736
786
  }
737
787
  ]
738
788
  },
@@ -783,34 +833,42 @@
783
833
  "part": "branch-row"
784
834
  },
785
835
  "children": [
786
- {
787
- "tagName": "jx-icon",
788
- "attributes": {
789
- "part": "branch-icon"
790
- },
791
- "$props": {
792
- "name": "git-branch"
793
- }
794
- },
795
836
  {
796
837
  "tagName": "div",
797
838
  "attributes": {
798
- "part": "branch-text"
839
+ "part": "branch-head"
799
840
  },
800
841
  "children": [
801
842
  {
802
- "tagName": "span",
843
+ "tagName": "jx-icon",
803
844
  "attributes": {
804
- "part": "branch-label"
845
+ "part": "branch-icon"
805
846
  },
806
- "textContent": "Active branch"
847
+ "$props": {
848
+ "name": "git-branch"
849
+ }
807
850
  },
808
851
  {
809
- "tagName": "span",
852
+ "tagName": "div",
810
853
  "attributes": {
811
- "part": "branch-name"
854
+ "part": "branch-text"
812
855
  },
813
- "textContent": "${state.branchName}"
856
+ "children": [
857
+ {
858
+ "tagName": "span",
859
+ "attributes": {
860
+ "part": "branch-label"
861
+ },
862
+ "textContent": "Active branch"
863
+ },
864
+ {
865
+ "tagName": "span",
866
+ "attributes": {
867
+ "part": "branch-name"
868
+ },
869
+ "textContent": "${state.branchName}"
870
+ }
871
+ ]
814
872
  }
815
873
  ]
816
874
  },
@@ -1794,7 +1852,7 @@
1794
1852
  {
1795
1853
  "tagName": "div",
1796
1854
  "attributes": {
1797
- "part": "error-slot",
1855
+ "part": "failure-slot",
1798
1856
  "role": "none"
1799
1857
  },
1800
1858
  "style": {
@@ -1807,7 +1865,7 @@
1807
1865
  "true": {
1808
1866
  "tagName": "p",
1809
1867
  "attributes": {
1810
- "part": "error",
1868
+ "part": "failure",
1811
1869
  "role": "alert"
1812
1870
  },
1813
1871
  "textContent": "${state.error}"
@@ -229,8 +229,8 @@ function emptyValues(): GitPanelValues {
229
229
  *
230
230
  * Nothing is called on the elements, so the mount is all this has to wait for: the DOCUMENT is what
231
231
  * this surface renders, and the kit elements inside it settle their own templates one
232
- * `connectedCallback` later without anybody here asking them to (guidelines §1.1, "await the
233
- * element").
232
+ * `connectedCallback` later without anybody here asking them to (studio-ui-guidelines.md §1.1,
233
+ * "await the element").
234
234
  */
235
235
  export function mountGitPanelSurface(
236
236
  container: HTMLElement,
@@ -49,7 +49,8 @@
49
49
  "margin": "0"
50
50
  },
51
51
  "& [part=\"code\"]": {
52
- "$description": "`<code>`, not a styled `<div>`: this is a literal string to be transcribed, and the element that says so is also the one a reader's own stylesheet and a screen reader's character-by-character mode already know about.",
52
+ "$description": "`<code>`, not a styled `<div>`: this is a literal string to be transcribed, and the element that says so is also the one a reader's own stylesheet and a screen reader's character-by-character mode already know about. It is this dialog's message, and the one string in it the reader must carry to another screen, so it opts back in to selection against the root's `user-select: none`. `all` rather than `text`: one click selects the whole code, so a copy never leaves a character behind.",
53
+ "userSelect": "all",
53
54
  "fontFamily": "var(--font-mono)",
54
55
  "fontSize": "24px",
55
56
  "fontWeight": "700",
@@ -12,9 +12,9 @@
12
12
  *
13
13
  * **Each setter writes what the control now holds, first.** Nothing here refuses a value today, but
14
14
  * a binding only writes when the scope CHANGES: an adapter that decided a value without announcing
15
- * the raw one first would leave the field showing text the scope does not have, silently (§9.3, "a
16
- * controlled input is authoritative only while the scope value moves"). The echo is one line per
17
- * setter and it is what makes a later refusal possible at all.
15
+ * the raw one first would leave the field showing text the scope does not have, silently
16
+ * (studio-ui-guidelines.md §9.3, "a controlled input is authoritative only while the scope value
17
+ * moves"). The echo is one line per setter and it is what makes a later refusal possible at all.
18
18
  *
19
19
  * @docs studio/interface
20
20
  */
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://jxsuite.com/schema/v1",
3
3
  "$id": "StudioGridOpen",
4
- "$description": "Every grid-able source a project has, grouped by where it comes from: the project's own pages and content collections first, then each connection's tables. It is the ISLAND of a confirm dialog rather than a dialog of its own — `ui/layers.ts`'s dialog owns the headline, the cancel button, modality and focus, and this document is only the list — because a second answer to \"what is a dialog\" is a defect (§12.5). Group headings are why it is not the kit menu: a menu row can carry a divider above it and cannot carry a name for the run it opens.",
4
+ "$description": "Every grid-able source a project has, grouped by where it comes from: the project's own pages and content collections first, then each connection's tables. It is the ISLAND of a confirm dialog rather than a dialog of its own — `ui/layers.ts`'s dialog owns the headline, the cancel button, modality and focus, and this document is only the list — because a second answer to \"what is a dialog\" is a defect (studio-ui-guidelines.md §12.5). Group headings are why it is not the kit menu: a menu row can carry a divider above it and cannot carry a name for the run it opens.",
5
5
  "tagName": "div",
6
6
  "attributes": {
7
7
  "part": "sources"
@@ -7,7 +7,7 @@
7
7
  "part": "grid"
8
8
  },
9
9
  "style": {
10
- "$description": "The frame's own layout and the engine's theme, and nothing that was a class. The toolbar is a single row that never wraps: the chrome budget (§12.2) caps what may stand in it, and the count is the only thing pinned to the far end.",
10
+ "$description": "The frame's own layout and the engine's theme, and nothing that was a class. The toolbar is a single row that never wraps: the chrome budget (studio-ui-guidelines.md §12.2) caps what may stand in it, and the count is the only thing pinned to the far end.",
11
11
  "display": "flex",
12
12
  "flexDirection": "column",
13
13
  "height": "100%",
@@ -459,7 +459,7 @@
459
459
  "textContent": "${state.viewLabel}"
460
460
  }
461
461
  ],
462
- "$description": "One control for the four facets a saved view is made of, because they are only ever adjusted together (§12.2). Its label is the applied view's name, so the toolbar says what is on screen before the panel is opened."
462
+ "$description": "One control for the four facets a saved view is made of, because they are only ever adjusted together (studio-ui-guidelines.md §12.2). Its label is the applied view's name, so the toolbar says what is on screen before the panel is opened."
463
463
  },
464
464
  {
465
465
  "tagName": "jx-textfield",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://jxsuite.com/schema/v1",
3
3
  "$id": "StudioGridViews",
4
- "$description": "The grid's View panel: the saved views, and the four facets one of them is made of — columns, sort, grouping, and the filter the toolbar box holds. ONE control rather than four, because the chrome budget caps what may stand in a toolbar (§12.2) and these four are only ever adjusted together. There is no Apply button: every edit writes the working layout and applies immediately, so the panel is never showing something the grid is not already doing.",
4
+ "$description": "The grid's View panel: the saved views, and the four facets one of them is made of — columns, sort, grouping, and the filter the toolbar box holds. ONE control rather than four, because the chrome budget caps what may stand in a toolbar (studio-ui-guidelines.md §12.2) and these four are only ever adjusted together. There is no Apply button: every edit writes the working layout and applies immediately, so the panel is never showing something the grid is not already doing.",
5
5
  "tagName": "jx-popover",
6
6
  "attributes": {
7
7
  "part": "views-panel"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://jxsuite.com/schema/v1",
3
3
  "$id": "StudioInspectorDock",
4
- "$description": "⑨ The Inspector dock's own chrome, as a Jx document over the kit: a header naming what the dock is pointed at, a real `tablist` of four tabs, and four `tabpanel`s. It draws no tab BODY — all four are mounted documents of their own (`surfaces/properties-panel.json`, `surfaces/style-panel.json`, `surfaces/logic-panel.json`, and the assistant's) — so each panel carries one empty `[part=\"panel-body\"]` island the adapter announces through `onNodeCreated` (studio-ui-guidelines.md §9.4). The four panels are keyed on the tab id and the id list never changes, so a body host is created ONCE and lives as long as the dock: that is what the old module's hand-built permanent containers were for, and it is now a property of a keyed `$map` rather than a rule someone has to keep. `panels/right-panel.ts` keeps every decision — which tab is selected, per document or detached; what the target's name is; and which of the four seams a host is handed to.",
4
+ "$description": "The Inspector dock's own chrome, as a Jx document over the kit: a header naming what the dock is pointed at, a real `tablist` of four tabs, and four `tabpanel`s. It draws no tab BODY — all four are mounted documents of their own (`surfaces/properties-panel.json`, `surfaces/style-panel.json`, `surfaces/logic-panel.json`, and the assistant's) — so each panel carries one empty `[part=\"panel-body\"]` island the adapter announces through `onNodeCreated` (studio-ui-guidelines.md §9.4). The four panels are keyed on the tab id and the id list never changes, so a body host is created ONCE and lives as long as the dock: that is what the old module's hand-built permanent containers were for, and it is now a property of a keyed `$map` rather than a rule someone has to keep. `panels/right-panel.ts` keeps every decision — which tab is selected, per document or detached; what the target's name is; and which of the four seams a host is handed to.",
5
5
  "tagName": "div",
6
6
  "attributes": {
7
7
  "part": "inspector-dock"
@@ -42,7 +42,7 @@
42
42
  }
43
43
  },
44
44
  "& [part=\"tabs\"]": {
45
- "$description": "Four words in a 280px dock, allowed to compress rather than to become anonymous — which is why the tabs are not icons (§3.2 ⑨). The kit tab's own 220px cap would let one tab push the last off the strip, so each takes an equal quarter.",
45
+ "$description": "Four words in a 280px dock, allowed to compress rather than to become anonymous — which is why the tabs are not icons (§6). The kit tab's own 220px cap would let one tab push the last off the strip, so each takes an equal quarter.",
46
46
  "flex": "0 0 auto",
47
47
  "gap": "0",
48
48
  "fontSize": "var(--jx-text-sm)"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://jxsuite.com/schema/v1",
3
3
  "$id": "StudioJumpBar",
4
- "$description": "⑥ The jump bar: one pane's address, outermost step first, every step a command the adapter has already resolved against the registry. A step is a button when its command can run and a readout when it cannot — an address with a hole in it is a lie about containment, so a step never disappears. A step with more than one place to go carries the chevron that opens its siblings; one alternative is not a choice and draws no control. Nothing here decides what the bar says, which step is where you are, or what a chevron opens.",
4
+ "$description": "The jump bar: one pane's address, outermost step first, every step a command the adapter has already resolved against the registry. A step is a button when its command can run and a readout when it cannot — an address with a hole in it is a lie about containment, so a step never disappears. A step with more than one place to go carries the chevron that opens its siblings; one alternative is not a choice and draws no control. Nothing here decides what the bar says, which step is where you are, or what a chevron opens.",
5
5
  "tagName": "nav",
6
6
  "attributes": {
7
7
  "part": "bar",
@@ -1,6 +1,6 @@
1
1
  /// <reference lib="dom" />
2
2
  /**
3
- * ⑥ The jump bar, as a Jx document over the kit — the mount seam, and nothing else.
3
+ * The jump bar, as a Jx document over the kit — the mount seam, and nothing else.
4
4
  *
5
5
  * `jump-bar.json` is the markup, the ARIA and the style; `panels/jump-bar.ts` is the flow — which
6
6
  * pane this bar is about, what its address is, which of its steps the registry can actually run,
@@ -315,7 +315,8 @@ export function mountLibrarySurface(
315
315
  let disposed = false;
316
316
  /* Nothing is called on an element here, so the mount is all there is to wait for: the two islands
317
317
  announce themselves through `onNodeCreated` as they are created, which is one `connectedCallback`
318
- EARLIER than awaiting the element would be (§1.1, "await the element"). */
318
+ EARLIER than awaiting the element would be (studio-ui-guidelines.md §1.1, "await the
319
+ element"). */
319
320
  const ready = mountSurface("library-pane", scope, host, {
320
321
  onNodeCreated: (element, _path, def, state) => {
321
322
  const part = partOf(def);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://jxsuite.com/schema/v1",
3
3
  "$id": "StudioLogicPanel",
4
- "$description": "The Inspector's **Logic** tab — everything about how the selected element BEHAVES, as a Jx document over the kit. Plan §6.5 re-split the inspector by task rather than by data type: wiring a `$switch`, wiring a repeater to a collection and wiring a click handler are one job, and they were three, split across two tabs because a `$switch` is stored as a property and a click handler as a property-shaped function. So there are four sections here — Repeating list, Condition, Events, and a custom element's outward contract (Observed Attributes · CSS Properties · CSS Parts) — and each of them is a projection. The adapter (`panels/events-panel.ts`) keeps every decision: what the selection is, which rungs a position permits, what a handler currently holds, which elements of a multi-selection disagree about a key, and what a commit writes. Nothing here reads the document, asks the schema a question or knows what a Value Source is. Two islands, both through `onNodeCreated` (studio-ui-guidelines.md §9.4): `[part=\"control-host\"]` receives the expression editor, which is a lit surface of its own, and `[part=\"statements-host\"]` receives the `statements` surface, which is a mounted document of its own. Every bindable row carries `data-prop`, which is what `inspector/field:<prop>` addresses.",
4
+ "$description": "The Inspector's **Logic** tab — everything about how the selected element BEHAVES, as a Jx document over the kit. The Inspector is split by task rather than by data type (§6): wiring a `$switch`, wiring a repeater to a collection and wiring a click handler are one job, and they were three, split across two tabs because a `$switch` is stored as a property and a click handler as a property-shaped function. So there are four sections here — Repeating list, Condition, Events, and a custom element's outward contract (Observed Attributes · CSS Properties · CSS Parts) — and each of them is a projection. The adapter (`panels/events-panel.ts`) keeps every decision: what the selection is, which rungs a position permits, what a handler currently holds, which elements of a multi-selection disagree about a key, and what a commit writes. Nothing here reads the document, asks the schema a question or knows what a Value Source is. Two islands, both through `onNodeCreated` (studio-ui-guidelines.md §9.4): `[part=\"control-host\"]` receives the expression editor, which is a lit surface of its own, and `[part=\"statements-host\"]` receives the `statements` surface, which is a mounted document of its own. Every bindable row carries `data-prop`, which is what `inspector/field:<prop>` addresses.",
5
5
  "tagName": "div",
6
6
  "attributes": {
7
7
  "part": "logic"
@@ -14,7 +14,7 @@
14
14
  "fontSize": "var(--jx-text-md)",
15
15
  "color": "var(--fg)",
16
16
  "& [part=\"empty\"]": {
17
- "$description": "The one empty-state pattern (§11.2), drawn here because a document cannot render a lit helper. It is a copy rather than a move — every panel still lit renders through that helper — and it goes when the last of them converts.",
17
+ "$description": "The one empty-state pattern (studio-ui-guidelines.md §11.2), drawn here because a document cannot render a lit helper. It is a copy rather than a move — every panel still lit renders through that helper — and it goes when the last of them converts.",
18
18
  "display": "flex",
19
19
  "flexDirection": "column",
20
20
  "alignItems": "center",
@@ -272,7 +272,7 @@
272
272
  },
273
273
  "children": [
274
274
  {
275
- "$description": "Repeating list. Filter and Sort are always drawn: they used to hide behind `+ Add filter`, which seeded `{ $ref: \"#/state/\" }` — a binding to the empty pointer, which is not a signal — so the row opened already bound to nothing and the only way to type a literal was to cycle the mode ring twice (§11.4). A repeater has exactly three inputs, and an empty row states that better than a button does.",
275
+ "$description": "Repeating list. Filter and Sort are always drawn: they used to hide behind `+ Add filter`, which seeded `{ $ref: \"#/state/\" }` — a binding to the empty pointer, which is not a signal — so the row opened already bound to nothing and the only way to type a literal was to cycle the mode ring twice (§6.6). A repeater has exactly three inputs, and an empty row states that better than a button does.",
276
276
  "tagName": "div",
277
277
  "attributes": {
278
278
  "part": "repeater-slot",
@@ -330,7 +330,7 @@
330
330
  "$ref": "$map/item/key"
331
331
  },
332
332
  "map": {
333
- "$description": "A bindable value as a first-class field row. Every position it serves is a single-line expression — a collection, a filter, a sort key, a `$switch` — so it draws one widget rather than dispatching over a widget type: the textarea and checkbox arms the lit version carried had no caller in either tab. The set dot clears the position outright and is disabled where the position is mandatory; the source chip opens the rung picker rather than cycling, so any rung the position permits is one action away (§6.3).",
333
+ "$description": "A bindable value as a first-class field row. Every position it serves is a single-line expression — a collection, a filter, a sort key, a `$switch` — so it draws one widget rather than dispatching over a widget type: the textarea and checkbox arms the lit version carried had no caller in either tab. The set dot clears the position outright and is disabled where the position is mandatory; the source chip opens the rung picker rather than cycling, so any rung the position permits is one action away (§6.6).",
334
334
  "tagName": "jx-field",
335
335
  "attributes": {
336
336
  "part": "field",
@@ -634,7 +634,7 @@
634
634
  "$ref": "$map/item/key"
635
635
  },
636
636
  "map": {
637
- "$description": "A bindable value as a first-class field row. Every position it serves is a single-line expression — a collection, a filter, a sort key, a `$switch` — so it draws one widget rather than dispatching over a widget type: the textarea and checkbox arms the lit version carried had no caller in either tab. The set dot clears the position outright and is disabled where the position is mandatory; the source chip opens the rung picker rather than cycling, so any rung the position permits is one action away (§6.3).",
637
+ "$description": "A bindable value as a first-class field row. Every position it serves is a single-line expression — a collection, a filter, a sort key, a `$switch` — so it draws one widget rather than dispatching over a widget type: the textarea and checkbox arms the lit version carried had no caller in either tab. The set dot clears the position outright and is disabled where the position is mandatory; the source chip opens the rung picker rather than cycling, so any rung the position permits is one action away (§6.6).",
638
638
  "tagName": "jx-field",
639
639
  "attributes": {
640
640
  "part": "field",
@@ -1145,7 +1145,7 @@
1145
1145
  "$ref": "$map/item/key"
1146
1146
  },
1147
1147
  "map": {
1148
- "$description": "One `on*` key. The Mixed contract (§6.5) splits in two and this row shows both halves: which events exist, how each is produced, and its removal are properties of the BATCH — binding one handler to six buttons is a single decision, so those three controls write to every selected element in one transaction — while what a handler CONTAINS is the PRIMARY's, because six elements do not share one body and broadcasting a keystroke into six of them would destroy five. The dot says `mixed` when the selected elements disagree; the body below it stays the primary's.",
1148
+ "$description": "One `on*` key. The Mixed contract (§6.7) splits in two and this row shows both halves: which events exist, how each is produced, and its removal are properties of the BATCH — binding one handler to six buttons is a single decision, so those three controls write to every selected element in one transaction — while what a handler CONTAINS is the PRIMARY's, because six elements do not share one body and broadcasting a keystroke into six of them would destroy five. The dot says `mixed` when the selected elements disagree; the body below it stays the primary's.",
1149
1149
  "tagName": "div",
1150
1150
  "attributes": {
1151
1151
  "part": "binding",
@@ -1159,7 +1159,7 @@
1159
1159
  },
1160
1160
  "children": [
1161
1161
  {
1162
- "$description": "The event NAME, and it is free-form rather than a list of ten. The menu offers what this element already binds plus the ten worth suggesting, and its last row asks for any other name through the one prompt dialog Studio has — so `ondragover`, `onpointerdown` and every custom event a component emits are bindable, which is exactly what §6.5 asks for and what the closed picker refused.",
1162
+ "$description": "The event NAME, and it is free-form rather than a list of ten. The menu offers what this element already binds plus the ten worth suggesting, and its last row asks for any other name through the one prompt dialog Studio has — so `ondragover`, `onpointerdown` and every custom event a component emits are bindable, which is exactly what §6.1 asks for and what the closed picker refused.",
1163
1163
  "tagName": "jx-action-button",
1164
1164
  "attributes": {
1165
1165
  "part": "event-name"