@jxsuite/studio 4.1.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (607) hide show
  1. package/README.md +1 -1
  2. package/data/elements-meta.json +5 -15
  3. package/data/html-meta.json +51 -6
  4. package/dist/chunks/{2020-n6tfwnda.js → 2020-g79n01v9.js} +14 -14
  5. package/dist/chunks/action-group-sp6tna8v.js +118 -0
  6. package/dist/chunks/adapter-nj7tnjfn.js +13 -0
  7. package/dist/chunks/cf-account-picker-fyf63pmy.js +495 -0
  8. package/dist/chunks/cf-settings-71bv5zn9.js +20 -0
  9. package/dist/chunks/color-area-v17df7b8.js +154 -0
  10. package/dist/chunks/color-field-anwybnkn.js +208 -0
  11. package/dist/chunks/color-slider-44ez96fc.js +79 -0
  12. package/dist/chunks/color-xgg3kfw7.js +35 -0
  13. package/dist/chunks/combobox-5e7jev23.js +236 -0
  14. package/dist/chunks/components-2w1f35qs.js +18 -0
  15. package/dist/chunks/content-source-3wqeas45.js +46 -0
  16. package/dist/chunks/convert-to-repeater-d0cgnb6d.js +639 -0
  17. package/dist/chunks/dialog-s890b918.js +85 -0
  18. package/dist/chunks/editor-3qhbg51x.js +35 -0
  19. package/dist/chunks/entry-commands-d6g50j7s.js +42 -0
  20. package/dist/chunks/extension-sections-fy7q4fe9.js +651 -0
  21. package/dist/chunks/file-ops-3btj6st0.js +47 -0
  22. package/dist/chunks/files-ef8fgs3w.js +72 -0
  23. package/dist/chunks/format-host-3c33nwr8.js +40 -0
  24. package/dist/chunks/fs-events-13tj6sex.js +18 -0
  25. package/dist/chunks/git-panel-4wp2rn9b.js +49 -0
  26. package/dist/chunks/icons-yy10wk9r.js +402 -0
  27. package/dist/chunks/iframe-entry-15g3n6xv.js +114 -0
  28. package/dist/chunks/iframe-entry-b27vq81n.js +203 -0
  29. package/dist/chunks/iframe-entry-nbyxee1y.js +154 -0
  30. package/dist/chunks/iframe-host-jgesd924.js +115 -0
  31. package/dist/chunks/{index-wcnt3r9g.js → index-mdmyx6s2.js} +11 -11
  32. package/dist/chunks/index-n4j7qxyr.js +109 -0
  33. package/dist/chunks/{javascript-q8kpmfah.js → javascript-xvrfrpkb.js} +8 -9
  34. package/dist/chunks/{jsonMode-dkr040ga.js → jsonMode-tyx2kj6p.js} +526 -527
  35. package/dist/chunks/jx-validate-j0wxk72w.js +15 -0
  36. package/dist/chunks/layers-1nq5evsh.js +29 -0
  37. package/dist/chunks/layers-panel-ar2gh90g.js +40 -0
  38. package/dist/chunks/listbox-6v2ac08j.js +44 -0
  39. package/dist/chunks/lit-html-m244w9nh.js +17 -0
  40. package/dist/chunks/media-picker-2qbetq73.js +33 -0
  41. package/dist/chunks/menu-q99sy9rf.js +285 -0
  42. package/dist/chunks/menu-rf7n72mf.js +14 -0
  43. package/dist/chunks/{monaco-binding-rj6xpx9y.js → monaco-binding-sw6en4dw.js} +12 -15
  44. package/dist/chunks/monaco-buffer-bhy3hb6m.js +24 -0
  45. package/dist/chunks/{monaco-setup-vx9bhp1d.js → monaco-setup-8r62fj6y.js} +27 -37
  46. package/dist/chunks/notify-628t0anh.js +21 -0
  47. package/dist/chunks/number-field-5cndyft8.js +72 -0
  48. package/dist/chunks/parse-0zx14y15.js +10 -0
  49. package/dist/chunks/platform-ts9cg1a4.js +15 -0
  50. package/dist/chunks/popover-47z3ytva.js +25 -0
  51. package/dist/chunks/publish-panel-98f7sr3g.js +27 -0
  52. package/dist/chunks/quick-search-srzz83k2.js +45 -0
  53. package/dist/chunks/references-n553f0e1.js +26 -0
  54. package/dist/chunks/right-panel-rrgx2dn3.js +45 -0
  55. package/dist/chunks/section-registry-5pq32t0q.js +25 -0
  56. package/dist/chunks/select-2r16ez41.js +49 -0
  57. package/dist/chunks/split-g7nm1rgb.js +191 -0
  58. package/dist/chunks/studio-0hqbpbd0.js +62 -0
  59. package/dist/chunks/studio-18avnhjp.js +2430 -0
  60. package/dist/chunks/{studio-kryvsw6j.js → studio-1k325pwf.js} +48 -48
  61. package/dist/chunks/{studio-msd847zn.js → studio-25hkdrkw.js} +357 -86
  62. package/dist/chunks/studio-26d7myd1.js +258 -0
  63. package/dist/chunks/{studio-4r1pv6zf.js → studio-38emantv.js} +22 -5
  64. package/dist/chunks/studio-3gxv60tn.js +422 -0
  65. package/dist/chunks/{studio-fbf92ckf.js → studio-3hxkd92t.js} +275 -163
  66. package/dist/chunks/studio-4m0haseg.js +185 -0
  67. package/dist/chunks/{studio-ynxwkrzd.js → studio-4wbb9ct0.js} +1953 -1785
  68. package/dist/chunks/{studio-1wagb550.js → studio-5523bpzt.js} +11 -11
  69. package/dist/chunks/{studio-x4qkdat5.js → studio-57mf66w2.js} +1749 -2481
  70. package/dist/chunks/studio-5jy81t3s.js +17463 -0
  71. package/dist/chunks/studio-5rt7sqa0.js +1168 -0
  72. package/dist/chunks/studio-5te5tqng.js +81 -0
  73. package/dist/chunks/{studio-p4ngc046.js → studio-6ewqv390.js} +9 -9
  74. package/dist/chunks/{studio-9ab8gqsm.js → studio-6nzaktvy.js} +7 -7
  75. package/dist/chunks/studio-6xa21ej9.js +28 -0
  76. package/dist/chunks/{studio-5ehhackm.js → studio-727xh0e3.js} +19 -19
  77. package/dist/chunks/{studio-ahn3pdgx.js → studio-79y5sz51.js} +52 -38
  78. package/dist/chunks/{studio-gcye7qka.js → studio-7e11jpa9.js} +21 -21
  79. package/dist/chunks/{studio-q7v10cg2.js → studio-7r42c6ca.js} +17 -7
  80. package/dist/chunks/studio-7xptrg0j.js +954 -0
  81. package/dist/chunks/{studio-cft9r4r7.js → studio-81390n6f.js} +22 -22
  82. package/dist/chunks/{studio-q43a5y9h.js → studio-8jn5yhyn.js} +16 -16
  83. package/dist/chunks/studio-8qtrpzr3.js +839 -0
  84. package/dist/chunks/{studio-dg7zyt5x.js → studio-98b3z07n.js} +1 -1
  85. package/dist/chunks/studio-9xxz1q69.js +1356 -0
  86. package/dist/chunks/studio-akbww0j5.js +13615 -0
  87. package/dist/chunks/{studio-x813zp48.js → studio-arfpe389.js} +30 -30
  88. package/dist/chunks/{studio-trxrabqf.js → studio-az3zd49t.js} +475 -283
  89. package/dist/chunks/studio-cpvb2ed1.js +1171 -0
  90. package/dist/chunks/{studio-f3wqjtk5.js → studio-d0300636.js} +5076 -18
  91. package/dist/chunks/{studio-bgxt93ga.js → studio-d055c37e.js} +13 -13
  92. package/dist/chunks/studio-d1ja2x9r.js +362 -0
  93. package/dist/chunks/{studio-b9b6t1dg.js → studio-e1f24eff.js} +5664 -5666
  94. package/dist/chunks/{studio-3bqpr0zh.js → studio-em9nw8eh.js} +299 -110
  95. package/dist/chunks/studio-erdatzvp.js +1190 -0
  96. package/dist/chunks/{studio-g1wdche0.js → studio-esrxgwh6.js} +80 -80
  97. package/dist/chunks/studio-fabxk6r9.js +2811 -0
  98. package/dist/chunks/{studio-3n4ndrzh.js → studio-h4nvnjvz.js} +303 -303
  99. package/dist/chunks/{studio-dm19q43r.js → studio-hhvs4sdg.js} +10 -10
  100. package/dist/chunks/{studio-q9jd1a60.js → studio-kcgff4r0.js} +15 -18
  101. package/dist/chunks/{studio-685s0ytq.js → studio-nqgawfks.js} +572 -572
  102. package/dist/chunks/{studio-xrapxwwc.js → studio-p1dw8wfw.js} +55 -29
  103. package/dist/chunks/studio-pm6hgy7r.js +4763 -0
  104. package/dist/chunks/studio-q0a3yk4n.js +33 -0
  105. package/dist/chunks/{studio-wcy8trfx.js → studio-q3x06vmj.js} +23 -22
  106. package/dist/chunks/studio-qahxvnan.js +111 -0
  107. package/dist/chunks/{studio-53n8bp04.js → studio-r6xmmtfh.js} +1 -1
  108. package/dist/chunks/{studio-2b946z26.js → studio-rkstz940.js} +3658 -6134
  109. package/dist/chunks/{studio-tvgyw9xw.js → studio-rnyf3f8e.js} +83 -250
  110. package/dist/chunks/studio-rpyah2ew.js +2805 -0
  111. package/dist/chunks/studio-rs76k67r.js +12 -0
  112. package/dist/chunks/{studio-jkftxyvz.js → studio-s6z853aq.js} +5858 -2152
  113. package/dist/chunks/{studio-6yw4y3my.js → studio-sgdc5pfc.js} +8 -8
  114. package/dist/chunks/studio-tb3ev01j.js +763 -0
  115. package/dist/chunks/{studio-t5wqwzdh.js → studio-tjjk7jvk.js} +1 -1
  116. package/dist/chunks/studio-vhv5tgxm.js +51 -0
  117. package/dist/chunks/{studio-qjy2z9bv.js → studio-vz68yn9e.js} +32 -137
  118. package/dist/chunks/studio-wqpngpsk.js +174 -0
  119. package/dist/chunks/{studio-b55y6ewx.js → studio-x3rty6tr.js} +58 -58
  120. package/dist/chunks/studio-xsykpvsh.js +8448 -0
  121. package/dist/chunks/{studio-92ab2jqe.js → studio-y9zedyjn.js} +14 -14
  122. package/dist/chunks/studio-yxa81f45.js +12 -0
  123. package/dist/chunks/swatch-group-t0n6h2rn.js +139 -0
  124. package/dist/chunks/tabs-wbp1cdws.js +156 -0
  125. package/dist/chunks/textfield-abk6qyee.js +73 -0
  126. package/dist/chunks/toast-780pvfbv.js +27 -0
  127. package/dist/chunks/toast-host-3sqv46sn.js +116 -0
  128. package/dist/chunks/toolbar-xbh5bhtr.js +194 -0
  129. package/dist/chunks/tooltip-eptb614w.js +369 -0
  130. package/dist/chunks/tree-a73p0pqm.js +367 -0
  131. package/dist/chunks/{tsMode-76kr53q0.js → tsMode-jy4m86rv.js} +83 -85
  132. package/dist/chunks/workspace-wrew8zk4.js +69 -0
  133. package/dist/chunks/{ws-client-6shc5rze.js → ws-client-ny4zc51r.js} +20 -22
  134. package/dist/iframe-entry.js +1780 -667
  135. package/dist/studio.js +52819 -36480
  136. package/dist/workers/editor.worker.js +1040 -1085
  137. package/dist/workers/json.worker.js +1946 -1991
  138. package/dist/workers/ts.worker.js +4960 -5005
  139. package/index.html +1 -0
  140. package/package.json +18 -52
  141. package/src/about/about-modal.ts +72 -123
  142. package/src/browse/library-commands.ts +20 -49
  143. package/src/browse/library-layouts.ts +87 -218
  144. package/src/browse/library-pane.ts +406 -438
  145. package/src/canvas/canvas-helpers.ts +0 -49
  146. package/src/canvas/canvas-live-render.ts +25 -2
  147. package/src/canvas/canvas-render.ts +666 -231
  148. package/src/canvas/canvas-surface.ts +0 -1
  149. package/src/canvas/canvas-utils.ts +310 -117
  150. package/src/canvas/dialog-path.ts +76 -0
  151. package/src/canvas/dialog-state.ts +67 -0
  152. package/src/canvas/diff-marks.ts +252 -0
  153. package/src/canvas/diff-toolbar.ts +349 -0
  154. package/src/canvas/diff-view.ts +123 -0
  155. package/src/canvas/edit-width-drag.ts +187 -0
  156. package/src/canvas/edit-width.ts +150 -0
  157. package/src/canvas/iframe-entry.ts +125 -8
  158. package/src/canvas/iframe-host.ts +271 -15
  159. package/src/canvas/iframe-interaction.ts +133 -13
  160. package/src/canvas/iframe-patch.ts +7 -1
  161. package/src/canvas/iframe-position.ts +5 -6
  162. package/src/canvas/iframe-protocol.ts +106 -5
  163. package/src/canvas/iframe-render.ts +373 -5
  164. package/src/canvas/iframe-slash.ts +2 -2
  165. package/src/canvas/iframe-subtree.ts +5 -8
  166. package/src/canvas/path-mapping.ts +25 -3
  167. package/src/canvas/popover-path.ts +106 -0
  168. package/src/canvas/popover-state.ts +155 -0
  169. package/src/canvas/surface-registry.ts +21 -10
  170. package/src/collab/presence-chips.ts +51 -73
  171. package/src/commands/app-commands.ts +10 -0
  172. package/src/commands/budget.ts +12 -0
  173. package/src/commands/command-args.ts +369 -6
  174. package/src/commands/defaults.ts +44 -14
  175. package/src/commands/live-context.ts +11 -5
  176. package/src/commands/reference.ts +12 -2
  177. package/src/commands/registry.ts +165 -8
  178. package/src/content/entry-commands.ts +16 -23
  179. package/src/content/entry-editor.ts +144 -101
  180. package/src/editor/canvas-slash-bridge.ts +2 -2
  181. package/src/editor/context-menu.ts +49 -200
  182. package/src/editor/convert-to-component.ts +42 -82
  183. package/src/editor/convert-to-repeater.ts +132 -173
  184. package/src/editor/inline-edit.ts +11 -0
  185. package/src/editor/shortcuts.ts +65 -26
  186. package/src/editor/slash-menu.ts +150 -157
  187. package/src/files/file-ops.ts +117 -11
  188. package/src/files/files.ts +943 -660
  189. package/src/files/json-layout.ts +474 -0
  190. package/src/files/serialize-document.ts +8 -1
  191. package/src/format/convert-file.ts +16 -10
  192. package/src/format/format-host.ts +50 -1
  193. package/src/github/github-auth.ts +71 -29
  194. package/src/github/github-publish.ts +57 -65
  195. package/src/grid/cell-editors.ts +46 -4
  196. package/src/grid/cell-popovers.ts +65 -62
  197. package/src/grid/grid-open.ts +86 -64
  198. package/src/grid/grid-panel.ts +390 -469
  199. package/src/grid/redirects-grid.ts +40 -44
  200. package/src/hosting/layout.ts +2 -0
  201. package/src/i18n/i18n-commands.ts +127 -62
  202. package/src/media/media-pane.ts +83 -133
  203. package/src/new-project/add-repo-modal.ts +125 -176
  204. package/src/new-project/import-tab.ts +181 -252
  205. package/src/new-project/location-fields.ts +93 -160
  206. package/src/new-project/new-project-modal.ts +376 -367
  207. package/src/packages/jxsuite-update.ts +76 -18
  208. package/src/panels/activity-panel.ts +137 -104
  209. package/src/panels/ai-chat/chat-markdown.ts +15 -13
  210. package/src/panels/ai-chat/chat-view.ts +307 -472
  211. package/src/panels/ai-chat/composer.ts +175 -163
  212. package/src/panels/ai-chat/sessions-view.ts +31 -62
  213. package/src/panels/ai-panel.ts +210 -185
  214. package/src/panels/block-action-bar.ts +437 -643
  215. package/src/panels/bottom-dock.ts +112 -47
  216. package/src/panels/chat-panel.ts +19 -14
  217. package/src/panels/data-explorer.ts +141 -102
  218. package/src/panels/data-grid.ts +183 -150
  219. package/src/panels/dnd.ts +75 -20
  220. package/src/panels/editors.ts +26 -19
  221. package/src/panels/elements-panel.ts +243 -186
  222. package/src/panels/empty-state.ts +26 -42
  223. package/src/panels/events-panel.ts +950 -729
  224. package/src/panels/formula-workspace.ts +434 -207
  225. package/src/panels/frontmatter-fields.ts +185 -153
  226. package/src/panels/frontmatter-panel.ts +411 -187
  227. package/src/panels/git-diff-open.ts +148 -0
  228. package/src/panels/git-panel.ts +679 -605
  229. package/src/panels/head-panel.ts +617 -435
  230. package/src/panels/i18n-panel.ts +153 -133
  231. package/src/panels/imports-panel.ts +388 -414
  232. package/src/panels/jump-bar.ts +174 -147
  233. package/src/panels/layers-panel.ts +785 -671
  234. package/src/panels/left-panel.ts +166 -94
  235. package/src/panels/navigator-panels.ts +1 -1
  236. package/src/panels/pane-context.ts +529 -677
  237. package/src/panels/pane-grid.ts +265 -241
  238. package/src/panels/panel-registry.ts +15 -4
  239. package/src/panels/problems-panel.ts +177 -99
  240. package/src/panels/properties-panel.ts +1525 -966
  241. package/src/panels/provenance.ts +31 -113
  242. package/src/panels/quick-search.ts +217 -172
  243. package/src/panels/right-panel.ts +135 -169
  244. package/src/panels/seo-modal.ts +346 -167
  245. package/src/panels/settings-menu.ts +109 -646
  246. package/src/panels/settings-pane.ts +102 -86
  247. package/src/panels/signals-panel.ts +1318 -1172
  248. package/src/panels/statement-editor.ts +556 -428
  249. package/src/panels/style-panel.ts +1367 -630
  250. package/src/panels/style-utils.ts +36 -32
  251. package/src/panels/stylebook-doc.ts +30 -73
  252. package/src/panels/stylebook-layers-panel.ts +202 -109
  253. package/src/panels/stylebook-panel.ts +124 -88
  254. package/src/panels/tab-strip.ts +385 -287
  255. package/src/platforms/cloud.ts +106 -16
  256. package/src/platforms/devserver.ts +13 -0
  257. package/src/publish/deploy-checklist.ts +124 -78
  258. package/src/publish/publish-commands.ts +4 -12
  259. package/src/publish/publish-panel.ts +134 -328
  260. package/src/services/a11y-report.ts +100 -43
  261. package/src/services/ai-command-tools.ts +468 -0
  262. package/src/services/ai-session-store.ts +6 -0
  263. package/src/services/ai-system-prompt.ts +110 -18
  264. package/src/services/ai-tools.ts +28 -143
  265. package/src/services/ai-write-report.ts +174 -0
  266. package/src/services/document-assistant.ts +50 -2
  267. package/src/services/idle.ts +16 -14
  268. package/src/services/live-surfaces.ts +237 -0
  269. package/src/services/model-uri.ts +75 -0
  270. package/src/services/notify.ts +63 -6
  271. package/src/services/popover-report.ts +325 -0
  272. package/src/services/surface-registry.ts +56 -0
  273. package/src/services/tool-executor.ts +6 -0
  274. package/src/settings/contexts-section.ts +301 -299
  275. package/src/settings/contributed-section.ts +361 -222
  276. package/src/settings/css-vars-editor.ts +320 -325
  277. package/src/settings/defs-editor.ts +572 -535
  278. package/src/settings/dependencies-editor.ts +79 -107
  279. package/src/settings/extension-commands.ts +379 -0
  280. package/src/settings/extension-rows.ts +113 -0
  281. package/src/settings/extensions-section.ts +287 -0
  282. package/src/settings/general-settings.ts +130 -181
  283. package/src/settings/head-editor.ts +10 -305
  284. package/src/settings/locales-section.ts +146 -196
  285. package/src/settings/preferences-accounts.ts +1 -1
  286. package/src/settings/preferences-dialog.ts +350 -330
  287. package/src/settings/project-sections.ts +108 -181
  288. package/src/settings/schema-field-ui.ts +11 -399
  289. package/src/settings/section-registry.ts +8 -1
  290. package/src/settings/settings-document.ts +31 -29
  291. package/src/shell/tree.ts +42 -87
  292. package/src/shell.ts +48 -36
  293. package/src/studio.ts +90 -67
  294. package/src/style/token-ref.ts +0 -39
  295. package/src/surfaces/about.json +263 -0
  296. package/src/surfaces/about.ts +163 -0
  297. package/src/surfaces/add-repo.json +486 -0
  298. package/src/surfaces/add-repo.ts +236 -0
  299. package/src/surfaces/ai-chat.json +2185 -0
  300. package/src/surfaces/ai-chat.ts +549 -0
  301. package/src/surfaces/ai-credentials-form.json +332 -0
  302. package/src/surfaces/ai-credentials-form.ts +151 -0
  303. package/src/surfaces/ai-managed-connect.json +108 -0
  304. package/src/surfaces/ai-managed-connect.ts +123 -0
  305. package/src/surfaces/ai-model-picker.json +114 -0
  306. package/src/surfaces/ai-model-picker.ts +139 -0
  307. package/src/surfaces/block-action-bar.json +640 -0
  308. package/src/surfaces/block-action-bar.ts +368 -0
  309. package/src/surfaces/bottom-dock.json +154 -0
  310. package/src/surfaces/bottom-dock.ts +125 -0
  311. package/src/surfaces/canvas-stage.json +444 -0
  312. package/src/surfaces/canvas-stage.ts +253 -0
  313. package/src/surfaces/cf-account-picker.json +300 -0
  314. package/src/surfaces/cf-account-picker.ts +214 -0
  315. package/src/surfaces/commandbar.json +984 -0
  316. package/src/{panels/toolbar.ts → surfaces/commandbar.ts} +414 -389
  317. package/src/surfaces/convert-repeater.json +309 -0
  318. package/src/surfaces/convert-repeater.ts +276 -0
  319. package/src/surfaces/data-actions.json +157 -0
  320. package/src/surfaces/data-actions.ts +115 -0
  321. package/src/surfaces/dialog.json +289 -0
  322. package/src/surfaces/dialog.ts +343 -0
  323. package/src/surfaces/diff-toolbar.json +266 -0
  324. package/src/surfaces/diff-toolbar.ts +139 -0
  325. package/src/surfaces/doc-header.json +739 -0
  326. package/src/surfaces/doc-header.ts +223 -0
  327. package/src/surfaces/empty-state.json +152 -0
  328. package/src/surfaces/empty-state.ts +173 -0
  329. package/src/surfaces/entry-editor.json +281 -0
  330. package/src/surfaces/entry-editor.ts +191 -0
  331. package/src/surfaces/expression-editor.json +977 -0
  332. package/src/surfaces/expression-editor.ts +266 -0
  333. package/src/surfaces/files-panel.json +592 -0
  334. package/src/surfaces/files-panel.ts +301 -0
  335. package/src/surfaces/formula-palette.json +364 -0
  336. package/src/surfaces/formula-palette.ts +340 -0
  337. package/src/surfaces/git-panel.json +1822 -0
  338. package/src/surfaces/git-panel.ts +272 -0
  339. package/src/surfaces/github-auth.json +112 -0
  340. package/src/surfaces/github-auth.ts +139 -0
  341. package/src/surfaces/github-publish.json +206 -0
  342. package/src/surfaces/github-publish.ts +169 -0
  343. package/src/surfaces/grid-cell.json +218 -0
  344. package/src/surfaces/grid-cell.ts +120 -0
  345. package/src/surfaces/grid-open.json +147 -0
  346. package/src/surfaces/grid-open.ts +87 -0
  347. package/src/surfaces/grid-panel.json +706 -0
  348. package/src/surfaces/grid-panel.ts +206 -0
  349. package/src/surfaces/grid-replace.json +179 -0
  350. package/src/surfaces/grid-replace.ts +89 -0
  351. package/src/surfaces/grid-views.json +446 -0
  352. package/src/surfaces/grid-views.ts +172 -0
  353. package/src/surfaces/inspector-dock.json +187 -0
  354. package/src/surfaces/inspector-dock.ts +161 -0
  355. package/src/surfaces/jump-bar.json +243 -0
  356. package/src/surfaces/jump-bar.ts +129 -0
  357. package/src/surfaces/jxsuite-update.json +146 -0
  358. package/src/surfaces/jxsuite-update.ts +149 -0
  359. package/src/surfaces/library-pane.json +1509 -0
  360. package/src/surfaces/library-pane.ts +363 -0
  361. package/src/surfaces/logic-panel.json +1949 -0
  362. package/src/surfaces/logic-panel.ts +369 -0
  363. package/src/surfaces/logic-workspace.json +685 -0
  364. package/src/surfaces/logic-workspace.ts +238 -0
  365. package/src/surfaces/media-browser.json +303 -0
  366. package/src/surfaces/media-browser.ts +145 -0
  367. package/src/surfaces/media-field.json +163 -0
  368. package/src/surfaces/media-field.ts +116 -0
  369. package/src/surfaces/media-pane.json +513 -0
  370. package/src/surfaces/media-pane.ts +197 -0
  371. package/src/surfaces/menu.json +232 -0
  372. package/src/surfaces/menu.ts +375 -0
  373. package/src/surfaces/navigator-dock.json +113 -0
  374. package/src/surfaces/navigator-dock.ts +130 -0
  375. package/src/surfaces/new-project.json +1654 -0
  376. package/src/surfaces/new-project.ts +411 -0
  377. package/src/surfaces/palette.json +535 -0
  378. package/src/surfaces/pane-context.json +1497 -0
  379. package/src/surfaces/pane-context.ts +513 -0
  380. package/src/surfaces/pane-grid.json +188 -0
  381. package/src/surfaces/pane-grid.ts +250 -0
  382. package/src/surfaces/panel-activity.json +563 -0
  383. package/src/surfaces/panel-activity.ts +187 -0
  384. package/src/surfaces/panel-data.json +141 -0
  385. package/src/surfaces/panel-data.ts +156 -0
  386. package/src/surfaces/panel-deploy-checklist.json +283 -0
  387. package/src/surfaces/panel-deploy-checklist.ts +175 -0
  388. package/src/surfaces/panel-elements.json +367 -0
  389. package/src/surfaces/panel-elements.ts +175 -0
  390. package/src/surfaces/panel-i18n.json +569 -0
  391. package/src/surfaces/panel-i18n.ts +212 -0
  392. package/src/surfaces/panel-imports.json +780 -0
  393. package/src/surfaces/panel-imports.ts +209 -0
  394. package/src/surfaces/panel-outline.json +734 -0
  395. package/src/surfaces/panel-outline.ts +326 -0
  396. package/src/surfaces/panel-page.json +1017 -0
  397. package/src/surfaces/panel-page.ts +240 -0
  398. package/src/surfaces/panel-problems.json +497 -0
  399. package/src/surfaces/panel-problems.ts +157 -0
  400. package/src/surfaces/panel-signals.json +1973 -0
  401. package/src/surfaces/panel-signals.ts +436 -0
  402. package/src/surfaces/panel-stylebook-layers.json +317 -0
  403. package/src/surfaces/panel-stylebook-layers.ts +155 -0
  404. package/src/surfaces/preferences.json +850 -0
  405. package/src/surfaces/preferences.ts +332 -0
  406. package/src/surfaces/progress-modal.json +110 -0
  407. package/src/surfaces/progress-modal.ts +150 -0
  408. package/src/surfaces/properties-panel.json +1578 -0
  409. package/src/surfaces/properties-panel.ts +337 -0
  410. package/src/surfaces/publish.json +945 -0
  411. package/src/surfaces/publish.ts +392 -0
  412. package/src/surfaces/push-plan.json +110 -0
  413. package/src/surfaces/push-plan.ts +87 -0
  414. package/src/surfaces/rail.json +255 -0
  415. package/src/surfaces/rail.ts +206 -0
  416. package/src/surfaces/reference-field.json +191 -0
  417. package/src/surfaces/reference-field.ts +168 -0
  418. package/src/surfaces/schema-builder.json +1011 -0
  419. package/src/surfaces/schema-builder.ts +181 -0
  420. package/src/surfaces/schema-form.json +1013 -0
  421. package/src/surfaces/schema-form.ts +287 -0
  422. package/src/surfaces/secret-field.json +60 -0
  423. package/src/surfaces/secret-field.ts +146 -0
  424. package/src/surfaces/seo.json +932 -0
  425. package/src/surfaces/seo.ts +334 -0
  426. package/src/surfaces/settings-contexts.json +538 -0
  427. package/src/surfaces/settings-contexts.ts +196 -0
  428. package/src/surfaces/settings-contributed.json +489 -0
  429. package/src/surfaces/settings-contributed.ts +199 -0
  430. package/src/surfaces/settings-css-vars.json +820 -0
  431. package/src/surfaces/settings-css-vars.ts +199 -0
  432. package/src/surfaces/settings-defs.json +1363 -0
  433. package/src/surfaces/settings-defs.ts +232 -0
  434. package/src/surfaces/settings-deploy.json +108 -0
  435. package/src/surfaces/settings-deploy.ts +135 -0
  436. package/src/surfaces/settings-extensions.json +486 -0
  437. package/src/surfaces/settings-extensions.ts +201 -0
  438. package/src/surfaces/settings-head.json +779 -0
  439. package/src/surfaces/settings-head.ts +397 -0
  440. package/src/surfaces/settings-locales.json +420 -0
  441. package/src/surfaces/settings-locales.ts +137 -0
  442. package/src/surfaces/settings-overview.json +423 -0
  443. package/src/surfaces/settings-overview.ts +218 -0
  444. package/src/surfaces/settings-packages.json +549 -0
  445. package/src/surfaces/settings-packages.ts +158 -0
  446. package/src/surfaces/settings-pane.json +147 -0
  447. package/src/surfaces/settings-pane.ts +150 -0
  448. package/src/surfaces/settings-rawjson.json +104 -0
  449. package/src/surfaces/settings-rawjson.ts +107 -0
  450. package/src/surfaces/shell.json +99 -0
  451. package/src/surfaces/shell.ts +30 -0
  452. package/src/surfaces/slash-menu.json +180 -0
  453. package/src/surfaces/slash-menu.ts +272 -0
  454. package/src/surfaces/statements.json +607 -0
  455. package/src/surfaces/statements.ts +238 -0
  456. package/src/surfaces/statusbar.json +94 -0
  457. package/src/{panels → surfaces}/statusbar.ts +163 -90
  458. package/src/surfaces/style-panel.json +1643 -0
  459. package/src/surfaces/style-panel.ts +338 -0
  460. package/src/surfaces/stylebook-chrome.json +122 -0
  461. package/src/surfaces/stylebook-chrome.ts +122 -0
  462. package/src/surfaces/tab-strip.json +448 -0
  463. package/src/surfaces/tab-strip.ts +200 -0
  464. package/src/surfaces/target-line.json +419 -0
  465. package/src/surfaces/target-line.ts +349 -0
  466. package/src/surfaces/toasts.json +189 -0
  467. package/src/surfaces/welcome.json +571 -0
  468. package/src/surfaces/welcome.ts +338 -0
  469. package/src/tabs/project-config.ts +71 -15
  470. package/src/tabs/tab.ts +52 -1
  471. package/src/types.ts +22 -0
  472. package/src/ui/ai-credentials-form.ts +104 -100
  473. package/src/ui/ai-managed-connect.ts +54 -36
  474. package/src/ui/ai-model-picker.ts +75 -47
  475. package/src/ui/cf-account-picker.ts +76 -141
  476. package/src/ui/color-selector.ts +80 -301
  477. package/src/ui/dynamic-slot.ts +43 -283
  478. package/src/ui/expression-editor.ts +797 -576
  479. package/src/ui/field-input.ts +8 -181
  480. package/src/ui/form-controls.ts +838 -366
  481. package/src/ui/formula-chips.ts +80 -85
  482. package/src/ui/kit.ts +33 -0
  483. package/src/ui/layers.ts +293 -593
  484. package/src/ui/media-picker.ts +203 -284
  485. package/src/ui/panel-resize.ts +251 -64
  486. package/src/ui/popover-surface.ts +153 -0
  487. package/src/ui/progress-modal.ts +22 -60
  488. package/src/ui/regions.ts +13 -7
  489. package/src/ui/schema-form.ts +906 -440
  490. package/src/ui/surface.ts +122 -0
  491. package/src/ui/unit-selector.ts +15 -131
  492. package/src/ui/value-source.ts +14 -0
  493. package/src/ui/virtual-window.ts +88 -9
  494. package/src/utils/canvas-media.ts +72 -0
  495. package/src/utils/edit-display.ts +7 -2
  496. package/src/utils/element-selectors.ts +69 -0
  497. package/src/utils/link-target.ts +2 -2
  498. package/src/utils/studio-utils.ts +0 -10
  499. package/src/view.ts +15 -0
  500. package/src/workspace/pane-derive.ts +36 -14
  501. package/src/workspace/workspace.ts +15 -6
  502. package/styles/canvas.css +72 -467
  503. package/styles/forced-colors.css +48 -82
  504. package/styles/forced-colors.json +41 -0
  505. package/styles/inspector.css +2 -1301
  506. package/styles/overlays.css +96 -2823
  507. package/styles/panels.css +6 -1423
  508. package/styles/shell-frame.css +272 -0
  509. package/styles/shell-frame.json +227 -0
  510. package/styles/shell.css +0 -1568
  511. package/styles/tokens.css +65 -136
  512. package/styles/tokens.json +84 -0
  513. package/dist/chunks/Overlay.dev-etqjwyf9.js +0 -23
  514. package/dist/chunks/adapter-jkcyhgtr.js +0 -14
  515. package/dist/chunks/cf-account-picker-en86v7x7.js +0 -163
  516. package/dist/chunks/cf-settings-45fgyx8y.js +0 -21
  517. package/dist/chunks/components-zmx10t62.js +0 -21
  518. package/dist/chunks/content-source-48xg86wj.js +0 -49
  519. package/dist/chunks/convert-to-repeater-43tfn7cs.js +0 -268
  520. package/dist/chunks/editor-cptq5jp1.js +0 -37
  521. package/dist/chunks/entry-commands-e63f1xc0.js +0 -46
  522. package/dist/chunks/extension-sections-txv08xxg.js +0 -311
  523. package/dist/chunks/file-ops-wbh4hhsx.js +0 -48
  524. package/dist/chunks/files-3kfkwhk4.js +0 -93
  525. package/dist/chunks/flow-qbfgrpeh.js +0 -634
  526. package/dist/chunks/focus-trap.esm-9t2drp0g.js +0 -1025
  527. package/dist/chunks/focus-visible-6eg70z18.js +0 -167
  528. package/dist/chunks/format-host-w16q81tf.js +0 -43
  529. package/dist/chunks/fs-events-hrrg328g.js +0 -21
  530. package/dist/chunks/git-panel-532whr1y.js +0 -59
  531. package/dist/chunks/index-zqxmqxmh.js +0 -109
  532. package/dist/chunks/jx-validate-8er6gbxy.js +0 -19
  533. package/dist/chunks/layers-panel-07hm7g5j.js +0 -67
  534. package/dist/chunks/layers-q75tj2mf.js +0 -45
  535. package/dist/chunks/lit-html-j055mkh8.js +0 -22
  536. package/dist/chunks/monaco-buffer-dqw0xxpx.js +0 -25
  537. package/dist/chunks/notify-yjm79n4s.js +0 -30
  538. package/dist/chunks/parse-24d0gay3.js +0 -19
  539. package/dist/chunks/platform-ba1j1gbh.js +0 -16
  540. package/dist/chunks/publish-panel-v9st96ja.js +0 -29
  541. package/dist/chunks/quick-search-zccjp6gv.js +0 -66
  542. package/dist/chunks/references-3qx8fkyp.js +0 -29
  543. package/dist/chunks/right-panel-vm3b6kwy.js +0 -46
  544. package/dist/chunks/section-registry-sx1ykvkw.js +0 -30
  545. package/dist/chunks/sp-overlay.dev-qgvhnxf4.js +0 -18
  546. package/dist/chunks/sp-popover.dev-n2etmqdp.js +0 -9
  547. package/dist/chunks/sp-progress-circle.dev-hryhj0es.js +0 -15
  548. package/dist/chunks/sp-tooltip.dev-4sastdnw.js +0 -15
  549. package/dist/chunks/sp-tray.dev-tkbscm06.js +0 -199
  550. package/dist/chunks/studio-0a5qrh01.js +0 -3
  551. package/dist/chunks/studio-0bq6eh7v.js +0 -12
  552. package/dist/chunks/studio-18j3bmcz.js +0 -14
  553. package/dist/chunks/studio-1ngbejft.js +0 -181
  554. package/dist/chunks/studio-4b5z1x43.js +0 -424
  555. package/dist/chunks/studio-4n2b5gzb.js +0 -357
  556. package/dist/chunks/studio-4rzyrtjz.js +0 -426
  557. package/dist/chunks/studio-5fx3g9jg.js +0 -4325
  558. package/dist/chunks/studio-5myknm0a.js +0 -1903
  559. package/dist/chunks/studio-7afd21nw.js +0 -67
  560. package/dist/chunks/studio-7nte2hj4.js +0 -613
  561. package/dist/chunks/studio-8jpzqk5s.js +0 -128
  562. package/dist/chunks/studio-8q517dfr.js +0 -24
  563. package/dist/chunks/studio-950k0dx6.js +0 -6939
  564. package/dist/chunks/studio-9n4mrmnb.js +0 -184
  565. package/dist/chunks/studio-a0tswy0w.js +0 -58
  566. package/dist/chunks/studio-ahnzd9rg.js +0 -23
  567. package/dist/chunks/studio-cmb03bg5.js +0 -13890
  568. package/dist/chunks/studio-d1ks410h.js +0 -175
  569. package/dist/chunks/studio-ef49pnzx.js +0 -387
  570. package/dist/chunks/studio-eqq1w638.js +0 -113
  571. package/dist/chunks/studio-ew0djmhg.js +0 -341
  572. package/dist/chunks/studio-gfgb8pe6.js +0 -1652
  573. package/dist/chunks/studio-h4rxscfc.js +0 -10
  574. package/dist/chunks/studio-jc994dnr.js +0 -1066
  575. package/dist/chunks/studio-kyh9avvv.js +0 -28
  576. package/dist/chunks/studio-m3hwn7y1.js +0 -120
  577. package/dist/chunks/studio-mtfnaqs9.js +0 -659
  578. package/dist/chunks/studio-n6j9t10q.js +0 -318
  579. package/dist/chunks/studio-n8b9wqwy.js +0 -291
  580. package/dist/chunks/studio-qcy05dp8.js +0 -1743
  581. package/dist/chunks/studio-qq6jym04.js +0 -53
  582. package/dist/chunks/studio-rdx8jcxy.js +0 -83
  583. package/dist/chunks/studio-rn9ta2mz.js +0 -111
  584. package/dist/chunks/studio-t7qb9db8.js +0 -665
  585. package/dist/chunks/studio-tmc5emrw.js +0 -8
  586. package/dist/chunks/studio-z6nw2ek2.js +0 -18
  587. package/dist/chunks/studio-zczps70q.js +0 -378
  588. package/dist/chunks/studio-zqazsct2.js +0 -1823
  589. package/dist/chunks/workspace-fjx52ryv.js +0 -89
  590. package/src/panels/activity-bar.ts +0 -251
  591. package/src/panels/panel-scheduler.ts +0 -219
  592. package/src/panels/style-inputs.ts +0 -237
  593. package/src/panels/target-line.ts +0 -274
  594. package/src/panels/welcome-screen.ts +0 -346
  595. package/src/ui/button-group.ts +0 -102
  596. package/src/ui/choice-field.ts +0 -72
  597. package/src/ui/field-row.ts +0 -249
  598. package/src/ui/formula-palette.ts +0 -213
  599. package/src/ui/icons.ts +0 -52
  600. package/src/ui/jx-theme.ts +0 -130
  601. package/src/ui/spectrum.ts +0 -340
  602. package/src/ui/value-selector.ts +0 -174
  603. package/src/ui/widgets.ts +0 -172
  604. /package/dist/chunks/{javascript-s56a8dpk.css → javascript-4abzjcy9.css} +0 -0
  605. /package/dist/chunks/{jsonMode-zr9sw0c7.css → jsonMode-vvmpmk34.css} +0 -0
  606. /package/dist/chunks/{monaco-setup-pav68602.css → monaco-setup-8vbyqnhr.css} +0 -0
  607. /package/dist/chunks/{tsMode-ef187txx.css → tsMode-hnxxb73h.css} +0 -0
@@ -11,16 +11,18 @@
11
11
  * it and revoke it (plan §9.3). Nothing about this form changed for the move, which is the argument
12
12
  * for it having been a reusable form rather than a section of a dialog.
13
13
  *
14
- * Built from Spectrum controls with its layout in `styles/shell.css`: a roaming credential the user
15
- * configures once does not get its own bespoke inputs, and it certainly does not get 200-character
16
- * inline `style=` strings that stop responding the moment the theme changes.
14
+ * This module is the FLOW; `surfaces/ai-credentials-form.json` is what it draws. It keeps the three
15
+ * drafts, decides which credentials a listing is sent with, what Save persists and re-reads, and
16
+ * whether Cancel is on offer; the surface renders those and reports what the reader did. `render()`
17
+ * hands back the surface's own host element rather than a template, because every gate is still a
18
+ * lit template that interpolates the form beside the keyless offer — see
19
+ * `surfaces/ai-credentials-form.ts` for why that element is the mount point and why re-rendering
20
+ * the gate cannot disturb it.
17
21
  *
22
+ * @docs studio/ai
18
23
  * @license MIT
19
24
  */
20
25
 
21
- import { html, nothing } from "lit-html";
22
- import { live } from "lit-html/directives/live.js";
23
- import type { TemplateResult } from "lit-html";
24
26
  import { fetchAvailableModels } from "../services/ai-models";
25
27
  import {
26
28
  getBaseUrl,
@@ -29,6 +31,16 @@ import {
29
31
  saveAiProvider,
30
32
  storedModel,
31
33
  } from "../services/ai-settings";
34
+ import { createAiCredentialsSurface } from "../surfaces/ai-credentials-form";
35
+ import type {
36
+ AiCredentialsSurface,
37
+ AiCredentialsView,
38
+ CredentialsModelRow,
39
+ } from "../surfaces/ai-credentials-form";
40
+
41
+ /** The blurb a host that says nothing gets. */
42
+ const DEFAULT_INTRO =
43
+ "Any OpenAI-compatible key works. Stored locally in this browser; sent only to the Studio proxy (never to a third party except your chosen endpoint).";
32
44
 
33
45
  export interface AiCredentialsFormOptions {
34
46
  /** Host re-render scheduler — called whenever the form's internal state changes. */
@@ -37,12 +49,22 @@ export interface AiCredentialsFormOptions {
37
49
  onSaved?: () => void;
38
50
  /** Called when Cancel dismisses the form (Cancel is only offered when a key already exists). */
39
51
  onCancel?: () => void;
40
- /** Optional context line (TemplateResult | string) replacing the default blurb. */
41
- intro?: unknown;
52
+ /**
53
+ * Optional context line replacing the default blurb.
54
+ *
55
+ * A string, not a template: the line is drawn by a document, and a document renders text rather
56
+ * than somebody else's markup. Nothing that passed one ever passed more than a sentence.
57
+ */
58
+ intro?: string;
42
59
  }
43
60
 
44
61
  export interface AiCredentialsForm {
45
- render: () => TemplateResult;
62
+ /**
63
+ * The form's host element.
64
+ *
65
+ * A gate interpolates it into its own lit template, which inserts a Node it is handed as-is.
66
+ */
67
+ render: () => HTMLElement;
46
68
  /** Preload drafts from the stored ai-settings and auto-fetch the model list. */
47
69
  startEdit: () => void;
48
70
  }
@@ -63,6 +85,9 @@ export function createAiCredentialsForm(opts: AiCredentialsFormOptions): AiCrede
63
85
  let modelsLoading = false;
64
86
  let modelsError = "";
65
87
 
88
+ /** Made on the first render, and kept for the life of the controller. */
89
+ let surface: AiCredentialsSurface | null = null;
90
+
66
91
  /**
67
92
  * Load the drafts from what is stored.
68
93
  *
@@ -104,7 +129,7 @@ export function createAiCredentialsForm(opts: AiCredentialsFormOptions): AiCrede
104
129
  loadDrafts();
105
130
  modelsError = "";
106
131
  /* The fetched list stays: it was listed under exactly these credentials, and dropping it
107
- collapsed the model combobox back to a free-text field on every save. The module cache is
132
+ collapsed the model combobox back to a bare text field on every save. The module cache is
108
133
  dropped by ai-models' own settings subscription, so this form does not have to remember to. */
109
134
  opts.onSaved?.();
110
135
  opts.requestRender();
@@ -148,96 +173,75 @@ export function createAiCredentialsForm(opts: AiCredentialsFormOptions): AiCrede
148
173
  }
149
174
  }
150
175
 
151
- /** The key + model + endpoint form column. */
152
- function render(): TemplateResult {
153
- const haveKey = hasOpenAiKey();
154
- return html`
155
- <div class="ai-creds-form">
156
- <div class="ai-creds-title">AI provider key</div>
157
- <div class="ai-creds-note">
158
- ${
159
- opts.intro === undefined
160
- ? html`
161
- Any OpenAI-compatible key works. Stored locally in this browser; sent only to the
162
- Studio proxy (never to a third party except your chosen endpoint).
163
- `
164
- : opts.intro
165
- }
166
- </div>
167
- <sp-textfield
168
- class="ai-creds-field"
169
- type="password"
170
- size="s"
171
- placeholder="sk-… or any compatible key"
172
- .value=${live(keyDraft)}
173
- @input=${(e: Event) => {
174
- keyDraft = (e.target as HTMLInputElement).value;
175
- }}
176
- ></sp-textfield>
177
- <div class="ai-creds-label">Model</div>
178
- ${
179
- availableModels.length > 0
180
- ? html`
181
- <sp-combobox
182
- class="ai-creds-field"
183
- size="s"
184
- allows-custom-value
185
- .value=${live(modelDraft)}
186
- @change=${(e: Event) => {
187
- modelDraft = (e.target as HTMLInputElement).value;
188
- }}
189
- @input=${(e: Event) => {
190
- modelDraft = (e.target as HTMLInputElement).value;
191
- }}
192
- >
193
- ${availableModels.map(
194
- (m) => html`<sp-menu-item value=${m.id}>${m.name}</sp-menu-item>`,
195
- )}
196
- </sp-combobox>
197
- `
198
- : html`
199
- <sp-textfield
200
- class="ai-creds-field"
201
- size="s"
202
- placeholder="Model ID (e.g. gpt-4o, claude-sonnet-4-20250514, etc.)"
203
- .value=${live(modelDraft)}
204
- @input=${(e: Event) => {
205
- modelDraft = (e.target as HTMLInputElement).value;
206
- }}
207
- ></sp-textfield>
208
- `
209
- }
210
- <div class="ai-creds-models">
211
- <sp-button size="s" variant="secondary" ?disabled=${modelsLoading} @click=${fetchModels}>
212
- ${
213
- modelsLoading
214
- ? "Fetching…"
215
- : availableModels.length > 0
216
- ? "Refresh models"
217
- : "Fetch models"
218
- }
219
- </sp-button>
220
- ${modelsError ? html`<span class="ai-creds-error">${modelsError}</span>` : nothing}
221
- </div>
222
- <sp-textfield
223
- class="ai-creds-field"
224
- size="s"
225
- placeholder="Endpoint (optional, e.g. http://localhost:11434/v1)"
226
- .value=${live(baseUrlDraft)}
227
- @input=${(e: Event) => {
228
- baseUrlDraft = (e.target as HTMLInputElement).value;
229
- }}
230
- ></sp-textfield>
231
- <div class="ai-creds-actions">
232
- ${
233
- haveKey
234
- ? html`<sp-button size="s" variant="secondary" @click=${cancel}>Cancel</sp-button>`
235
- : nothing
236
- }
237
- <sp-button size="s" variant="primary" @click=${save}>Save</sp-button>
238
- </div>
239
- </div>
240
- `;
176
+ /**
177
+ * The catalogue as rows — the list the combobox will draw, never a corpus it matches against. A
178
+ * model with no name of its own is called by its id.
179
+ */
180
+ function rows(): CredentialsModelRow[] {
181
+ return availableModels.map((model) => ({ label: model.name, value: model.id }));
182
+ }
183
+
184
+ /** What the form says right now — the whole of what the surface is told. */
185
+ function view(): AiCredentialsView {
186
+ return {
187
+ baseUrlDraft,
188
+ fetchLabel: modelsLoading
189
+ ? "Fetching…"
190
+ : availableModels.length > 0
191
+ ? "Refresh models"
192
+ : "Fetch models",
193
+ haveKey: hasOpenAiKey(),
194
+ intro: opts.intro ?? DEFAULT_INTRO,
195
+ keyDraft,
196
+ modelDraft,
197
+ models: rows(),
198
+ modelsError,
199
+ modelsLoading,
200
+ };
201
+ }
202
+
203
+ /**
204
+ * What the reader typed, announced on the scope before anything else reads it.
205
+ *
206
+ * A document's binding writes only when the value it reads CHANGES (§9.3), so a draft the flow
207
+ * decided without the raw text passing through would leave the field holding something the flow
208
+ * does not have. Nothing rewrites a draft today; the echo is what makes a rewrite possible.
209
+ */
210
+ function setKey(value: string) {
211
+ keyDraft = value;
212
+ surface?.update(view());
213
+ }
214
+
215
+ /**
216
+ * Typed, picked from the catalogue, or committed — the combobox says all three through one value,
217
+ * and the draft is the one place it lands.
218
+ */
219
+ function setModel(value: string) {
220
+ modelDraft = value;
221
+ surface?.update(view());
222
+ }
223
+
224
+ function setBaseUrl(value: string) {
225
+ baseUrlDraft = value;
226
+ surface?.update(view());
227
+ }
228
+
229
+ function render(): HTMLElement {
230
+ if (surface) {
231
+ surface.update(view());
232
+ } else {
233
+ surface = createAiCredentialsSurface(view(), {
234
+ cancel,
235
+ fetchModels: () => {
236
+ void fetchModels();
237
+ },
238
+ save,
239
+ setBaseUrl,
240
+ setKey,
241
+ setModel,
242
+ });
243
+ }
244
+ return surface.host;
241
245
  }
242
246
 
243
247
  return { render, startEdit };
@@ -9,6 +9,13 @@
9
9
  * gate on credentials (the assistant sidebar and the New Project modal's Import/Agent tabs) embed
10
10
  * this alongside the form so both real paths are always on offer.
11
11
  *
12
+ * This module is the FLOW; `surfaces/ai-managed-connect.json` is what it draws. It decides whether
13
+ * the offer applies, what a finished OAuth round trip meant, and the words a fresh grant and a
14
+ * lapsed one get; the surface renders those words and reports the click. `render()` hands back the
15
+ * surface's own host element rather than a template, because every gate is still a lit template
16
+ * that interpolates the offer beside the key form — see `surfaces/ai-managed-connect.ts` for why
17
+ * that element is the mount point and why re-rendering the gate cannot disturb it.
18
+ *
12
19
  * State is per-instance (closure-scoped) like the credentials form; the capability probe behind
13
20
  * `ensureProbe` is shared module-wide by services/ai-models.ts.
14
21
  *
@@ -16,8 +23,6 @@
16
23
  * @license MIT
17
24
  */
18
25
 
19
- import { html, nothing } from "lit-html";
20
- import type { TemplateResult } from "lit-html";
21
26
  import { getPlatform, hasPlatform } from "../platform";
22
27
  import {
23
28
  ensureProxyProbe,
@@ -27,6 +32,8 @@ import {
27
32
  proxyStateCode,
28
33
  resetModelCache,
29
34
  } from "../services/ai-models";
35
+ import { createManagedConnectSurface } from "../surfaces/ai-managed-connect";
36
+ import type { ManagedConnectSurface, ManagedConnectView } from "../surfaces/ai-managed-connect";
30
37
  import type { CfConnectOutcome } from "../types";
31
38
 
32
39
  export interface ManagedConnectOptions {
@@ -39,10 +46,27 @@ export interface ManagedConnect {
39
46
  canOffer: () => boolean;
40
47
  /** Fire the shared capability probe, repainting the host when it settles. */
41
48
  ensureProbe: () => void;
42
- /** The CTA block, or `nothing` when the platform cannot broker AI. */
43
- render: () => TemplateResult | typeof nothing;
49
+ /**
50
+ * The CTA block's host element, or `null` when the platform cannot broker AI.
51
+ *
52
+ * A gate interpolates it into its own lit template, which inserts a Node it is handed as-is;
53
+ * `null` clears that position exactly as `nothing` did.
54
+ */
55
+ render: () => HTMLElement | null;
44
56
  }
45
57
 
58
+ /**
59
+ * A lede that says which path is recommended, and one that explains why the button is back.
60
+ *
61
+ * A lapsed grant and a fresh one get different words. The backend distinguishes them because
62
+ * "connect" is an invitation and "reconnect" is an explanation — and on a managed platform the
63
+ * lapsed case is the common one: a Cloudflare access token lives an hour.
64
+ */
65
+ const LEDE_FRESH =
66
+ "Recommended — run the assistant on Workers AI in your own Cloudflare account. No API key to create, copy or rotate.";
67
+ const LEDE_LAPSED =
68
+ "Your Cloudflare connection has expired. Reconnect to keep using the assistant.";
69
+
46
70
  /**
47
71
  * Create a managed-connect controller bound to a host's render scheduler.
48
72
  *
@@ -52,6 +76,8 @@ export interface ManagedConnect {
52
76
  export function createManagedConnect(opts: ManagedConnectOptions): ManagedConnect {
53
77
  let busy = false;
54
78
  let connectError = "";
79
+ /** Made on the first render that offers, and kept for the life of the controller. */
80
+ let surface: ManagedConnectSurface | null = null;
55
81
 
56
82
  /*
57
83
  * Offer the keyless path when the proxy is managed and the platform can run the hosted OAuth flow
@@ -137,40 +163,32 @@ export function createManagedConnect(opts: ManagedConnectOptions): ManagedConnec
137
163
  opts.requestRender();
138
164
  }
139
165
 
140
- function render(): TemplateResult | typeof nothing {
166
+ /** What the offer says right now — the whole of what the surface is told. */
167
+ function view(): ManagedConnectView {
168
+ const lapsed = proxyStateCode() === "cf_reconnect_required";
169
+ const idleLabel = lapsed ? "Reconnect Cloudflare" : "Connect Cloudflare";
170
+ return {
171
+ buttonLabel: busy ? (lapsed ? "Reconnecting…" : "Connecting…") : idleLabel,
172
+ busy,
173
+ error: connectError,
174
+ intro: lapsed ? LEDE_LAPSED : LEDE_FRESH,
175
+ };
176
+ }
177
+
178
+ function render(): HTMLElement | null {
141
179
  if (!canOffer()) {
142
- return nothing;
180
+ return null;
143
181
  }
144
- /*
145
- * A lapsed grant and a fresh one get different words. The backend distinguishes them because
146
- * "connect" is an invitation and "reconnect" is an explanation — and on a managed platform the
147
- * lapsed case is the common one: a Cloudflare access token lives an hour.
148
- */
149
- const lapsed = proxyStateCode() === "cf_reconnect_required";
150
- const busyLabel = lapsed ? "Reconnecting…" : "Connecting…";
151
- return html`
152
- <div class="ai-managed-connect" data-jx-recommended="cloudflare">
153
- <div class="ai-managed-connect-lede">
154
- ${
155
- lapsed
156
- ? "Your Cloudflare connection has expired. Reconnect to keep using the assistant."
157
- : "Recommended — run the assistant on Workers AI in your own Cloudflare account. No API key to create, copy or rotate."
158
- }
159
- </div>
160
- <sp-button
161
- size="s"
162
- variant="accent"
163
- ?disabled=${busy}
164
- @click=${() => {
165
- void connect();
166
- }}
167
- >
168
- ${busy ? busyLabel : lapsed ? "Reconnect Cloudflare" : "Connect Cloudflare"}
169
- </sp-button>
170
- ${connectError ? html`<div class="ai-managed-connect-error">${connectError}</div>` : nothing}
171
- <div class="ai-managed-connect-divider">— or bring your own key —</div>
172
- </div>
173
- `;
182
+ if (surface) {
183
+ surface.update(view());
184
+ } else {
185
+ surface = createManagedConnectSurface(view(), {
186
+ connect: () => {
187
+ void connect();
188
+ },
189
+ });
190
+ }
191
+ return surface.host;
174
192
  }
175
193
 
176
194
  return { canOffer, ensureProbe, render };
@@ -1,6 +1,6 @@
1
1
  /// <reference lib="dom" />
2
2
  /**
3
- * Ai-model-picker.ts — the provider's model catalogue as one `sp-picker`, for every surface that
3
+ * Ai-model-picker.ts — the provider's model catalogue as one control, for every surface that
4
4
  * chooses a model.
5
5
  *
6
6
  * It was private to `panels/ai-chat/composer.ts`, which was correct while the chat composer was the
@@ -14,14 +14,18 @@
14
14
  * and the catalogue becomes UNAVAILABLE rather than stale. Holding it in a closure is what once let
15
15
  * the picker offer one provider's models while another was configured.
16
16
  *
17
+ * This module is the FLOW; `surfaces/ai-model-picker.json` is what it draws. `render()` hands back
18
+ * the surface's own host element rather than a template, because both hosts are still lit templates
19
+ * that interpolate the picker into a row of their own — see `surfaces/ai-model-picker.ts` for why
20
+ * that element is the mount point and why re-rendering the row cannot disturb it.
21
+ *
17
22
  * A closure factory (precedent: `createComposer`, `createAiCredentialsForm`) so two hosts never
18
23
  * share a loading flag or a failed-fetch record.
19
24
  *
25
+ * @docs studio/ai
20
26
  * @license MIT
21
27
  */
22
28
 
23
- import { html, nothing } from "lit-html";
24
- import { live } from "lit-html/directives/live.js";
25
29
  import {
26
30
  aiConnection,
27
31
  cachedModels,
@@ -30,14 +34,17 @@ import {
30
34
  preferredModel,
31
35
  } from "../services/ai-models";
32
36
  import { setModel } from "../services/ai-settings";
37
+ import { createModelPickerSurface } from "../surfaces/ai-model-picker";
33
38
 
34
- import type { TemplateResult } from "lit-html";
35
39
  import type { AiCredentials } from "../services/ai-models";
36
-
37
- /** The `sp-menu-item` value that means "try listing again" rather than "select this model". */
38
- export const RETRY_MODELS = "__retry_models__";
39
-
40
- /** The `sp-menu-item` value of the disabled placeholder shown during the first fetch. */
40
+ import type {
41
+ ModelPickerRow,
42
+ ModelPickerSurface,
43
+ ModelPickerView,
44
+ ModelPickerWidth,
45
+ } from "../surfaces/ai-model-picker";
46
+
47
+ /** The row value of the disabled placeholder shown during the first listing. */
41
48
  export const LOADING_MODELS = "__loading__";
42
49
 
43
50
  /** What a listed model's row says when the backend reported it cannot call tools. */
@@ -70,14 +77,26 @@ export interface ModelPickerOptions {
70
77
  * the assistant.
71
78
  */
72
79
  onChange?: (id: string) => void;
73
- /** Extra class on the `sp-picker`, so a host can size it without touching this module. */
74
- className?: string;
75
- /** Picker size; `"s"` (the composer's) by default. */
76
- size?: "s" | "m";
80
+ /**
81
+ * Which of the surface's two shapes to draw. `"compact"` (the composer's) by default; the Import
82
+ * form's field column asks for `"fill"`.
83
+ *
84
+ * This replaced a `className`. A document styles through `part` rather than through a class
85
+ * (`ui.md` §3.1), so the two rules the hosts used to supply are one attribute the document
86
+ * branches on — and a host can no longer reach in and restyle a control it does not own.
87
+ */
88
+ width?: ModelPickerWidth;
89
+ /** Control size; `"sm"` (the composer's) by default. */
90
+ size?: "sm" | "md";
77
91
  }
78
92
 
79
93
  export interface ModelPicker {
80
- render: () => TemplateResult;
94
+ /**
95
+ * The picker's host element.
96
+ *
97
+ * A host interpolates it into its own lit template, which inserts a Node it is handed as-is.
98
+ */
99
+ render: () => HTMLElement;
81
100
  /** Whether a fetch is in flight — for a host that wants to disable a submit button. */
82
101
  isLoading: () => boolean;
83
102
  /** The last fetch's failure, or `""`. */
@@ -110,6 +129,9 @@ export function createModelPicker(opts: ModelPickerOptions): ModelPicker {
110
129
  */
111
130
  let attempted: AiCredentials | null = null;
112
131
 
132
+ /** Made on the first render, and kept for the life of the controller. */
133
+ let surface: ModelPickerSurface | null = null;
134
+
113
135
  function sameConnection(a: AiCredentials | null, b: AiCredentials): boolean {
114
136
  return a !== null && a.apiKey === b.apiKey && a.baseUrl === b.baseUrl;
115
137
  }
@@ -133,22 +155,23 @@ export function createModelPicker(opts: ModelPickerOptions): ModelPicker {
133
155
  });
134
156
  }
135
157
 
136
- function onPickerChange(e: Event) {
137
- const { value } = e.target as HTMLInputElement;
138
- if (value === RETRY_MODELS) {
139
- attempted = null;
140
- ensureModels(true);
141
- // Re-render so the picker snaps back to the current model instead of showing "Retry".
142
- opts.requestRender();
143
- return;
144
- }
158
+ /** List again, from the beginning: a refusal is forgotten so the same credentials are re-asked. */
159
+ function retry() {
160
+ attempted = null;
161
+ ensureModels(true);
162
+ opts.requestRender();
163
+ }
164
+
165
+ function choose(value: string) {
166
+ /* The placeholder is disabled, so a reader cannot land on it; a host driving the control
167
+ directly still can, and a state is not a model. */
145
168
  if (value && value !== LOADING_MODELS) {
146
169
  onChange(value);
147
170
  }
148
171
  }
149
172
 
150
- function render(): TemplateResult {
151
- ensureModels();
173
+ /** The rows to offer — what the catalogue holds, plus the one state that is worth a row. */
174
+ function rows(): ModelPickerRow[] {
152
175
  const current = getModel();
153
176
  const listed = cachedModels(aiConnection()) ?? [];
154
177
  /* A catalogue that does not contain the current model still has to show it selected — an
@@ -156,28 +179,33 @@ export function createModelPicker(opts: ModelPickerOptions): ModelPicker {
156
179
  const items = listed.some((m) => m.id === current)
157
180
  ? listed
158
181
  : [{ id: current, name: current }, ...listed];
159
- return html`
160
- <sp-picker
161
- size=${opts.size ?? "s"}
162
- quiet
163
- class=${opts.className ?? "ai-model-picker"}
164
- title=${failure ? `Couldn't load models: ${failure}` : "Model"}
165
- .value=${live(current)}
166
- @change=${onPickerChange}
167
- >
168
- ${items.map((m) => html`<sp-menu-item value=${m.id}>${itemLabel(m)}</sp-menu-item>`)}
169
- ${
170
- loading
171
- ? html`<sp-menu-item disabled value=${LOADING_MODELS}>Loading models…</sp-menu-item>`
172
- : nothing
173
- }
174
- ${
175
- failure
176
- ? html`<sp-menu-item value=${RETRY_MODELS}>Retry loading models</sp-menu-item>`
177
- : nothing
178
- }
179
- </sp-picker>
180
- `;
182
+ const offered: ModelPickerRow[] = items.map((m) => ({ label: itemLabel(m), value: m.id }));
183
+ if (loading) {
184
+ offered.push({ disabled: true, label: "Loading models…", value: LOADING_MODELS });
185
+ }
186
+ return offered;
187
+ }
188
+
189
+ /** What the picker says right now — the whole of what the surface is told. */
190
+ function view(): ModelPickerView {
191
+ return {
192
+ failure,
193
+ hint: failure ? `Couldn't load models: ${failure}` : "Model",
194
+ options: rows(),
195
+ size: opts.size ?? "sm",
196
+ value: getModel(),
197
+ width: opts.width ?? "compact",
198
+ };
199
+ }
200
+
201
+ function render(): HTMLElement {
202
+ ensureModels();
203
+ if (surface) {
204
+ surface.update(view());
205
+ } else {
206
+ surface = createModelPickerSurface(view(), { choose, retry });
207
+ }
208
+ return surface.host;
181
209
  }
182
210
 
183
211
  return {