@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
@@ -0,0 +1,481 @@
1
+ /// <reference lib="dom" />
2
+ /**
3
+ * Activity — where a long operation lives while it runs, and what it leaves behind (plan §7.3).
4
+ *
5
+ * What this replaces: `ui/progress-modal.ts` was **the only surface in Studio with a real error
6
+ * view** — a red headline, the captured log in a `<pre>`, an explicit Close — and it had four call
7
+ * sites, all package operations. It blocked the whole app, offered no cancel, and vanished
8
+ * completely on success, so a `bun install` that hung had no exit and one that failed had a log you
9
+ * could read exactly once. Every OTHER long operation — git clone, publish, media upload, site
10
+ * import, project open — got a three-second grey line or nothing at all.
11
+ *
12
+ * An activity is a **record**, like a notification and a command:
13
+ *
14
+ * - It is **persistent** — a finished operation stays on the list, with its log, until the list is
15
+ * cleared, so "what did the import actually do?" is answerable after the fact;
16
+ * - It is **inspectable** — the log is the same captured output the modal used to show, and it is
17
+ * attached to the entry rather than to a modal that is about to close;
18
+ * - It can be **cancelled** — an operation that hands over a `cancel` callback gets a Cancel button
19
+ * on its row, which is the affordance a hung install has never had;
20
+ * - And it **fails into Problems** — {@link ActivityHandle.fail} raises a `notify.error` carrying the
21
+ * log as its `detail`, so the failure outlives the run and carries a Retry command. That is
22
+ * §7.3's "the progress modal's error view is promoted into Problems", in one function.
23
+ *
24
+ * **Nothing here blocks.** `showProgressModal` still exists for the four dependency-install sites
25
+ * §7.3 keeps blocking, and it is now a thin front end over {@link beginActivity} — so even the
26
+ * blocking case leaves an inspectable entry behind, and closing the modal no longer loses it.
27
+ *
28
+ * `services/idle.ts` reads {@link activityIdleBlockers}: an open operation means the app is not
29
+ * settled, which is the §13.6 S4 obligation every phase's checklist carries.
30
+ */
31
+
32
+ import { html, nothing } from "lit-html";
33
+ import { renderDeployChecklist } from "../publish/deploy-checklist";
34
+ import { repeat } from "lit-html/directives/repeat.js";
35
+ import { reactive } from "../reactivity";
36
+ import { now } from "../services/clock";
37
+ import { notify } from "../services/notify";
38
+ import { registerPanel } from "./panel-registry";
39
+ import { renderEmptyState } from "./empty-state";
40
+ import type { PanelBody } from "./panel-registry";
41
+ import type { TemplateResult } from "lit-html";
42
+
43
+ /** How an operation ended, or that it has not. */
44
+ export const ACTIVITY_STATES = ["running", "done", "failed", "cancelled"] as const;
45
+
46
+ export type ActivityState = (typeof ACTIVITY_STATES)[number];
47
+
48
+ /** One named phase of an operation — "Install dependencies", "Sync with the remote". */
49
+ export interface ActivityStep {
50
+ label: string;
51
+ state: "pending" | "running" | "done" | "failed";
52
+ }
53
+
54
+ /**
55
+ * One operation, as recorded.
56
+ *
57
+ * Mutable and reactive on purpose: an activity is the one record in the app that CHANGES while you
58
+ * watch it, which is the whole difference between it and a
59
+ * {@link import("../services/notify") .Notification}. A host repaints by reading it.
60
+ */
61
+ export interface ActivityEntry {
62
+ readonly id: string;
63
+ readonly title: string;
64
+ /** The line under the title — what the operation is doing right now. */
65
+ status: string;
66
+ state: ActivityState;
67
+ /** The captured output, one entry per chunk. Rendered in the expanded row. */
68
+ log: string[];
69
+ steps: ActivityStep[];
70
+ /** Epoch ms from {@link now}, so a pinned clock pins the duration a row prints. */
71
+ readonly startedAt: number;
72
+ endedAt: number | null;
73
+ /** Who is running it: "Packages", "Source Control", "Publish". Printed beside the title. */
74
+ readonly source?: string;
75
+ /** Whether a `cancel` callback was handed over — the row draws Cancel iff this is true. */
76
+ cancellable: boolean;
77
+ /** Whether this row's log is unfolded. A view flag, on the record, so a repaint keeps it. */
78
+ expanded: boolean;
79
+ }
80
+
81
+ /**
82
+ * Every operation this session, oldest first — running and finished alike.
83
+ *
84
+ * Exported as the array rather than behind a getter for the same reason `notify`'s stores are: that
85
+ * is what makes it trackable, so a lit render effect that reads it re-runs when an operation
86
+ * starts, logs a line or ends, with no subscription to remember to release.
87
+ */
88
+ export const activities: ActivityEntry[] = reactive([]);
89
+
90
+ /**
91
+ * How many FINISHED entries are kept. Running ones are never retired — an operation the app is
92
+ * still doing is not history, and dropping it would take its Cancel button with it.
93
+ */
94
+ export const MAX_FINISHED_ACTIVITIES = 20;
95
+
96
+ /**
97
+ * Entry id → the callback that stops it.
98
+ *
99
+ * Held beside the record rather than on it: a closure inside a reactive proxy is a value effects
100
+ * would track and nothing would ever compare, and the record is otherwise plain data. The record
101
+ * carries `cancellable` so a renderer never needs this map.
102
+ */
103
+ const _cancels = new Map<string, () => void>();
104
+
105
+ let _seq = 0;
106
+
107
+ /** Monotonic within a page load, and stable enough to be a lit `repeat` key. */
108
+ function nextId(): string {
109
+ _seq += 1;
110
+ return `a${_seq}`;
111
+ }
112
+
113
+ /** Whether an entry has stopped. */
114
+ export function isFinished(entry: ActivityEntry): boolean {
115
+ return entry.state !== "running";
116
+ }
117
+
118
+ /** Drop the oldest finished entries once there are more than {@link MAX_FINISHED_ACTIVITIES}. */
119
+ function retireOldest(): void {
120
+ let excess = activities.filter((entry) => isFinished(entry)).length - MAX_FINISHED_ACTIVITIES;
121
+ while (excess > 0) {
122
+ const at = activities.findIndex((entry) => isFinished(entry));
123
+ if (at === -1) {
124
+ return;
125
+ }
126
+ _cancels.delete(activities[at]!.id);
127
+ activities.splice(at, 1);
128
+ excess -= 1;
129
+ }
130
+ }
131
+
132
+ /** What {@link beginActivity} is told about an operation up front. */
133
+ export interface ActivityOptions {
134
+ /** What the operation IS — "Open project", "Update dependencies". Never changes. */
135
+ title: string;
136
+ /** What it is doing right now. Changes as it goes. */
137
+ status?: string;
138
+ /** Who is running it — "Packages", "Source Control". Groups nothing yet; printed on the row. */
139
+ source?: string;
140
+ /** The plan, declared up front so the row shows how far along it is. */
141
+ steps?: readonly string[];
142
+ /**
143
+ * Stop the operation.
144
+ *
145
+ * Its presence is what draws the Cancel button, so an operation that cannot honestly be stopped
146
+ * must not pass one — a Cancel that does nothing is the failure §7 exists to end, restated as a
147
+ * button.
148
+ */
149
+ cancel?: () => void;
150
+ }
151
+
152
+ /** The live handle an operation drives its own entry through. */
153
+ export interface ActivityHandle {
154
+ readonly id: string;
155
+ /** The record itself, for a caller that wants to read its own log back. */
156
+ readonly entry: ActivityEntry;
157
+ /** Replace the line under the title. */
158
+ setStatus: (text: string) => void;
159
+ /** Append captured output. Blank chunks are dropped, so a trailing newline is not a log line. */
160
+ log: (chunk: string) => void;
161
+ /** Mark `label` as the running step; every step before it is done. Appends an unplanned one. */
162
+ step: (label: string) => void;
163
+ /** Finish successfully. */
164
+ done: (status?: string) => void;
165
+ /**
166
+ * Finish with a failure — and raise the Problem that outlives it.
167
+ *
168
+ * The log goes into the notification's `detail`, so the persistent, inspectable error view §7.3
169
+ * asks for is the Problems row, not a modal that has to stay open to be read.
170
+ */
171
+ fail: (message: string, opts?: { action?: string; path?: string }) => void;
172
+ }
173
+
174
+ /**
175
+ * Start recording an operation.
176
+ *
177
+ * @param {ActivityOptions} options
178
+ * @returns {ActivityHandle}
179
+ */
180
+ export function beginActivity(options: ActivityOptions): ActivityHandle {
181
+ const entry: ActivityEntry = {
182
+ cancellable: options.cancel !== undefined,
183
+ endedAt: null,
184
+ expanded: false,
185
+ id: nextId(),
186
+ log: [],
187
+ startedAt: now(),
188
+ state: "running",
189
+ status: options.status ?? "",
190
+ steps: (options.steps ?? []).map((label) => ({ label, state: "pending" as const })),
191
+ title: options.title,
192
+ ...(options.source === undefined ? {} : { source: options.source }),
193
+ };
194
+ if (options.cancel) {
195
+ _cancels.set(entry.id, options.cancel);
196
+ }
197
+ activities.push(entry);
198
+ // The PROXY, not the literal: writing through the raw object a `reactive()` array was handed
199
+ // Skips every effect depending on it, which is the one bug that would make a running operation
200
+ // Look frozen. Read back before anything is retired, so the reference is unambiguous.
201
+ const live = activities.at(-1) as ActivityEntry;
202
+ retireOldest();
203
+
204
+ const finish = (state: ActivityState, status?: string) => {
205
+ if (isFinished(live)) {
206
+ return;
207
+ }
208
+ live.state = state;
209
+ live.endedAt = now();
210
+ if (status !== undefined) {
211
+ live.status = status;
212
+ }
213
+ for (const step of live.steps) {
214
+ step.state = step.state === "done" ? "done" : state === "done" ? "done" : "failed";
215
+ }
216
+ live.cancellable = false;
217
+ _cancels.delete(live.id);
218
+ retireOldest();
219
+ };
220
+
221
+ return {
222
+ done(status?: string) {
223
+ finish("done", status);
224
+ },
225
+ entry: live,
226
+ fail(message: string, opts: { action?: string; path?: string } = {}) {
227
+ // An operation that has already ended does not get to raise a Problem: the first outcome is
228
+ // The one that happened, and a late `fail()` after a successful `done()` would put a failure
229
+ // On a list whose whole promise is that everything on it still needs fixing.
230
+ if (isFinished(live)) {
231
+ return;
232
+ }
233
+ const detail = live.log.join("\n");
234
+ finish("failed", message);
235
+ notify.error(message, {
236
+ source: live.source ?? live.title,
237
+ ...(detail === "" ? {} : { detail }),
238
+ ...(opts.action === undefined ? {} : { action: opts.action }),
239
+ ...(opts.path === undefined ? {} : { path: opts.path }),
240
+ });
241
+ },
242
+ id: live.id,
243
+ log(chunk: string) {
244
+ const text = chunk.replace(/\s+$/, "");
245
+ if (text !== "") {
246
+ live.log.push(text);
247
+ }
248
+ },
249
+ setStatus(text: string) {
250
+ if (!isFinished(live)) {
251
+ live.status = text;
252
+ }
253
+ },
254
+ step(label: string) {
255
+ let at = live.steps.findIndex((step) => step.label === label);
256
+ if (at === -1) {
257
+ live.steps.push({ label, state: "pending" });
258
+ at = live.steps.length - 1;
259
+ }
260
+ for (const [index, step] of live.steps.entries()) {
261
+ step.state = index < at ? "done" : index === at ? "running" : step.state;
262
+ }
263
+ live.status = label;
264
+ },
265
+ };
266
+ }
267
+
268
+ /** One entry by id, or `undefined`. */
269
+ export function activityById(id: string): ActivityEntry | undefined {
270
+ return activities.find((entry) => entry.id === id);
271
+ }
272
+
273
+ /** Everything still running, oldest first — what the badge counts and idle waits on. */
274
+ export function runningActivities(): ActivityEntry[] {
275
+ return activities.filter((entry) => !isFinished(entry));
276
+ }
277
+
278
+ /**
279
+ * Stop an operation: run its callback, mark it cancelled. Returns whether anything was stopped.
280
+ *
281
+ * The callback runs BEFORE the state changes, so an implementation that throws leaves the entry
282
+ * honestly still running rather than claiming a cancellation that did not happen.
283
+ */
284
+ export function cancelActivity(id: string): boolean {
285
+ const entry = activityById(id);
286
+ const stop = _cancels.get(id);
287
+ if (!entry || !stop || isFinished(entry)) {
288
+ return false;
289
+ }
290
+ stop();
291
+ _cancels.delete(id);
292
+ entry.state = "cancelled";
293
+ entry.endedAt = now();
294
+ entry.cancellable = false;
295
+ entry.status = "Cancelled";
296
+ return true;
297
+ }
298
+
299
+ /** Drop every finished entry. Returns how many went. Running operations are kept. */
300
+ export function clearFinishedActivities(): number {
301
+ const kept = activities.filter((entry) => !isFinished(entry));
302
+ const removed = activities.length - kept.length;
303
+ activities.splice(0, activities.length, ...kept);
304
+ return removed;
305
+ }
306
+
307
+ /** Clear the whole list — tests, and the "close project" path. */
308
+ export function resetActivities(): void {
309
+ activities.splice(0);
310
+ _cancels.clear();
311
+ }
312
+
313
+ /**
314
+ * What is still running, as `services/idle.ts` phrases it.
315
+ *
316
+ * §13.6 S4 puts this on every phase's checklist: an app with an operation in flight has not
317
+ * finished reacting, so a screenshot taken now photographs a half-done import. A FINISHED entry is
318
+ * not a blocker — the list stays on screen forever and waiting for it to empty would never settle.
319
+ */
320
+ export function activityIdleBlockers(): readonly string[] {
321
+ return runningActivities().map(
322
+ (entry) => `activity: ${entry.title} — ${entry.status || "running"}`,
323
+ );
324
+ }
325
+
326
+ // ─── Rendering ────────────────────────────────────────────────────────────────
327
+
328
+ /** The state glyphs. One character each: the row's job is a line of text, not an illustration. */
329
+ const STATE_ICON: Readonly<Record<ActivityState, string>> = {
330
+ cancelled: "⊘",
331
+ done: "✓",
332
+ failed: "✕",
333
+ running: "⋯",
334
+ };
335
+
336
+ const STEP_ICON: Readonly<Record<ActivityStep["state"], string>> = {
337
+ done: "✓",
338
+ failed: "✕",
339
+ pending: "·",
340
+ running: "⋯",
341
+ };
342
+
343
+ /** How long it took, in the coarsest unit that is still true. */
344
+ export function activityDuration(entry: ActivityEntry, at: number = now()): string {
345
+ const ms = Math.max(0, (entry.endedAt ?? at) - entry.startedAt);
346
+ if (ms < 1000) {
347
+ return `${ms}ms`;
348
+ }
349
+ const seconds = Math.round(ms / 1000);
350
+ return seconds < 60 ? `${seconds}s` : `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
351
+ }
352
+
353
+ function stepsTpl(entry: ActivityEntry): TemplateResult | typeof nothing {
354
+ if (entry.steps.length === 0) {
355
+ return nothing;
356
+ }
357
+ return html`<ol class="activity-steps">
358
+ ${entry.steps.map(
359
+ (step) => html`<li class="activity-step activity-step--${step.state}">
360
+ <span class="activity-step-icon" aria-hidden="true">${STEP_ICON[step.state]}</span>
361
+ ${step.label}
362
+ </li>`,
363
+ )}
364
+ </ol>`;
365
+ }
366
+
367
+ function logTpl(entry: ActivityEntry): TemplateResult | typeof nothing {
368
+ if (entry.log.length === 0) {
369
+ return nothing;
370
+ }
371
+ return html`<button
372
+ class="activity-log-toggle"
373
+ aria-expanded=${entry.expanded ? "true" : "false"}
374
+ @click=${() => {
375
+ entry.expanded = !entry.expanded;
376
+ }}
377
+ >
378
+ ${entry.expanded ? "Hide log" : `Show log (${entry.log.length} line(s))`}
379
+ </button>
380
+ ${entry.expanded ? html`<pre class="activity-log">${entry.log.join("\n")}</pre>` : nothing}`;
381
+ }
382
+
383
+ /** One operation. */
384
+ function activityTpl(entry: ActivityEntry): TemplateResult {
385
+ return html`
386
+ <li class="activity-row activity-row--${entry.state}">
387
+ <span class="activity-icon" aria-hidden="true">${STATE_ICON[entry.state]}</span>
388
+ <div class="activity-body">
389
+ <div class="activity-head">
390
+ <span class="activity-title">${entry.title}</span>
391
+ ${entry.source ? html`<span class="activity-source">${entry.source}</span>` : nothing}
392
+ <span class="activity-duration">${activityDuration(entry)}</span>
393
+ </div>
394
+ ${entry.status ? html`<div class="activity-status">${entry.status}</div>` : nothing}
395
+ ${stepsTpl(entry)} ${logTpl(entry)}
396
+ </div>
397
+ ${
398
+ entry.cancellable
399
+ ? html`<button
400
+ class="activity-cancel"
401
+ title="Stop this operation"
402
+ @click=${() => {
403
+ cancelActivity(entry.id);
404
+ }}
405
+ >
406
+ Cancel
407
+ </button>`
408
+ : nothing
409
+ }
410
+ </li>
411
+ `;
412
+ }
413
+
414
+ /**
415
+ * The Activity tab's body.
416
+ *
417
+ * Newest LAST, like a log and unlike a menu: an operation that starts while you are reading one
418
+ * that is already running must not push it off the top.
419
+ */
420
+ export function renderActivityList(): PanelBody {
421
+ // The Deploy checklist lives here because a deploy IS a long operation with a log — which is why
422
+ // P4 folded Deploy into Activity rather than giving it a fifth dock tab. It renders above the
423
+ // Run log and before any operation has started, because its whole job is to say what is missing
424
+ // BEFORE you begin.
425
+ const checklist = renderDeployChecklist();
426
+ if (activities.length === 0) {
427
+ return html`${checklist}${renderEmptyState({
428
+ detail: "Installs, clones, publishes and imports report here while they run.",
429
+ message: "Long operations show their progress, their log and their Cancel button here.",
430
+ })}`;
431
+ }
432
+ const finished = activities.filter((entry) => isFinished(entry)).length;
433
+ return html`
434
+ ${checklist}
435
+ <div class="activity-panel">
436
+ ${
437
+ finished > 0
438
+ ? html`<div class="activity-actions">
439
+ <button
440
+ class="activity-clear"
441
+ @click=${() => {
442
+ clearFinishedActivities();
443
+ }}
444
+ >
445
+ Clear ${finished} finished
446
+ </button>
447
+ </div>`
448
+ : nothing
449
+ }
450
+ <ul class="activity-list">
451
+ ${repeat(
452
+ activities,
453
+ (entry) => entry.id,
454
+ (entry) => activityTpl(entry),
455
+ )}
456
+ </ul>
457
+ </div>
458
+ `;
459
+ }
460
+
461
+ /**
462
+ * Define the Activity panel. Called by `panels/bottom-dock.ts`, beside the state it writes.
463
+ *
464
+ * `level: "project"` because an operation is a thing done TO a project — an install, a clone, a
465
+ * publish — and the list must not empty itself when the last document closes, which is the same
466
+ * rule that hoisted source control off `TabUi`.
467
+ */
468
+ export function registerActivityPanel(): void {
469
+ registerPanel({
470
+ id: "activity",
471
+ title: "Activity",
472
+ level: "project",
473
+ dock: "bottom",
474
+ icon: "sp-icon-data",
475
+ // No rail button: the Bottom dock's tabs are reached by ⌘J and `view.setBottomTab`, and a
476
+ // Fifth rail slot for a surface with no steady state would spend chrome §2 principle 9 caps.
477
+ rail: false,
478
+ badge: () => (runningActivities().length > 0 ? runningActivities().length : null),
479
+ render: () => renderActivityList(),
480
+ });
481
+ }
@@ -3,8 +3,12 @@
3
3
  *
4
4
  * Wraps @jxsuite/markup/md-html (sanitized markdown → HTML) with a per-message cache
5
5
  * keyed by message id + content length, so re-renders during streaming only re-parse
6
- * the message that actually grew. The HTML goes through unsafeHTML, which is safe here
7
- * because md-html sanitizes (raw HTML dropped, javascript: URLs stripped).
6
+ * the message that actually grew.
7
+ *
8
+ * The HTML goes through `unsafeHTML`, which is this app's ONE injection sink, and it goes through
9
+ * the Trusted Types policy on the way. md-html already sanitizes — raw HTML dropped, javascript:
10
+ * URLs stripped — and the policy asserts that it did, rather than taking a comment's word for it.
11
+ * A `createHTML` that passed its input through unchanged would satisfy the API and defend nothing.
8
12
  *
9
13
  * @license MIT
10
14
  */
@@ -13,6 +17,7 @@ import { html } from "lit-html";
13
17
  import type { TemplateResult } from "lit-html";
14
18
  import { unsafeHTML } from "lit-html/directives/unsafe-html.js";
15
19
  import { markdownToHtml } from "@jxsuite/markup/md-html";
20
+ import { trustedHtml } from "../../services/trusted-types";
16
21
 
17
22
  const cache = new Map<string, { len: number; html: string }>();
18
23
 
@@ -29,7 +34,7 @@ export function renderMarkdown(id: string, content: string): TemplateResult {
29
34
  entry = { len: content.length, html: markdownToHtml(content) };
30
35
  cache.set(id, entry);
31
36
  }
32
- return html`<div class="ai-msg-md">${unsafeHTML(entry.html)}</div>`;
37
+ return html`<div class="ai-msg-md">${unsafeHTML(String(trustedHtml(entry.html)))}</div>`;
33
38
  }
34
39
 
35
40
  /** Drop all cached renders (call on session switch / new chat). */