@jxsuite/studio 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (419) hide show
  1. package/canvas.html +21 -0
  2. package/dist/chunks/Overlay.dev-qfjzkms8.js +23 -0
  3. package/dist/chunks/{Overlay.dev-cszx7yn5.js.map → Overlay.dev-qfjzkms8.js.map} +1 -1
  4. package/dist/chunks/{adapter-z8fkmbmv.js → adapter-qfnesn5v.js} +2 -2
  5. package/dist/chunks/{cf-settings-mmyv436d.js → cf-settings-73sh5z4p.js} +3 -3
  6. package/dist/chunks/{components-0hzentwq.js → components-2bpqp4mq.js} +5 -7
  7. package/dist/chunks/{components-0hzentwq.js.map → components-2bpqp4mq.js.map} +1 -1
  8. package/dist/chunks/content-source-34gnkbnn.js +38 -0
  9. package/dist/chunks/content-source-34gnkbnn.js.map +9 -0
  10. package/dist/chunks/convert-to-repeater-t8kxre5s.js +258 -0
  11. package/dist/chunks/convert-to-repeater-t8kxre5s.js.map +10 -0
  12. package/dist/chunks/extension-sections-6mqydz35.js +301 -0
  13. package/dist/chunks/extension-sections-6mqydz35.js.map +11 -0
  14. package/dist/chunks/files-8kn321h1.js +70 -0
  15. package/dist/chunks/files-8kn321h1.js.map +9 -0
  16. package/dist/chunks/{format-host-2c188n41.js → format-host-mkwsmt8d.js} +3 -3
  17. package/dist/chunks/git-panel-tjbr191d.js +51 -0
  18. package/dist/chunks/git-panel-tjbr191d.js.map +9 -0
  19. package/dist/chunks/{index-baeg2x3y.js → index-7pxchcce.js} +4 -3
  20. package/dist/chunks/{index-baeg2x3y.js.map → index-7pxchcce.js.map} +3 -3
  21. package/dist/chunks/{jx-validate-qx8degj7.js → jx-validate-v6qgknrs.js} +3 -3
  22. package/dist/chunks/layers-panel-87pb25km.js +58 -0
  23. package/dist/chunks/layers-panel-87pb25km.js.map +9 -0
  24. package/dist/chunks/{monaco-setup-zjdp9zdw.js → monaco-setup-e0yh25j4.js} +4 -75
  25. package/dist/chunks/{monaco-setup-zjdp9zdw.js.map → monaco-setup-e0yh25j4.js.map} +3 -4
  26. package/dist/chunks/publish-panel-m0fcgdrt.js +21 -0
  27. package/dist/chunks/publish-panel-m0fcgdrt.js.map +9 -0
  28. package/dist/chunks/quick-search-rhs6cbsb.js +53 -0
  29. package/dist/chunks/quick-search-rhs6cbsb.js.map +9 -0
  30. package/dist/chunks/right-panel-zpdxd98t.js +37 -0
  31. package/dist/chunks/right-panel-zpdxd98t.js.map +9 -0
  32. package/dist/chunks/section-registry-zmckaxf4.js +30 -0
  33. package/dist/chunks/section-registry-zmckaxf4.js.map +9 -0
  34. package/dist/chunks/sp-overlay.dev-9ran0sfq.js +18 -0
  35. package/dist/chunks/sp-overlay.dev-9ran0sfq.js.map +9 -0
  36. package/dist/chunks/sp-popover.dev-rebmdncr.js +9 -0
  37. package/dist/chunks/sp-popover.dev-rebmdncr.js.map +9 -0
  38. package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js +15 -0
  39. package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js.map +9 -0
  40. package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js +15 -0
  41. package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js.map +9 -0
  42. package/dist/chunks/{sp-tray.dev-pb2fsd65.js → sp-tray.dev-ey59vfh7.js} +10 -8
  43. package/dist/chunks/{sp-tray.dev-pb2fsd65.js.map → sp-tray.dev-ey59vfh7.js.map} +2 -2
  44. package/dist/chunks/{studio-9qr6fq7p.js → studio-0rqqhrdy.js} +10 -378
  45. package/dist/chunks/{studio-9qr6fq7p.js.map → studio-0rqqhrdy.js.map} +4 -14
  46. package/dist/chunks/{studio-5x6tqqec.js → studio-2sj1jj3v.js} +10 -8
  47. package/dist/chunks/{studio-5x6tqqec.js.map → studio-2sj1jj3v.js.map} +2 -2
  48. package/dist/chunks/{studio-h3fw0wn8.js → studio-3fk1ac9z.js} +6 -4
  49. package/dist/chunks/{studio-h3fw0wn8.js.map → studio-3fk1ac9z.js.map} +2 -2
  50. package/dist/chunks/studio-41exgzhq.js +6690 -0
  51. package/dist/chunks/studio-41exgzhq.js.map +38 -0
  52. package/dist/chunks/{studio-7v2bpweq.js → studio-4mqb9a0j.js} +6 -4
  53. package/dist/chunks/{studio-7v2bpweq.js.map → studio-4mqb9a0j.js.map} +2 -2
  54. package/dist/chunks/studio-50k77cca.js +1787 -0
  55. package/dist/chunks/studio-50k77cca.js.map +18 -0
  56. package/dist/chunks/{studio-56v3zwk6.js → studio-6a0h7sne.js} +10 -8
  57. package/dist/chunks/{studio-56v3zwk6.js.map → studio-6a0h7sne.js.map} +2 -2
  58. package/dist/chunks/studio-6f0am8f2.js +53 -0
  59. package/dist/chunks/studio-6f0am8f2.js.map +10 -0
  60. package/dist/chunks/studio-6nmjc5qk.js +7002 -0
  61. package/dist/chunks/studio-6nmjc5qk.js.map +32 -0
  62. package/dist/chunks/studio-7afd21nw.js +67 -0
  63. package/dist/chunks/studio-7afd21nw.js.map +10 -0
  64. package/dist/chunks/{studio-xze4zrs1.js → studio-7bmdvzne.js} +2 -2
  65. package/dist/chunks/studio-7bmdvzne.js.map +10 -0
  66. package/dist/chunks/studio-8jpzqk5s.js +128 -0
  67. package/dist/chunks/studio-8jpzqk5s.js.map +10 -0
  68. package/dist/chunks/studio-94m77tgk.js +1482 -0
  69. package/dist/chunks/studio-94m77tgk.js.map +13 -0
  70. package/dist/chunks/studio-9je6w5sq.js +1000 -0
  71. package/dist/chunks/studio-9je6w5sq.js.map +16 -0
  72. package/dist/chunks/{studio-w7c6kvk7.js → studio-a7pzveq1.js} +2 -2
  73. package/dist/chunks/{studio-97qcgvdn.js → studio-adn0z1k3.js} +14 -8
  74. package/dist/chunks/{studio-97qcgvdn.js.map → studio-adn0z1k3.js.map} +3 -3
  75. package/dist/chunks/{studio-kr88ryr7.js → studio-bsxxx3x2.js} +17 -15
  76. package/dist/chunks/{studio-kr88ryr7.js.map → studio-bsxxx3x2.js.map} +7 -6
  77. package/dist/chunks/studio-bw5dz6km.js +608 -0
  78. package/dist/chunks/studio-bw5dz6km.js.map +21 -0
  79. package/dist/chunks/studio-c6s5getc.js +4232 -0
  80. package/dist/chunks/studio-c6s5getc.js.map +39 -0
  81. package/dist/chunks/studio-cjm7fdjf.js +451 -0
  82. package/dist/chunks/studio-cjm7fdjf.js.map +14 -0
  83. package/dist/chunks/{studio-cx91mnh8.js → studio-ckwz4d3x.js} +53 -53
  84. package/dist/chunks/{studio-cx91mnh8.js.map → studio-ckwz4d3x.js.map} +5 -5
  85. package/dist/chunks/studio-dg7zyt5x.js +28 -0
  86. package/dist/chunks/studio-dg7zyt5x.js.map +10 -0
  87. package/dist/chunks/studio-dzcyvvvz.js +166 -0
  88. package/dist/chunks/studio-dzcyvvvz.js.map +10 -0
  89. package/dist/chunks/{studio-7kqe41sa.js → studio-evkr5d3b.js} +15 -7
  90. package/dist/chunks/{studio-7kqe41sa.js.map → studio-evkr5d3b.js.map} +5 -4
  91. package/dist/chunks/studio-f12h6177.js +411 -0
  92. package/dist/chunks/studio-f12h6177.js.map +13 -0
  93. package/dist/chunks/studio-hbp1s8m9.js +1817 -0
  94. package/dist/chunks/studio-hbp1s8m9.js.map +14 -0
  95. package/dist/chunks/studio-k2sxjph5.js +15295 -0
  96. package/dist/chunks/studio-k2sxjph5.js.map +235 -0
  97. package/dist/chunks/studio-myje51t3.js +385 -0
  98. package/dist/chunks/studio-myje51t3.js.map +12 -0
  99. package/dist/chunks/studio-na6rwzhw.js +353 -0
  100. package/dist/chunks/studio-na6rwzhw.js.map +11 -0
  101. package/dist/chunks/{studio-4k0m4fmp.js → studio-p471gg5n.js} +126 -3
  102. package/dist/chunks/studio-p471gg5n.js.map +14 -0
  103. package/dist/chunks/{studio-9bjwf0d4.js → studio-rgwcpast.js} +5 -46
  104. package/dist/chunks/{studio-9bjwf0d4.js.map → studio-rgwcpast.js.map} +4 -5
  105. package/dist/chunks/{studio-hhj92gcr.js → studio-s519zc99.js} +3 -3
  106. package/dist/chunks/studio-sas7mt3k.js +75 -0
  107. package/dist/chunks/studio-sas7mt3k.js.map +10 -0
  108. package/dist/chunks/studio-t5wqwzdh.js +74 -0
  109. package/dist/chunks/studio-t5wqwzdh.js.map +10 -0
  110. package/dist/chunks/{studio-9qpspwfn.js → studio-temv5bw4.js} +5 -5
  111. package/dist/chunks/{studio-9qpspwfn.js.map → studio-temv5bw4.js.map} +1 -1
  112. package/dist/chunks/{studio-qkvt37c0.js → studio-tr20m8g8.js} +669 -18
  113. package/dist/chunks/studio-tr20m8g8.js.map +9 -0
  114. package/dist/chunks/{studio-ygzav7z5.js → studio-v96qfnww.js} +5514 -4291
  115. package/dist/chunks/studio-v96qfnww.js.map +54 -0
  116. package/dist/chunks/studio-vcetc91k.js +659 -0
  117. package/dist/chunks/studio-vcetc91k.js.map +10 -0
  118. package/dist/chunks/{studio-n9zmpxjg.js → studio-vmymjefp.js} +2972 -4937
  119. package/dist/chunks/studio-vmymjefp.js.map +98 -0
  120. package/dist/chunks/{studio-bghqfmea.js → studio-wwseqyw0.js} +2 -2
  121. package/dist/chunks/studio-x9hmy5kr.js +390 -0
  122. package/dist/chunks/studio-x9hmy5kr.js.map +10 -0
  123. package/dist/chunks/studio-xa0ce0n7.js +335 -0
  124. package/dist/chunks/studio-xa0ce0n7.js.map +10 -0
  125. package/dist/chunks/studio-xm3dbxvn.js +378 -0
  126. package/dist/chunks/studio-xm3dbxvn.js.map +19 -0
  127. package/dist/chunks/{studio-nqw433kv.js → studio-xmvbhg31.js} +2 -2
  128. package/dist/chunks/studio-zv37yrfa.js +1054 -0
  129. package/dist/chunks/studio-zv37yrfa.js.map +13 -0
  130. package/dist/chunks/{ws-client-q7hkz3j9.js → ws-client-654ts66j.js} +6 -4
  131. package/dist/chunks/ws-client-654ts66j.js.map +11 -0
  132. package/dist/iframe-entry.js +668 -230
  133. package/dist/studio.js +23711 -35185
  134. package/index.html +35 -4685
  135. package/package.json +17 -15
  136. package/src/about/about-modal.ts +42 -11
  137. package/src/browse/library-commands.ts +240 -0
  138. package/src/browse/library-layouts.ts +369 -0
  139. package/src/browse/library-model.ts +396 -0
  140. package/src/browse/library-pane.ts +1049 -0
  141. package/src/browse/library-preview.ts +252 -0
  142. package/src/browse/library-source.ts +150 -0
  143. package/src/canvas/canvas-helpers.ts +33 -9
  144. package/src/canvas/canvas-live-render.ts +45 -29
  145. package/src/canvas/canvas-patcher.ts +151 -31
  146. package/src/canvas/canvas-perf.ts +46 -7
  147. package/src/canvas/canvas-render.ts +1092 -220
  148. package/src/canvas/canvas-surface.ts +240 -0
  149. package/src/canvas/canvas-utils.ts +1166 -124
  150. package/src/canvas/iframe-drop.ts +2 -1
  151. package/src/canvas/iframe-entry.ts +241 -4
  152. package/src/canvas/iframe-host.ts +1226 -143
  153. package/src/canvas/iframe-inline-edit.ts +31 -0
  154. package/src/canvas/iframe-interaction.ts +76 -16
  155. package/src/canvas/iframe-keys.ts +107 -45
  156. package/src/canvas/iframe-overlay.ts +38 -1
  157. package/src/canvas/iframe-protocol.ts +137 -2
  158. package/src/canvas/iframe-render.ts +70 -2
  159. package/src/canvas/iframe-slash.ts +6 -0
  160. package/src/canvas/path-mapping.ts +56 -6
  161. package/src/canvas/surface-registry.ts +292 -0
  162. package/src/collab/collab-commands.ts +244 -0
  163. package/src/collab/collab-session.ts +198 -32
  164. package/src/collab/collab-state.ts +28 -2
  165. package/src/collab/presence-chips.ts +100 -9
  166. package/src/commands/active-registry.ts +42 -0
  167. package/src/commands/app-commands.ts +176 -0
  168. package/src/commands/budget.ts +158 -0
  169. package/src/commands/command-args.ts +253 -0
  170. package/src/commands/context.ts +387 -0
  171. package/src/commands/defaults.ts +580 -0
  172. package/src/commands/keymap.ts +571 -0
  173. package/src/commands/levels.ts +345 -0
  174. package/src/commands/live-context.ts +193 -0
  175. package/src/commands/reference.ts +227 -0
  176. package/src/commands/registry.ts +293 -0
  177. package/src/component-props.ts +3 -2
  178. package/src/content/draft-state.ts +106 -0
  179. package/src/content/entry-commands.ts +282 -0
  180. package/src/content/entry-editor.ts +327 -0
  181. package/src/content/entry-fields.ts +116 -0
  182. package/src/content/entry-model.ts +175 -0
  183. package/src/editor/canvas-context-menu.ts +17 -11
  184. package/src/editor/canvas-slash-bridge.ts +11 -4
  185. package/src/editor/context-menu.ts +804 -204
  186. package/src/editor/convert-to-component.ts +31 -10
  187. package/src/editor/convert-to-repeater.ts +3 -2
  188. package/src/editor/inline-edit-apply.ts +5 -5
  189. package/src/editor/inline-edit.ts +86 -50
  190. package/src/editor/insert-zone-action.ts +1 -1
  191. package/src/editor/shortcuts.ts +1043 -329
  192. package/src/editor/slash-menu.ts +1 -0
  193. package/src/files/elements.ts +166 -0
  194. package/src/files/file-ops.ts +178 -31
  195. package/src/files/files.ts +898 -268
  196. package/src/files/fs-events.ts +21 -0
  197. package/src/files/media-meta.ts +203 -0
  198. package/src/files/media-paths.ts +141 -0
  199. package/src/files/media-upload.ts +7 -3
  200. package/src/files/media-usage.ts +189 -0
  201. package/src/github/github-auth.ts +235 -33
  202. package/src/github/github-publish.ts +80 -21
  203. package/src/grid/grid-controller.ts +152 -12
  204. package/src/grid/grid-layout.ts +225 -20
  205. package/src/grid/grid-open.ts +120 -0
  206. package/src/grid/grid-panel.ts +554 -39
  207. package/src/grid/grid-source.ts +27 -1
  208. package/src/grid/redirects-grid.ts +599 -0
  209. package/src/grid/redirects.ts +398 -0
  210. package/src/grid/sources/content-source.ts +108 -2
  211. package/src/i18n/i18n-commands.ts +322 -0
  212. package/src/new-project/add-repo-modal.ts +8 -10
  213. package/src/new-project/import-tab.ts +34 -9
  214. package/src/new-project/location-fields.ts +9 -1
  215. package/src/new-project/new-project-modal.ts +270 -262
  216. package/src/packages/jxsuite-update.ts +97 -48
  217. package/src/packages/pull-package-sync.ts +18 -9
  218. package/src/page-params.ts +2 -1
  219. package/src/panels/activity-bar.ts +152 -91
  220. package/src/panels/activity-panel.ts +481 -0
  221. package/src/panels/ai-chat/chat-markdown.ts +8 -3
  222. package/src/panels/ai-chat/chat-view.ts +245 -18
  223. package/src/panels/ai-chat/composer.ts +31 -5
  224. package/src/panels/ai-chat/sessions-view.ts +17 -10
  225. package/src/panels/ai-panel.ts +279 -120
  226. package/src/panels/block-action-bar.ts +1115 -224
  227. package/src/panels/bottom-dock.ts +337 -0
  228. package/src/panels/canvas-dnd-bridge.ts +37 -8
  229. package/src/panels/chat-panel.ts +29 -12
  230. package/src/panels/data-explorer.ts +254 -112
  231. package/src/panels/data-grid.ts +10 -4
  232. package/src/panels/dnd.ts +28 -51
  233. package/src/panels/editors.ts +434 -107
  234. package/src/panels/elements-panel.ts +66 -2
  235. package/src/panels/empty-state.ts +112 -0
  236. package/src/panels/events-panel.ts +596 -82
  237. package/src/panels/formula-workspace.ts +408 -218
  238. package/src/panels/frontmatter-fields.ts +51 -10
  239. package/src/panels/frontmatter-panel.ts +357 -79
  240. package/src/panels/git-panel.ts +375 -164
  241. package/src/panels/head-panel.ts +791 -85
  242. package/src/panels/i18n-panel.ts +592 -0
  243. package/src/panels/imports-panel.ts +95 -85
  244. package/src/panels/jump-bar.ts +584 -0
  245. package/src/panels/layers-panel.ts +1106 -328
  246. package/src/panels/left-panel.ts +109 -204
  247. package/src/panels/navigator-panels.ts +131 -0
  248. package/src/panels/overlays.ts +7 -2
  249. package/src/panels/pane-context.ts +1477 -0
  250. package/src/panels/pane-grid.ts +406 -0
  251. package/src/panels/panel-registry.ts +340 -0
  252. package/src/panels/panel-scheduler.ts +75 -0
  253. package/src/panels/problems-panel.ts +234 -0
  254. package/src/panels/properties-panel.ts +946 -1139
  255. package/src/panels/provenance.ts +258 -0
  256. package/src/panels/quick-search.ts +791 -122
  257. package/src/panels/right-panel.ts +228 -102
  258. package/src/panels/seo-modal.ts +395 -0
  259. package/src/panels/settings-pane.ts +203 -0
  260. package/src/panels/signals-panel.ts +354 -137
  261. package/src/panels/statement-editor.ts +41 -25
  262. package/src/panels/statusbar.ts +342 -106
  263. package/src/panels/style-panel.ts +974 -463
  264. package/src/panels/style-utils.ts +3 -3
  265. package/src/panels/stylebook-doc.ts +4 -2
  266. package/src/panels/stylebook-layers-panel.ts +3 -2
  267. package/src/panels/stylebook-panel.ts +51 -26
  268. package/src/panels/tab-strip.ts +1058 -78
  269. package/src/panels/target-line.ts +274 -0
  270. package/src/panels/toolbar.ts +631 -484
  271. package/src/panels/welcome-screen.ts +301 -198
  272. package/src/platform-errors.ts +26 -3
  273. package/src/platform.ts +96 -2
  274. package/src/platforms/cloud.ts +71 -8
  275. package/src/platforms/devserver.ts +92 -29
  276. package/src/publish/deploy-checklist.ts +383 -0
  277. package/src/publish/pages-service.ts +10 -1
  278. package/src/publish/publish-commands.ts +218 -0
  279. package/src/publish/publish-panel.ts +110 -16
  280. package/src/recent-projects.ts +3 -2
  281. package/src/services/a11y-report.ts +505 -0
  282. package/src/services/ai-models.ts +75 -2
  283. package/src/services/ai-project-tools.ts +29 -10
  284. package/src/services/ai-system-prompt.ts +53 -14
  285. package/src/services/ai-tools.ts +39 -3
  286. package/src/services/ai-writes.ts +154 -0
  287. package/src/services/announce.ts +97 -0
  288. package/src/services/automation.ts +424 -175
  289. package/src/services/cem-export.ts +9 -4
  290. package/src/services/clock.ts +61 -0
  291. package/src/services/document-assistant.ts +36 -8
  292. package/src/services/idle.ts +179 -0
  293. package/src/services/import-client.ts +26 -0
  294. package/src/services/monaco-buffer.ts +627 -0
  295. package/src/services/monaco-lazy.ts +36 -0
  296. package/src/services/notify.ts +271 -0
  297. package/src/services/profile.ts +155 -0
  298. package/src/services/references.ts +0 -0
  299. package/src/services/token-lint.ts +3 -2
  300. package/src/services/tool-executor.ts +53 -7
  301. package/src/services/trusted-types.ts +123 -0
  302. package/src/settings/contexts-section.ts +427 -0
  303. package/src/settings/contributed-section.ts +149 -11
  304. package/src/settings/css-vars-editor.ts +306 -349
  305. package/src/settings/defs-editor.ts +93 -34
  306. package/src/settings/dependencies-editor.ts +7 -7
  307. package/src/settings/extension-sections.ts +37 -5
  308. package/src/settings/general-settings.ts +204 -121
  309. package/src/settings/locales-section.ts +347 -0
  310. package/src/settings/preferences-accounts.ts +140 -0
  311. package/src/settings/preferences-dialog.ts +620 -0
  312. package/src/settings/preferences-keymap.ts +270 -0
  313. package/src/settings/project-sections.ts +260 -0
  314. package/src/settings/section-registry.ts +169 -0
  315. package/src/settings/settings-document.ts +385 -0
  316. package/src/shell.ts +1549 -0
  317. package/src/site-context.ts +45 -20
  318. package/src/state.ts +14 -275
  319. package/src/store.ts +88 -43
  320. package/src/studio.ts +790 -346
  321. package/src/style/live-preview.ts +36 -0
  322. package/src/style/project-styles.ts +349 -0
  323. package/src/style/token-ref.ts +123 -0
  324. package/src/tabs/patch-ops.ts +16 -4
  325. package/src/tabs/project-config.ts +416 -0
  326. package/src/tabs/selection.ts +323 -0
  327. package/src/tabs/tab.ts +182 -47
  328. package/src/tabs/transact.ts +209 -28
  329. package/src/types.ts +68 -13
  330. package/src/ui/ai-credentials-form.ts +39 -35
  331. package/src/ui/ai-managed-connect.ts +113 -0
  332. package/src/ui/dynamic-slot.ts +224 -81
  333. package/src/ui/expression-editor.ts +71 -63
  334. package/src/ui/field-input.ts +4 -6
  335. package/src/ui/field-row.ts +215 -38
  336. package/src/ui/form-controls.ts +194 -7
  337. package/src/ui/layers.ts +492 -69
  338. package/src/ui/media-picker.ts +115 -25
  339. package/src/ui/panel-resize.ts +109 -91
  340. package/src/ui/progress-modal.ts +131 -50
  341. package/src/ui/regions.ts +462 -0
  342. package/src/ui/schema-form.ts +229 -45
  343. package/src/ui/spectrum.ts +24 -8
  344. package/src/ui/timing.ts +49 -0
  345. package/src/ui/value-selector.ts +20 -0
  346. package/src/ui/value-source.ts +348 -0
  347. package/src/ui/virtual-window.ts +400 -0
  348. package/src/utils/edit-display.ts +3 -2
  349. package/src/utils/inherited-style.ts +67 -37
  350. package/src/view.ts +64 -78
  351. package/src/workspace/pane-derive.ts +1258 -0
  352. package/src/workspace/session.ts +317 -0
  353. package/src/workspace/workspace.ts +1345 -23
  354. package/styles/canvas.css +653 -0
  355. package/styles/forced-colors.css +106 -0
  356. package/styles/inspector.css +1454 -0
  357. package/styles/overlays.css +2704 -0
  358. package/styles/panels.css +1701 -0
  359. package/styles/shell.css +1423 -0
  360. package/styles/tokens.css +151 -0
  361. package/dist/chunks/Overlay.dev-cszx7yn5.js +0 -22
  362. package/dist/chunks/extension-sections-qct0gt8f.js +0 -531
  363. package/dist/chunks/extension-sections-qct0gt8f.js.map +0 -12
  364. package/dist/chunks/files-02zn5y24.js +0 -50
  365. package/dist/chunks/files-02zn5y24.js.map +0 -9
  366. package/dist/chunks/git-panel-mbb0y0hz.js +0 -28
  367. package/dist/chunks/git-panel-mbb0y0hz.js.map +0 -9
  368. package/dist/chunks/layers-panel-9qekmqk1.js +0 -26
  369. package/dist/chunks/layers-panel-9qekmqk1.js.map +0 -9
  370. package/dist/chunks/settings-modal-gj0hrah4.js +0 -29
  371. package/dist/chunks/settings-modal-gj0hrah4.js.map +0 -9
  372. package/dist/chunks/sp-overlay.dev-earn5as8.js +0 -17
  373. package/dist/chunks/sp-overlay.dev-earn5as8.js.map +0 -9
  374. package/dist/chunks/sp-popover.dev-frxtfejn.js +0 -8
  375. package/dist/chunks/sp-popover.dev-frxtfejn.js.map +0 -9
  376. package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js +0 -14
  377. package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js.map +0 -9
  378. package/dist/chunks/sp-tooltip.dev-a9fywesm.js +0 -21
  379. package/dist/chunks/sp-tooltip.dev-a9fywesm.js.map +0 -10
  380. package/dist/chunks/studio-4k0m4fmp.js.map +0 -13
  381. package/dist/chunks/studio-568nx4t5.js +0 -469
  382. package/dist/chunks/studio-568nx4t5.js.map +0 -14
  383. package/dist/chunks/studio-9smfzqhc.js +0 -19
  384. package/dist/chunks/studio-9smfzqhc.js.map +0 -10
  385. package/dist/chunks/studio-asvf0j9e.js +0 -429
  386. package/dist/chunks/studio-asvf0j9e.js.map +0 -13
  387. package/dist/chunks/studio-d77qm3pk.js +0 -3427
  388. package/dist/chunks/studio-d77qm3pk.js.map +0 -26
  389. package/dist/chunks/studio-j6gqyjf4.js +0 -1854
  390. package/dist/chunks/studio-j6gqyjf4.js.map +0 -18
  391. package/dist/chunks/studio-n9zmpxjg.js.map +0 -115
  392. package/dist/chunks/studio-qkvt37c0.js.map +0 -9
  393. package/dist/chunks/studio-rq0vxb19.js +0 -3744
  394. package/dist/chunks/studio-rq0vxb19.js.map +0 -22
  395. package/dist/chunks/studio-wd6ewdvd.js +0 -853
  396. package/dist/chunks/studio-wd6ewdvd.js.map +0 -12
  397. package/dist/chunks/studio-xq0t7n5t.js +0 -140
  398. package/dist/chunks/studio-xq0t7n5t.js.map +0 -10
  399. package/dist/chunks/studio-xze4zrs1.js.map +0 -10
  400. package/dist/chunks/studio-ygzav7z5.js.map +0 -46
  401. package/dist/chunks/studio-zmy7241e.js +0 -399
  402. package/dist/chunks/studio-zmy7241e.js.map +0 -12
  403. package/dist/chunks/ws-client-q7hkz3j9.js.map +0 -11
  404. package/src/browse/browse-modal.ts +0 -69
  405. package/src/browse/browse.ts +0 -904
  406. package/src/canvas/canvas-diff.ts +0 -216
  407. package/src/canvas/nested-site-style.ts +0 -58
  408. package/src/new-project/design-fields.ts +0 -264
  409. package/src/new-project/templates.ts +0 -61
  410. package/src/panels/tab-bar.ts +0 -548
  411. package/src/settings/settings-modal.ts +0 -203
  412. /package/dist/chunks/{adapter-z8fkmbmv.js.map → adapter-qfnesn5v.js.map} +0 -0
  413. /package/dist/chunks/{cf-settings-mmyv436d.js.map → cf-settings-73sh5z4p.js.map} +0 -0
  414. /package/dist/chunks/{format-host-2c188n41.js.map → format-host-mkwsmt8d.js.map} +0 -0
  415. /package/dist/chunks/{jx-validate-qx8degj7.js.map → jx-validate-v6qgknrs.js.map} +0 -0
  416. /package/dist/chunks/{studio-w7c6kvk7.js.map → studio-a7pzveq1.js.map} +0 -0
  417. /package/dist/chunks/{studio-hhj92gcr.js.map → studio-s519zc99.js.map} +0 -0
  418. /package/dist/chunks/{studio-bghqfmea.js.map → studio-wwseqyw0.js.map} +0 -0
  419. /package/dist/chunks/{studio-nqw433kv.js.map → studio-xmvbhg31.js.map} +0 -0
@@ -5,9 +5,17 @@
5
5
  * Maps schema property types to Spectrum controls (enum → picker, boolean → checkbox,
6
6
  * number/integer → number-field, `json-schema` format → multiline JSON editor, array-of-objects →
7
7
  * multi-row inline form, other array/object → JSON text field, default → textfield). Hosts commit
8
- * edits through a single `onChange(patch)` callback; dynamic enum choices and `$ref` bindings
9
- * resolve through a {@link SchemaFormContext}. Custom controls register by name via
10
- * {@link registerFormControl} and are consulted first for `ui` overrides.
8
+ * edits through a single `onChange(patch)` callback; dynamic enum choices resolve through a
9
+ * {@link SchemaFormContext}. Custom controls register by name via {@link registerFormControl} and
10
+ * are consulted first for `ui` overrides.
11
+ *
12
+ * **Binding is the same ladder as everywhere else** (§6.6). A host that names somewhere a value can
13
+ * come from — route params, the document's signals — gets a Value Source chip on every scalar
14
+ * field, drawn by `ui/dynamic-slot.ts` and named by `ui/value-source.ts`. It replaces two things: a
15
+ * private `Static value / $params/… / Custom…` picker that mounted only when the field ALREADY held
16
+ * a `$ref` (so no form had a gesture for starting a binding at all), and a link button beside the
17
+ * textfield that silently committed the first route param. A host that names no source — the
18
+ * project settings forms — draws no chip and edits fixed values, exactly as before.
11
19
  */
12
20
 
13
21
  import { html, nothing } from "lit-html";
@@ -16,7 +24,11 @@ import { live } from "lit-html/directives/live.js";
16
24
  import { styleMap } from "lit-html/directives/style-map.js";
17
25
  import { isRef } from "@jxsuite/schema/guards";
18
26
  import { renderFieldRow } from "./field-row";
27
+ import { renderDynamicSlot } from "./dynamic-slot";
28
+ import { configFieldSchema } from "./value-source";
19
29
  import type { TemplateResult } from "lit-html";
30
+ import type { SignalOption } from "./dynamic-slot";
31
+ import type { JsonValue } from "../types";
20
32
 
21
33
  /** A (possibly nested) JSON Schema node, covering both object and property level keys. */
22
34
  export interface JsonSchema {
@@ -32,6 +44,12 @@ export interface JsonSchema {
32
44
  examples?: string[];
33
45
  name?: string;
34
46
  items?: JsonSchema;
47
+ /**
48
+ * A pointer to another schema. `#/content/<type>` is the one this engine acts on: it is how
49
+ * site-architecture.md §6.1 declares a relationship between collections, and it is what the
50
+ * schema-builder writes (`form-controls.ts`'s `onChangeRefTarget`).
51
+ */
52
+ $ref?: string;
35
53
  }
36
54
 
37
55
  /** Host-provided context threaded to every control. */
@@ -40,7 +58,13 @@ export interface SchemaFormContext {
40
58
  resolvePointer: (pointer: string, scope?: Record<string, unknown>) => unknown;
41
59
  /** Route params available for `$ref` bindings (e.g. from the document path). */
42
60
  params?: string[] | undefined;
43
- /** Unique prefix for per-field ephemeral UI state (e.g. the binding control's custom mode). */
61
+ /**
62
+ * State keys a field may bind to. Together with {@link params} this is the whole answer to "where
63
+ * could this value come from" — and naming none of them is how a host says the form edits fixed
64
+ * values only, which is why the settings forms show no Value Source chip.
65
+ */
66
+ signals?: string[] | undefined;
67
+ /** Unique prefix for the dynamic slot's per-field, per-rung value memory. */
44
68
  fieldKeyPrefix?: string | undefined;
45
69
  /**
46
70
  * Commit hook for the "secret" control: stores the VALUE in the platform's secret store (never
@@ -73,6 +97,30 @@ export interface RenderFormOptions {
73
97
  */
74
98
  ui?: Record<string, { control?: string; enum?: unknown }> | undefined;
75
99
  rerender?: (() => void) | undefined;
100
+ /**
101
+ * Externally-produced diagnostics, keyed by property name — §7.1's inline tier, sourced.
102
+ *
103
+ * This is how a validator that runs over the WHOLE document reaches the one field it is about:
104
+ * `jx-validate`'s `project.json` errors (until now wired only to the AI's `write_project_config`,
105
+ * so a human editing the same file through Settings got no validation at all), Monaco's markers
106
+ * for the same file open in the code view, and a host's own commit-time rejection.
107
+ *
108
+ * A host message wins over {@link validateFieldValue}'s intrinsic check, because the host knows
109
+ * things the property schema alone does not — that this enum value names a connector that was
110
+ * just deleted, say. An empty string means "no error", so a host can pass a lookup result
111
+ * straight through.
112
+ */
113
+ errors?: Record<string, string> | undefined;
114
+ /** How many times each field has been refused in a row; drives the row's repeat counter. */
115
+ errorCounts?: Record<string, number> | undefined;
116
+ /**
117
+ * Report required-but-empty fields inline. Off by default, and that default is §7.1's rule
118
+ * literally applied: a form the user has not touched yet has not committed anything, so painting
119
+ * every required field red the moment it renders is telling them they got something wrong before
120
+ * they did anything. Required-ness is already shown — the label carries a `*`. A host that
121
+ * validates on submit turns this on for the render that follows the rejected submit.
122
+ */
123
+ showRequired?: boolean | undefined;
76
124
  }
77
125
 
78
126
  // ─── Control registry ────────────────────────────────────────────────────────
@@ -89,8 +137,30 @@ export function getFormControl(name: string): SchemaFormControl | undefined {
89
137
  return controlRegistry.get(name);
90
138
  }
91
139
 
92
- /** Inert context used when a host renders a form without one. */
93
- const NULL_CONTEXT: SchemaFormContext = {
140
+ // ─── References between collections ──────────────────────────────────────────
141
+
142
+ /** `#/content/<type>` — a property whose value is the id of an entry in another collection. */
143
+ const CONTENT_REF = /^#\/content\/([^/]+)$/;
144
+
145
+ /**
146
+ * The collection a property references, or null when it references nothing.
147
+ *
148
+ * Exported because it is the ONE test for "is this field a relationship", and three surfaces have
149
+ * to agree on it: this engine, the frontmatter renderer, and the grid's relationship cell. A fourth
150
+ * reading of `$ref` is how the picker ends up existing three times with three behaviours.
151
+ */
152
+ export function referenceTarget(schema: { $ref?: string } | undefined): string | null {
153
+ const match = typeof schema?.$ref === "string" ? CONTENT_REF.exec(schema.$ref) : null;
154
+ return match ? match[1]! : null;
155
+ }
156
+
157
+ /**
158
+ * Inert context used when a host renders a form without one.
159
+ *
160
+ * Exported because a host with genuinely nowhere to resolve from — the frontmatter renderer, whose
161
+ * one registered control reads FILES — should name this rather than write a second empty closure.
162
+ */
163
+ export const NULL_FORM_CONTEXT: SchemaFormContext = {
94
164
  resolvePointer: () => {
95
165
  // Nothing to resolve against without a host context
96
166
  },
@@ -173,6 +243,9 @@ function refTextField(key: string, refVal: string, onChange: (next: unknown) =>
173
243
  * @param {(val: unknown) => void} onChange
174
244
  * @param {SchemaFormContext | undefined} ctx
175
245
  * @param {Record<string, unknown>} [scope] - Scope for dependent enum refs (the parent form value)
246
+ * @param {() => void} [rerender] - Repaint hook, threaded so an inline reference can show its
247
+ * choices once they load — an async control with no way to ask for a second frame renders its
248
+ * loading state forever.
176
249
  */
177
250
  export function renderInlineField(
178
251
  key: string,
@@ -181,10 +254,23 @@ export function renderInlineField(
181
254
  onChange: (val: unknown) => void,
182
255
  ctx?: SchemaFormContext,
183
256
  scope?: Record<string, unknown>,
257
+ rerender?: () => void,
184
258
  ) {
185
259
  if (isRef(value)) {
186
260
  return refTextField(key, value.$ref, onChange);
187
261
  }
262
+ const referenceControl =
263
+ referenceTarget(schema) === null ? undefined : controlRegistry.get("reference");
264
+ if (referenceControl) {
265
+ return referenceControl({
266
+ ctx: ctx ?? NULL_FORM_CONTEXT,
267
+ key,
268
+ onChange,
269
+ rerender,
270
+ schema,
271
+ value,
272
+ });
273
+ }
188
274
  const enumValues = resolveFormEnum(schema.enum, ctx, scope);
189
275
 
190
276
  if (enumValues) {
@@ -287,19 +373,26 @@ function renderPropertyControl(
287
373
  }
288
374
  }
289
375
 
290
- if (
291
- isRef(currentValue) &&
292
- ps.format !== "json-schema" &&
293
- ps.type !== "object" &&
294
- ps.type !== "array"
295
- ) {
296
- const binding = controlRegistry.get("binding");
297
- if (binding) {
298
- return binding(controlArgs);
299
- }
376
+ /* A ref left in a form whose host named nowhere to bind: no ladder is drawn, so the pointer is
377
+ edited as the string it is rather than rendered as "[object Object]" in a typed widget. */
378
+ if (isRef(currentValue) && isBindableField(ps)) {
300
379
  return refTextField(prop, currentValue.$ref, commit);
301
380
  }
302
381
 
382
+ /* A relationship to another collection (`$ref: "#/content/<type>"`) is the registered `reference`
383
+ control, wherever the form is drawn — §9.2's "one picker" is this dispatch plus the single
384
+ `registerFormControl("reference", …)` in `ui/form-controls.ts`. It is deliberately NOT an enum:
385
+ the choices are entry files on disk, so they are read asynchronously and can be stale, and a
386
+ schema `enum` is a closed set the document itself declares. When the control is not registered
387
+ (a bare-Bun import of this engine), the field falls through to the plain textfield below rather
388
+ than rendering nothing. */
389
+ if (referenceTarget(ps) !== null) {
390
+ const referenceControl = controlRegistry.get("reference");
391
+ if (referenceControl) {
392
+ return referenceControl(controlArgs);
393
+ }
394
+ }
395
+
303
396
  const enumValues = resolveFormEnum(opts.ui?.[prop]?.enum ?? ps.enum, ctx, value);
304
397
  if (enumValues) {
305
398
  return html`
@@ -425,6 +518,7 @@ function renderPropertyControl(
425
518
  },
426
519
  ctx,
427
520
  value,
521
+ opts.rerender,
428
522
  ),
429
523
  )}
430
524
  <sp-action-button
@@ -466,35 +560,99 @@ function renderPropertyControl(
466
560
 
467
561
  /** @type {ReturnType<typeof setTimeout> | undefined} */
468
562
  let debounce: ReturnType<typeof setTimeout> | undefined;
469
- const params = ctx.params ?? [];
470
563
  const ph = ps.default !== undefined ? String(ps.default) : (ps.examples?.[0] ?? "");
471
- return html`<div style="display:flex;gap:4px;align-items:center">
472
- <sp-textfield
473
- size="s"
474
- style="flex:1"
475
- .value=${currentValue ?? ""}
476
- placeholder=${ph || nothing}
477
- title=${ps.description || nothing}
478
- @input=${(e: Event) => {
479
- clearTimeout(debounce);
480
- debounce = setTimeout(() => commit((e.target as HTMLInputElement).value || undefined), 400);
481
- }}
482
- ></sp-textfield>
483
- ${
484
- params.length > 0
485
- ? html`<sp-action-button
486
- quiet
487
- size="s"
488
- title="Bind to route param"
489
- @click=${() => {
490
- commit({ $ref: `#/$params/${params[0]}` });
491
- opts.rerender?.();
492
- }}
493
- ><sp-icon-link slot="icon"></sp-icon-link
494
- ></sp-action-button>`
495
- : nothing
564
+ return html`<sp-textfield
565
+ size="s"
566
+ style="flex:1"
567
+ .value=${currentValue ?? ""}
568
+ placeholder=${ph || nothing}
569
+ title=${ps.description || nothing}
570
+ @input=${(e: Event) => {
571
+ clearTimeout(debounce);
572
+ debounce = setTimeout(() => commit((e.target as HTMLInputElement).value || undefined), 400);
573
+ }}
574
+ ></sp-textfield>`;
575
+ }
576
+
577
+ // ─── The Value Source ladder (§6.6) ──────────────────────────────────────────
578
+
579
+ /**
580
+ * Whether a property is edited as a single value at all. The three that are not — a nested JSON
581
+ * Schema, an object and an array — are edited as raw JSON or as a multi-row sub-form, and a chip
582
+ * offering to replace that editor with a signal pointer would be offering to delete the user's
583
+ * work.
584
+ */
585
+ function isBindableField(ps: JsonSchema): boolean {
586
+ return ps.format !== "json-schema" && ps.type !== "object" && ps.type !== "array";
587
+ }
588
+
589
+ /** Every pointer this form's host says a value may come from. */
590
+ function refSourcesFor(ctx: SchemaFormContext): SignalOption[] {
591
+ return [
592
+ ...(ctx.signals ?? []).map((name) => ({ label: name, value: `#/state/${name}` })),
593
+ ...(ctx.params ?? []).map((name) => ({ label: `$params/${name}`, value: `#/$params/${name}` })),
594
+ ];
595
+ }
596
+
597
+ // ─── Field validation (§7.1, inline tier) ────────────────────────────────────
598
+
599
+ /**
600
+ * Why this value is not acceptable for this property schema, or `""` when it is.
601
+ *
602
+ * Deliberately narrow: the checks a _property_ schema can make on its own, at the moment the value
603
+ * is committed. Anything cross-field, cross-document or extension-defined belongs to whoever ran
604
+ * the real validator and arrives through {@link RenderFormOptions.errors} — a form control is not a
605
+ * second implementation of JSON Schema, it is the place a verdict gets rendered.
606
+ *
607
+ * A `$ref` binding is never judged here. Its value is resolved at render time from state the form
608
+ * cannot see, so type-checking the reference itself would refuse every correct binding.
609
+ *
610
+ * @param {JsonSchema} schema
611
+ * @param {unknown} value
612
+ * @param {boolean} isRequired
613
+ * @returns {string}
614
+ */
615
+ export function validateFieldValue(
616
+ schema: JsonSchema,
617
+ value: unknown,
618
+ isRequired: boolean,
619
+ ): string {
620
+ if (isRef(value)) {
621
+ return "";
622
+ }
623
+ const empty = value === undefined || value === null || value === "";
624
+ if (empty) {
625
+ return isRequired ? "Required." : "";
626
+ }
627
+ if (Array.isArray(schema.enum) && !schema.enum.includes(value)) {
628
+ return `Choose one of: ${schema.enum.map(String).join(", ")}.`;
629
+ }
630
+ if (schema.type === "number" || schema.type === "integer") {
631
+ const n = typeof value === "number" ? value : Number(value);
632
+ if (!Number.isFinite(n)) {
633
+ return "Enter a number.";
634
+ }
635
+ if (schema.type === "integer" && !Number.isInteger(n)) {
636
+ return "Enter a whole number.";
637
+ }
638
+ if (schema.minimum !== undefined && n < schema.minimum) {
639
+ return `Must be ${schema.minimum} or more.`;
640
+ }
641
+ if (schema.maximum !== undefined && n > schema.maximum) {
642
+ return `Must be ${schema.maximum} or less.`;
496
643
  }
497
- </div>`;
644
+ return "";
645
+ }
646
+ if (schema.type === "boolean" && typeof value !== "boolean") {
647
+ return "Must be true or false.";
648
+ }
649
+ if (schema.type === "array" && !Array.isArray(value)) {
650
+ return "Must be a list.";
651
+ }
652
+ if (schema.type === "object" && (typeof value !== "object" || Array.isArray(value))) {
653
+ return "Must be an object.";
654
+ }
655
+ return "";
498
656
  }
499
657
 
500
658
  // ─── Form rendering ──────────────────────────────────────────────────────────
@@ -514,15 +672,41 @@ export function renderForm(
514
672
  opts: RenderFormOptions,
515
673
  ): TemplateResult {
516
674
  const required = new Set(schema.required);
517
- const ctx = opts.context ?? NULL_CONTEXT;
675
+ const ctx = opts.context ?? NULL_FORM_CONTEXT;
676
+ const refSources = refSourcesFor(ctx);
518
677
 
519
678
  const propertyFields = Object.entries(schema.properties ?? {}).map(([prop, ps]) => {
520
679
  const labelText = prop + (required.has(prop) ? " *" : "");
680
+ // Host diagnostics win over the intrinsic check — see RenderFormOptions.errors.
681
+ const error =
682
+ opts.errors?.[prop] ||
683
+ validateFieldValue(ps, value[prop], Boolean(opts.showRequired) && required.has(prop));
684
+ const count = opts.errorCounts?.[prop];
685
+ const staticWidget = renderPropertyControl(prop, ps, value, required, opts, ctx);
686
+ /* A `ui.control` override owns its whole field — the secret control writes an env-var NAME
687
+ rather than the value it was handed, so a rung switch above it would be editing a different
688
+ thing than the one on screen. */
689
+ const laddered =
690
+ refSources.length > 0 && isBindableField(ps) && !opts.ui?.[prop]?.control
691
+ ? renderDynamicSlot({
692
+ allowCustomRef: true,
693
+ caps: { schema: configFieldSchema(ps) },
694
+ extraSignals: refSources,
695
+ fieldKey: `${ctx.fieldKeyPrefix ?? ""}.${prop}`,
696
+ onChange: (v?: JsonValue) => opts.onChange({ [prop]: v }),
697
+ staticWidget,
698
+ stateDefs: [],
699
+ value: value[prop],
700
+ })
701
+ : null;
521
702
  return renderFieldRow({
522
703
  hasValue: false,
523
704
  label: labelText,
524
705
  prop: ps.name || prop,
525
- widget: renderPropertyControl(prop, ps, value, required, opts, ctx),
706
+ widget: laddered ? laddered.widget : staticWidget,
707
+ ...(laddered ? { labelExtra: laddered.modeButton } : {}),
708
+ ...(error ? { error } : {}),
709
+ ...(count === undefined ? {} : { errorCount: count }),
526
710
  });
527
711
  });
528
712
 
@@ -36,7 +36,16 @@ import { FieldLabel } from "@spectrum-web-components/field-label/src/FieldLabel.
36
36
  import { Checkbox } from "@spectrum-web-components/checkbox/src/Checkbox.js";
37
37
  import { Switch as SpSwitch } from "@spectrum-web-components/switch/src/Switch.js";
38
38
  import { Divider } from "@spectrum-web-components/divider/src/Divider.js";
39
- import { Tooltip } from "@spectrum-web-components/tooltip/src/Tooltip.js";
39
+ /* SIDE-EFFECT IMPORT, deliberately unlike every other row in this file.
40
+ Registering `sp-tooltip` ourselves from the class-only module made Studio the first definer, and
41
+ the package's OWN registering entry is reached later by a dynamic import (the textfield's
42
+ truncated-value controller) — which then calls `customElements.define` for a name we already
43
+ took, and throws `NotSupportedError` in the console during ordinary panel use. Our loop's
44
+ `customElements.get` guard cannot help: the second define is Spectrum's own call inside
45
+ node_modules. The tooltip package declares `sideEffects: ["./sp-*.js", …]`, so this import
46
+ survives bundling, and putting Spectrum's module in the static graph makes it the single definer
47
+ while the later dynamic import hits the module cache. */
48
+ import "@spectrum-web-components/tooltip/sp-tooltip.js";
40
49
  import { Overlay } from "@spectrum-web-components/overlay/src/Overlay.js";
41
50
  import { OverlayTrigger } from "@spectrum-web-components/overlay/src/OverlayTrigger.js";
42
51
  import { Dialog } from "@spectrum-web-components/dialog/src/Dialog.js";
@@ -58,6 +67,9 @@ import { TableRow } from "@spectrum-web-components/table/src/TableRow.js";
58
67
  import { TableCell } from "@spectrum-web-components/table/src/TableCell.js";
59
68
 
60
69
  // Icons
70
+ import { IconRailBottom } from "@spectrum-web-components/icons-workflow/src/elements/IconRailBottom.js";
71
+ import { IconRailLeft } from "@spectrum-web-components/icons-workflow/src/elements/IconRailLeft.js";
72
+ import { IconRailRight } from "@spectrum-web-components/icons-workflow/src/elements/IconRailRight.js";
61
73
  import { IconFolder } from "@spectrum-web-components/icons-workflow/src/elements/IconFolder.js";
62
74
  import { IconFolderOpen } from "@spectrum-web-components/icons-workflow/src/elements/IconFolderOpen.js";
63
75
  import { IconDocument } from "@spectrum-web-components/icons-workflow/src/elements/IconDocument.js";
@@ -92,7 +104,6 @@ import { IconSettings } from "@spectrum-web-components/icons-workflow/src/elemen
92
104
  import { IconInfo } from "@spectrum-web-components/icons-workflow/src/elements/IconInfo.js";
93
105
  import { IconBack } from "@spectrum-web-components/icons-workflow/src/elements/IconBack.js";
94
106
  import { IconProperties } from "@spectrum-web-components/icons-workflow/src/elements/IconProperties.js";
95
- import { IconEvent } from "@spectrum-web-components/icons-workflow/src/elements/IconEvent.js";
96
107
  import { IconMore } from "@spectrum-web-components/icons-workflow/src/elements/IconMore.js";
97
108
 
98
109
  // Layout / alignment icons
@@ -106,6 +117,10 @@ import { IconTextAlignRight } from "@spectrum-web-components/icons-workflow/src/
106
117
  import { IconTextAlignJustify } from "@spectrum-web-components/icons-workflow/src/elements/IconTextAlignJustify.js";
107
118
  import { IconAlignTop } from "@spectrum-web-components/icons-workflow/src/elements/IconAlignTop.js";
108
119
  import { IconAlignBottom } from "@spectrum-web-components/icons-workflow/src/elements/IconAlignBottom.js";
120
+ import { IconPlay } from "@spectrum-web-components/icons-workflow/src/elements/IconPlay.js";
121
+ import { IconSearch } from "@spectrum-web-components/icons-workflow/src/elements/IconSearch.js";
122
+ import { IconShare } from "@spectrum-web-components/icons-workflow/src/elements/IconShare.js";
123
+ import { IconShowMenu } from "@spectrum-web-components/icons-workflow/src/elements/IconShowMenu.js";
109
124
  import { IconAlignMiddle } from "@spectrum-web-components/icons-workflow/src/elements/IconAlignMiddle.js";
110
125
  import { IconAlignLeft } from "@spectrum-web-components/icons-workflow/src/elements/IconAlignLeft.js";
111
126
  import { IconAlignRight } from "@spectrum-web-components/icons-workflow/src/elements/IconAlignRight.js";
@@ -132,8 +147,6 @@ import { IconStop } from "@spectrum-web-components/icons-workflow/src/elements/I
132
147
  import { IconHistory } from "@spectrum-web-components/icons-workflow/src/elements/IconHistory.js";
133
148
  import { IconAttach } from "@spectrum-web-components/icons-workflow/src/elements/IconAttach.js";
134
149
  import { IconViewList } from "@spectrum-web-components/icons-workflow/src/elements/IconViewList.js";
135
- import { IconRailRightClose } from "@spectrum-web-components/icons-workflow/src/elements/IconRailRightClose.js";
136
- import { IconRailRightOpen } from "@spectrum-web-components/icons-workflow/src/elements/IconRailRightOpen.js";
137
150
  import { IconRectangle } from "@spectrum-web-components/icons-workflow/src/elements/IconRectangle.js";
138
151
 
139
152
  // Inline formatting icons
@@ -184,7 +197,6 @@ const components = [
184
197
  ["sp-checkbox", Checkbox],
185
198
  ["sp-switch", SpSwitch],
186
199
  ["sp-divider", Divider],
187
- ["sp-tooltip", Tooltip],
188
200
  ["sp-overlay", Overlay],
189
201
  ["overlay-trigger", OverlayTrigger],
190
202
  ["sp-dialog", Dialog],
@@ -204,6 +216,9 @@ const components = [
204
216
  ["sp-table-body", TableBody],
205
217
  ["sp-table-row", TableRow],
206
218
  ["sp-table-cell", TableCell],
219
+ ["sp-icon-rail-bottom", IconRailBottom],
220
+ ["sp-icon-rail-left", IconRailLeft],
221
+ ["sp-icon-rail-right", IconRailRight],
207
222
  ["sp-icon-folder", IconFolder],
208
223
  ["sp-icon-folder-open", IconFolderOpen],
209
224
  ["sp-icon-document", IconDocument],
@@ -238,7 +253,6 @@ const components = [
238
253
  ["sp-icon-info", IconInfo],
239
254
  ["sp-icon-back", IconBack],
240
255
  ["sp-icon-properties", IconProperties],
241
- ["sp-icon-event", IconEvent],
242
256
  ["sp-icon-more", IconMore],
243
257
  ["sp-icon-arrow-right", IconArrowRight],
244
258
  ["sp-icon-arrow-left", IconArrowLeft],
@@ -250,6 +264,10 @@ const components = [
250
264
  ["sp-icon-text-align-justify", IconTextAlignJustify],
251
265
  ["sp-icon-align-top", IconAlignTop],
252
266
  ["sp-icon-align-bottom", IconAlignBottom],
267
+ ["sp-icon-play", IconPlay],
268
+ ["sp-icon-search", IconSearch],
269
+ ["sp-icon-share", IconShare],
270
+ ["sp-icon-show-menu", IconShowMenu],
253
271
  ["sp-icon-align-middle", IconAlignMiddle],
254
272
  ["sp-icon-align-left", IconAlignLeft],
255
273
  ["sp-icon-align-right", IconAlignRight],
@@ -268,8 +286,6 @@ const components = [
268
286
  ["sp-icon-download", IconDownload],
269
287
  ["sp-icon-checkmark", IconCheckmark],
270
288
  ["sp-icon-view-column", IconViewColumn],
271
- ["sp-icon-rail-right-close", IconRailRightClose],
272
- ["sp-icon-rail-right-open", IconRailRightOpen],
273
289
  ["sp-icon-rectangle", IconRectangle],
274
290
  ["sp-icon-box", IconBox],
275
291
  ["sp-icon-visibility", IconVisibility],
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Timing.ts — Studio's latency vocabulary.
3
+ *
4
+ * Every user-visible delay in Studio expresses one of a small number of intents: "wait until the
5
+ * user stops typing", "hold a message on screen long enough to read", "check the repo again". Each
6
+ * call site used to pick its own number for its intent, so the same intent shipped as 350, 400 and
7
+ * 600 ms in three different panels and a retune meant a grep. Name the intent once here, import the
8
+ * name, and the retune is a single edit.
9
+ *
10
+ * All values are milliseconds. The two input debounces are contractual:
11
+ * `specs/studio-ui-guidelines.md` §4.4 fixes 400 ms for text inputs and 500 ms for code/expression
12
+ * textareas. Do not change either without releasing that spec section.
13
+ */
14
+
15
+ /**
16
+ * Text/style input debounce — the §4.4 standard. Long enough that a normal typing cadence produces
17
+ * one commit per pause rather than one per keystroke, short enough that the canvas still feels
18
+ * live.
19
+ */
20
+ export const INPUT_DEBOUNCE = 400;
21
+
22
+ /**
23
+ * Code and expression textareas — the §4.4 standard. Longer than {@link INPUT_DEBOUNCE} because
24
+ * each commit re-parses source (or re-lints), and because half-typed code is usually invalid, so
25
+ * committing eagerly just burns work on states the user is about to leave.
26
+ */
27
+ export const CODE_DEBOUNCE = 500;
28
+
29
+ /**
30
+ * Draft-layer live preview (ui/field-input.ts) — how long after a keystroke the in-progress draft
31
+ * is pushed to the document so the canvas updates while the field stays focused. Deliberately below
32
+ * {@link INPUT_DEBOUNCE}: this commit is provisional (the draft survives it, and blur/Enter commits
33
+ * again), so it can afford to fire sooner than a committing input.
34
+ */
35
+ export const LIVE_PREVIEW = 350;
36
+
37
+ /*
38
+ * `STATUS_MESSAGE = 3000` used to live here: how long a transient message stayed in the status bar
39
+ * before it erased itself. It had one reader, `statusMessage`, which is deleted — the bar carries
40
+ * ambient state now and outcomes go to `services/notify.ts`, whose `TOAST_LIFETIME_MS` is per
41
+ * SEVERITY (§7.1 caps the band at 4–8s) rather than one number for a failure and a save alike.
42
+ */
43
+
44
+ /**
45
+ * Git status poll while the Git panel is open. Deliberately coarse: it exists to notice changes
46
+ * made outside Studio, and each tick shells out to git, so a faster cadence buys little and costs
47
+ * I/O.
48
+ */
49
+ export const POLL_GIT = 30_000;
@@ -6,6 +6,11 @@
6
6
  * dropdown overlay (manual combobox) when it doesn't. Both modes share identical styled menu items,
7
7
  * ensuring visual consistency.
8
8
  *
9
+ * The option list is a set of SUGGESTIONS, never a whitelist: both modes emit `change` on commit
10
+ * (picker selection, menu selection, or blur/Enter in the textfield) and combobox mode also emits
11
+ * `input` while typing, so a caller can offer a short list of common values without forbidding the
12
+ * rest — which is what lets a control like the event-name field stop being a list of ten.
13
+ *
9
14
  * Usage: html`<jx-value-selector size="s" .value=${"italic"} placeholder="normal" .options=${[{
10
15
  * value: "italic", label: "Italic", style: "font-style: italic" }]} @change=${handler}
11
16
  * @input=${handler}
@@ -101,6 +106,20 @@ export class JxValueSelector extends LitElement {
101
106
  this.dispatchEvent(new Event("input", { bubbles: true, composed: true }));
102
107
  }
103
108
 
109
+ /**
110
+ * Combobox mode: textfield @change handler (blur / Enter).
111
+ *
112
+ * Without this, a typed value only ever reached listeners as `input`. Every consumer that binds
113
+ * `@change` — the pattern for "commit this to the document" everywhere else in the app — saw
114
+ * nothing at all, so the free-form half of this dual-mode control was decorative: you could type
115
+ * a value the option list did not contain and it would never be written down.
116
+ */
117
+ _handleTextChange(e: Event) {
118
+ e.stopPropagation();
119
+ this.value = (e.target as HTMLInputElement).value;
120
+ this.dispatchEvent(new Event("change", { bubbles: true, composed: true }));
121
+ }
122
+
104
123
  /** Set popover min-width to match trigger width (replicates sp-picker behavior) */
105
124
  _setPopoverWidth(e: Event) {
106
125
  const group = this.querySelector(".jx-combobox-group");
@@ -133,6 +152,7 @@ export class JxValueSelector extends LitElement {
133
152
  placeholder=${this.placeholder}
134
153
  .value=${live(this.value || "")}
135
154
  @input=${this._handleInput}
155
+ @change=${this._handleTextChange}
136
156
  @click=${(e: Event) => e.stopPropagation()}
137
157
  ></sp-textfield>
138
158
  <sp-picker-button size=${this.size}></sp-picker-button>