@elabs-ai/components-ai 4.1.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (527) hide show
  1. package/README.md +3 -3
  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-AXMNJMMH.js +984 -0
  106. package/dist/chunk-AXMNJMMH.js.map +1 -0
  107. package/dist/chunk-BA3AEMOU.js +21 -0
  108. package/dist/chunk-BA3AEMOU.js.map +1 -0
  109. package/dist/chunk-BBHFOYML.js +336 -0
  110. package/dist/chunk-BBHFOYML.js.map +1 -0
  111. package/dist/chunk-BHUVISIY.js +221 -0
  112. package/dist/chunk-BHUVISIY.js.map +1 -0
  113. package/dist/chunk-BM2LWERA.js +100 -0
  114. package/dist/chunk-BM2LWERA.js.map +1 -0
  115. package/dist/chunk-CMOYXNPJ.js +211 -0
  116. package/dist/chunk-CMOYXNPJ.js.map +1 -0
  117. package/dist/chunk-CZP3RHC4.js +74 -0
  118. package/dist/chunk-CZP3RHC4.js.map +1 -0
  119. package/dist/chunk-DDG5JHQT.js +112 -0
  120. package/dist/chunk-DDG5JHQT.js.map +1 -0
  121. package/dist/chunk-DJODXO7I.js +38 -0
  122. package/dist/chunk-DJODXO7I.js.map +1 -0
  123. package/dist/chunk-DWJDJLPU.js +192 -0
  124. package/dist/chunk-DWJDJLPU.js.map +1 -0
  125. package/dist/chunk-DZW6LM22.js +45 -0
  126. package/dist/chunk-DZW6LM22.js.map +1 -0
  127. package/dist/chunk-ELGCZLZF.js +305 -0
  128. package/dist/chunk-ELGCZLZF.js.map +1 -0
  129. package/dist/chunk-EV3U6ZZB.js +209 -0
  130. package/dist/chunk-EV3U6ZZB.js.map +1 -0
  131. package/dist/chunk-EY7LVUKQ.js +87 -0
  132. package/dist/chunk-EY7LVUKQ.js.map +1 -0
  133. package/dist/chunk-F4C74F7M.js +230 -0
  134. package/dist/chunk-F4C74F7M.js.map +1 -0
  135. package/dist/chunk-FERYDFZA.js +108 -0
  136. package/dist/chunk-FERYDFZA.js.map +1 -0
  137. package/dist/chunk-FUIYG2DS.js +166 -0
  138. package/dist/chunk-FUIYG2DS.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-LMNSBOBG.js +19 -0
  156. package/dist/chunk-LMNSBOBG.js.map +1 -0
  157. package/dist/chunk-MBI7D6IL.js +42 -0
  158. package/dist/chunk-MBI7D6IL.js.map +1 -0
  159. package/dist/chunk-MLFMYCPH.js +192 -0
  160. package/dist/chunk-MLFMYCPH.js.map +1 -0
  161. package/dist/chunk-MOK66734.js +33 -0
  162. package/dist/chunk-MOK66734.js.map +1 -0
  163. package/dist/chunk-MXTAWPYM.js +196 -0
  164. package/dist/chunk-MXTAWPYM.js.map +1 -0
  165. package/dist/chunk-NCL2UZKI.js +96 -0
  166. package/dist/chunk-NCL2UZKI.js.map +1 -0
  167. package/dist/chunk-NET4YLRY.js +107 -0
  168. package/dist/chunk-NET4YLRY.js.map +1 -0
  169. package/dist/chunk-NIG67CFM.js +329 -0
  170. package/dist/chunk-NIG67CFM.js.map +1 -0
  171. package/dist/chunk-NMVNNO3L.js +10 -0
  172. package/dist/chunk-NMVNNO3L.js.map +1 -0
  173. package/dist/chunk-NP7VID4K.js +2 -0
  174. package/dist/chunk-NP7VID4K.js.map +1 -0
  175. package/dist/chunk-NPUCMAG2.js +382 -0
  176. package/dist/chunk-NPUCMAG2.js.map +1 -0
  177. package/dist/chunk-NSCLRHES.js +102 -0
  178. package/dist/chunk-NSCLRHES.js.map +1 -0
  179. package/dist/chunk-OEUXHVFW.js +86 -0
  180. package/dist/chunk-OEUXHVFW.js.map +1 -0
  181. package/dist/chunk-ONBHFIMZ.js +137 -0
  182. package/dist/chunk-ONBHFIMZ.js.map +1 -0
  183. package/dist/chunk-OPH2HHL2.js +228 -0
  184. package/dist/chunk-OPH2HHL2.js.map +1 -0
  185. package/dist/chunk-OQERHIQP.js +287 -0
  186. package/dist/chunk-OQERHIQP.js.map +1 -0
  187. package/dist/chunk-P6YJAZFG.js +103 -0
  188. package/dist/chunk-P6YJAZFG.js.map +1 -0
  189. package/dist/chunk-PG7ERDOD.js +65 -0
  190. package/dist/chunk-PG7ERDOD.js.map +1 -0
  191. package/dist/chunk-PIB5JBMA.js +90 -0
  192. package/dist/chunk-PIB5JBMA.js.map +1 -0
  193. package/dist/chunk-PQ5BPIWQ.js +22 -0
  194. package/dist/chunk-PQ5BPIWQ.js.map +1 -0
  195. package/dist/chunk-PQBF6ZIQ.js +55 -0
  196. package/dist/chunk-PQBF6ZIQ.js.map +1 -0
  197. package/dist/chunk-PTWCTSZL.js +173 -0
  198. package/dist/chunk-PTWCTSZL.js.map +1 -0
  199. package/dist/chunk-QJUNPVOS.js +101 -0
  200. package/dist/chunk-QJUNPVOS.js.map +1 -0
  201. package/dist/chunk-QUDZOTRV.js +43 -0
  202. package/dist/chunk-QUDZOTRV.js.map +1 -0
  203. package/dist/chunk-RB7G65JC.js +213 -0
  204. package/dist/chunk-RB7G65JC.js.map +1 -0
  205. package/dist/chunk-RPHAOR7P.js +45 -0
  206. package/dist/chunk-RPHAOR7P.js.map +1 -0
  207. package/dist/chunk-RTCSH2AN.js +331 -0
  208. package/dist/chunk-RTCSH2AN.js.map +1 -0
  209. package/dist/chunk-S3ISPW3A.js +28 -0
  210. package/dist/chunk-S3ISPW3A.js.map +1 -0
  211. package/dist/chunk-SEVN656N.js +36 -0
  212. package/dist/chunk-SEVN656N.js.map +1 -0
  213. package/dist/chunk-SKVG672B.js +64 -0
  214. package/dist/chunk-SKVG672B.js.map +1 -0
  215. package/dist/chunk-SPQIU7GA.js +236 -0
  216. package/dist/chunk-SPQIU7GA.js.map +1 -0
  217. package/dist/chunk-SSGJ6MEM.js +1076 -0
  218. package/dist/chunk-SSGJ6MEM.js.map +1 -0
  219. package/dist/chunk-SSKZ2AED.js +118 -0
  220. package/dist/chunk-SSKZ2AED.js.map +1 -0
  221. package/dist/chunk-T56JFGXI.js +561 -0
  222. package/dist/chunk-T56JFGXI.js.map +1 -0
  223. package/dist/chunk-TCB6O74A.js +137 -0
  224. package/dist/chunk-TCB6O74A.js.map +1 -0
  225. package/dist/chunk-TTEYPO6X.js +57 -0
  226. package/dist/chunk-TTEYPO6X.js.map +1 -0
  227. package/dist/chunk-TWPHAJNM.js +462 -0
  228. package/dist/chunk-TWPHAJNM.js.map +1 -0
  229. package/dist/chunk-TXJJLP4O.js +336 -0
  230. package/dist/chunk-TXJJLP4O.js.map +1 -0
  231. package/dist/chunk-TZ6TB7VM.js +245 -0
  232. package/dist/chunk-TZ6TB7VM.js.map +1 -0
  233. package/dist/chunk-UBLKJJ7K.js +278 -0
  234. package/dist/chunk-UBLKJJ7K.js.map +1 -0
  235. package/dist/chunk-UCJ6IUFS.js +52 -0
  236. package/dist/chunk-UCJ6IUFS.js.map +1 -0
  237. package/dist/chunk-UCKFJ3QF.js +197 -0
  238. package/dist/chunk-UCKFJ3QF.js.map +1 -0
  239. package/dist/chunk-UPXSLILN.js +20 -0
  240. package/dist/chunk-UPXSLILN.js.map +1 -0
  241. package/dist/chunk-V4DORGWJ.js +92 -0
  242. package/dist/chunk-V4DORGWJ.js.map +1 -0
  243. package/dist/chunk-V6E5DYZD.js +80 -0
  244. package/dist/chunk-V6E5DYZD.js.map +1 -0
  245. package/dist/chunk-VLLYKF3P.js +96 -0
  246. package/dist/chunk-VLLYKF3P.js.map +1 -0
  247. package/dist/chunk-VLNBTOH6.js +43 -0
  248. package/dist/chunk-VLNBTOH6.js.map +1 -0
  249. package/dist/chunk-WMDSMSPL.js +303 -0
  250. package/dist/chunk-WMDSMSPL.js.map +1 -0
  251. package/dist/chunk-WU5BLGTF.js +149 -0
  252. package/dist/chunk-WU5BLGTF.js.map +1 -0
  253. package/dist/chunk-WYTZVSGK.js +245 -0
  254. package/dist/chunk-WYTZVSGK.js.map +1 -0
  255. package/dist/chunk-X47QMM6K.js +187 -0
  256. package/dist/chunk-X47QMM6K.js.map +1 -0
  257. package/dist/chunk-XNBKO32Y.js +174 -0
  258. package/dist/chunk-XNBKO32Y.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 +403 -108
  300. package/dist/index.js +671 -13205
  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 +12 -10
  405. package/schemas/a2ui-surface.v1.schema.json +5425 -0
  406. package/src/__contract__/audio-visualizer.contract.test.tsx +49 -0
  407. package/src/__contract__/chat-shell.contract.test.tsx +49 -0
  408. package/src/__contract__/grouped-parts.contract.test.tsx +49 -0
  409. package/src/__contract__/image.contract.test.tsx +49 -0
  410. package/src/__contract__/markdown-view.contract.test.tsx +49 -0
  411. package/src/__contract__/message-feedback.contract.test.tsx +49 -0
  412. package/src/__contract__/message-form.contract.test.tsx +49 -0
  413. package/src/__contract__/message-table.contract.test.tsx +49 -0
  414. package/src/__contract__/model-provider-logo.contract.test.tsx +49 -0
  415. package/src/__contract__/persona.contract.test.tsx +49 -0
  416. package/src/__contract__/prompt-input-effort.contract.test.tsx +49 -0
  417. package/src/__contract__/prompt-input-mode.contract.test.tsx +49 -0
  418. package/src/_chat-shell-rail.tsx +4 -2
  419. package/src/_flow-boundary.tsx +2 -2
  420. package/src/_lazy-cjk.test.ts +43 -0
  421. package/src/_lazy-cjk.ts +73 -0
  422. package/src/_lazy-math.test.ts +63 -0
  423. package/src/_lazy-math.ts +90 -0
  424. package/src/_persona-rive.tsx +27 -41
  425. package/src/_streamdown-i18n.ts +73 -21
  426. package/src/_streamdown-safety.ts +2 -2
  427. package/src/_theme-scope-store.test.ts +83 -0
  428. package/src/_theme-scope-store.ts +103 -0
  429. package/src/a2ui/a2ui-surface.stories.tsx +662 -0
  430. package/src/a2ui/a2ui-surface.test.tsx +201 -0
  431. package/src/a2ui/a2ui-surface.tsx +354 -0
  432. package/src/a2ui/catalog.source.json +772 -0
  433. package/src/a2ui/core/a2ui-core.test.ts +178 -0
  434. package/src/a2ui/core/catalog.generated.ts +1006 -0
  435. package/src/a2ui/core/complete-json.ts +81 -0
  436. package/src/a2ui/core/index.ts +10 -0
  437. package/src/a2ui/core/schema.ts +111 -0
  438. package/src/a2ui/core/spec.ts +148 -0
  439. package/src/a2ui/core/validate.ts +266 -0
  440. package/src/a2ui/index.ts +7 -0
  441. package/src/a2ui/ui-catalog.tsx +225 -0
  442. package/src/a2ui/wave1-chart-spec.test.ts +87 -0
  443. package/src/a2ui/wave2-chart-spec.test.ts +108 -0
  444. package/src/agent-event.tsx +1 -1
  445. package/src/agent.tsx +18 -13
  446. package/src/agentic-workspace.stories.tsx +6 -45
  447. package/src/artifact.tsx +2 -2
  448. package/src/asset-preview.test.tsx +40 -0
  449. package/src/asset-preview.tsx +83 -12
  450. package/src/attachments.tsx +7 -4
  451. package/src/chat-shell.test.tsx +40 -10
  452. package/src/chat-shell.tsx +90 -44
  453. package/src/chat.stories.tsx +47 -42
  454. package/src/code-block.test.tsx +100 -1
  455. package/src/code-block.tsx +166 -103
  456. package/src/commit.tsx +30 -41
  457. package/src/composer.stories.tsx +4 -5
  458. package/src/composer.test.tsx +45 -0
  459. package/src/composer.tsx +104 -21
  460. package/src/confirmation.tsx +1 -1
  461. package/src/context-panel.stories.tsx +1 -1
  462. package/src/context-panel.tsx +2 -2
  463. package/src/conversation.stories.tsx +24 -0
  464. package/src/conversation.test.tsx +69 -0
  465. package/src/conversation.tsx +47 -8
  466. package/src/diff-view.stories.tsx +79 -0
  467. package/src/diff-view.test.tsx +52 -2
  468. package/src/diff-view.tsx +92 -36
  469. package/src/environment-variables.tsx +20 -37
  470. package/src/file-tree.test.tsx +21 -0
  471. package/src/file-tree.tsx +33 -16
  472. package/src/gallery.stories.tsx +42 -0
  473. package/src/gallery.tsx +2 -2
  474. package/src/grouped-parts.stories.tsx +23 -0
  475. package/src/grouped-parts.tsx +1 -1
  476. package/src/index.ts +1 -0
  477. package/src/inline-citation.tsx +5 -5
  478. package/src/jsx-preview.tsx +151 -43
  479. package/src/markdown-view.test.tsx +7 -3
  480. package/src/markdown-view.tsx +8 -1
  481. package/src/message-compare.stories.tsx +40 -0
  482. package/src/message-compare.tsx +2 -1
  483. package/src/message-form.stories.tsx +36 -3
  484. package/src/message-form.test.tsx +8 -2
  485. package/src/message-form.tsx +16 -8
  486. package/src/message-table.stories.tsx +26 -2
  487. package/src/message-table.test.tsx +7 -0
  488. package/src/message-table.tsx +9 -5
  489. package/src/message.test.tsx +73 -3
  490. package/src/message.tsx +36 -12
  491. package/src/model-provider-logo.test.tsx +57 -3
  492. package/src/model-provider-logo.tsx +45 -11
  493. package/src/open-in-chat.tsx +50 -29
  494. package/src/package-info.tsx +23 -20
  495. package/src/prompt-input-slash.stories.tsx +1 -1
  496. package/src/prompt-input.test.tsx +67 -1
  497. package/src/prompt-input.tsx +42 -4
  498. package/src/queue.tsx +4 -4
  499. package/src/reasoning.stories.tsx +27 -0
  500. package/src/reasoning.tsx +17 -6
  501. package/src/sandbox.tsx +3 -3
  502. package/src/schema-display.test.tsx +56 -0
  503. package/src/schema-display.tsx +68 -37
  504. package/src/session-header.stories.tsx +35 -1
  505. package/src/session-header.tsx +1 -1
  506. package/src/snippet.test.tsx +6 -2
  507. package/src/snippet.tsx +14 -34
  508. package/src/sources.stories.tsx +30 -0
  509. package/src/sources.tsx +4 -1
  510. package/src/speech-input.test.tsx +109 -0
  511. package/src/speech-input.tsx +31 -3
  512. package/src/stack-trace.tsx +20 -36
  513. package/src/streamdown-i18n.test.tsx +23 -0
  514. package/src/templates-ai-assistant.stories.tsx +151 -87
  515. package/src/test-results.tsx +47 -27
  516. package/src/token-usage.tsx +6 -6
  517. package/src/tool.stories.tsx +39 -0
  518. package/src/tool.test.tsx +65 -0
  519. package/src/tool.tsx +61 -25
  520. package/src/toolbar.tsx +0 -10
  521. package/src/transcription.tsx +1 -1
  522. package/src/voice-selector.tsx +5 -5
  523. package/src/web-preview.test.tsx +51 -1
  524. package/src/web-preview.tsx +39 -8
  525. package/dist/_flow-boundary-SHNWLQG5.js.map +0 -1
  526. package/dist/_persona-rive-JEG44YHX.js.map +0 -1
  527. /package/dist/{_audio-player-media-chrome-T3XVXWRZ.js.map → _audio-player-media-chrome.js.map} +0 -0
@@ -0,0 +1,215 @@
1
+ "use client";
2
+ import {
3
+ A2UI_COMMON_PROPS,
4
+ A2UI_VERSION
5
+ } from "./chunk-4XRNIZMG.js";
6
+
7
+ // src/a2ui/core/validate.ts
8
+ var isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
9
+ var isA2uiElement = (v) => isRecord(v) && typeof v.type === "string";
10
+ var ELEMENT_KEYS = /* @__PURE__ */ new Set(["type", "id", "props", "children", "on"]);
11
+ function checkValue(value, schema, path, report, errors, catalog) {
12
+ if (schema.enum) {
13
+ if (!schema.enum.includes(value)) {
14
+ report({
15
+ path,
16
+ code: "invalid-value",
17
+ message: `must be one of ${schema.enum.map((e) => JSON.stringify(e)).join(", ")}; got ${JSON.stringify(value)}`
18
+ });
19
+ }
20
+ return;
21
+ }
22
+ const t = schema.type;
23
+ const bad = (expected) => report({
24
+ path,
25
+ code: "invalid-value",
26
+ message: `expected ${expected}; got ${Array.isArray(value) ? "array" : typeof value}`
27
+ });
28
+ switch (t) {
29
+ case "string":
30
+ if (typeof value !== "string") bad("a string");
31
+ break;
32
+ case "number":
33
+ if (typeof value !== "number" || !Number.isFinite(value)) bad("a number");
34
+ break;
35
+ case "boolean":
36
+ if (typeof value !== "boolean") bad("a boolean");
37
+ break;
38
+ case "array":
39
+ if (!Array.isArray(value)) bad("an array");
40
+ break;
41
+ case "object":
42
+ if (!isRecord(value)) bad("an object");
43
+ break;
44
+ case "node": {
45
+ const items = Array.isArray(value) ? value : [value];
46
+ items.forEach((item, i) => {
47
+ const p = Array.isArray(value) ? `${path}[${i}]` : path;
48
+ if (typeof item === "string" || typeof item === "number") return;
49
+ if (isA2uiElement(item)) return checkNode(item, p, errors, catalog);
50
+ report({
51
+ path: p,
52
+ code: "invalid-value",
53
+ message: "expected text or a node ({ type, \u2026 })"
54
+ });
55
+ });
56
+ break;
57
+ }
58
+ case "any":
59
+ break;
60
+ }
61
+ }
62
+ function checkAction(value, path, report) {
63
+ if (!isRecord(value) || typeof value.name !== "string" || !value.name.trim()) {
64
+ report({
65
+ path,
66
+ code: "invalid-action",
67
+ message: 'an action is { "name": "<host verb>", "payload"?: <json> }'
68
+ });
69
+ return false;
70
+ }
71
+ return true;
72
+ }
73
+ function checkNode(node, path, errors, catalog) {
74
+ const report = (e) => errors.push({ ...e, node: path });
75
+ if (typeof node === "string") return;
76
+ if (!isA2uiElement(node)) {
77
+ report({
78
+ path,
79
+ code: "invalid-node",
80
+ message: 'a node is a string or { "type": "<catalog type>", \u2026 }'
81
+ });
82
+ return;
83
+ }
84
+ const entry = catalog[node.type];
85
+ if (!entry) {
86
+ report({
87
+ path: `${path}.type`,
88
+ code: "unknown-type",
89
+ message: `"${node.type}" is not in the catalog (run \`brand-ui a2ui catalog\`)`
90
+ });
91
+ return;
92
+ }
93
+ for (const key of Object.keys(node)) {
94
+ if (!ELEMENT_KEYS.has(key)) {
95
+ report({
96
+ path: `${path}.${key}`,
97
+ code: "invalid-node",
98
+ message: `unknown key "${key}" \u2014 a node has type, id, props, children, on`
99
+ });
100
+ }
101
+ }
102
+ if (node.id !== void 0 && typeof node.id !== "string") {
103
+ report({ path: `${path}.id`, code: "invalid-value", message: "id must be a string" });
104
+ }
105
+ const props = node.props;
106
+ if (props !== void 0 && !isRecord(props)) {
107
+ report({ path: `${path}.props`, code: "invalid-value", message: "props must be an object" });
108
+ } else {
109
+ const allowed = entry.builtin ? entry.props : { ...A2UI_COMMON_PROPS, ...entry.props };
110
+ for (const [name, schema] of Object.entries(entry.props)) {
111
+ if (schema.required && (props === void 0 || props[name] === void 0)) {
112
+ report({
113
+ path: `${path}.props.${name}`,
114
+ code: "missing-prop",
115
+ message: `"${node.type}" requires "${name}"`
116
+ });
117
+ }
118
+ }
119
+ if (props) {
120
+ for (const [name, value] of Object.entries(props)) {
121
+ const schema = allowed[name];
122
+ if (!schema) {
123
+ report({
124
+ path: `${path}.props.${name}`,
125
+ code: "unknown-prop",
126
+ message: `"${name}" is not a prop of "${node.type}" (allowed: ${Object.keys(allowed).join(", ") || "none"})`
127
+ });
128
+ continue;
129
+ }
130
+ checkValue(value, schema, `${path}.props.${name}`, report, errors, catalog);
131
+ }
132
+ }
133
+ }
134
+ if (node.children !== void 0) {
135
+ if (!entry.children) {
136
+ report({
137
+ path: `${path}.children`,
138
+ code: "children-not-allowed",
139
+ message: `"${node.type}" does not take children`
140
+ });
141
+ } else if (!Array.isArray(node.children)) {
142
+ report({
143
+ path: `${path}.children`,
144
+ code: "invalid-value",
145
+ message: "children must be an array of nodes"
146
+ });
147
+ } else {
148
+ node.children.forEach(
149
+ (child, i) => checkNode(child, `${path}.children[${i}]`, errors, catalog)
150
+ );
151
+ }
152
+ }
153
+ if (node.on !== void 0) {
154
+ if (!isRecord(node.on)) {
155
+ report({ path: `${path}.on`, code: "invalid-value", message: "on must be an object" });
156
+ } else {
157
+ for (const [event, action] of Object.entries(node.on)) {
158
+ if (!entry.events[event]) {
159
+ report({
160
+ path: `${path}.on.${event}`,
161
+ code: "unknown-event",
162
+ message: `"${node.type}" has no "${event}" event (${Object.keys(entry.events).join(", ") || "none"})`
163
+ });
164
+ continue;
165
+ }
166
+ checkAction(action, `${path}.on.${event}`, report);
167
+ }
168
+ }
169
+ }
170
+ }
171
+ function validateA2uiSurface(input, catalog) {
172
+ const errors = [];
173
+ const report = (e) => errors.push({ ...e, node: "root" });
174
+ if (!isRecord(input)) {
175
+ return {
176
+ ok: false,
177
+ spec: null,
178
+ errors: [
179
+ {
180
+ path: "",
181
+ node: "root",
182
+ code: "invalid-root",
183
+ message: 'expected { "a2ui": "1", "root": \u2026 }'
184
+ }
185
+ ]
186
+ };
187
+ }
188
+ if (input.a2ui !== A2UI_VERSION) {
189
+ report({
190
+ path: "a2ui",
191
+ code: "unsupported-version",
192
+ message: `expected "a2ui": "${A2UI_VERSION}"; got ${JSON.stringify(input.a2ui)}`
193
+ });
194
+ }
195
+ if (input.title !== void 0 && typeof input.title !== "string") {
196
+ report({ path: "title", code: "invalid-value", message: "title must be a string" });
197
+ }
198
+ if (input.root === void 0) {
199
+ report({ path: "root", code: "invalid-root", message: "root is required" });
200
+ } else {
201
+ checkNode(input.root, "root", errors, catalog);
202
+ }
203
+ const spec = input;
204
+ return errors.length ? { ok: false, spec, errors } : { ok: true, spec, errors: [] };
205
+ }
206
+ function invalidNodePaths(errors) {
207
+ return new Set(errors.map((e) => e.node));
208
+ }
209
+
210
+ export {
211
+ isA2uiElement,
212
+ validateA2uiSurface,
213
+ invalidNodePaths
214
+ };
215
+ //# sourceMappingURL=chunk-7FD5CZEU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/a2ui/core/validate.ts"],"sourcesContent":["/**\n * validate.ts — `validateA2uiSurface`: is this JSON a surface the catalog can\n * render? Never throws, never repairs; every problem is a typed `A2uiError` with\n * a path, so an agent can fix its own output from the message and a host can\n * prune the failing subtree while streaming (`invalidNodePaths`).\n */\nimport {\n A2UI_COMMON_PROPS,\n A2UI_VERSION,\n type A2uiAction,\n type A2uiCatalogSchema,\n type A2uiCatalogTypeSchema,\n type A2uiElement,\n type A2uiError,\n type A2uiNode,\n type A2uiPropSchema,\n type A2uiSurfaceSpec,\n} from \"./spec\";\n\nexport type A2uiValidation =\n | { ok: true; spec: A2uiSurfaceSpec; errors: [] }\n | { ok: false; spec: A2uiSurfaceSpec | null; errors: A2uiError[] };\n\ntype Report = (e: Omit<A2uiError, \"node\">) => void;\n\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n typeof v === \"object\" && v !== null && !Array.isArray(v);\n\n/** An element-shaped value: an object with a string `type`. */\nexport const isA2uiElement = (v: unknown): v is A2uiElement =>\n isRecord(v) && typeof v.type === \"string\";\n\n/** Reserved keys on an element — anything else is a typo, not a prop. */\nconst ELEMENT_KEYS = new Set([\"type\", \"id\", \"props\", \"children\", \"on\"]);\n\nfunction checkValue(\n value: unknown,\n schema: A2uiPropSchema,\n path: string,\n report: Report,\n errors: A2uiError[],\n catalog: A2uiCatalogSchema,\n): void {\n if (schema.enum) {\n if (!schema.enum.includes(value as string | number)) {\n report({\n path,\n code: \"invalid-value\",\n message: `must be one of ${schema.enum.map((e) => JSON.stringify(e)).join(\", \")}; got ${JSON.stringify(value)}`,\n });\n }\n return;\n }\n const t = schema.type;\n const bad = (expected: string) =>\n report({\n path,\n code: \"invalid-value\",\n message: `expected ${expected}; got ${Array.isArray(value) ? \"array\" : typeof value}`,\n });\n switch (t) {\n case \"string\":\n if (typeof value !== \"string\") bad(\"a string\");\n break;\n case \"number\":\n if (typeof value !== \"number\" || !Number.isFinite(value)) bad(\"a number\");\n break;\n case \"boolean\":\n if (typeof value !== \"boolean\") bad(\"a boolean\");\n break;\n case \"array\":\n if (!Array.isArray(value)) bad(\"an array\");\n break;\n case \"object\":\n if (!isRecord(value)) bad(\"an object\");\n break;\n case \"node\": {\n // Text, a number, one element, or a list of nodes — each element validated.\n const items = Array.isArray(value) ? value : [value];\n items.forEach((item, i) => {\n const p = Array.isArray(value) ? `${path}[${i}]` : path;\n if (typeof item === \"string\" || typeof item === \"number\") return;\n if (isA2uiElement(item)) return checkNode(item, p, errors, catalog);\n report({\n path: p,\n code: \"invalid-value\",\n message: \"expected text or a node ({ type, … })\",\n });\n });\n break;\n }\n case \"any\":\n break;\n }\n}\n\nfunction checkAction(value: unknown, path: string, report: Report): value is A2uiAction {\n if (!isRecord(value) || typeof value.name !== \"string\" || !value.name.trim()) {\n report({\n path,\n code: \"invalid-action\",\n message: 'an action is { \"name\": \"<host verb>\", \"payload\"?: <json> }',\n });\n return false;\n }\n return true;\n}\n\nfunction checkNode(\n node: unknown,\n path: string,\n errors: A2uiError[],\n catalog: A2uiCatalogSchema,\n): void {\n const report: Report = (e) => errors.push({ ...e, node: path });\n if (typeof node === \"string\") return;\n if (!isA2uiElement(node)) {\n report({\n path,\n code: \"invalid-node\",\n message: 'a node is a string or { \"type\": \"<catalog type>\", … }',\n });\n return;\n }\n const entry: A2uiCatalogTypeSchema | undefined = catalog[node.type];\n if (!entry) {\n report({\n path: `${path}.type`,\n code: \"unknown-type\",\n message: `\"${node.type}\" is not in the catalog (run \\`brand-ui a2ui catalog\\`)`,\n });\n return;\n }\n for (const key of Object.keys(node)) {\n if (!ELEMENT_KEYS.has(key)) {\n report({\n path: `${path}.${key}`,\n code: \"invalid-node\",\n message: `unknown key \"${key}\" — a node has type, id, props, children, on`,\n });\n }\n }\n if (node.id !== undefined && typeof node.id !== \"string\") {\n report({ path: `${path}.id`, code: \"invalid-value\", message: \"id must be a string\" });\n }\n const props = node.props;\n if (props !== undefined && !isRecord(props)) {\n report({ path: `${path}.props`, code: \"invalid-value\", message: \"props must be an object\" });\n } else {\n const allowed: Record<string, A2uiPropSchema> = entry.builtin\n ? entry.props\n : { ...A2UI_COMMON_PROPS, ...entry.props };\n for (const [name, schema] of Object.entries(entry.props)) {\n if (schema.required && (props === undefined || props[name] === undefined)) {\n report({\n path: `${path}.props.${name}`,\n code: \"missing-prop\",\n message: `\"${node.type}\" requires \"${name}\"`,\n });\n }\n }\n if (props) {\n for (const [name, value] of Object.entries(props)) {\n const schema = allowed[name];\n if (!schema) {\n report({\n path: `${path}.props.${name}`,\n code: \"unknown-prop\",\n message: `\"${name}\" is not a prop of \"${node.type}\" (allowed: ${Object.keys(allowed).join(\", \") || \"none\"})`,\n });\n continue;\n }\n checkValue(value, schema, `${path}.props.${name}`, report, errors, catalog);\n }\n }\n }\n if (node.children !== undefined) {\n if (!entry.children) {\n report({\n path: `${path}.children`,\n code: \"children-not-allowed\",\n message: `\"${node.type}\" does not take children`,\n });\n } else if (!Array.isArray(node.children)) {\n report({\n path: `${path}.children`,\n code: \"invalid-value\",\n message: \"children must be an array of nodes\",\n });\n } else {\n node.children.forEach((child, i) =>\n checkNode(child, `${path}.children[${i}]`, errors, catalog),\n );\n }\n }\n if (node.on !== undefined) {\n if (!isRecord(node.on)) {\n report({ path: `${path}.on`, code: \"invalid-value\", message: \"on must be an object\" });\n } else {\n for (const [event, action] of Object.entries(node.on)) {\n if (!entry.events[event]) {\n report({\n path: `${path}.on.${event}`,\n code: \"unknown-event\",\n message: `\"${node.type}\" has no \"${event}\" event (${Object.keys(entry.events).join(\", \") || \"none\"})`,\n });\n continue;\n }\n checkAction(action, `${path}.on.${event}`, report);\n }\n }\n }\n}\n\n/**\n * Validate an untrusted value (a parsed tool result, a streamed JSON prefix)\n * against `catalog`. `ok: false` carries every problem found, in document order.\n */\nexport function validateA2uiSurface(input: unknown, catalog: A2uiCatalogSchema): A2uiValidation {\n const errors: A2uiError[] = [];\n const report: Report = (e) => errors.push({ ...e, node: \"root\" });\n if (!isRecord(input)) {\n return {\n ok: false,\n spec: null,\n errors: [\n {\n path: \"\",\n node: \"root\",\n code: \"invalid-root\",\n message: 'expected { \"a2ui\": \"1\", \"root\": … }',\n },\n ],\n };\n }\n if (input.a2ui !== A2UI_VERSION) {\n report({\n path: \"a2ui\",\n code: \"unsupported-version\",\n message: `expected \"a2ui\": \"${A2UI_VERSION}\"; got ${JSON.stringify(input.a2ui)}`,\n });\n }\n if (input.title !== undefined && typeof input.title !== \"string\") {\n report({ path: \"title\", code: \"invalid-value\", message: \"title must be a string\" });\n }\n if (input.root === undefined) {\n report({ path: \"root\", code: \"invalid-root\", message: \"root is required\" });\n } else {\n checkNode(input.root, \"root\", errors, catalog);\n }\n const spec = input as unknown as A2uiSurfaceSpec;\n return errors.length ? { ok: false, spec, errors } : { ok: true, spec, errors: [] };\n}\n\n/**\n * The set of NODE paths (`root`, `root.children[1]`, …) that own at least one\n * error — the renderer drops exactly those subtrees while a surface is still\n * streaming, so a half-arrived node never blanks its finished siblings.\n */\nexport function invalidNodePaths(errors: A2uiError[]): Set<string> {\n return new Set(errors.map((e) => e.node));\n}\n\n/** Re-export for hosts that want the version without importing the whole spec module. */\nexport { A2UI_VERSION };\nexport type { A2uiNode };\n"],"mappings":"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","names":[]}
@@ -0,0 +1,266 @@
1
+ "use client";
2
+
3
+ // src/attachments.tsx
4
+ import { Button } from "@elabs-ai/components-ui";
5
+ import { HoverCard, HoverCardContent, HoverCardTrigger } from "@elabs-ai/components-ui";
6
+ import { cn } from "@elabs-ai/components-ui/lib/cn";
7
+ import {
8
+ FileTextIcon,
9
+ GlobeIcon,
10
+ ImageIcon,
11
+ Music2Icon,
12
+ PaperclipIcon,
13
+ VideoIcon,
14
+ XIcon
15
+ } from "lucide-react";
16
+ import { createContext, useCallback, useContext, useMemo } from "react";
17
+ import { jsx, jsxs } from "react/jsx-runtime";
18
+ var mediaCategoryIcons = {
19
+ audio: Music2Icon,
20
+ document: FileTextIcon,
21
+ image: ImageIcon,
22
+ source: GlobeIcon,
23
+ unknown: PaperclipIcon,
24
+ video: VideoIcon
25
+ };
26
+ var getMediaCategory = (data) => {
27
+ if (data.type === "source-document") {
28
+ return "source";
29
+ }
30
+ const mediaType = data.mediaType ?? "";
31
+ if (mediaType.startsWith("image/")) {
32
+ return "image";
33
+ }
34
+ if (mediaType.startsWith("video/")) {
35
+ return "video";
36
+ }
37
+ if (mediaType.startsWith("audio/")) {
38
+ return "audio";
39
+ }
40
+ if (mediaType.startsWith("application/") || mediaType.startsWith("text/")) {
41
+ return "document";
42
+ }
43
+ return "unknown";
44
+ };
45
+ var getAttachmentLabel = (data) => {
46
+ if (data.type === "source-document") {
47
+ return data.title || data.filename || "Source";
48
+ }
49
+ const category = getMediaCategory(data);
50
+ return data.filename || (category === "image" ? "Image" : "Attachment");
51
+ };
52
+ var renderAttachmentImage = (url, filename, isGrid) => isGrid ? /* @__PURE__ */ jsx(
53
+ "img",
54
+ {
55
+ alt: filename || "Image",
56
+ className: "size-full object-cover",
57
+ height: 96,
58
+ src: url,
59
+ width: 96
60
+ }
61
+ ) : /* @__PURE__ */ jsx(
62
+ "img",
63
+ {
64
+ alt: filename || "Image",
65
+ className: "size-full rounded object-cover",
66
+ height: 20,
67
+ src: url,
68
+ width: 20
69
+ }
70
+ );
71
+ var AttachmentsContext = createContext(null);
72
+ var AttachmentContext = createContext(null);
73
+ var useAttachmentsContext = () => useContext(AttachmentsContext) ?? { variant: "grid" };
74
+ var useAttachmentContext = () => {
75
+ const ctx = useContext(AttachmentContext);
76
+ if (!ctx) {
77
+ throw new Error("Attachment components must be used within <Attachment>");
78
+ }
79
+ return ctx;
80
+ };
81
+ var Attachments = ({
82
+ variant = "grid",
83
+ className,
84
+ children,
85
+ ...props
86
+ }) => {
87
+ const contextValue = useMemo(() => ({ variant }), [variant]);
88
+ return /* @__PURE__ */ jsx(AttachmentsContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
89
+ "div",
90
+ {
91
+ className: cn(
92
+ "flex items-start",
93
+ variant === "list" ? "flex-col gap-2" : "flex-wrap gap-2",
94
+ variant === "grid" && "ms-auto w-fit",
95
+ className
96
+ ),
97
+ ...props,
98
+ children
99
+ }
100
+ ) });
101
+ };
102
+ var Attachment = ({ data, onRemove, className, children, ...props }) => {
103
+ const { variant } = useAttachmentsContext();
104
+ const mediaCategory = getMediaCategory(data);
105
+ const contextValue = useMemo(
106
+ () => ({ data, mediaCategory, onRemove, variant }),
107
+ [data, mediaCategory, onRemove, variant]
108
+ );
109
+ return /* @__PURE__ */ jsx(AttachmentContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
110
+ "div",
111
+ {
112
+ className: cn(
113
+ "group relative",
114
+ variant === "grid" && "size-24 overflow-hidden rounded-lg",
115
+ variant === "inline" && [
116
+ "flex h-8 cursor-pointer select-none items-center gap-1.5",
117
+ "rounded-md border border-border px-1.5",
118
+ "font-medium text-body transition-colors duration-fast ease-standard motion-reduce:transition-none",
119
+ "hover:bg-accent/50 hover:text-accent-foreground"
120
+ ],
121
+ variant === "list" && [
122
+ "flex w-full items-center gap-3 rounded-lg border p-3",
123
+ "hover:bg-accent/50"
124
+ ],
125
+ className
126
+ ),
127
+ ...props,
128
+ children
129
+ }
130
+ ) });
131
+ };
132
+ var AttachmentPreview = ({
133
+ fallbackIcon,
134
+ className,
135
+ ...props
136
+ }) => {
137
+ const { data, mediaCategory, variant } = useAttachmentContext();
138
+ const iconSize = variant === "inline" ? "size-3" : "size-4";
139
+ const renderIcon = (Icon) => /* @__PURE__ */ jsx(Icon, { className: cn(iconSize, "text-muted-foreground") });
140
+ const renderContent = () => {
141
+ if (mediaCategory === "image" && data.type === "file" && data.url) {
142
+ return renderAttachmentImage(data.url, data.filename, variant === "grid");
143
+ }
144
+ if (mediaCategory === "video" && data.type === "file" && data.url) {
145
+ return /* @__PURE__ */ jsx("video", { className: "size-full object-cover", muted: true, src: data.url });
146
+ }
147
+ const Icon = mediaCategoryIcons[mediaCategory];
148
+ return fallbackIcon ?? renderIcon(Icon);
149
+ };
150
+ return /* @__PURE__ */ jsx(
151
+ "div",
152
+ {
153
+ className: cn(
154
+ "flex shrink-0 items-center justify-center overflow-hidden",
155
+ variant === "grid" && "size-full bg-muted",
156
+ variant === "inline" && "size-5 rounded bg-background",
157
+ variant === "list" && "size-12 rounded bg-muted",
158
+ className
159
+ ),
160
+ ...props,
161
+ children: renderContent()
162
+ }
163
+ );
164
+ };
165
+ var AttachmentInfo = ({
166
+ showMediaType = false,
167
+ className,
168
+ ...props
169
+ }) => {
170
+ const { data, variant } = useAttachmentContext();
171
+ const label = getAttachmentLabel(data);
172
+ if (variant === "grid") {
173
+ return null;
174
+ }
175
+ return /* @__PURE__ */ jsxs("div", { className: cn("min-w-0 flex-1", className), ...props, children: [
176
+ /* @__PURE__ */ jsx("span", { className: "block truncate", children: label }),
177
+ showMediaType && data.mediaType && /* @__PURE__ */ jsx("span", { className: "block truncate text-muted-foreground text-meta", children: data.mediaType })
178
+ ] });
179
+ };
180
+ var AttachmentRemove = ({
181
+ label = "Remove",
182
+ className,
183
+ children,
184
+ ...props
185
+ }) => {
186
+ const { onRemove, variant } = useAttachmentContext();
187
+ const handleClick = useCallback(
188
+ (e) => {
189
+ e.stopPropagation();
190
+ onRemove?.();
191
+ },
192
+ [onRemove]
193
+ );
194
+ if (!onRemove) {
195
+ return null;
196
+ }
197
+ return /* @__PURE__ */ jsxs(
198
+ Button,
199
+ {
200
+ "aria-label": label,
201
+ className: cn(
202
+ variant === "grid" && [
203
+ "absolute top-2 end-2 size-6 rounded-full p-0",
204
+ "bg-background/80 backdrop-blur-sm",
205
+ "opacity-0 transition-opacity group-hover:opacity-100",
206
+ "hover:bg-background",
207
+ "[&>svg]:size-3"
208
+ ],
209
+ variant === "inline" && [
210
+ "size-5 rounded p-0",
211
+ "opacity-0 transition-opacity group-hover:opacity-100",
212
+ "[&>svg]:size-2.5"
213
+ ],
214
+ variant === "list" && ["size-8 shrink-0 rounded p-0", "[&>svg]:size-4"],
215
+ className
216
+ ),
217
+ onClick: handleClick,
218
+ type: "button",
219
+ variant: "ghost",
220
+ ...props,
221
+ children: [
222
+ children ?? /* @__PURE__ */ jsx(XIcon, {}),
223
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: label })
224
+ ]
225
+ }
226
+ );
227
+ };
228
+ var AttachmentHoverCard = ({
229
+ openDelay = 0,
230
+ closeDelay = 0,
231
+ ...props
232
+ }) => /* @__PURE__ */ jsx(HoverCard, { closeDelay, openDelay, ...props });
233
+ var AttachmentHoverCardTrigger = (props) => /* @__PURE__ */ jsx(HoverCardTrigger, { ...props });
234
+ var AttachmentHoverCardContent = ({
235
+ align = "start",
236
+ className,
237
+ ...props
238
+ }) => /* @__PURE__ */ jsx(HoverCardContent, { align, className: cn("w-auto p-2", className), ...props });
239
+ var AttachmentEmpty = ({ className, children, ...props }) => /* @__PURE__ */ jsx(
240
+ "div",
241
+ {
242
+ className: cn(
243
+ "flex items-center justify-center p-4 text-muted-foreground text-body",
244
+ className
245
+ ),
246
+ ...props,
247
+ children: children ?? "No attachments"
248
+ }
249
+ );
250
+
251
+ export {
252
+ getMediaCategory,
253
+ getAttachmentLabel,
254
+ useAttachmentsContext,
255
+ useAttachmentContext,
256
+ Attachments,
257
+ Attachment,
258
+ AttachmentPreview,
259
+ AttachmentInfo,
260
+ AttachmentRemove,
261
+ AttachmentHoverCard,
262
+ AttachmentHoverCardTrigger,
263
+ AttachmentHoverCardContent,
264
+ AttachmentEmpty
265
+ };
266
+ //# sourceMappingURL=chunk-7RL6KZDF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/attachments.tsx"],"sourcesContent":["\"use client\";\n\nimport { Button } from \"@elabs-ai/components-ui\";\nimport { HoverCard, HoverCardContent, HoverCardTrigger } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport type { FileUIPart, SourceDocumentUIPart } from \"ai\";\nimport {\n FileTextIcon,\n GlobeIcon,\n ImageIcon,\n Music2Icon,\n PaperclipIcon,\n VideoIcon,\n XIcon,\n} from \"lucide-react\";\nimport type { ComponentProps, HTMLAttributes, ReactNode } from \"react\";\nimport { createContext, useCallback, useContext, useMemo } from \"react\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type AttachmentData =\n | (FileUIPart & { id: string })\n | (SourceDocumentUIPart & { id: string });\n\nexport type AttachmentMediaCategory =\n | \"image\"\n | \"video\"\n | \"audio\"\n | \"document\"\n | \"source\"\n | \"unknown\";\n\nexport type AttachmentVariant = \"grid\" | \"inline\" | \"list\";\n\nconst mediaCategoryIcons: Record<AttachmentMediaCategory, typeof ImageIcon> = {\n audio: Music2Icon,\n document: FileTextIcon,\n image: ImageIcon,\n source: GlobeIcon,\n unknown: PaperclipIcon,\n video: VideoIcon,\n};\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\nexport const getMediaCategory = (data: AttachmentData): AttachmentMediaCategory => {\n if (data.type === \"source-document\") {\n return \"source\";\n }\n\n const mediaType = data.mediaType ?? \"\";\n\n if (mediaType.startsWith(\"image/\")) {\n return \"image\";\n }\n if (mediaType.startsWith(\"video/\")) {\n return \"video\";\n }\n if (mediaType.startsWith(\"audio/\")) {\n return \"audio\";\n }\n if (mediaType.startsWith(\"application/\") || mediaType.startsWith(\"text/\")) {\n return \"document\";\n }\n\n return \"unknown\";\n};\n\nexport const getAttachmentLabel = (data: AttachmentData): string => {\n if (data.type === \"source-document\") {\n return data.title || data.filename || \"Source\";\n }\n\n const category = getMediaCategory(data);\n return data.filename || (category === \"image\" ? \"Image\" : \"Attachment\");\n};\n\nconst renderAttachmentImage = (url: string, filename: string | undefined, isGrid: boolean) =>\n isGrid ? (\n <img\n alt={filename || \"Image\"}\n className=\"size-full object-cover\"\n height={96}\n src={url}\n width={96}\n />\n ) : (\n <img\n alt={filename || \"Image\"}\n className=\"size-full rounded object-cover\"\n height={20}\n src={url}\n width={20}\n />\n );\n\n// ============================================================================\n// Contexts\n// ============================================================================\n\ninterface AttachmentsContextValue {\n variant: AttachmentVariant;\n}\n\nconst AttachmentsContext = createContext<AttachmentsContextValue | null>(null);\n\ninterface AttachmentContextValue {\n data: AttachmentData;\n mediaCategory: AttachmentMediaCategory;\n onRemove?: () => void;\n variant: AttachmentVariant;\n}\n\nconst AttachmentContext = createContext<AttachmentContextValue | null>(null);\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\nexport const useAttachmentsContext = () =>\n useContext(AttachmentsContext) ?? { variant: \"grid\" as const };\n\nexport const useAttachmentContext = () => {\n const ctx = useContext(AttachmentContext);\n if (!ctx) {\n throw new Error(\"Attachment components must be used within <Attachment>\");\n }\n return ctx;\n};\n\n// ============================================================================\n// Attachments - Container\n// ============================================================================\n\nexport type AttachmentsProps = HTMLAttributes<HTMLDivElement> & {\n variant?: AttachmentVariant;\n};\n\nexport const Attachments = ({\n variant = \"grid\",\n className,\n children,\n ...props\n}: AttachmentsProps) => {\n const contextValue = useMemo(() => ({ variant }), [variant]);\n\n return (\n <AttachmentsContext.Provider value={contextValue}>\n <div\n className={cn(\n \"flex items-start\",\n variant === \"list\" ? \"flex-col gap-2\" : \"flex-wrap gap-2\",\n variant === \"grid\" && \"ms-auto w-fit\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n </AttachmentsContext.Provider>\n );\n};\n\n// ============================================================================\n// Attachment - Item\n// ============================================================================\n\nexport type AttachmentProps = HTMLAttributes<HTMLDivElement> & {\n data: AttachmentData;\n onRemove?: () => void;\n};\n\nexport const Attachment = ({ data, onRemove, className, children, ...props }: AttachmentProps) => {\n const { variant } = useAttachmentsContext();\n const mediaCategory = getMediaCategory(data);\n\n const contextValue = useMemo<AttachmentContextValue>(\n () => ({ data, mediaCategory, onRemove, variant }),\n [data, mediaCategory, onRemove, variant],\n );\n\n return (\n <AttachmentContext.Provider value={contextValue}>\n <div\n className={cn(\n \"group relative\",\n variant === \"grid\" && \"size-24 overflow-hidden rounded-lg\",\n variant === \"inline\" && [\n \"flex h-8 cursor-pointer select-none items-center gap-1.5\",\n \"rounded-md border border-border px-1.5\",\n \"font-medium text-body transition-colors duration-fast ease-standard motion-reduce:transition-none\",\n \"hover:bg-accent/50 hover:text-accent-foreground\",\n ],\n variant === \"list\" && [\n \"flex w-full items-center gap-3 rounded-lg border p-3\",\n \"hover:bg-accent/50\",\n ],\n className,\n )}\n {...props}\n >\n {children}\n </div>\n </AttachmentContext.Provider>\n );\n};\n\n// ============================================================================\n// AttachmentPreview - Media preview\n// ============================================================================\n\nexport type AttachmentPreviewProps = HTMLAttributes<HTMLDivElement> & {\n fallbackIcon?: ReactNode;\n};\n\nexport const AttachmentPreview = ({\n fallbackIcon,\n className,\n ...props\n}: AttachmentPreviewProps) => {\n const { data, mediaCategory, variant } = useAttachmentContext();\n\n const iconSize = variant === \"inline\" ? \"size-3\" : \"size-4\";\n\n const renderIcon = (Icon: typeof ImageIcon) => (\n <Icon className={cn(iconSize, \"text-muted-foreground\")} />\n );\n\n const renderContent = () => {\n if (mediaCategory === \"image\" && data.type === \"file\" && data.url) {\n return renderAttachmentImage(data.url, data.filename, variant === \"grid\");\n }\n\n if (mediaCategory === \"video\" && data.type === \"file\" && data.url) {\n return <video className=\"size-full object-cover\" muted src={data.url} />;\n }\n\n const Icon = mediaCategoryIcons[mediaCategory];\n return fallbackIcon ?? renderIcon(Icon);\n };\n\n return (\n <div\n className={cn(\n \"flex shrink-0 items-center justify-center overflow-hidden\",\n variant === \"grid\" && \"size-full bg-muted\",\n variant === \"inline\" && \"size-5 rounded bg-background\",\n variant === \"list\" && \"size-12 rounded bg-muted\",\n className,\n )}\n {...props}\n >\n {renderContent()}\n </div>\n );\n};\n\n// ============================================================================\n// AttachmentInfo - Name and type display\n// ============================================================================\n\nexport type AttachmentInfoProps = HTMLAttributes<HTMLDivElement> & {\n showMediaType?: boolean;\n};\n\nexport const AttachmentInfo = ({\n showMediaType = false,\n className,\n ...props\n}: AttachmentInfoProps) => {\n const { data, variant } = useAttachmentContext();\n const label = getAttachmentLabel(data);\n\n if (variant === \"grid\") {\n return null;\n }\n\n return (\n <div className={cn(\"min-w-0 flex-1\", className)} {...props}>\n <span className=\"block truncate\">{label}</span>\n {showMediaType && data.mediaType && (\n <span className=\"block truncate text-muted-foreground text-meta\">{data.mediaType}</span>\n )}\n </div>\n );\n};\n\n// ============================================================================\n// AttachmentRemove - Remove button\n// ============================================================================\n\nexport type AttachmentRemoveProps = ComponentProps<typeof Button> & {\n label?: string;\n};\n\nexport const AttachmentRemove = ({\n label = \"Remove\",\n className,\n children,\n ...props\n}: AttachmentRemoveProps) => {\n const { onRemove, variant } = useAttachmentContext();\n\n const handleClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onRemove?.();\n },\n [onRemove],\n );\n\n if (!onRemove) {\n return null;\n }\n\n return (\n <Button\n aria-label={label}\n className={cn(\n variant === \"grid\" && [\n \"absolute top-2 end-2 size-6 rounded-full p-0\",\n \"bg-background/80 backdrop-blur-sm\",\n \"opacity-0 transition-opacity group-hover:opacity-100\",\n \"hover:bg-background\",\n \"[&>svg]:size-3\",\n ],\n variant === \"inline\" && [\n \"size-5 rounded p-0\",\n \"opacity-0 transition-opacity group-hover:opacity-100\",\n \"[&>svg]:size-2.5\",\n ],\n variant === \"list\" && [\"size-8 shrink-0 rounded p-0\", \"[&>svg]:size-4\"],\n className,\n )}\n onClick={handleClick}\n type=\"button\"\n variant=\"ghost\"\n {...props}\n >\n {children ?? <XIcon />}\n <span className=\"sr-only\">{label}</span>\n </Button>\n );\n};\n\n// ============================================================================\n// AttachmentHoverCard - Hover preview\n// ============================================================================\n\nexport type AttachmentHoverCardProps = ComponentProps<typeof HoverCard>;\n\nexport const AttachmentHoverCard = ({\n openDelay = 0,\n closeDelay = 0,\n ...props\n}: AttachmentHoverCardProps) => (\n <HoverCard closeDelay={closeDelay} openDelay={openDelay} {...props} />\n);\n\nexport type AttachmentHoverCardTriggerProps = ComponentProps<typeof HoverCardTrigger>;\n\nexport const AttachmentHoverCardTrigger = (props: AttachmentHoverCardTriggerProps) => (\n <HoverCardTrigger {...props} />\n);\n\nexport type AttachmentHoverCardContentProps = ComponentProps<typeof HoverCardContent>;\n\nexport const AttachmentHoverCardContent = ({\n align = \"start\",\n className,\n ...props\n}: AttachmentHoverCardContentProps) => (\n <HoverCardContent align={align} className={cn(\"w-auto p-2\", className)} {...props} />\n);\n\n// ============================================================================\n// AttachmentEmpty - Empty state\n// ============================================================================\n\nexport type AttachmentEmptyProps = HTMLAttributes<HTMLDivElement>;\n\nexport const AttachmentEmpty = ({ className, children, ...props }: AttachmentEmptyProps) => (\n <div\n className={cn(\n \"flex items-center justify-center p-4 text-muted-foreground text-body\",\n className,\n )}\n {...props}\n >\n {children ?? \"No attachments\"}\n </div>\n);\n"],"mappings":"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","names":[]}