@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.
- package/README.md +3 -3
- package/dist/{_audio-player-media-chrome-T3XVXWRZ.js → _audio-player-media-chrome.js} +1 -1
- package/dist/_code-block-theme.js +12 -0
- package/dist/_code-block-theme.js.map +1 -0
- package/dist/{_flow-boundary-SHNWLQG5.js → _flow-boundary.js} +1 -1
- package/dist/_flow-boundary.js.map +1 -0
- package/dist/_flow-lazy.js +8 -0
- package/dist/_flow-lazy.js.map +1 -0
- package/dist/_lazy-boundary-conformance.js +2 -0
- package/dist/_lazy-boundary-conformance.js.map +1 -0
- package/dist/_lazy-cjk.js +13 -0
- package/dist/_lazy-cjk.js.map +1 -0
- package/dist/_lazy-engine-boundary.js +9 -0
- package/dist/_lazy-engine-boundary.js.map +1 -0
- package/dist/_lazy-math.js +13 -0
- package/dist/_lazy-math.js.map +1 -0
- package/dist/_lazy-mermaid.js +12 -0
- package/dist/_lazy-mermaid.js.map +1 -0
- package/dist/_mermaid-error-panel.js +9 -0
- package/dist/_mermaid-error-panel.js.map +1 -0
- package/dist/{_persona-rive-JEG44YHX.js → _persona-rive.js} +19 -24
- package/dist/_persona-rive.js.map +1 -0
- package/dist/_streamdown-i18n.js +21 -0
- package/dist/_streamdown-i18n.js.map +1 -0
- package/dist/_streamdown-safety.js +10 -0
- package/dist/_streamdown-safety.js.map +1 -0
- package/dist/_theme-scope-store.js +13 -0
- package/dist/_theme-scope-store.js.map +1 -0
- package/dist/a2ui/a2ui-surface.js +17 -0
- package/dist/a2ui/a2ui-surface.js.map +1 -0
- package/dist/a2ui/core/catalog.generated.js +10 -0
- package/dist/a2ui/core/catalog.generated.js.map +1 -0
- package/dist/a2ui/core/complete-json.js +10 -0
- package/dist/a2ui/core/complete-json.js.map +1 -0
- package/dist/a2ui/core/index.js +37 -0
- package/dist/a2ui/core/index.js.map +1 -0
- package/dist/a2ui/core/schema.js +11 -0
- package/dist/a2ui/core/schema.js.map +1 -0
- package/dist/a2ui/core/spec.js +10 -0
- package/dist/a2ui/core/spec.js.map +1 -0
- package/dist/a2ui/core/validate.js +16 -0
- package/dist/a2ui/core/validate.js.map +1 -0
- package/dist/a2ui/index.js +54 -0
- package/dist/a2ui/index.js.map +1 -0
- package/dist/a2ui/ui-catalog.js +18 -0
- package/dist/a2ui/ui-catalog.js.map +1 -0
- package/dist/agent-event.js +10 -0
- package/dist/agent-event.js.map +1 -0
- package/dist/agent-timeline.js +11 -0
- package/dist/agent-timeline.js.map +1 -0
- package/dist/agent.js +25 -0
- package/dist/agent.js.map +1 -0
- package/dist/artifact.js +23 -0
- package/dist/artifact.js.map +1 -0
- package/dist/asset-preview.js +22 -0
- package/dist/asset-preview.js.map +1 -0
- package/dist/attachments.js +33 -0
- package/dist/attachments.js.map +1 -0
- package/dist/audio-player.js +30 -0
- package/dist/audio-player.js.map +1 -0
- package/dist/audio-visualizer.js +9 -0
- package/dist/audio-visualizer.js.map +1 -0
- package/dist/canvas.js +10 -0
- package/dist/canvas.js.map +1 -0
- package/dist/chain-of-thought.js +22 -0
- package/dist/chain-of-thought.js.map +1 -0
- package/dist/chat-greeting.js +8 -0
- package/dist/chat-greeting.js.map +1 -0
- package/dist/chat-shell.js +9 -0
- package/dist/chat-shell.js.map +1 -0
- package/dist/checkpoint.js +13 -0
- package/dist/checkpoint.js.map +1 -0
- package/dist/chunk-2XOIG5TG.js +72 -0
- package/dist/chunk-2XOIG5TG.js.map +1 -0
- package/dist/chunk-34CQ2VHM.js +172 -0
- package/dist/chunk-34CQ2VHM.js.map +1 -0
- package/dist/chunk-3TDHPXZZ.js +60 -0
- package/dist/chunk-3TDHPXZZ.js.map +1 -0
- package/dist/chunk-3XNPMDZY.js +478 -0
- package/dist/chunk-3XNPMDZY.js.map +1 -0
- package/dist/chunk-3YPT3V7L.js +56 -0
- package/dist/chunk-3YPT3V7L.js.map +1 -0
- package/dist/chunk-475UEU2Q.js +87 -0
- package/dist/chunk-475UEU2Q.js.map +1 -0
- package/dist/chunk-4CBTII2I.js +95 -0
- package/dist/chunk-4CBTII2I.js.map +1 -0
- package/dist/chunk-4XRNIZMG.js +22 -0
- package/dist/chunk-4XRNIZMG.js.map +1 -0
- package/dist/chunk-5NNWUKK5.js +2 -0
- package/dist/chunk-5NNWUKK5.js.map +1 -0
- package/dist/chunk-5UOMU27Z.js +164 -0
- package/dist/chunk-5UOMU27Z.js.map +1 -0
- package/dist/chunk-5VGYZ62I.js +264 -0
- package/dist/chunk-5VGYZ62I.js.map +1 -0
- package/dist/chunk-6IQPH2OS.js +21 -0
- package/dist/chunk-6IQPH2OS.js.map +1 -0
- package/dist/chunk-6PB2MXCI.js +482 -0
- package/dist/chunk-6PB2MXCI.js.map +1 -0
- package/dist/chunk-7FD5CZEU.js +215 -0
- package/dist/chunk-7FD5CZEU.js.map +1 -0
- package/dist/chunk-7RL6KZDF.js +266 -0
- package/dist/chunk-7RL6KZDF.js.map +1 -0
- package/dist/chunk-ADOYAGGK.js +482 -0
- package/dist/chunk-ADOYAGGK.js.map +1 -0
- package/dist/chunk-AXMNJMMH.js +984 -0
- package/dist/chunk-AXMNJMMH.js.map +1 -0
- package/dist/chunk-BA3AEMOU.js +21 -0
- package/dist/chunk-BA3AEMOU.js.map +1 -0
- package/dist/chunk-BBHFOYML.js +336 -0
- package/dist/chunk-BBHFOYML.js.map +1 -0
- package/dist/chunk-BHUVISIY.js +221 -0
- package/dist/chunk-BHUVISIY.js.map +1 -0
- package/dist/chunk-BM2LWERA.js +100 -0
- package/dist/chunk-BM2LWERA.js.map +1 -0
- package/dist/chunk-CMOYXNPJ.js +211 -0
- package/dist/chunk-CMOYXNPJ.js.map +1 -0
- package/dist/chunk-CZP3RHC4.js +74 -0
- package/dist/chunk-CZP3RHC4.js.map +1 -0
- package/dist/chunk-DDG5JHQT.js +112 -0
- package/dist/chunk-DDG5JHQT.js.map +1 -0
- package/dist/chunk-DJODXO7I.js +38 -0
- package/dist/chunk-DJODXO7I.js.map +1 -0
- package/dist/chunk-DWJDJLPU.js +192 -0
- package/dist/chunk-DWJDJLPU.js.map +1 -0
- package/dist/chunk-DZW6LM22.js +45 -0
- package/dist/chunk-DZW6LM22.js.map +1 -0
- package/dist/chunk-ELGCZLZF.js +305 -0
- package/dist/chunk-ELGCZLZF.js.map +1 -0
- package/dist/chunk-EV3U6ZZB.js +209 -0
- package/dist/chunk-EV3U6ZZB.js.map +1 -0
- package/dist/chunk-EY7LVUKQ.js +87 -0
- package/dist/chunk-EY7LVUKQ.js.map +1 -0
- package/dist/chunk-F4C74F7M.js +230 -0
- package/dist/chunk-F4C74F7M.js.map +1 -0
- package/dist/chunk-FERYDFZA.js +108 -0
- package/dist/chunk-FERYDFZA.js.map +1 -0
- package/dist/chunk-FUIYG2DS.js +166 -0
- package/dist/chunk-FUIYG2DS.js.map +1 -0
- package/dist/chunk-GKYZT3LA.js +136 -0
- package/dist/chunk-GKYZT3LA.js.map +1 -0
- package/dist/chunk-H42LRUQ4.js +102 -0
- package/dist/chunk-H42LRUQ4.js.map +1 -0
- package/dist/chunk-HVXM2G5F.js +222 -0
- package/dist/chunk-HVXM2G5F.js.map +1 -0
- package/dist/chunk-I4RDAGVY.js +53 -0
- package/dist/chunk-I4RDAGVY.js.map +1 -0
- package/dist/chunk-IQJG4IDX.js +208 -0
- package/dist/chunk-IQJG4IDX.js.map +1 -0
- package/dist/chunk-IX2PXG4Y.js +144 -0
- package/dist/chunk-IX2PXG4Y.js.map +1 -0
- package/dist/chunk-IXICSOOP.js +287 -0
- package/dist/chunk-IXICSOOP.js.map +1 -0
- package/dist/chunk-JY5HSN4D.js +84 -0
- package/dist/chunk-JY5HSN4D.js.map +1 -0
- package/dist/chunk-LMNSBOBG.js +19 -0
- package/dist/chunk-LMNSBOBG.js.map +1 -0
- package/dist/chunk-MBI7D6IL.js +42 -0
- package/dist/chunk-MBI7D6IL.js.map +1 -0
- package/dist/chunk-MLFMYCPH.js +192 -0
- package/dist/chunk-MLFMYCPH.js.map +1 -0
- package/dist/chunk-MOK66734.js +33 -0
- package/dist/chunk-MOK66734.js.map +1 -0
- package/dist/chunk-MXTAWPYM.js +196 -0
- package/dist/chunk-MXTAWPYM.js.map +1 -0
- package/dist/chunk-NCL2UZKI.js +96 -0
- package/dist/chunk-NCL2UZKI.js.map +1 -0
- package/dist/chunk-NET4YLRY.js +107 -0
- package/dist/chunk-NET4YLRY.js.map +1 -0
- package/dist/chunk-NIG67CFM.js +329 -0
- package/dist/chunk-NIG67CFM.js.map +1 -0
- package/dist/chunk-NMVNNO3L.js +10 -0
- package/dist/chunk-NMVNNO3L.js.map +1 -0
- package/dist/chunk-NP7VID4K.js +2 -0
- package/dist/chunk-NP7VID4K.js.map +1 -0
- package/dist/chunk-NPUCMAG2.js +382 -0
- package/dist/chunk-NPUCMAG2.js.map +1 -0
- package/dist/chunk-NSCLRHES.js +102 -0
- package/dist/chunk-NSCLRHES.js.map +1 -0
- package/dist/chunk-OEUXHVFW.js +86 -0
- package/dist/chunk-OEUXHVFW.js.map +1 -0
- package/dist/chunk-ONBHFIMZ.js +137 -0
- package/dist/chunk-ONBHFIMZ.js.map +1 -0
- package/dist/chunk-OPH2HHL2.js +228 -0
- package/dist/chunk-OPH2HHL2.js.map +1 -0
- package/dist/chunk-OQERHIQP.js +287 -0
- package/dist/chunk-OQERHIQP.js.map +1 -0
- package/dist/chunk-P6YJAZFG.js +103 -0
- package/dist/chunk-P6YJAZFG.js.map +1 -0
- package/dist/chunk-PG7ERDOD.js +65 -0
- package/dist/chunk-PG7ERDOD.js.map +1 -0
- package/dist/chunk-PIB5JBMA.js +90 -0
- package/dist/chunk-PIB5JBMA.js.map +1 -0
- package/dist/chunk-PQ5BPIWQ.js +22 -0
- package/dist/chunk-PQ5BPIWQ.js.map +1 -0
- package/dist/chunk-PQBF6ZIQ.js +55 -0
- package/dist/chunk-PQBF6ZIQ.js.map +1 -0
- package/dist/chunk-PTWCTSZL.js +173 -0
- package/dist/chunk-PTWCTSZL.js.map +1 -0
- package/dist/chunk-QJUNPVOS.js +101 -0
- package/dist/chunk-QJUNPVOS.js.map +1 -0
- package/dist/chunk-QUDZOTRV.js +43 -0
- package/dist/chunk-QUDZOTRV.js.map +1 -0
- package/dist/chunk-RB7G65JC.js +213 -0
- package/dist/chunk-RB7G65JC.js.map +1 -0
- package/dist/chunk-RPHAOR7P.js +45 -0
- package/dist/chunk-RPHAOR7P.js.map +1 -0
- package/dist/chunk-RTCSH2AN.js +331 -0
- package/dist/chunk-RTCSH2AN.js.map +1 -0
- package/dist/chunk-S3ISPW3A.js +28 -0
- package/dist/chunk-S3ISPW3A.js.map +1 -0
- package/dist/chunk-SEVN656N.js +36 -0
- package/dist/chunk-SEVN656N.js.map +1 -0
- package/dist/chunk-SKVG672B.js +64 -0
- package/dist/chunk-SKVG672B.js.map +1 -0
- package/dist/chunk-SPQIU7GA.js +236 -0
- package/dist/chunk-SPQIU7GA.js.map +1 -0
- package/dist/chunk-SSGJ6MEM.js +1076 -0
- package/dist/chunk-SSGJ6MEM.js.map +1 -0
- package/dist/chunk-SSKZ2AED.js +118 -0
- package/dist/chunk-SSKZ2AED.js.map +1 -0
- package/dist/chunk-T56JFGXI.js +561 -0
- package/dist/chunk-T56JFGXI.js.map +1 -0
- package/dist/chunk-TCB6O74A.js +137 -0
- package/dist/chunk-TCB6O74A.js.map +1 -0
- package/dist/chunk-TTEYPO6X.js +57 -0
- package/dist/chunk-TTEYPO6X.js.map +1 -0
- package/dist/chunk-TWPHAJNM.js +462 -0
- package/dist/chunk-TWPHAJNM.js.map +1 -0
- package/dist/chunk-TXJJLP4O.js +336 -0
- package/dist/chunk-TXJJLP4O.js.map +1 -0
- package/dist/chunk-TZ6TB7VM.js +245 -0
- package/dist/chunk-TZ6TB7VM.js.map +1 -0
- package/dist/chunk-UBLKJJ7K.js +278 -0
- package/dist/chunk-UBLKJJ7K.js.map +1 -0
- package/dist/chunk-UCJ6IUFS.js +52 -0
- package/dist/chunk-UCJ6IUFS.js.map +1 -0
- package/dist/chunk-UCKFJ3QF.js +197 -0
- package/dist/chunk-UCKFJ3QF.js.map +1 -0
- package/dist/chunk-UPXSLILN.js +20 -0
- package/dist/chunk-UPXSLILN.js.map +1 -0
- package/dist/chunk-V4DORGWJ.js +92 -0
- package/dist/chunk-V4DORGWJ.js.map +1 -0
- package/dist/chunk-V6E5DYZD.js +80 -0
- package/dist/chunk-V6E5DYZD.js.map +1 -0
- package/dist/chunk-VLLYKF3P.js +96 -0
- package/dist/chunk-VLLYKF3P.js.map +1 -0
- package/dist/chunk-VLNBTOH6.js +43 -0
- package/dist/chunk-VLNBTOH6.js.map +1 -0
- package/dist/chunk-WMDSMSPL.js +303 -0
- package/dist/chunk-WMDSMSPL.js.map +1 -0
- package/dist/chunk-WU5BLGTF.js +149 -0
- package/dist/chunk-WU5BLGTF.js.map +1 -0
- package/dist/chunk-WYTZVSGK.js +245 -0
- package/dist/chunk-WYTZVSGK.js.map +1 -0
- package/dist/chunk-X47QMM6K.js +187 -0
- package/dist/chunk-X47QMM6K.js.map +1 -0
- package/dist/chunk-XNBKO32Y.js +174 -0
- package/dist/chunk-XNBKO32Y.js.map +1 -0
- package/dist/chunk-YHUSW7D2.js +40 -0
- package/dist/chunk-YHUSW7D2.js.map +1 -0
- package/dist/chunk-YSKD7UXX.js +126 -0
- package/dist/chunk-YSKD7UXX.js.map +1 -0
- package/dist/chunk-YYRDGWOU.js +72 -0
- package/dist/chunk-YYRDGWOU.js.map +1 -0
- package/dist/chunk-ZIGZMWM7.js +19 -0
- package/dist/chunk-ZIGZMWM7.js.map +1 -0
- package/dist/chunk-ZKRTUKNP.js +40 -0
- package/dist/chunk-ZKRTUKNP.js.map +1 -0
- package/dist/code-block.js +38 -0
- package/dist/code-block.js.map +1 -0
- package/dist/commit.js +51 -0
- package/dist/commit.js.map +1 -0
- package/dist/composer.js +15 -0
- package/dist/composer.js.map +1 -0
- package/dist/confirmation.js +53 -0
- package/dist/confirmation.js.map +1 -0
- package/dist/connection.js +8 -0
- package/dist/connection.js.map +1 -0
- package/dist/context-panel.js +25 -0
- package/dist/context-panel.js.map +1 -0
- package/dist/controls.js +10 -0
- package/dist/controls.js.map +1 -0
- package/dist/conversation.js +19 -0
- package/dist/conversation.js.map +1 -0
- package/dist/diff-view.js +15 -0
- package/dist/diff-view.js.map +1 -0
- package/dist/edge.js +10 -0
- package/dist/edge.js.map +1 -0
- package/dist/environment-variables.js +29 -0
- package/dist/environment-variables.js.map +1 -0
- package/dist/file-tree.js +23 -0
- package/dist/file-tree.js.map +1 -0
- package/dist/gallery.js +9 -0
- package/dist/gallery.js.map +1 -0
- package/dist/grouped-parts.js +21 -0
- package/dist/grouped-parts.js.map +1 -0
- package/dist/image.js +9 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +403 -108
- package/dist/index.js +671 -13205
- package/dist/index.js.map +1 -1
- package/dist/inline-citation.js +39 -0
- package/dist/inline-citation.js.map +1 -0
- package/dist/jsx-preview.js +17 -0
- package/dist/jsx-preview.js.map +1 -0
- package/dist/markdown-view.js +17 -0
- package/dist/markdown-view.js.map +1 -0
- package/dist/message-compare.js +12 -0
- package/dist/message-compare.js.map +1 -0
- package/dist/message-edit.js +19 -0
- package/dist/message-edit.js.map +1 -0
- package/dist/message-feedback.js +11 -0
- package/dist/message-feedback.js.map +1 -0
- package/dist/message-form-spec.js +38 -0
- package/dist/message-form-spec.js.map +1 -0
- package/dist/message-form.js +26 -0
- package/dist/message-form.js.map +1 -0
- package/dist/message-table-spec.js +26 -0
- package/dist/message-table-spec.js.map +1 -0
- package/dist/message-table.js +12 -0
- package/dist/message-table.js.map +1 -0
- package/dist/message.js +51 -0
- package/dist/message.js.map +1 -0
- package/dist/mic-selector.js +27 -0
- package/dist/mic-selector.js.map +1 -0
- package/dist/model-provider-logo.js +13 -0
- package/dist/model-provider-logo.js.map +1 -0
- package/dist/motion-config.js +9 -0
- package/dist/motion-config.js.map +1 -0
- package/dist/node.js +22 -0
- package/dist/node.js.map +1 -0
- package/dist/open-in-chat.js +31 -0
- package/dist/open-in-chat.js.map +1 -0
- package/dist/package-info.js +25 -0
- package/dist/package-info.js.map +1 -0
- package/dist/panel.js +10 -0
- package/dist/panel.js.map +1 -0
- package/dist/part-groups.js +18 -0
- package/dist/part-groups.js.map +1 -0
- package/dist/permission-mode-select.js +9 -0
- package/dist/permission-mode-select.js.map +1 -0
- package/dist/persona-sources.js +8 -0
- package/dist/persona-sources.js.map +1 -0
- package/dist/persona.js +14 -0
- package/dist/persona.js.map +1 -0
- package/dist/plan.js +32 -0
- package/dist/plan.js.map +1 -0
- package/dist/prompt-input-effort.js +9 -0
- package/dist/prompt-input-effort.js.map +1 -0
- package/dist/prompt-input-mode.js +10 -0
- package/dist/prompt-input-mode.js.map +1 -0
- package/dist/prompt-input-slash.js +12 -0
- package/dist/prompt-input-slash.js.map +1 -0
- package/dist/prompt-input.js +89 -0
- package/dist/prompt-input.js.map +1 -0
- package/dist/queue.js +37 -0
- package/dist/queue.js.map +1 -0
- package/dist/reasoning.js +23 -0
- package/dist/reasoning.js.map +1 -0
- package/dist/sandbox.js +28 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/schema-display.js +33 -0
- package/dist/schema-display.js.map +1 -0
- package/dist/selection-toolbar.js +11 -0
- package/dist/selection-toolbar.js.map +1 -0
- package/dist/session-header.js +9 -0
- package/dist/session-header.js.map +1 -0
- package/dist/session-status-bar.js +9 -0
- package/dist/session-status-bar.js.map +1 -0
- package/dist/shimmer.js +9 -0
- package/dist/shimmer.js.map +1 -0
- package/dist/snippet.js +17 -0
- package/dist/snippet.js.map +1 -0
- package/dist/sources.js +17 -0
- package/dist/sources.js.map +1 -0
- package/dist/speech-input.js +9 -0
- package/dist/speech-input.js.map +1 -0
- package/dist/stack-trace.js +27 -0
- package/dist/stack-trace.js.map +1 -0
- package/dist/suggestion.js +16 -0
- package/dist/suggestion.js.map +1 -0
- package/dist/task.js +18 -0
- package/dist/task.js.map +1 -0
- package/dist/test-results.js +43 -0
- package/dist/test-results.js.map +1 -0
- package/dist/token-usage.js +27 -0
- package/dist/token-usage.js.map +1 -0
- package/dist/tool-result-card.js +9 -0
- package/dist/tool-result-card.js.map +1 -0
- package/dist/tool.js +27 -0
- package/dist/tool.js.map +1 -0
- package/dist/toolbar.js +10 -0
- package/dist/toolbar.js.map +1 -0
- package/dist/transcription.js +11 -0
- package/dist/transcription.js.map +1 -0
- package/dist/turn-status.js +9 -0
- package/dist/turn-status.js.map +1 -0
- package/dist/use-audio-level.js +9 -0
- package/dist/use-audio-level.js.map +1 -0
- package/dist/voice-selector.js +47 -0
- package/dist/voice-selector.js.map +1 -0
- package/dist/web-preview.js +19 -0
- package/dist/web-preview.js.map +1 -0
- package/package.json +12 -10
- package/schemas/a2ui-surface.v1.schema.json +5425 -0
- package/src/__contract__/audio-visualizer.contract.test.tsx +49 -0
- package/src/__contract__/chat-shell.contract.test.tsx +49 -0
- package/src/__contract__/grouped-parts.contract.test.tsx +49 -0
- package/src/__contract__/image.contract.test.tsx +49 -0
- package/src/__contract__/markdown-view.contract.test.tsx +49 -0
- package/src/__contract__/message-feedback.contract.test.tsx +49 -0
- package/src/__contract__/message-form.contract.test.tsx +49 -0
- package/src/__contract__/message-table.contract.test.tsx +49 -0
- package/src/__contract__/model-provider-logo.contract.test.tsx +49 -0
- package/src/__contract__/persona.contract.test.tsx +49 -0
- package/src/__contract__/prompt-input-effort.contract.test.tsx +49 -0
- package/src/__contract__/prompt-input-mode.contract.test.tsx +49 -0
- package/src/_chat-shell-rail.tsx +4 -2
- package/src/_flow-boundary.tsx +2 -2
- package/src/_lazy-cjk.test.ts +43 -0
- package/src/_lazy-cjk.ts +73 -0
- package/src/_lazy-math.test.ts +63 -0
- package/src/_lazy-math.ts +90 -0
- package/src/_persona-rive.tsx +27 -41
- package/src/_streamdown-i18n.ts +73 -21
- package/src/_streamdown-safety.ts +2 -2
- package/src/_theme-scope-store.test.ts +83 -0
- package/src/_theme-scope-store.ts +103 -0
- package/src/a2ui/a2ui-surface.stories.tsx +662 -0
- package/src/a2ui/a2ui-surface.test.tsx +201 -0
- package/src/a2ui/a2ui-surface.tsx +354 -0
- package/src/a2ui/catalog.source.json +772 -0
- package/src/a2ui/core/a2ui-core.test.ts +178 -0
- package/src/a2ui/core/catalog.generated.ts +1006 -0
- package/src/a2ui/core/complete-json.ts +81 -0
- package/src/a2ui/core/index.ts +10 -0
- package/src/a2ui/core/schema.ts +111 -0
- package/src/a2ui/core/spec.ts +148 -0
- package/src/a2ui/core/validate.ts +266 -0
- package/src/a2ui/index.ts +7 -0
- package/src/a2ui/ui-catalog.tsx +225 -0
- package/src/a2ui/wave1-chart-spec.test.ts +87 -0
- package/src/a2ui/wave2-chart-spec.test.ts +108 -0
- package/src/agent-event.tsx +1 -1
- package/src/agent.tsx +18 -13
- package/src/agentic-workspace.stories.tsx +6 -45
- package/src/artifact.tsx +2 -2
- package/src/asset-preview.test.tsx +40 -0
- package/src/asset-preview.tsx +83 -12
- package/src/attachments.tsx +7 -4
- package/src/chat-shell.test.tsx +40 -10
- package/src/chat-shell.tsx +90 -44
- package/src/chat.stories.tsx +47 -42
- package/src/code-block.test.tsx +100 -1
- package/src/code-block.tsx +166 -103
- package/src/commit.tsx +30 -41
- package/src/composer.stories.tsx +4 -5
- package/src/composer.test.tsx +45 -0
- package/src/composer.tsx +104 -21
- package/src/confirmation.tsx +1 -1
- package/src/context-panel.stories.tsx +1 -1
- package/src/context-panel.tsx +2 -2
- package/src/conversation.stories.tsx +24 -0
- package/src/conversation.test.tsx +69 -0
- package/src/conversation.tsx +47 -8
- package/src/diff-view.stories.tsx +79 -0
- package/src/diff-view.test.tsx +52 -2
- package/src/diff-view.tsx +92 -36
- package/src/environment-variables.tsx +20 -37
- package/src/file-tree.test.tsx +21 -0
- package/src/file-tree.tsx +33 -16
- package/src/gallery.stories.tsx +42 -0
- package/src/gallery.tsx +2 -2
- package/src/grouped-parts.stories.tsx +23 -0
- package/src/grouped-parts.tsx +1 -1
- package/src/index.ts +1 -0
- package/src/inline-citation.tsx +5 -5
- package/src/jsx-preview.tsx +151 -43
- package/src/markdown-view.test.tsx +7 -3
- package/src/markdown-view.tsx +8 -1
- package/src/message-compare.stories.tsx +40 -0
- package/src/message-compare.tsx +2 -1
- package/src/message-form.stories.tsx +36 -3
- package/src/message-form.test.tsx +8 -2
- package/src/message-form.tsx +16 -8
- package/src/message-table.stories.tsx +26 -2
- package/src/message-table.test.tsx +7 -0
- package/src/message-table.tsx +9 -5
- package/src/message.test.tsx +73 -3
- package/src/message.tsx +36 -12
- package/src/model-provider-logo.test.tsx +57 -3
- package/src/model-provider-logo.tsx +45 -11
- package/src/open-in-chat.tsx +50 -29
- package/src/package-info.tsx +23 -20
- package/src/prompt-input-slash.stories.tsx +1 -1
- package/src/prompt-input.test.tsx +67 -1
- package/src/prompt-input.tsx +42 -4
- package/src/queue.tsx +4 -4
- package/src/reasoning.stories.tsx +27 -0
- package/src/reasoning.tsx +17 -6
- package/src/sandbox.tsx +3 -3
- package/src/schema-display.test.tsx +56 -0
- package/src/schema-display.tsx +68 -37
- package/src/session-header.stories.tsx +35 -1
- package/src/session-header.tsx +1 -1
- package/src/snippet.test.tsx +6 -2
- package/src/snippet.tsx +14 -34
- package/src/sources.stories.tsx +30 -0
- package/src/sources.tsx +4 -1
- package/src/speech-input.test.tsx +109 -0
- package/src/speech-input.tsx +31 -3
- package/src/stack-trace.tsx +20 -36
- package/src/streamdown-i18n.test.tsx +23 -0
- package/src/templates-ai-assistant.stories.tsx +151 -87
- package/src/test-results.tsx +47 -27
- package/src/token-usage.tsx +6 -6
- package/src/tool.stories.tsx +39 -0
- package/src/tool.test.tsx +65 -0
- package/src/tool.tsx +61 -25
- package/src/toolbar.tsx +0 -10
- package/src/transcription.tsx +1 -1
- package/src/voice-selector.tsx +5 -5
- package/src/web-preview.test.tsx +51 -1
- package/src/web-preview.tsx +39 -8
- package/dist/_flow-boundary-SHNWLQG5.js.map +0 -1
- package/dist/_persona-rive-JEG44YHX.js.map +0 -1
- /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":[]}
|