@elabs-ai/components-ai 4.2.0 → 5.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 (462) hide show
  1. package/README.md +1 -1
  2. package/dist/{_audio-player-media-chrome-T3XVXWRZ.js → _audio-player-media-chrome.js} +1 -1
  3. package/dist/_code-block-theme.js +12 -0
  4. package/dist/_code-block-theme.js.map +1 -0
  5. package/dist/{_flow-boundary-SHNWLQG5.js → _flow-boundary.js} +1 -1
  6. package/dist/_flow-boundary.js.map +1 -0
  7. package/dist/_flow-lazy.js +8 -0
  8. package/dist/_flow-lazy.js.map +1 -0
  9. package/dist/_lazy-boundary-conformance.js +2 -0
  10. package/dist/_lazy-boundary-conformance.js.map +1 -0
  11. package/dist/_lazy-cjk.js +13 -0
  12. package/dist/_lazy-cjk.js.map +1 -0
  13. package/dist/_lazy-engine-boundary.js +9 -0
  14. package/dist/_lazy-engine-boundary.js.map +1 -0
  15. package/dist/_lazy-math.js +13 -0
  16. package/dist/_lazy-math.js.map +1 -0
  17. package/dist/_lazy-mermaid.js +12 -0
  18. package/dist/_lazy-mermaid.js.map +1 -0
  19. package/dist/_mermaid-error-panel.js +9 -0
  20. package/dist/_mermaid-error-panel.js.map +1 -0
  21. package/dist/{_persona-rive-JEG44YHX.js → _persona-rive.js} +19 -24
  22. package/dist/_persona-rive.js.map +1 -0
  23. package/dist/_streamdown-i18n.js +21 -0
  24. package/dist/_streamdown-i18n.js.map +1 -0
  25. package/dist/_streamdown-safety.js +10 -0
  26. package/dist/_streamdown-safety.js.map +1 -0
  27. package/dist/_theme-scope-store.js +13 -0
  28. package/dist/_theme-scope-store.js.map +1 -0
  29. package/dist/a2ui/a2ui-surface.js +17 -0
  30. package/dist/a2ui/a2ui-surface.js.map +1 -0
  31. package/dist/a2ui/core/catalog.generated.js +10 -0
  32. package/dist/a2ui/core/catalog.generated.js.map +1 -0
  33. package/dist/a2ui/core/complete-json.js +10 -0
  34. package/dist/a2ui/core/complete-json.js.map +1 -0
  35. package/dist/a2ui/core/index.js +37 -0
  36. package/dist/a2ui/core/index.js.map +1 -0
  37. package/dist/a2ui/core/schema.js +11 -0
  38. package/dist/a2ui/core/schema.js.map +1 -0
  39. package/dist/a2ui/core/spec.js +10 -0
  40. package/dist/a2ui/core/spec.js.map +1 -0
  41. package/dist/a2ui/core/validate.js +16 -0
  42. package/dist/a2ui/core/validate.js.map +1 -0
  43. package/dist/a2ui/index.js +54 -0
  44. package/dist/a2ui/index.js.map +1 -0
  45. package/dist/a2ui/ui-catalog.js +18 -0
  46. package/dist/a2ui/ui-catalog.js.map +1 -0
  47. package/dist/agent-event.js +10 -0
  48. package/dist/agent-event.js.map +1 -0
  49. package/dist/agent-timeline.js +11 -0
  50. package/dist/agent-timeline.js.map +1 -0
  51. package/dist/agent.js +25 -0
  52. package/dist/agent.js.map +1 -0
  53. package/dist/artifact.js +23 -0
  54. package/dist/artifact.js.map +1 -0
  55. package/dist/asset-preview.js +22 -0
  56. package/dist/asset-preview.js.map +1 -0
  57. package/dist/attachments.js +33 -0
  58. package/dist/attachments.js.map +1 -0
  59. package/dist/audio-player.js +30 -0
  60. package/dist/audio-player.js.map +1 -0
  61. package/dist/audio-visualizer.js +9 -0
  62. package/dist/audio-visualizer.js.map +1 -0
  63. package/dist/canvas.js +10 -0
  64. package/dist/canvas.js.map +1 -0
  65. package/dist/chain-of-thought.js +22 -0
  66. package/dist/chain-of-thought.js.map +1 -0
  67. package/dist/chat-greeting.js +8 -0
  68. package/dist/chat-greeting.js.map +1 -0
  69. package/dist/chat-shell.js +9 -0
  70. package/dist/chat-shell.js.map +1 -0
  71. package/dist/checkpoint.js +13 -0
  72. package/dist/checkpoint.js.map +1 -0
  73. package/dist/chunk-2XOIG5TG.js +72 -0
  74. package/dist/chunk-2XOIG5TG.js.map +1 -0
  75. package/dist/chunk-34CQ2VHM.js +172 -0
  76. package/dist/chunk-34CQ2VHM.js.map +1 -0
  77. package/dist/chunk-3TDHPXZZ.js +60 -0
  78. package/dist/chunk-3TDHPXZZ.js.map +1 -0
  79. package/dist/chunk-3XNPMDZY.js +478 -0
  80. package/dist/chunk-3XNPMDZY.js.map +1 -0
  81. package/dist/chunk-3YPT3V7L.js +56 -0
  82. package/dist/chunk-3YPT3V7L.js.map +1 -0
  83. package/dist/chunk-475UEU2Q.js +87 -0
  84. package/dist/chunk-475UEU2Q.js.map +1 -0
  85. package/dist/chunk-4CBTII2I.js +95 -0
  86. package/dist/chunk-4CBTII2I.js.map +1 -0
  87. package/dist/chunk-4XRNIZMG.js +22 -0
  88. package/dist/chunk-4XRNIZMG.js.map +1 -0
  89. package/dist/chunk-5NNWUKK5.js +2 -0
  90. package/dist/chunk-5NNWUKK5.js.map +1 -0
  91. package/dist/chunk-5UOMU27Z.js +164 -0
  92. package/dist/chunk-5UOMU27Z.js.map +1 -0
  93. package/dist/chunk-5VGYZ62I.js +264 -0
  94. package/dist/chunk-5VGYZ62I.js.map +1 -0
  95. package/dist/chunk-6IQPH2OS.js +21 -0
  96. package/dist/chunk-6IQPH2OS.js.map +1 -0
  97. package/dist/chunk-6PB2MXCI.js +482 -0
  98. package/dist/chunk-6PB2MXCI.js.map +1 -0
  99. package/dist/chunk-7FD5CZEU.js +215 -0
  100. package/dist/chunk-7FD5CZEU.js.map +1 -0
  101. package/dist/chunk-7RL6KZDF.js +266 -0
  102. package/dist/chunk-7RL6KZDF.js.map +1 -0
  103. package/dist/chunk-ADOYAGGK.js +482 -0
  104. package/dist/chunk-ADOYAGGK.js.map +1 -0
  105. package/dist/chunk-BA3AEMOU.js +21 -0
  106. package/dist/chunk-BA3AEMOU.js.map +1 -0
  107. package/dist/chunk-BBHFOYML.js +336 -0
  108. package/dist/chunk-BBHFOYML.js.map +1 -0
  109. package/dist/chunk-BHUVISIY.js +221 -0
  110. package/dist/chunk-BHUVISIY.js.map +1 -0
  111. package/dist/chunk-BM2LWERA.js +100 -0
  112. package/dist/chunk-BM2LWERA.js.map +1 -0
  113. package/dist/chunk-CMOYXNPJ.js +211 -0
  114. package/dist/chunk-CMOYXNPJ.js.map +1 -0
  115. package/dist/chunk-CZP3RHC4.js +74 -0
  116. package/dist/chunk-CZP3RHC4.js.map +1 -0
  117. package/dist/chunk-DDG5JHQT.js +112 -0
  118. package/dist/chunk-DDG5JHQT.js.map +1 -0
  119. package/dist/chunk-DJODXO7I.js +38 -0
  120. package/dist/chunk-DJODXO7I.js.map +1 -0
  121. package/dist/chunk-DWJDJLPU.js +192 -0
  122. package/dist/chunk-DWJDJLPU.js.map +1 -0
  123. package/dist/chunk-DZW6LM22.js +45 -0
  124. package/dist/chunk-DZW6LM22.js.map +1 -0
  125. package/dist/chunk-ELGCZLZF.js +305 -0
  126. package/dist/chunk-ELGCZLZF.js.map +1 -0
  127. package/dist/chunk-EV3U6ZZB.js +209 -0
  128. package/dist/chunk-EV3U6ZZB.js.map +1 -0
  129. package/dist/chunk-EY7LVUKQ.js +87 -0
  130. package/dist/chunk-EY7LVUKQ.js.map +1 -0
  131. package/dist/chunk-F4C74F7M.js +230 -0
  132. package/dist/chunk-F4C74F7M.js.map +1 -0
  133. package/dist/chunk-FERYDFZA.js +108 -0
  134. package/dist/chunk-FERYDFZA.js.map +1 -0
  135. package/dist/chunk-FUIYG2DS.js +166 -0
  136. package/dist/chunk-FUIYG2DS.js.map +1 -0
  137. package/dist/chunk-GA7M34KU.js +236 -0
  138. package/dist/chunk-GA7M34KU.js.map +1 -0
  139. package/dist/chunk-GKYZT3LA.js +136 -0
  140. package/dist/chunk-GKYZT3LA.js.map +1 -0
  141. package/dist/chunk-H42LRUQ4.js +102 -0
  142. package/dist/chunk-H42LRUQ4.js.map +1 -0
  143. package/dist/chunk-HVXM2G5F.js +222 -0
  144. package/dist/chunk-HVXM2G5F.js.map +1 -0
  145. package/dist/chunk-I4RDAGVY.js +53 -0
  146. package/dist/chunk-I4RDAGVY.js.map +1 -0
  147. package/dist/chunk-IQJG4IDX.js +208 -0
  148. package/dist/chunk-IQJG4IDX.js.map +1 -0
  149. package/dist/chunk-IX2PXG4Y.js +144 -0
  150. package/dist/chunk-IX2PXG4Y.js.map +1 -0
  151. package/dist/chunk-IXICSOOP.js +287 -0
  152. package/dist/chunk-IXICSOOP.js.map +1 -0
  153. package/dist/chunk-JY5HSN4D.js +84 -0
  154. package/dist/chunk-JY5HSN4D.js.map +1 -0
  155. package/dist/chunk-L4SU3QJV.js +174 -0
  156. package/dist/chunk-L4SU3QJV.js.map +1 -0
  157. package/dist/chunk-LMNSBOBG.js +19 -0
  158. package/dist/chunk-LMNSBOBG.js.map +1 -0
  159. package/dist/chunk-MBI7D6IL.js +42 -0
  160. package/dist/chunk-MBI7D6IL.js.map +1 -0
  161. package/dist/chunk-MLFMYCPH.js +192 -0
  162. package/dist/chunk-MLFMYCPH.js.map +1 -0
  163. package/dist/chunk-MOK66734.js +33 -0
  164. package/dist/chunk-MOK66734.js.map +1 -0
  165. package/dist/chunk-MXTAWPYM.js +196 -0
  166. package/dist/chunk-MXTAWPYM.js.map +1 -0
  167. package/dist/chunk-NCL2UZKI.js +96 -0
  168. package/dist/chunk-NCL2UZKI.js.map +1 -0
  169. package/dist/chunk-NET4YLRY.js +107 -0
  170. package/dist/chunk-NET4YLRY.js.map +1 -0
  171. package/dist/chunk-NIG67CFM.js +329 -0
  172. package/dist/chunk-NIG67CFM.js.map +1 -0
  173. package/dist/chunk-NMVNNO3L.js +10 -0
  174. package/dist/chunk-NMVNNO3L.js.map +1 -0
  175. package/dist/chunk-NP7VID4K.js +2 -0
  176. package/dist/chunk-NP7VID4K.js.map +1 -0
  177. package/dist/chunk-NPUCMAG2.js +382 -0
  178. package/dist/chunk-NPUCMAG2.js.map +1 -0
  179. package/dist/chunk-NSCLRHES.js +102 -0
  180. package/dist/chunk-NSCLRHES.js.map +1 -0
  181. package/dist/chunk-OEUXHVFW.js +86 -0
  182. package/dist/chunk-OEUXHVFW.js.map +1 -0
  183. package/dist/chunk-ONBHFIMZ.js +137 -0
  184. package/dist/chunk-ONBHFIMZ.js.map +1 -0
  185. package/dist/chunk-OPH2HHL2.js +228 -0
  186. package/dist/chunk-OPH2HHL2.js.map +1 -0
  187. package/dist/chunk-OQERHIQP.js +287 -0
  188. package/dist/chunk-OQERHIQP.js.map +1 -0
  189. package/dist/chunk-P6YJAZFG.js +103 -0
  190. package/dist/chunk-P6YJAZFG.js.map +1 -0
  191. package/dist/chunk-PG7ERDOD.js +65 -0
  192. package/dist/chunk-PG7ERDOD.js.map +1 -0
  193. package/dist/chunk-PIB5JBMA.js +90 -0
  194. package/dist/chunk-PIB5JBMA.js.map +1 -0
  195. package/dist/chunk-PQ5BPIWQ.js +22 -0
  196. package/dist/chunk-PQ5BPIWQ.js.map +1 -0
  197. package/dist/chunk-PQBF6ZIQ.js +55 -0
  198. package/dist/chunk-PQBF6ZIQ.js.map +1 -0
  199. package/dist/chunk-PTWCTSZL.js +173 -0
  200. package/dist/chunk-PTWCTSZL.js.map +1 -0
  201. package/dist/chunk-QJUNPVOS.js +101 -0
  202. package/dist/chunk-QJUNPVOS.js.map +1 -0
  203. package/dist/chunk-QOBSEGCG.js +996 -0
  204. package/dist/chunk-QOBSEGCG.js.map +1 -0
  205. package/dist/chunk-QUDZOTRV.js +43 -0
  206. package/dist/chunk-QUDZOTRV.js.map +1 -0
  207. package/dist/chunk-RB7G65JC.js +213 -0
  208. package/dist/chunk-RB7G65JC.js.map +1 -0
  209. package/dist/chunk-RPHAOR7P.js +45 -0
  210. package/dist/chunk-RPHAOR7P.js.map +1 -0
  211. package/dist/chunk-RTCSH2AN.js +331 -0
  212. package/dist/chunk-RTCSH2AN.js.map +1 -0
  213. package/dist/chunk-S3ISPW3A.js +28 -0
  214. package/dist/chunk-S3ISPW3A.js.map +1 -0
  215. package/dist/chunk-SEVN656N.js +36 -0
  216. package/dist/chunk-SEVN656N.js.map +1 -0
  217. package/dist/chunk-SKVG672B.js +64 -0
  218. package/dist/chunk-SKVG672B.js.map +1 -0
  219. package/dist/chunk-SSGJ6MEM.js +1076 -0
  220. package/dist/chunk-SSGJ6MEM.js.map +1 -0
  221. package/dist/chunk-SSKZ2AED.js +118 -0
  222. package/dist/chunk-SSKZ2AED.js.map +1 -0
  223. package/dist/chunk-T56JFGXI.js +561 -0
  224. package/dist/chunk-T56JFGXI.js.map +1 -0
  225. package/dist/chunk-TCB6O74A.js +137 -0
  226. package/dist/chunk-TCB6O74A.js.map +1 -0
  227. package/dist/chunk-TTEYPO6X.js +57 -0
  228. package/dist/chunk-TTEYPO6X.js.map +1 -0
  229. package/dist/chunk-TWPHAJNM.js +462 -0
  230. package/dist/chunk-TWPHAJNM.js.map +1 -0
  231. package/dist/chunk-TXJJLP4O.js +336 -0
  232. package/dist/chunk-TXJJLP4O.js.map +1 -0
  233. package/dist/chunk-TZ6TB7VM.js +245 -0
  234. package/dist/chunk-TZ6TB7VM.js.map +1 -0
  235. package/dist/chunk-UBLKJJ7K.js +278 -0
  236. package/dist/chunk-UBLKJJ7K.js.map +1 -0
  237. package/dist/chunk-UCJ6IUFS.js +52 -0
  238. package/dist/chunk-UCJ6IUFS.js.map +1 -0
  239. package/dist/chunk-UCKFJ3QF.js +197 -0
  240. package/dist/chunk-UCKFJ3QF.js.map +1 -0
  241. package/dist/chunk-UPXSLILN.js +20 -0
  242. package/dist/chunk-UPXSLILN.js.map +1 -0
  243. package/dist/chunk-V4DORGWJ.js +92 -0
  244. package/dist/chunk-V4DORGWJ.js.map +1 -0
  245. package/dist/chunk-V6E5DYZD.js +80 -0
  246. package/dist/chunk-V6E5DYZD.js.map +1 -0
  247. package/dist/chunk-VLLYKF3P.js +96 -0
  248. package/dist/chunk-VLLYKF3P.js.map +1 -0
  249. package/dist/chunk-VLNBTOH6.js +43 -0
  250. package/dist/chunk-VLNBTOH6.js.map +1 -0
  251. package/dist/chunk-WMDSMSPL.js +303 -0
  252. package/dist/chunk-WMDSMSPL.js.map +1 -0
  253. package/dist/chunk-WU5BLGTF.js +149 -0
  254. package/dist/chunk-WU5BLGTF.js.map +1 -0
  255. package/dist/chunk-WYTZVSGK.js +245 -0
  256. package/dist/chunk-WYTZVSGK.js.map +1 -0
  257. package/dist/chunk-X47QMM6K.js +187 -0
  258. package/dist/chunk-X47QMM6K.js.map +1 -0
  259. package/dist/chunk-YHUSW7D2.js +40 -0
  260. package/dist/chunk-YHUSW7D2.js.map +1 -0
  261. package/dist/chunk-YSKD7UXX.js +126 -0
  262. package/dist/chunk-YSKD7UXX.js.map +1 -0
  263. package/dist/chunk-YYRDGWOU.js +72 -0
  264. package/dist/chunk-YYRDGWOU.js.map +1 -0
  265. package/dist/chunk-ZIGZMWM7.js +19 -0
  266. package/dist/chunk-ZIGZMWM7.js.map +1 -0
  267. package/dist/chunk-ZKRTUKNP.js +40 -0
  268. package/dist/chunk-ZKRTUKNP.js.map +1 -0
  269. package/dist/code-block.js +38 -0
  270. package/dist/code-block.js.map +1 -0
  271. package/dist/commit.js +51 -0
  272. package/dist/commit.js.map +1 -0
  273. package/dist/composer.js +15 -0
  274. package/dist/composer.js.map +1 -0
  275. package/dist/confirmation.js +53 -0
  276. package/dist/confirmation.js.map +1 -0
  277. package/dist/connection.js +8 -0
  278. package/dist/connection.js.map +1 -0
  279. package/dist/context-panel.js +25 -0
  280. package/dist/context-panel.js.map +1 -0
  281. package/dist/controls.js +10 -0
  282. package/dist/controls.js.map +1 -0
  283. package/dist/conversation.js +19 -0
  284. package/dist/conversation.js.map +1 -0
  285. package/dist/diff-view.js +15 -0
  286. package/dist/diff-view.js.map +1 -0
  287. package/dist/edge.js +10 -0
  288. package/dist/edge.js.map +1 -0
  289. package/dist/environment-variables.js +29 -0
  290. package/dist/environment-variables.js.map +1 -0
  291. package/dist/file-tree.js +23 -0
  292. package/dist/file-tree.js.map +1 -0
  293. package/dist/gallery.js +9 -0
  294. package/dist/gallery.js.map +1 -0
  295. package/dist/grouped-parts.js +21 -0
  296. package/dist/grouped-parts.js.map +1 -0
  297. package/dist/image.js +9 -0
  298. package/dist/image.js.map +1 -0
  299. package/dist/index.d.ts +366 -98
  300. package/dist/index.js +672 -13577
  301. package/dist/index.js.map +1 -1
  302. package/dist/inline-citation.js +39 -0
  303. package/dist/inline-citation.js.map +1 -0
  304. package/dist/jsx-preview.js +17 -0
  305. package/dist/jsx-preview.js.map +1 -0
  306. package/dist/markdown-view.js +17 -0
  307. package/dist/markdown-view.js.map +1 -0
  308. package/dist/message-compare.js +12 -0
  309. package/dist/message-compare.js.map +1 -0
  310. package/dist/message-edit.js +19 -0
  311. package/dist/message-edit.js.map +1 -0
  312. package/dist/message-feedback.js +11 -0
  313. package/dist/message-feedback.js.map +1 -0
  314. package/dist/message-form-spec.js +38 -0
  315. package/dist/message-form-spec.js.map +1 -0
  316. package/dist/message-form.js +26 -0
  317. package/dist/message-form.js.map +1 -0
  318. package/dist/message-table-spec.js +26 -0
  319. package/dist/message-table-spec.js.map +1 -0
  320. package/dist/message-table.js +12 -0
  321. package/dist/message-table.js.map +1 -0
  322. package/dist/message.js +51 -0
  323. package/dist/message.js.map +1 -0
  324. package/dist/mic-selector.js +27 -0
  325. package/dist/mic-selector.js.map +1 -0
  326. package/dist/model-provider-logo.js +13 -0
  327. package/dist/model-provider-logo.js.map +1 -0
  328. package/dist/motion-config.js +9 -0
  329. package/dist/motion-config.js.map +1 -0
  330. package/dist/node.js +22 -0
  331. package/dist/node.js.map +1 -0
  332. package/dist/open-in-chat.js +31 -0
  333. package/dist/open-in-chat.js.map +1 -0
  334. package/dist/package-info.js +25 -0
  335. package/dist/package-info.js.map +1 -0
  336. package/dist/panel.js +10 -0
  337. package/dist/panel.js.map +1 -0
  338. package/dist/part-groups.js +18 -0
  339. package/dist/part-groups.js.map +1 -0
  340. package/dist/permission-mode-select.js +9 -0
  341. package/dist/permission-mode-select.js.map +1 -0
  342. package/dist/persona-sources.js +8 -0
  343. package/dist/persona-sources.js.map +1 -0
  344. package/dist/persona.js +14 -0
  345. package/dist/persona.js.map +1 -0
  346. package/dist/plan.js +32 -0
  347. package/dist/plan.js.map +1 -0
  348. package/dist/prompt-input-effort.js +9 -0
  349. package/dist/prompt-input-effort.js.map +1 -0
  350. package/dist/prompt-input-mode.js +10 -0
  351. package/dist/prompt-input-mode.js.map +1 -0
  352. package/dist/prompt-input-slash.js +12 -0
  353. package/dist/prompt-input-slash.js.map +1 -0
  354. package/dist/prompt-input.js +89 -0
  355. package/dist/prompt-input.js.map +1 -0
  356. package/dist/queue.js +37 -0
  357. package/dist/queue.js.map +1 -0
  358. package/dist/reasoning.js +23 -0
  359. package/dist/reasoning.js.map +1 -0
  360. package/dist/sandbox.js +28 -0
  361. package/dist/sandbox.js.map +1 -0
  362. package/dist/schema-display.js +33 -0
  363. package/dist/schema-display.js.map +1 -0
  364. package/dist/selection-toolbar.js +11 -0
  365. package/dist/selection-toolbar.js.map +1 -0
  366. package/dist/session-header.js +9 -0
  367. package/dist/session-header.js.map +1 -0
  368. package/dist/session-status-bar.js +9 -0
  369. package/dist/session-status-bar.js.map +1 -0
  370. package/dist/shimmer.js +9 -0
  371. package/dist/shimmer.js.map +1 -0
  372. package/dist/snippet.js +17 -0
  373. package/dist/snippet.js.map +1 -0
  374. package/dist/sources.js +17 -0
  375. package/dist/sources.js.map +1 -0
  376. package/dist/speech-input.js +9 -0
  377. package/dist/speech-input.js.map +1 -0
  378. package/dist/stack-trace.js +27 -0
  379. package/dist/stack-trace.js.map +1 -0
  380. package/dist/suggestion.js +16 -0
  381. package/dist/suggestion.js.map +1 -0
  382. package/dist/task.js +18 -0
  383. package/dist/task.js.map +1 -0
  384. package/dist/test-results.js +43 -0
  385. package/dist/test-results.js.map +1 -0
  386. package/dist/token-usage.js +27 -0
  387. package/dist/token-usage.js.map +1 -0
  388. package/dist/tool-result-card.js +9 -0
  389. package/dist/tool-result-card.js.map +1 -0
  390. package/dist/tool.js +27 -0
  391. package/dist/tool.js.map +1 -0
  392. package/dist/toolbar.js +10 -0
  393. package/dist/toolbar.js.map +1 -0
  394. package/dist/transcription.js +11 -0
  395. package/dist/transcription.js.map +1 -0
  396. package/dist/turn-status.js +9 -0
  397. package/dist/turn-status.js.map +1 -0
  398. package/dist/use-audio-level.js +9 -0
  399. package/dist/use-audio-level.js.map +1 -0
  400. package/dist/voice-selector.js +47 -0
  401. package/dist/voice-selector.js.map +1 -0
  402. package/dist/web-preview.js +19 -0
  403. package/dist/web-preview.js.map +1 -0
  404. package/package.json +11 -9
  405. package/schemas/a2ui-surface.v1.schema.json +5434 -0
  406. package/src/_chat-shell-rail.tsx +3 -1
  407. package/src/_flow-boundary.tsx +2 -2
  408. package/src/_persona-rive.tsx +27 -41
  409. package/src/a2ui/a2ui-surface.stories.tsx +662 -0
  410. package/src/a2ui/a2ui-surface.test.tsx +201 -0
  411. package/src/a2ui/a2ui-surface.tsx +354 -0
  412. package/src/a2ui/catalog.source.json +772 -0
  413. package/src/a2ui/core/a2ui-core.test.ts +178 -0
  414. package/src/a2ui/core/catalog.generated.ts +1019 -0
  415. package/src/a2ui/core/complete-json.ts +81 -0
  416. package/src/a2ui/core/index.ts +10 -0
  417. package/src/a2ui/core/schema.ts +111 -0
  418. package/src/a2ui/core/spec.ts +148 -0
  419. package/src/a2ui/core/validate.ts +266 -0
  420. package/src/a2ui/index.ts +7 -0
  421. package/src/a2ui/ui-catalog.tsx +225 -0
  422. package/src/a2ui/wave1-chart-spec.test.ts +87 -0
  423. package/src/a2ui/wave2-chart-spec.test.ts +108 -0
  424. package/src/agentic-workspace.stories.tsx +6 -45
  425. package/src/chat-shell.test.tsx +40 -10
  426. package/src/chat-shell.tsx +90 -44
  427. package/src/chat.stories.tsx +47 -42
  428. package/src/composer.stories.tsx +4 -5
  429. package/src/composer.test.tsx +45 -0
  430. package/src/composer.tsx +104 -21
  431. package/src/context-panel.stories.tsx +1 -1
  432. package/src/context-panel.tsx +1 -1
  433. package/src/conversation.stories.tsx +1 -0
  434. package/src/conversation.test.tsx +16 -0
  435. package/src/conversation.tsx +16 -2
  436. package/src/diff-view.stories.tsx +79 -0
  437. package/src/diff-view.tsx +3 -2
  438. package/src/file-tree.tsx +24 -17
  439. package/src/gallery.stories.tsx +42 -0
  440. package/src/gallery.tsx +2 -2
  441. package/src/grouped-parts.stories.tsx +23 -0
  442. package/src/grouped-parts.tsx +1 -1
  443. package/src/index.ts +1 -0
  444. package/src/message-compare.stories.tsx +40 -0
  445. package/src/message-compare.tsx +2 -1
  446. package/src/message-form.tsx +1 -1
  447. package/src/message-table.stories.tsx +24 -0
  448. package/src/message-table.tsx +1 -1
  449. package/src/package-info.tsx +12 -9
  450. package/src/reasoning.stories.tsx +27 -0
  451. package/src/reasoning.tsx +1 -1
  452. package/src/session-header.stories.tsx +35 -1
  453. package/src/session-header.tsx +1 -1
  454. package/src/sources.stories.tsx +30 -0
  455. package/src/sources.tsx +4 -1
  456. package/src/templates-ai-assistant.stories.tsx +151 -87
  457. package/src/tool.stories.tsx +39 -0
  458. package/src/tool.tsx +3 -3
  459. package/src/toolbar.tsx +0 -10
  460. package/dist/_flow-boundary-SHNWLQG5.js.map +0 -1
  461. package/dist/_persona-rive-JEG44YHX.js.map +0 -1
  462. /package/dist/{_audio-player-media-chrome-T3XVXWRZ.js.map → _audio-player-media-chrome.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/prompt-input.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandSeparator,\n} from \"@elabs-ai/components-ui\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@elabs-ai/components-ui\";\nimport { HoverCard, HoverCardContent, HoverCardTrigger } from \"@elabs-ai/components-ui\";\nimport {\n InputGroup,\n InputGroupAddon,\n InputGroupButton,\n InputGroupTextarea,\n} from \"@elabs-ai/components-ui\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@elabs-ai/components-ui\";\nimport { Spinner } from \"@elabs-ai/components-ui\";\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { useLocale } from \"@elabs-ai/components-ui\";\nimport type { ChatStatus, FileUIPart, SourceDocumentUIPart } from \"ai\";\nimport { CornerDownLeftIcon, ImageIcon, Monitor, PlusIcon, SquareIcon, XIcon } from \"lucide-react\";\nimport { nanoid } from \"nanoid\";\nimport type {\n ChangeEvent,\n ChangeEventHandler,\n ClipboardEventHandler,\n ComponentProps,\n FormEvent,\n FormEventHandler,\n HTMLAttributes,\n KeyboardEventHandler,\n PropsWithChildren,\n ReactNode,\n RefObject,\n} from \"react\";\nimport {\n Children,\n createContext,\n isValidElement,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nconst convertBlobUrlToDataUrl = async (url: string): Promise<string | null> => {\n try {\n const response = await fetch(url);\n const blob = await response.blob();\n // FileReader uses callback-based API, wrapping in Promise is necessary\n // oxlint-disable-next-line eslint-plugin-promise(avoid-new)\n return new Promise((resolve) => {\n const reader = new FileReader();\n // oxlint-disable-next-line eslint-plugin-unicorn(prefer-add-event-listener)\n reader.onloadend = () => resolve(reader.result as string);\n // oxlint-disable-next-line eslint-plugin-unicorn(prefer-add-event-listener)\n reader.onerror = () => resolve(null);\n reader.readAsDataURL(blob);\n });\n } catch {\n return null;\n }\n};\n\nconst captureScreenshot = async (): Promise<File | null> => {\n if (typeof navigator === \"undefined\" || !navigator.mediaDevices?.getDisplayMedia) {\n return null;\n }\n\n let stream: MediaStream | null = null;\n const video = document.createElement(\"video\");\n video.muted = true;\n video.playsInline = true;\n\n try {\n stream = await navigator.mediaDevices.getDisplayMedia({\n audio: false,\n video: true,\n });\n\n video.srcObject = stream;\n\n // Video element uses callback-based API, wrapping in Promise is necessary\n // oxlint-disable-next-line eslint-plugin-promise(avoid-new)\n await new Promise<void>((resolve, reject) => {\n // oxlint-disable-next-line eslint-plugin-unicorn(prefer-add-event-listener)\n video.onloadedmetadata = () => resolve();\n // oxlint-disable-next-line eslint-plugin-unicorn(prefer-add-event-listener)\n video.onerror = () => reject(new Error(\"Failed to load screen stream\"));\n });\n\n await video.play();\n\n const width = video.videoWidth;\n const height = video.videoHeight;\n if (!width || !height) {\n return null;\n }\n\n const canvas = document.createElement(\"canvas\");\n canvas.width = width;\n canvas.height = height;\n const context = canvas.getContext(\"2d\");\n if (!context) {\n return null;\n }\n\n context.drawImage(video, 0, 0, width, height);\n // canvas.toBlob uses callback-based API, wrapping in Promise is necessary\n // oxlint-disable-next-line eslint-plugin-promise(avoid-new)\n const blob = await new Promise<Blob | null>((resolve) => {\n canvas.toBlob(resolve, \"image/png\");\n });\n if (!blob) {\n return null;\n }\n\n const timestamp = new Date()\n .toISOString()\n .replaceAll(/[:.]/g, \"-\")\n .replace(\"T\", \"_\")\n .replace(\"Z\", \"\");\n\n return new File([blob], `screenshot-${timestamp}.png`, {\n lastModified: Date.now(),\n type: \"image/png\",\n });\n } finally {\n if (stream) {\n for (const track of stream.getTracks()) {\n track.stop();\n }\n }\n video.pause();\n video.srcObject = null;\n }\n};\n\n// ============================================================================\n// Provider Context & Types\n// ============================================================================\n\nexport interface AttachmentsContext {\n files: (FileUIPart & { id: string })[];\n add: (files: File[] | FileList) => void;\n remove: (id: string) => void;\n clear: () => void;\n openFileDialog: () => void;\n fileInputRef: RefObject<HTMLInputElement | null>;\n}\n\nexport interface TextInputContext {\n value: string;\n setInput: (v: string) => void;\n clear: () => void;\n}\n\nexport interface PromptInputControllerProps {\n textInput: TextInputContext;\n attachments: AttachmentsContext;\n /** INTERNAL: Allows PromptInput to register its file textInput + \"open\" callback */\n __registerFileInput: (ref: RefObject<HTMLInputElement | null>, open: () => void) => void;\n}\n\nconst PromptInputController = createContext<PromptInputControllerProps | null>(null);\nconst ProviderAttachmentsContext = createContext<AttachmentsContext | null>(null);\n\nexport const usePromptInputController = () => {\n const ctx = useContext(PromptInputController);\n if (!ctx) {\n throw new Error(\n \"Wrap your component inside <PromptInputProvider> to use usePromptInputController().\",\n );\n }\n return ctx;\n};\n\n// Optional variants (do NOT throw). Useful for dual-mode components.\nconst useOptionalPromptInputController = () => useContext(PromptInputController);\n\nexport const useProviderAttachments = () => {\n const ctx = useContext(ProviderAttachmentsContext);\n if (!ctx) {\n throw new Error(\n \"Wrap your component inside <PromptInputProvider> to use useProviderAttachments().\",\n );\n }\n return ctx;\n};\n\nconst useOptionalProviderAttachments = () => useContext(ProviderAttachmentsContext);\n\nexport type PromptInputProviderProps = PropsWithChildren<{\n initialInput?: string;\n}>;\n\n/**\n * Optional global provider that lifts PromptInput state outside of PromptInput.\n * If you don't use it, PromptInput stays fully self-managed.\n */\nexport const PromptInputProvider = ({\n initialInput: initialTextInput = \"\",\n children,\n}: PromptInputProviderProps) => {\n // ----- textInput state\n const [textInput, setTextInput] = useState(initialTextInput);\n const clearInput = useCallback(() => setTextInput(\"\"), []);\n\n // ----- attachments state (global when wrapped)\n const [attachmentFiles, setAttachmentFiles] = useState<(FileUIPart & { id: string })[]>([]);\n const fileInputRef = useRef<HTMLInputElement | null>(null);\n // oxlint-disable-next-line eslint(no-empty-function)\n const openRef = useRef<() => void>(() => {});\n\n const add = useCallback((files: File[] | FileList) => {\n const incoming = [...files];\n if (incoming.length === 0) {\n return;\n }\n\n setAttachmentFiles((prev) => [\n ...prev,\n ...incoming.map((file) => ({\n filename: file.name,\n id: nanoid(),\n mediaType: file.type,\n type: \"file\" as const,\n url: URL.createObjectURL(file),\n })),\n ]);\n }, []);\n\n const remove = useCallback((id: string) => {\n setAttachmentFiles((prev) => {\n const found = prev.find((f) => f.id === id);\n if (found?.url) {\n URL.revokeObjectURL(found.url);\n }\n return prev.filter((f) => f.id !== id);\n });\n }, []);\n\n const clear = useCallback(() => {\n setAttachmentFiles((prev) => {\n for (const f of prev) {\n if (f.url) {\n URL.revokeObjectURL(f.url);\n }\n }\n return [];\n });\n }, []);\n\n // Keep a ref to attachments for cleanup on unmount (avoids stale closure)\n const attachmentsRef = useRef(attachmentFiles);\n\n useEffect(() => {\n attachmentsRef.current = attachmentFiles;\n }, [attachmentFiles]);\n\n // Cleanup blob URLs on unmount to prevent memory leaks\n useEffect(\n () => () => {\n for (const f of attachmentsRef.current) {\n if (f.url) {\n URL.revokeObjectURL(f.url);\n }\n }\n },\n [],\n );\n\n const openFileDialog = useCallback(() => {\n openRef.current?.();\n }, []);\n\n const attachments = useMemo<AttachmentsContext>(\n () => ({\n add,\n clear,\n fileInputRef,\n files: attachmentFiles,\n openFileDialog,\n remove,\n }),\n [attachmentFiles, add, remove, clear, openFileDialog],\n );\n\n const __registerFileInput = useCallback(\n (ref: RefObject<HTMLInputElement | null>, open: () => void) => {\n fileInputRef.current = ref.current;\n openRef.current = open;\n },\n [],\n );\n\n const controller = useMemo<PromptInputControllerProps>(\n () => ({\n __registerFileInput,\n attachments,\n textInput: {\n clear: clearInput,\n setInput: setTextInput,\n value: textInput,\n },\n }),\n [textInput, clearInput, attachments, __registerFileInput],\n );\n\n return (\n <PromptInputController.Provider value={controller}>\n <ProviderAttachmentsContext.Provider value={attachments}>\n {children}\n </ProviderAttachmentsContext.Provider>\n </PromptInputController.Provider>\n );\n};\n\n// ============================================================================\n// Component Context & Hooks\n// ============================================================================\n\nconst LocalAttachmentsContext = createContext<AttachmentsContext | null>(null);\n\n/**\n * Submit-readiness, lifted into `PromptInput` so the guard and the affordance\n * agree. `handleSubmit` is the invariant (it is reachable via `requestSubmit()`\n * or a consumer's own button); `PromptInputSubmit`'s disabled state is the\n * affordance. Both read `canSubmit` — a live-looking button that does nothing\n * is an accessibility lie, and a guard nobody can see is a dead end.\n */\ninterface PromptInputSubmitStateContextValue {\n /** Non-whitespace text, or at least one attachment. */\n canSubmit: boolean;\n /**\n * INTERNAL — the uncontrolled textarea reports empty↔non-empty transitions.\n * A boolean, so React bails out on identical state and typing does not make\n * an uncontrolled input re-render per keystroke.\n */\n setHasText: (hasText: boolean) => void;\n /**\n * True while at least one `PromptInputStop` is mounted (#351). When a\n * consumer composes a dedicated Stop control, `PromptInputSubmit` never\n * needs to double as Stop — it stays the Send action in every state.\n */\n hasDedicatedStop: boolean;\n /** Registers a mounted `PromptInputStop`; returns its unregister fn. */\n registerStop: () => () => void;\n}\n\nconst PromptInputSubmitStateContext = createContext<PromptInputSubmitStateContextValue | null>(\n null,\n);\n\n/** Optional — `PromptInputSubmit` may legitimately render outside a `PromptInput`. */\nconst useOptionalSubmitState = () => useContext(PromptInputSubmitStateContext);\n\n/** The `data-slot` the Enter handler uses to find the send control. */\nconst SUBMIT_SLOT = \"prompt-input-submit\";\n\nexport const usePromptInputAttachments = () => {\n // Prefer local context (inside PromptInput) as it has validation, fall back to provider\n const provider = useOptionalProviderAttachments();\n const local = useContext(LocalAttachmentsContext);\n const context = local ?? provider;\n if (!context) {\n throw new Error(\n \"usePromptInputAttachments must be used within a PromptInput or PromptInputProvider\",\n );\n }\n return context;\n};\n\n// ============================================================================\n// Referenced Sources (Local to PromptInput)\n// ============================================================================\n\nexport interface ReferencedSourcesContext {\n sources: (SourceDocumentUIPart & { id: string })[];\n add: (sources: SourceDocumentUIPart[] | SourceDocumentUIPart) => void;\n remove: (id: string) => void;\n clear: () => void;\n}\n\nexport const LocalReferencedSourcesContext = createContext<ReferencedSourcesContext | null>(null);\n\nexport const usePromptInputReferencedSources = () => {\n const ctx = useContext(LocalReferencedSourcesContext);\n if (!ctx) {\n throw new Error(\n \"usePromptInputReferencedSources must be used within a LocalReferencedSourcesContext.Provider\",\n );\n }\n return ctx;\n};\n\nexport type PromptInputActionAddAttachmentsProps = ComponentProps<typeof DropdownMenuItem> & {\n label?: string;\n};\n\nexport const PromptInputActionAddAttachments = ({\n label = \"Add photos or files\",\n ...props\n}: PromptInputActionAddAttachmentsProps) => {\n const attachments = usePromptInputAttachments();\n\n const handleSelect = useCallback(\n (e: Event) => {\n e.preventDefault();\n attachments.openFileDialog();\n },\n [attachments],\n );\n\n return (\n <DropdownMenuItem {...props} onSelect={handleSelect}>\n <ImageIcon className=\"me-2 size-4\" /> {label}\n </DropdownMenuItem>\n );\n};\n\nexport type PromptInputActionAddScreenshotProps = ComponentProps<typeof DropdownMenuItem> & {\n label?: string;\n};\n\nexport const PromptInputActionAddScreenshot = ({\n label = \"Take screenshot\",\n onSelect,\n ...props\n}: PromptInputActionAddScreenshotProps) => {\n const attachments = usePromptInputAttachments();\n\n const handleSelect = useCallback(\n async (event: Event) => {\n onSelect?.(event);\n if (event.defaultPrevented) {\n return;\n }\n\n try {\n const screenshot = await captureScreenshot();\n if (screenshot) {\n attachments.add([screenshot]);\n }\n } catch (error) {\n if (\n error instanceof DOMException &&\n (error.name === \"NotAllowedError\" || error.name === \"AbortError\")\n ) {\n return;\n }\n throw error;\n }\n },\n [onSelect, attachments],\n );\n\n return (\n <DropdownMenuItem {...props} onSelect={handleSelect}>\n <Monitor className=\"me-2 size-4\" />\n {label}\n </DropdownMenuItem>\n );\n};\n\nexport interface PromptInputMessage {\n text: string;\n files: FileUIPart[];\n}\n\nexport type PromptInputProps = Omit<HTMLAttributes<HTMLFormElement>, \"onSubmit\" | \"onError\"> & {\n // e.g., \"image/*\" or leave undefined for any\n accept?: string;\n multiple?: boolean;\n // When true, accepts drops anywhere on document. Default false (opt-in).\n globalDrop?: boolean;\n // Render a hidden input with given name and keep it in sync for native form posts. Default false.\n syncHiddenInput?: boolean;\n // Minimal constraints\n maxFiles?: number;\n // bytes\n maxFileSize?: number;\n /**\n * The fill of the inner well (the `InputGroup` `variant`). `\"surface\"`\n * (default) is the standard muted composer look; `\"card\"` renders a\n * `bg-card` well for nesting inside an already-tinted outer frame — the\n * \"double card\" look (#254). e.g.\n * `<div className=\"rounded-xl bg-surface-muted p-1.5\"><PromptInput tone=\"card\">…</PromptInput></div>`.\n * The well fill is NOT universally \"white\": `--card` reads lighter\n * (raised) than `--surface-muted` on light themes, but darker (recessed) on\n * dark — the same theme-dependent trade-off documented\n * for `bg-surface-muted`-as-a-well in `styling-and-tokens.md`. The well\n * stays a legible, distinct tone against the outer frame in every theme;\n * only the \"raised\" framing is light-themes-specific.\n */\n tone?: \"surface\" | \"card\";\n onError?: (err: { code: \"max_files\" | \"max_file_size\" | \"accept\"; message: string }) => void;\n onSubmit: (\n message: PromptInputMessage,\n event: FormEvent<HTMLFormElement>,\n ) => void | Promise<void>;\n /**\n * Classes for the inner surface (the visible `InputGroup` well), e.g. to shape\n * its corners. `className` styles the outer `<form>`; this styles the well —\n * the only way to reach it from outside (used by `Composer`).\n */\n surfaceClassName?: string;\n};\n\nexport const PromptInput = ({\n className,\n surfaceClassName,\n tone = \"surface\",\n accept,\n multiple,\n globalDrop,\n syncHiddenInput,\n maxFiles,\n maxFileSize,\n onError,\n onSubmit,\n children,\n ...props\n}: PromptInputProps) => {\n // Try to use a provider controller if present\n const controller = useOptionalPromptInputController();\n const usingProvider = !!controller;\n\n // Microcopy goes through the locale seam. `useLocale` is provider-optional —\n // with no <LocaleProvider> it returns the shipped English defaults, so this is\n // not a breaking change and needs no ancestor. See ADR 0017.\n const { t } = useLocale();\n\n // Refs\n const inputRef = useRef<HTMLInputElement | null>(null);\n const formRef = useRef<HTMLFormElement | null>(null);\n // In-flight guard for handleSubmit (#1.9) — a ref, not state, so a second\n // Enter/click during the same synchronous event-handling pass sees the\n // updated value immediately (no waiting for a re-render).\n const isSubmittingRef = useRef(false);\n\n // ----- Local attachments (only used when no provider)\n const [items, setItems] = useState<(FileUIPart & { id: string })[]>([]);\n const files = usingProvider ? controller.attachments.files : items;\n\n // ----- Submit readiness (drives both the guard and the disabled affordance)\n const [hasLocalText, setHasLocalText] = useState(false);\n const hasText = usingProvider ? controller.textInput.value.trim().length > 0 : hasLocalText;\n\n // ----- Dedicated Stop control registration (#351 — the composed \"separate\"\n // arrangement). A ref counter tolerates >1 mounted PromptInputStop; the\n // boolean state is what's actually read, so React bails out on identical\n // values the same way `setHasText` does.\n const [hasDedicatedStop, setHasDedicatedStop] = useState(false);\n const stopCountRef = useRef(0);\n const registerStop = useCallback(() => {\n stopCountRef.current += 1;\n setHasDedicatedStop(true);\n return () => {\n stopCountRef.current = Math.max(0, stopCountRef.current - 1);\n if (stopCountRef.current === 0) {\n setHasDedicatedStop(false);\n }\n };\n }, []);\n\n // ----- Local referenced sources (always local to PromptInput)\n const [referencedSources, setReferencedSources] = useState<\n (SourceDocumentUIPart & { id: string })[]\n >([]);\n\n // Keep a ref to files for cleanup on unmount (avoids stale closure)\n const filesRef = useRef(files);\n\n useEffect(() => {\n filesRef.current = files;\n }, [files]);\n\n const openFileDialogLocal = useCallback(() => {\n inputRef.current?.click();\n }, []);\n\n const matchesAccept = useCallback(\n (f: File) => {\n if (!accept || accept.trim() === \"\") {\n return true;\n }\n\n const patterns = accept\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n\n return patterns.some((pattern) => {\n if (pattern.endsWith(\"/*\")) {\n // e.g: image/* -> image/\n const prefix = pattern.slice(0, -1);\n return f.type.startsWith(prefix);\n }\n return f.type === pattern;\n });\n },\n [accept],\n );\n\n const addLocal = useCallback(\n (fileList: File[] | FileList) => {\n const incoming = [...fileList];\n const accepted = incoming.filter((f) => matchesAccept(f));\n if (incoming.length && accepted.length === 0) {\n onError?.({\n code: \"accept\",\n message: t(\"ai.promptInput.errorAccept\"),\n });\n return;\n }\n const withinSize = (f: File) => (maxFileSize ? f.size <= maxFileSize : true);\n const sized = accepted.filter(withinSize);\n if (accepted.length > 0 && sized.length === 0) {\n onError?.({\n code: \"max_file_size\",\n message: t(\"ai.promptInput.errorMaxFileSize\"),\n });\n return;\n }\n\n setItems((prev) => {\n const capacity =\n typeof maxFiles === \"number\" ? Math.max(0, maxFiles - prev.length) : undefined;\n const capped = typeof capacity === \"number\" ? sized.slice(0, capacity) : sized;\n if (typeof capacity === \"number\" && sized.length > capacity) {\n onError?.({\n code: \"max_files\",\n message: t(\"ai.promptInput.errorMaxFiles\"),\n });\n }\n const next: (FileUIPart & { id: string })[] = [];\n for (const file of capped) {\n next.push({\n filename: file.name,\n id: nanoid(),\n mediaType: file.type,\n type: \"file\",\n url: URL.createObjectURL(file),\n });\n }\n return [...prev, ...next];\n });\n },\n [matchesAccept, maxFiles, maxFileSize, onError],\n );\n\n const removeLocal = useCallback(\n (id: string) =>\n setItems((prev) => {\n const found = prev.find((file) => file.id === id);\n if (found?.url) {\n URL.revokeObjectURL(found.url);\n }\n return prev.filter((file) => file.id !== id);\n }),\n [],\n );\n\n // Wrapper that validates files before calling provider's add\n const addWithProviderValidation = useCallback(\n (fileList: File[] | FileList) => {\n const incoming = [...fileList];\n const accepted = incoming.filter((f) => matchesAccept(f));\n if (incoming.length && accepted.length === 0) {\n onError?.({\n code: \"accept\",\n message: t(\"ai.promptInput.errorAccept\"),\n });\n return;\n }\n const withinSize = (f: File) => (maxFileSize ? f.size <= maxFileSize : true);\n const sized = accepted.filter(withinSize);\n if (accepted.length > 0 && sized.length === 0) {\n onError?.({\n code: \"max_file_size\",\n message: t(\"ai.promptInput.errorMaxFileSize\"),\n });\n return;\n }\n\n const currentCount = files.length;\n const capacity =\n typeof maxFiles === \"number\" ? Math.max(0, maxFiles - currentCount) : undefined;\n const capped = typeof capacity === \"number\" ? sized.slice(0, capacity) : sized;\n if (typeof capacity === \"number\" && sized.length > capacity) {\n onError?.({\n code: \"max_files\",\n message: t(\"ai.promptInput.errorMaxFiles\"),\n });\n }\n\n if (capped.length > 0) {\n controller?.attachments.add(capped);\n }\n },\n [matchesAccept, maxFileSize, maxFiles, onError, files.length, controller],\n );\n\n const clearAttachments = useCallback(\n () =>\n usingProvider\n ? controller?.attachments.clear()\n : setItems((prev) => {\n for (const file of prev) {\n if (file.url) {\n URL.revokeObjectURL(file.url);\n }\n }\n return [];\n }),\n [usingProvider, controller],\n );\n\n const clearReferencedSources = useCallback(() => setReferencedSources([]), []);\n\n const add = usingProvider ? addWithProviderValidation : addLocal;\n const remove = usingProvider ? controller.attachments.remove : removeLocal;\n const openFileDialog = usingProvider\n ? controller.attachments.openFileDialog\n : openFileDialogLocal;\n\n const clear = useCallback(() => {\n clearAttachments();\n clearReferencedSources();\n }, [clearAttachments, clearReferencedSources]);\n\n // Let provider know about our hidden file input so external menus can call openFileDialog()\n useEffect(() => {\n if (!usingProvider) {\n return;\n }\n controller.__registerFileInput(inputRef, () => inputRef.current?.click());\n }, [usingProvider, controller]);\n\n // Note: File input cannot be programmatically set for security reasons\n // The syncHiddenInput prop is no longer functional\n useEffect(() => {\n if (syncHiddenInput && inputRef.current && files.length === 0) {\n inputRef.current.value = \"\";\n }\n }, [files, syncHiddenInput]);\n\n // Attach drop handlers on nearest form and document (opt-in)\n useEffect(() => {\n const form = formRef.current;\n if (!form) {\n return;\n }\n if (globalDrop) {\n // when global drop is on, let the document-level handler own drops\n return;\n }\n\n const onDragOver = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) {\n e.preventDefault();\n }\n };\n const onDrop = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) {\n e.preventDefault();\n }\n if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) {\n add(e.dataTransfer.files);\n }\n };\n form.addEventListener(\"dragover\", onDragOver);\n form.addEventListener(\"drop\", onDrop);\n return () => {\n form.removeEventListener(\"dragover\", onDragOver);\n form.removeEventListener(\"drop\", onDrop);\n };\n }, [add, globalDrop]);\n\n useEffect(() => {\n if (!globalDrop) {\n return;\n }\n\n const onDragOver = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) {\n e.preventDefault();\n }\n };\n const onDrop = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) {\n e.preventDefault();\n }\n if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) {\n add(e.dataTransfer.files);\n }\n };\n document.addEventListener(\"dragover\", onDragOver);\n document.addEventListener(\"drop\", onDrop);\n return () => {\n document.removeEventListener(\"dragover\", onDragOver);\n document.removeEventListener(\"drop\", onDrop);\n };\n }, [add, globalDrop]);\n\n useEffect(\n () => () => {\n if (!usingProvider) {\n for (const f of filesRef.current) {\n if (f.url) {\n URL.revokeObjectURL(f.url);\n }\n }\n }\n },\n [usingProvider],\n );\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = useCallback(\n (event) => {\n if (event.currentTarget.files) {\n add(event.currentTarget.files);\n }\n // Reset input value to allow selecting files that were previously removed\n event.currentTarget.value = \"\";\n },\n [add],\n );\n\n const attachmentsCtx = useMemo<AttachmentsContext>(\n () => ({\n add,\n clear: clearAttachments,\n fileInputRef: inputRef,\n files: files.map((item) => ({ ...item, id: item.id })),\n openFileDialog,\n remove,\n }),\n [files, add, remove, clearAttachments, openFileDialog],\n );\n\n const submitState = useMemo<PromptInputSubmitStateContextValue>(\n () => ({\n canSubmit: hasText || files.length > 0,\n hasDedicatedStop,\n registerStop,\n setHasText: setHasLocalText,\n }),\n [hasText, files.length, hasDedicatedStop, registerStop],\n );\n\n const refsCtx = useMemo<ReferencedSourcesContext>(\n () => ({\n add: (incoming: SourceDocumentUIPart[] | SourceDocumentUIPart) => {\n const array = Array.isArray(incoming) ? incoming : [incoming];\n setReferencedSources((prev) => [...prev, ...array.map((s) => ({ ...s, id: nanoid() }))]);\n },\n clear: clearReferencedSources,\n remove: (id: string) => {\n setReferencedSources((prev) => prev.filter((s) => s.id !== id));\n },\n sources: referencedSources,\n }),\n [referencedSources, clearReferencedSources],\n );\n\n const handleSubmit: FormEventHandler<HTMLFormElement> = useCallback(\n async (event) => {\n event.preventDefault();\n\n // In-flight guard (#1.9): a second Enter/click fired while the first\n // submission is still being processed (mid blob conversion, mid async\n // `onSubmit`) must not fire a second one — otherwise a double-Enter\n // submits the same attachments twice.\n if (isSubmittingRef.current) {\n return;\n }\n\n const form = event.currentTarget;\n const text = usingProvider\n ? controller.textInput.value\n : (() => {\n const formData = new FormData(form);\n return (formData.get(\"message\") as string) || \"\";\n })();\n\n // Nothing to send: no text AND no attachments. This runs BEFORE the reset\n // below — a later guard would still have wiped the composer. Only the\n // guard trims; the untrimmed `text` still reaches `onSubmit`, preserving\n // the existing payload semantics. An attachments-only submit (no text) is\n // legitimate and must still go through.\n if (text.trim().length === 0 && files.length === 0) {\n return;\n }\n\n isSubmittingRef.current = true;\n\n // The uncontrolled textarea's DOM value is about to be wiped by\n // `form.reset()` below, before `onSubmit` has even run. Snapshot it so a\n // sync throw / rejected promise can restore exactly what the user typed\n // instead of losing it.\n const textarea = usingProvider\n ? null\n : form.querySelector<HTMLTextAreaElement>('textarea[name=\"message\"]');\n\n const restoreTextOnFailure = () => {\n if (textarea) {\n textarea.value = text;\n setHasLocalText(text.trim().length > 0);\n }\n };\n\n // Reset form immediately after capturing text to avoid race condition\n // where user input during async blob conversion would be lost\n if (!usingProvider) {\n form.reset();\n // `form.reset()` fires no change event, so tell the submit affordance.\n setHasLocalText(false);\n }\n\n try {\n // Convert blob URLs to data URLs asynchronously\n const convertedFiles: FileUIPart[] = await Promise.all(\n files.map(async ({ id: _id, ...item }) => {\n if (item.url?.startsWith(\"blob:\")) {\n const dataUrl = await convertBlobUrlToDataUrl(item.url);\n // If conversion failed, keep the original blob URL\n return {\n ...item,\n url: dataUrl ?? item.url,\n };\n }\n return item;\n }),\n );\n\n const result = onSubmit({ files: convertedFiles, text }, event);\n\n // Handle both sync and async onSubmit\n if (result instanceof Promise) {\n try {\n await result;\n clear();\n if (usingProvider) {\n controller.textInput.clear();\n }\n } catch {\n // Don't clear on error - user may want to retry; restore the text\n // the early reset above wiped.\n restoreTextOnFailure();\n }\n } else {\n // Sync function completed without throwing, clear inputs\n clear();\n if (usingProvider) {\n controller.textInput.clear();\n }\n }\n } catch {\n // Don't clear on error - user may want to retry; restore the text the\n // early reset above wiped.\n restoreTextOnFailure();\n } finally {\n isSubmittingRef.current = false;\n }\n },\n [usingProvider, controller, files, onSubmit, clear],\n );\n\n // Render with or without local provider\n const inner = (\n <>\n <input\n accept={accept}\n aria-label={t(\"ai.promptInput.uploadFiles\")}\n className=\"hidden\"\n multiple={multiple}\n onChange={handleChange}\n ref={inputRef}\n title={t(\"ai.promptInput.uploadFiles\")}\n type=\"file\"\n />\n <form className={cn(\"w-full\", className)} onSubmit={handleSubmit} ref={formRef} {...props}>\n {/* The composer is a soft fill + focus ring, not a hard box (#194,\n research 02 §3a BTN-3 / 08 §C.1): the chat footer already draws a\n `border-t` (chat-shell.tsx), so the box border was redundant. */}\n <InputGroup variant={tone} className={cn(\"overflow-hidden\", surfaceClassName)}>\n {children}\n </InputGroup>\n </form>\n </>\n );\n\n const withReferencedSources = (\n <LocalReferencedSourcesContext.Provider value={refsCtx}>\n <PromptInputSubmitStateContext.Provider value={submitState}>\n {inner}\n </PromptInputSubmitStateContext.Provider>\n </LocalReferencedSourcesContext.Provider>\n );\n\n // Always provide LocalAttachmentsContext so children get validated add function\n return (\n <LocalAttachmentsContext.Provider value={attachmentsCtx}>\n {withReferencedSources}\n </LocalAttachmentsContext.Provider>\n );\n};\n\nexport type PromptInputBodyProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputBody = ({ className, ...props }: PromptInputBodyProps) => (\n <div className={cn(\"contents\", className)} {...props} />\n);\n\nexport type PromptInputTextareaProps = ComponentProps<typeof InputGroupTextarea>;\n\nexport const PromptInputTextarea = ({\n onChange,\n onKeyDown,\n className,\n placeholder,\n ...props\n}: PromptInputTextareaProps) => {\n const { t } = useLocale();\n const controller = useOptionalPromptInputController();\n const attachments = usePromptInputAttachments();\n const submitState = useOptionalSubmitState();\n const [isComposing, setIsComposing] = useState(false);\n\n const handleKeyDown: KeyboardEventHandler<HTMLTextAreaElement> = useCallback(\n (e) => {\n // Call the external onKeyDown handler first\n onKeyDown?.(e);\n\n // If the external handler prevented default, don't run internal logic\n if (e.defaultPrevented) {\n return;\n }\n\n if (e.key === \"Enter\") {\n if (isComposing || e.nativeEvent.isComposing) {\n return;\n }\n if (e.shiftKey) {\n return;\n }\n e.preventDefault();\n\n // Don't submit when the send control is unavailable. Query by data-slot,\n // NOT `button[type=\"submit\"]`: PromptInputSubmit flips to type=\"button\"\n // while generating, so the old selector matched nothing mid-stream and\n // `null?.disabled` (undefined, falsy) let Enter send a second message.\n const { form } = e.currentTarget;\n const submitControl = form?.querySelector<HTMLButtonElement>(\n `[data-slot=\"${SUBMIT_SLOT}\"]`,\n );\n // `data-action` is the current contract (#351): \"stop\" blocks Enter,\n // \"send\" (including the running+typed flip) lets it through. Fall back\n // to the older `data-generating` flag for a consumer-supplied control\n // that still only sets that attribute.\n const action =\n submitControl?.dataset.action ??\n (submitControl?.dataset.generating === \"true\" ? \"stop\" : undefined);\n // `aria-disabled` is checked alongside the real `disabled` property: the\n // resting empty-composer state marks the control aria-disabled so it stays\n // FOCUSABLE (a real `disabled` button is skipped by the tab order and\n // announces nothing), while a consumer-supplied `disabled` is a genuine\n // DOM disable. Enter must be refused for both.\n if (\n submitControl?.disabled ||\n submitControl?.getAttribute(\"aria-disabled\") === \"true\" ||\n action === \"stop\"\n ) {\n return;\n }\n\n form?.requestSubmit();\n }\n\n // Remove last attachment when Backspace is pressed and textarea is empty\n if (e.key === \"Backspace\" && e.currentTarget.value === \"\" && attachments.files.length > 0) {\n e.preventDefault();\n const lastAttachment = attachments.files.at(-1);\n if (lastAttachment) {\n attachments.remove(lastAttachment.id);\n }\n }\n },\n [onKeyDown, isComposing, attachments],\n );\n\n const handlePaste: ClipboardEventHandler<HTMLTextAreaElement> = useCallback(\n (event) => {\n const items = event.clipboardData?.items;\n\n if (!items) {\n return;\n }\n\n const files: File[] = [];\n\n for (const item of items) {\n if (item.kind === \"file\") {\n const file = item.getAsFile();\n if (file) {\n files.push(file);\n }\n }\n }\n\n if (files.length > 0) {\n event.preventDefault();\n attachments.add(files);\n }\n },\n [attachments],\n );\n\n const handleCompositionEnd = useCallback(() => setIsComposing(false), []);\n const handleCompositionStart = useCallback(() => setIsComposing(true), []);\n\n const controlledProps = controller\n ? {\n onChange: (e: ChangeEvent<HTMLTextAreaElement>) => {\n controller.textInput.setInput(e.currentTarget.value);\n onChange?.(e);\n },\n value: controller.textInput.value,\n }\n : {\n // Uncontrolled: report only the empty↔non-empty transition so the submit\n // affordance can enable/disable. Boolean state ⇒ React bails out on\n // identical values, so this stays cheap per keystroke.\n onChange: (e: ChangeEvent<HTMLTextAreaElement>) => {\n submitState?.setHasText(e.currentTarget.value.trim().length > 0);\n onChange?.(e);\n },\n };\n\n return (\n <InputGroupTextarea\n className={cn(\"field-sizing-content max-h-48 min-h-10\", className)}\n name=\"message\"\n onCompositionEnd={handleCompositionEnd}\n onCompositionStart={handleCompositionStart}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n placeholder={placeholder ?? t(\"ai.promptInput.placeholder\")}\n {...props}\n {...controlledProps}\n />\n );\n};\n\nexport type PromptInputHeaderProps = Omit<ComponentProps<typeof InputGroupAddon>, \"align\">;\n\nexport const PromptInputHeader = ({ className, ...props }: PromptInputHeaderProps) => (\n <InputGroupAddon\n align=\"block-end\"\n className={cn(\"order-first flex-wrap gap-1\", className)}\n {...props}\n />\n);\n\nexport type PromptInputFooterProps = Omit<ComponentProps<typeof InputGroupAddon>, \"align\">;\n\nexport const PromptInputFooter = ({ className, ...props }: PromptInputFooterProps) => (\n <InputGroupAddon\n align=\"block-end\"\n className={cn(\"justify-between gap-1\", className)}\n {...props}\n />\n);\n\nexport type PromptInputToolsProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputTools = ({ className, ...props }: PromptInputToolsProps) => (\n <div className={cn(\"flex min-w-0 items-center gap-1\", className)} {...props} />\n);\n\nexport type PromptInputButtonTooltip =\n | string\n | {\n content: ReactNode;\n shortcut?: string;\n side?: ComponentProps<typeof TooltipContent>[\"side\"];\n };\n\nexport type PromptInputButtonProps = ComponentProps<typeof InputGroupButton> & {\n tooltip?: PromptInputButtonTooltip;\n};\n\n/**\n * True when `node` renders any visible text (a non-blank string/number node,\n * at any nesting depth) rather than icon-only content (bare SVGs/icon\n * components). Adapts the same \"inspect the children's shape\" notion the\n * size heuristic below uses (`Children.count(...) > 1`) to the question that\n * actually matters for the accessible name: is there a visible label already,\n * not merely how many top-level children there are.\n */\nconst hasVisibleText = (node: ReactNode): boolean => {\n if (typeof node === \"string\" || typeof node === \"number\") {\n return String(node).trim().length > 0;\n }\n if (Array.isArray(node)) {\n return node.some(hasVisibleText);\n }\n if (isValidElement<{ children?: ReactNode }>(node)) {\n return hasVisibleText(node.props.children);\n }\n return false;\n};\n\nexport const PromptInputButton = ({\n variant = \"ghost\",\n className,\n size,\n tooltip,\n \"aria-label\": ariaLabelProp,\n ...props\n}: PromptInputButtonProps) => {\n const newSize = size ?? (Children.count(props.children) > 1 ? \"sm\" : \"icon-sm\");\n\n const tooltipContent = tooltip\n ? typeof tooltip === \"string\"\n ? tooltip\n : tooltip.content\n : undefined;\n\n // Icon-only buttons (Attach, Voice, …) commonly carry ONLY a tooltip and no\n // visible text, so the tooltip is the only description of what the button\n // does — default the accessible name to it. A button that already has a\n // VISIBLE TEXT label must NOT have that label replaced by the tooltip (WCAG\n // 2.5.3 Label in Name) — the derived name is opt-in to icon-only buttons\n // only. An explicit, DEFINED `aria-label` still wins over the derived\n // default; an explicitly-passed `aria-label={undefined}` must NOT clobber\n // it, so we pull `aria-label` out of `props` above (it is applied, as the\n // final computed value, AFTER the `{...props}` spread below — the spread\n // can no longer reintroduce the `undefined` key over it).\n const isIconOnly = !hasVisibleText(props.children);\n const ariaLabel =\n ariaLabelProp ??\n (isIconOnly && typeof tooltipContent === \"string\" ? tooltipContent : undefined);\n\n const button = (\n <InputGroupButton\n className={cn(className)}\n size={newSize}\n type=\"button\"\n variant={variant}\n {...props}\n aria-label={ariaLabel}\n />\n );\n\n if (!tooltip) {\n return button;\n }\n\n const shortcut = typeof tooltip === \"string\" ? undefined : tooltip.shortcut;\n const side = typeof tooltip === \"string\" ? \"top\" : (tooltip.side ?? \"top\");\n\n // Self-provide so the button works anywhere — a consumer rendering a bare\n // composer (a block, a story) shouldn't have to remember to mount a global\n // TooltipProvider. Mirrors the ThemeSwitcher self-provision convention.\n return (\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>{button}</TooltipTrigger>\n <TooltipContent side={side}>\n {tooltipContent}\n {shortcut && <span className=\"ms-2 text-muted-foreground\">{shortcut}</span>}\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n );\n};\n\nexport type PromptInputActionMenuProps = ComponentProps<typeof DropdownMenu>;\nexport const PromptInputActionMenu = (props: PromptInputActionMenuProps) => (\n <DropdownMenu {...props} />\n);\n\nexport type PromptInputActionMenuTriggerProps = PromptInputButtonProps;\n\nexport const PromptInputActionMenuTrigger = ({\n className,\n children,\n ...props\n}: PromptInputActionMenuTriggerProps) => (\n <DropdownMenuTrigger asChild>\n <PromptInputButton className={className} {...props}>\n {children ?? <PlusIcon className=\"size-4\" />}\n </PromptInputButton>\n </DropdownMenuTrigger>\n);\n\nexport type PromptInputActionMenuContentProps = ComponentProps<typeof DropdownMenuContent>;\nexport const PromptInputActionMenuContent = ({\n className,\n ...props\n}: PromptInputActionMenuContentProps) => (\n <DropdownMenuContent align=\"start\" className={cn(className)} {...props} />\n);\n\nexport type PromptInputActionMenuItemProps = ComponentProps<typeof DropdownMenuItem>;\nexport const PromptInputActionMenuItem = ({\n className,\n ...props\n}: PromptInputActionMenuItemProps) => <DropdownMenuItem className={cn(className)} {...props} />;\n\n// Note: Actions that perform side-effects (like opening a file dialog)\n// are provided in opt-in modules (e.g., prompt-input-attachments).\n\n/**\n * Which action the merged primary control currently performs (#351). The\n * component owns the AFFORDANCE only — it always invokes `onSubmit` (via the\n * normal form submit) once the action is \"send\", never `onStop`. What a\n * mid-turn submit MEANS (queued, interleaved, dropped) is entirely up to the\n * app's own `onSubmit`/runtime — brand-ui asserts nothing about that (D5).\n */\nexport type PromptInputSubmitAction = \"send\" | \"stop\";\n\nexport type PromptInputSubmitProps = ComponentProps<typeof InputGroupButton> & {\n status?: ChatStatus;\n onStop?: () => void;\n /**\n * Glyph for the SEND action only — survives the send↔stop flip, so a\n * consumer's resting glyph (e.g. `Composer`'s circular arrow) is no longer\n * lost while generating with a non-empty composer. Prefer this over\n * `children`.\n */\n sendIcon?: ReactNode;\n /**\n * @deprecated Replaces the glyph for **every** status — ready, submitted,\n * streaming AND error — which is why generating/error affordances can\n * disappear even though the control is still live. Prefer `sendIcon`,\n * which only ever replaces the resting Send glyph.\n */\n children?: ReactNode;\n};\n\n/**\n * Merged primary-action contract (#351):\n * 1. `ready`/`undefined`/`error` → **Send** (unchanged).\n * 2. `submitted`/`streaming` + composer EMPTY → **Stop** (unchanged).\n * 3. `submitted`/`streaming` + composer NON-EMPTY → **Send** (the fix — a\n * follow-up can always be composed and submitted mid-turn).\n * 4. A `PromptInputStop` mounted alongside → this control is ALWAYS Send;\n * the dedicated control owns stopping (the composed \"separate\" shape).\n */\nexport const PromptInputSubmit = ({\n className,\n variant = \"default\",\n size = \"icon-sm\",\n status,\n onStop,\n onClick,\n children,\n sendIcon,\n disabled,\n ...props\n}: PromptInputSubmitProps) => {\n const { t } = useLocale();\n const isGenerating = status === \"submitted\" || status === \"streaming\";\n const submitState = useOptionalSubmitState();\n\n const action: PromptInputSubmitAction =\n isGenerating && !submitState?.canSubmit && !submitState?.hasDedicatedStop ? \"stop\" : \"send\";\n\n // Auto-disable only the Send action at rest, and only inside a PromptInput\n // (a standalone submit has no context and keeps working). `error` must stay\n // clickable to retry, and the Stop action is never auto-disabled. An\n // explicit `disabled` prop always wins.\n //\n // NOTE this drives `aria-disabled`, not the native attribute — see the render.\n const autoDisabled =\n action === \"send\" && status !== \"error\" && submitState ? !submitState.canSubmit : false;\n\n let Icon = sendIcon ?? <CornerDownLeftIcon className=\"size-4\" data-rtl-flip />;\n\n if (action === \"stop\") {\n Icon = status === \"submitted\" ? <Spinner /> : <SquareIcon className=\"size-4\" />;\n } else if (status === \"error\") {\n Icon = <XIcon className=\"size-4\" />;\n }\n\n const handleClick = useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n // `aria-disabled` (see the render) does not block activation the way the\n // native attribute does, so the handler has to.\n if (autoDisabled) {\n e.preventDefault();\n return;\n }\n if (action === \"stop\" && onStop) {\n e.preventDefault();\n onStop();\n return;\n }\n onClick?.(e);\n },\n [autoDisabled, action, onStop, onClick],\n );\n\n return (\n <InputGroupButton\n aria-label={action === \"stop\" ? t(\"ai.promptInput.stop\") : t(\"ai.promptInput.submit\")}\n /*\n * `aria-disabled`, NOT the native `disabled` attribute, for the RESTING\n * empty-composer state.\n *\n * Two reasons. (1) A focused control that becomes natively disabled is\n * removed from the focus order by the HTML focus-fixup rule, so focus\n * drops to <body> — after every keyboard-initiated send, since the\n * composer clears and the button goes not-ready in the same commit. That\n * silently strands keyboard and screen-reader users mid-conversation.\n * (2) `interaction-guidelines.md` says a submit stays enabled until the\n * request starts; aria-disabled keeps it a real, focusable tab stop that\n * still announces its state, while `handleClick` + `handleSubmit` do the\n * actual blocking.\n *\n * An explicit `disabled` prop is still honoured natively — that is the\n * consumer deliberately taking the control out of the tab order.\n */\n aria-disabled={autoDisabled || undefined}\n className={cn(autoDisabled && \"cursor-not-allowed opacity-50 hover:bg-primary\", className)}\n data-action={action}\n data-generating={action === \"stop\" ? \"true\" : undefined}\n data-slot={SUBMIT_SLOT}\n disabled={disabled}\n onClick={handleClick}\n size={size}\n type={autoDisabled || (action === \"stop\" && onStop) ? \"button\" : \"submit\"}\n variant={variant}\n {...props}\n >\n {children ?? (\n <span\n key={`${status ?? \"ready\"}-${action}`}\n className=\"flex animate-in fade-in-0 zoom-in-95 duration-fast ease-entrance\"\n >\n {Icon}\n </span>\n )}\n </InputGroupButton>\n );\n};\n\n/** The `data-slot` `PromptInputStop` renders with. */\nconst STOP_SLOT = \"prompt-input-stop\";\n\nexport type PromptInputStopProps = ComponentProps<typeof InputGroupButton> & {\n status?: ChatStatus;\n onStop: () => void;\n /** Glyph override; defaults to a square Stop icon. */\n children?: ReactNode;\n};\n\n/**\n * A dedicated Stop control — the composed answer to \"two buttons\" (#351;\n * never a `mode` prop, per `component-api.md`'s ban on behavioural-mode\n * props). Renders `null` unless the turn is running (`status` is `submitted`\n * or `streaming`). While at least one `PromptInputStop` is mounted inside the\n * same `PromptInput`, `PromptInputSubmit` stays the Send action in every\n * state — the dedicated control owns stopping instead.\n */\nexport const PromptInputStop = ({\n className,\n variant = \"outline\",\n size = \"icon-sm\",\n status,\n onStop,\n onClick,\n children,\n ...props\n}: PromptInputStopProps) => {\n const { t } = useLocale();\n const submitState = useOptionalSubmitState();\n const isGenerating = status === \"submitted\" || status === \"streaming\";\n\n useEffect(() => {\n const unregister = submitState?.registerStop();\n return unregister;\n }, [submitState]);\n\n const handleClick = useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(e);\n if (e.defaultPrevented) {\n return;\n }\n onStop();\n },\n [onClick, onStop],\n );\n\n if (!isGenerating) {\n return null;\n }\n\n return (\n <InputGroupButton\n aria-label={t(\"ai.promptInput.stop\")}\n className={cn(className)}\n data-slot={STOP_SLOT}\n onClick={handleClick}\n size={size}\n type=\"button\"\n variant={variant}\n {...props}\n >\n {children ?? <SquareIcon className=\"size-4\" />}\n </InputGroupButton>\n );\n};\n\nexport type PromptInputSelectProps = ComponentProps<typeof Select>;\n\nexport const PromptInputSelect = (props: PromptInputSelectProps) => <Select {...props} />;\n\nexport type PromptInputSelectTriggerProps = ComponentProps<typeof SelectTrigger>;\n\nexport const PromptInputSelectTrigger = ({\n className,\n ...props\n}: PromptInputSelectTriggerProps) => (\n <SelectTrigger\n className={cn(\n \"border-none bg-transparent font-medium text-muted-foreground shadow-none transition-colors\",\n \"hover:bg-accent hover:text-foreground aria-expanded:bg-accent aria-expanded:text-foreground\",\n className,\n )}\n {...props}\n />\n);\n\nexport type PromptInputSelectContentProps = ComponentProps<typeof SelectContent>;\n\nexport const PromptInputSelectContent = ({\n className,\n ...props\n}: PromptInputSelectContentProps) => <SelectContent className={cn(className)} {...props} />;\n\nexport type PromptInputSelectItemProps = ComponentProps<typeof SelectItem>;\n\nexport const PromptInputSelectItem = ({ className, ...props }: PromptInputSelectItemProps) => (\n <SelectItem className={cn(className)} {...props} />\n);\n\nexport type PromptInputSelectValueProps = ComponentProps<typeof SelectValue>;\n\nexport const PromptInputSelectValue = ({ className, ...props }: PromptInputSelectValueProps) => (\n <SelectValue className={cn(className)} {...props} />\n);\n\nexport type PromptInputHoverCardProps = ComponentProps<typeof HoverCard>;\n\nexport const PromptInputHoverCard = ({\n openDelay = 0,\n closeDelay = 0,\n ...props\n}: PromptInputHoverCardProps) => (\n <HoverCard closeDelay={closeDelay} openDelay={openDelay} {...props} />\n);\n\nexport type PromptInputHoverCardTriggerProps = ComponentProps<typeof HoverCardTrigger>;\n\nexport const PromptInputHoverCardTrigger = (props: PromptInputHoverCardTriggerProps) => (\n <HoverCardTrigger {...props} />\n);\n\nexport type PromptInputHoverCardContentProps = ComponentProps<typeof HoverCardContent>;\n\nexport const PromptInputHoverCardContent = ({\n align = \"start\",\n ...props\n}: PromptInputHoverCardContentProps) => <HoverCardContent align={align} {...props} />;\n\nexport type PromptInputTabsListProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputTabsList = ({ className, ...props }: PromptInputTabsListProps) => (\n <div className={cn(className)} {...props} />\n);\n\nexport type PromptInputTabProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputTab = ({ className, ...props }: PromptInputTabProps) => (\n <div className={cn(className)} {...props} />\n);\n\nexport type PromptInputTabLabelProps = HTMLAttributes<HTMLHeadingElement>;\n\nexport const PromptInputTabLabel = ({ className, ...props }: PromptInputTabLabelProps) => (\n // Content provided via children in props\n // oxlint-disable-next-line eslint-plugin-jsx-a11y(heading-has-content)\n <h3\n className={cn(\"mb-2 px-3 font-medium text-muted-foreground text-meta\", className)}\n {...props}\n />\n);\n\nexport type PromptInputTabBodyProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputTabBody = ({ className, ...props }: PromptInputTabBodyProps) => (\n <div className={cn(\"space-y-1\", className)} {...props} />\n);\n\nexport type PromptInputTabItemProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputTabItem = ({ className, ...props }: PromptInputTabItemProps) => (\n <div\n className={cn(\"flex items-center gap-2 px-3 py-2 text-meta hover:bg-accent\", className)}\n {...props}\n />\n);\n\nexport type PromptInputCommandProps = ComponentProps<typeof Command>;\n\nexport const PromptInputCommand = ({ className, ...props }: PromptInputCommandProps) => (\n <Command className={cn(className)} {...props} />\n);\n\nexport type PromptInputCommandInputProps = ComponentProps<typeof CommandInput>;\n\nexport const PromptInputCommandInput = ({ className, ...props }: PromptInputCommandInputProps) => (\n <CommandInput className={cn(className)} {...props} />\n);\n\nexport type PromptInputCommandListProps = ComponentProps<typeof CommandList>;\n\nexport const PromptInputCommandList = ({ className, ...props }: PromptInputCommandListProps) => (\n <CommandList className={cn(className)} {...props} />\n);\n\nexport type PromptInputCommandEmptyProps = ComponentProps<typeof CommandEmpty>;\n\nexport const PromptInputCommandEmpty = ({ className, ...props }: PromptInputCommandEmptyProps) => (\n <CommandEmpty className={cn(className)} {...props} />\n);\n\nexport type PromptInputCommandGroupProps = ComponentProps<typeof CommandGroup>;\n\nexport const PromptInputCommandGroup = ({ className, ...props }: PromptInputCommandGroupProps) => (\n <CommandGroup className={cn(className)} {...props} />\n);\n\nexport type PromptInputCommandItemProps = ComponentProps<typeof CommandItem>;\n\n/**\n * A selectable row inside `PromptInputCommand` (e.g. an `@`-mention popup).\n *\n * `id`/`role`/`aria-selected` are assigned internally by the `cmdk` dependency\n * itself — one layer below this wrapper and below `@elabs-ai/components-ui`'s\n * own `CommandItem` — and applied AFTER any props you pass, so a\n * consumer-supplied `id`/`role`/`aria-selected` is silently overridden\n * (`CommandItem` warns about this in development; #365).\n *\n * To wire `aria-activedescendant` from an input rendered OUTSIDE this\n * `PromptInputCommand` tree (the composer textarea driving the popup), use\n * `PromptInputCommand`'s `onActiveItemIdChange` callback (inherited from\n * `@elabs-ai/components-ui`'s `Command`, since `PromptInputCommandProps =\n * ComponentProps<typeof Command>`) instead of reading the id back\n * positionally from the DOM:\n *\n * ```tsx\n * const [activeId, setActiveId] = useState<string>();\n * <textarea role=\"combobox\" aria-expanded={open} aria-controls={listId}\n * aria-activedescendant={activeId} />\n * <PromptInputCommand onActiveItemIdChange={setActiveId}>…</PromptInputCommand>\n * ```\n */\nexport const PromptInputCommandItem = ({ className, ...props }: PromptInputCommandItemProps) => (\n <CommandItem className={cn(className)} {...props} />\n);\n\nexport type PromptInputCommandSeparatorProps = ComponentProps<typeof CommandSeparator>;\n\nexport const PromptInputCommandSeparator = ({\n className,\n ...props\n}: PromptInputCommandSeparatorProps) => <CommandSeparator className={cn(className)} {...props} />;\n"],"mappings":"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","names":[]}
@@ -0,0 +1,118 @@
1
+ "use client";
2
+
3
+ // src/_code-block-theme.ts
4
+ import { resolveThemeIsDark, resolveTokenColor } from "@elabs-ai/components-tokens";
5
+ var FALLBACK_BACKGROUND = "#ffffff";
6
+ var FALLBACK_FOREGROUND = "#111111";
7
+ var ROOT_SCOPE_KEY = "__root__";
8
+ function getThemeScopeKey(el) {
9
+ const root = el ?? (typeof document !== "undefined" ? document.documentElement : null);
10
+ return root?.getAttribute("data-theme") || ROOT_SCOPE_KEY;
11
+ }
12
+ function codeBlockThemeId(scopeKey) {
13
+ return `brand-code-${scopeKey}`;
14
+ }
15
+ function buildCodeBlockTheme(el) {
16
+ const root = el ?? (typeof document !== "undefined" ? document.documentElement : null);
17
+ const read = (name, fallback) => resolveTokenColor(name, { el: root, fallback });
18
+ const background = read("--code-background", FALLBACK_BACKGROUND);
19
+ const foreground = read("--code-foreground", FALLBACK_FOREGROUND);
20
+ const comment = read("--code-comment", foreground);
21
+ const string_ = read("--code-string", foreground);
22
+ const number = read("--code-number", foreground);
23
+ const constant = read("--code-constant", foreground);
24
+ const keyword = read("--code-keyword", foreground);
25
+ const func = read("--code-function", foreground);
26
+ const type = read("--code-type", foreground);
27
+ const tag = read("--code-tag", foreground);
28
+ const property = read("--code-property", foreground);
29
+ return {
30
+ // Keyed on the RAW scope, not the validated name — see the module doc
31
+ // comment + `getThemeScopeKey` for why "unset" and "light" must get
32
+ // different cache buckets.
33
+ name: codeBlockThemeId(getThemeScopeKey(root)),
34
+ type: resolveThemeIsDark(root) ? "dark" : "light",
35
+ bg: background,
36
+ fg: foreground,
37
+ colors: {
38
+ "editor.background": background,
39
+ "editor.foreground": foreground
40
+ },
41
+ settings: [
42
+ { settings: { foreground } },
43
+ {
44
+ scope: ["comment", "punctuation.definition.comment"],
45
+ settings: { foreground: comment, fontStyle: "italic" }
46
+ },
47
+ {
48
+ scope: ["string", "string.quoted", "string.template", "punctuation.definition.string"],
49
+ settings: { foreground: string_ }
50
+ },
51
+ {
52
+ scope: ["constant.numeric", "constant.character", "constant.character.escape"],
53
+ settings: { foreground: number }
54
+ },
55
+ {
56
+ scope: ["constant.language", "constant.other", "support.constant"],
57
+ settings: { foreground: constant }
58
+ },
59
+ {
60
+ scope: [
61
+ "keyword",
62
+ "keyword.control",
63
+ "keyword.operator",
64
+ "storage.type",
65
+ "storage.modifier"
66
+ ],
67
+ settings: { foreground: keyword }
68
+ },
69
+ {
70
+ scope: [
71
+ "entity.name.function",
72
+ "support.function",
73
+ "meta.function-call",
74
+ "variable.function"
75
+ ],
76
+ settings: { foreground: func }
77
+ },
78
+ {
79
+ scope: [
80
+ "entity.name.type",
81
+ "entity.name.class",
82
+ "support.type",
83
+ "support.class",
84
+ "entity.other.inherited-class"
85
+ ],
86
+ settings: { foreground: type }
87
+ },
88
+ {
89
+ scope: ["entity.name.tag", "punctuation.definition.tag"],
90
+ settings: { foreground: tag }
91
+ },
92
+ {
93
+ scope: [
94
+ "entity.other.attribute-name",
95
+ "variable.other.property",
96
+ "meta.object-literal.key",
97
+ "support.type.property-name"
98
+ ],
99
+ settings: { foreground: property }
100
+ }
101
+ // Deliberately NO `invalid`/`invalid.illegal` rule here (#315 follow-up):
102
+ // it used to alias to the SAME color as `tag`, so a perfectly valid
103
+ // <div>/JSX tag — the most common markup element in the languages this
104
+ // component renders — was indistinguishable from genuinely broken syntax.
105
+ // Leaving the scope unmapped falls through to the base `{ settings:
106
+ // { foreground } }` rule above (Shiki/TextMate cascade), same as most
107
+ // grammars' own default. If a dedicated "this token is invalid" highlight
108
+ // is ever wanted, it needs its OWN `--code-*` token, not a reuse of `tag`.
109
+ ]
110
+ };
111
+ }
112
+
113
+ export {
114
+ getThemeScopeKey,
115
+ codeBlockThemeId,
116
+ buildCodeBlockTheme
117
+ };
118
+ //# sourceMappingURL=chunk-SSKZ2AED.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/_code-block-theme.ts"],"sourcesContent":["/**\n * _code-block-theme — derives a Shiki theme from brand-ui's `--code-*` tokens\n * instead of a hardcoded `github-light`/`github-dark` literal (issue #315).\n *\n * Shiki can't read CSS custom properties at tokenize time, so — the same\n * \"wrap an engine, theme it from tokens\" pattern as `@elabs-ai/components-editor`'s\n * Monaco bridge (`monaco-theme-bridge.ts`), `@elabs-ai/components-maps`' `useTokenColor`,\n * and this package's own `buildInteractiveTerminalTheme` — this module reads the\n * ACTIVE theme's resolved token colors at call time via `resolveTokenColor`\n * (`@elabs-ai/components-tokens`, ADR 0015: oklch → hex, no canvas needed since every\n * `--code-*` token is authored as `oklch()`) and builds a single Shiki\n * `ThemeRegistrationRaw` that matches whatever brand theme is currently active\n * — including a low-chroma monochrome ink palette, never a recolored GitHub\n * theme. Callers re-derive (and re-highlight) whenever `data-theme` changes;\n * see `code-block.tsx`'s `data-theme` MutationObserver.\n *\n * `buildCodeBlockTheme` takes a single `el` (default `<html>`) and derives BOTH\n * the theme id/type AND the resolved colors from that SAME element — never a\n * separately-requested theme name. A CodeBlock nested inside a region-scoped\n * `<div data-theme=\"dark\">` (a supported `ThemeProvider`/decorator pattern,\n * see @.claude/rules/theming.md) resolves ITS region's theme this way: pass a\n * descendant of that region as `el` and the id/type/colors all agree by\n * construction (there is no \"themeName\" parameter that could disagree with what\n * `el` actually renders).\n *\n * The highlight-cache key (`codeBlockThemeId`, consumed by `code-block.tsx`'s\n * `getTokensCacheKey`) is keyed on `getThemeScopeKey` — the RAW `data-theme`\n * attribute — and must NOT be collapsed to a validated/normalized theme name.\n * This matters: \"no `data-theme` attribute yet\" (the first render, before\n * `ThemeProvider` mounts and writes the attribute) and an EXPLICIT\n * `data-theme=\"light\"` are DIFFERENT palettes, because `:root`'s fallback\n * `--code-*` values are intentionally their OWN neutral placeholder theme, not\n * a byte-identical copy of `[data-theme=\"light\"]`'s (see `themes.css`'s\n * \"`:root` holds the DEFAULT (light) theme\" header — a deliberately distinct\n * palette, not an alias). If the cache key normalized \"unset\" to \"light\", a\n * code block that first tokenizes before `ThemeProvider` mounts would cache\n * `:root`'s colors under the SAME key `ThemeProvider` later writes explicitly\n * — so the (correct) `light` colors would never take effect; the cache hit\n * would return the stale `:root` colors forever (#315 follow-up). Keying on the\n * raw attribute gives \"no attribute\" and \"light\" distinct cache entries, so the\n * mutation from one to the other is a genuine cache miss and re-tokenizes.\n *\n * ADR 0029 removed the `getActiveThemeName` helper this file used to export.\n * Theme names are open now, so \"narrow the attribute to a known theme\" is not a\n * meaningful operation — a consumer theme is as real as a shipped one. The two\n * things it was used for are both answered off the element directly:\n * `resolveThemeIsDark(el)` for the light/dark `type`, and `resolveTokenColor`\n * for the colors.\n */\n\nimport { resolveThemeIsDark, resolveTokenColor } from \"@elabs-ai/components-tokens\";\nimport type { ThemeRegistrationRaw } from \"shiki\";\n\nconst FALLBACK_BACKGROUND = \"#ffffff\";\nconst FALLBACK_FOREGROUND = \"#111111\";\n/** Cache-key sentinel for \"no `data-theme` attribute present\" — see `getThemeScopeKey`. */\nconst ROOT_SCOPE_KEY = \"__root__\";\n\n/**\n * Reads the RAW `data-theme` attribute off `el` (default `<html>`) — or the\n * `\"__root__\"` sentinel when the attribute is absent. It deliberately does NOT\n * collapse \"unset\" and \"explicit light\" into one value (see the module comment),\n * and it never validates the name against a registry: a consumer theme gets its\n * own cache bucket, which is exactly right — it has its own `--code-*` values.\n */\nexport function getThemeScopeKey(el?: Element | null): string {\n const root = el ?? (typeof document !== \"undefined\" ? document.documentElement : null);\n return root?.getAttribute(\"data-theme\") || ROOT_SCOPE_KEY;\n}\n\n/** Shiki theme `name` for a given theme-scope key — also the highlight-cache key. */\nexport function codeBlockThemeId(scopeKey: string): string {\n return `brand-code-${scopeKey}`;\n}\n\n/**\n * Builds a Shiki `ThemeRegistrationRaw` from the resolved `--code-*` tokens of\n * whichever brand theme is active on `el` (default `<html>`). The theme id, its\n * light/dark `type` and its colors are ALL derived from THIS SAME element, so\n * they can never disagree. `type` comes from `resolveThemeIsDark` (the theme's\n * own `color-scheme`) rather than a registry lookup, so a consumer-authored\n * theme gets the right Shiki type without registering here (ADR 0029). Scopes\n * follow the common TextMate categories Shiki's bundled grammars emit across\n * languages.\n */\nexport function buildCodeBlockTheme(el?: Element | null): ThemeRegistrationRaw {\n const root = el ?? (typeof document !== \"undefined\" ? document.documentElement : null);\n const read = (name: string, fallback: string) => resolveTokenColor(name, { el: root, fallback });\n\n const background = read(\"--code-background\", FALLBACK_BACKGROUND);\n const foreground = read(\"--code-foreground\", FALLBACK_FOREGROUND);\n const comment = read(\"--code-comment\", foreground);\n const string_ = read(\"--code-string\", foreground);\n const number = read(\"--code-number\", foreground);\n const constant = read(\"--code-constant\", foreground);\n const keyword = read(\"--code-keyword\", foreground);\n const func = read(\"--code-function\", foreground);\n const type = read(\"--code-type\", foreground);\n const tag = read(\"--code-tag\", foreground);\n const property = read(\"--code-property\", foreground);\n\n return {\n // Keyed on the RAW scope, not the validated name — see the module doc\n // comment + `getThemeScopeKey` for why \"unset\" and \"light\" must get\n // different cache buckets.\n name: codeBlockThemeId(getThemeScopeKey(root)),\n type: resolveThemeIsDark(root) ? \"dark\" : \"light\",\n bg: background,\n fg: foreground,\n colors: {\n \"editor.background\": background,\n \"editor.foreground\": foreground,\n },\n settings: [\n { settings: { foreground } },\n {\n scope: [\"comment\", \"punctuation.definition.comment\"],\n settings: { foreground: comment, fontStyle: \"italic\" },\n },\n {\n scope: [\"string\", \"string.quoted\", \"string.template\", \"punctuation.definition.string\"],\n settings: { foreground: string_ },\n },\n {\n scope: [\"constant.numeric\", \"constant.character\", \"constant.character.escape\"],\n settings: { foreground: number },\n },\n {\n scope: [\"constant.language\", \"constant.other\", \"support.constant\"],\n settings: { foreground: constant },\n },\n {\n scope: [\n \"keyword\",\n \"keyword.control\",\n \"keyword.operator\",\n \"storage.type\",\n \"storage.modifier\",\n ],\n settings: { foreground: keyword },\n },\n {\n scope: [\n \"entity.name.function\",\n \"support.function\",\n \"meta.function-call\",\n \"variable.function\",\n ],\n settings: { foreground: func },\n },\n {\n scope: [\n \"entity.name.type\",\n \"entity.name.class\",\n \"support.type\",\n \"support.class\",\n \"entity.other.inherited-class\",\n ],\n settings: { foreground: type },\n },\n {\n scope: [\"entity.name.tag\", \"punctuation.definition.tag\"],\n settings: { foreground: tag },\n },\n {\n scope: [\n \"entity.other.attribute-name\",\n \"variable.other.property\",\n \"meta.object-literal.key\",\n \"support.type.property-name\",\n ],\n settings: { foreground: property },\n },\n // Deliberately NO `invalid`/`invalid.illegal` rule here (#315 follow-up):\n // it used to alias to the SAME color as `tag`, so a perfectly valid\n // <div>/JSX tag — the most common markup element in the languages this\n // component renders — was indistinguishable from genuinely broken syntax.\n // Leaving the scope unmapped falls through to the base `{ settings:\n // { foreground } }` rule above (Shiki/TextMate cascade), same as most\n // grammars' own default. If a dedicated \"this token is invalid\" highlight\n // is ever wanted, it needs its OWN `--code-*` token, not a reuse of `tag`.\n ],\n };\n}\n"],"mappings":"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","names":[]}