@elabs-ai/components-ai 4.2.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 +1 -1
- 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 +366 -98
- package/dist/index.js +672 -13577
- 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 +11 -9
- package/schemas/a2ui-surface.v1.schema.json +5425 -0
- package/src/_chat-shell-rail.tsx +3 -1
- package/src/_flow-boundary.tsx +2 -2
- package/src/_persona-rive.tsx +27 -41
- 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/agentic-workspace.stories.tsx +6 -45
- package/src/chat-shell.test.tsx +40 -10
- package/src/chat-shell.tsx +90 -44
- package/src/chat.stories.tsx +47 -42
- package/src/composer.stories.tsx +4 -5
- package/src/composer.test.tsx +45 -0
- package/src/composer.tsx +104 -21
- package/src/context-panel.stories.tsx +1 -1
- package/src/context-panel.tsx +1 -1
- package/src/conversation.stories.tsx +1 -0
- package/src/conversation.test.tsx +16 -0
- package/src/conversation.tsx +16 -2
- package/src/diff-view.stories.tsx +79 -0
- package/src/diff-view.tsx +3 -2
- package/src/file-tree.tsx +24 -17
- 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/message-compare.stories.tsx +40 -0
- package/src/message-compare.tsx +2 -1
- package/src/message-form.tsx +1 -1
- package/src/message-table.stories.tsx +24 -0
- package/src/message-table.tsx +1 -1
- package/src/package-info.tsx +12 -9
- package/src/reasoning.stories.tsx +27 -0
- package/src/reasoning.tsx +1 -1
- package/src/session-header.stories.tsx +35 -1
- package/src/session-header.tsx +1 -1
- package/src/sources.stories.tsx +30 -0
- package/src/sources.tsx +4 -1
- package/src/templates-ai-assistant.stories.tsx +151 -87
- package/src/tool.stories.tsx +39 -0
- package/src/tool.tsx +3 -3
- package/src/toolbar.tsx +0 -10
- 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,192 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/environment-variables.tsx
|
|
4
|
+
import { Badge } from "@elabs-ai/components-ui";
|
|
5
|
+
import { Button } from "@elabs-ai/components-ui";
|
|
6
|
+
import { Switch } from "@elabs-ai/components-ui";
|
|
7
|
+
import { cn } from "@elabs-ai/components-ui/lib/cn";
|
|
8
|
+
import { useCopyToClipboard, useLocale } from "@elabs-ai/components-ui";
|
|
9
|
+
import { CheckIcon, CopyIcon, EyeIcon, EyeOffIcon } from "lucide-react";
|
|
10
|
+
import { createContext, useCallback, useContext, useMemo, useState } from "react";
|
|
11
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
var noop = () => {
|
|
13
|
+
};
|
|
14
|
+
var EnvironmentVariablesContext = createContext({
|
|
15
|
+
setShowValues: noop,
|
|
16
|
+
showValues: false
|
|
17
|
+
});
|
|
18
|
+
var EnvironmentVariables = ({
|
|
19
|
+
showValues: controlledShowValues,
|
|
20
|
+
defaultShowValues = false,
|
|
21
|
+
onShowValuesChange,
|
|
22
|
+
className,
|
|
23
|
+
children,
|
|
24
|
+
...props
|
|
25
|
+
}) => {
|
|
26
|
+
const [internalShowValues, setInternalShowValues] = useState(defaultShowValues);
|
|
27
|
+
const showValues = controlledShowValues ?? internalShowValues;
|
|
28
|
+
const setShowValues = useCallback(
|
|
29
|
+
(show) => {
|
|
30
|
+
setInternalShowValues(show);
|
|
31
|
+
onShowValuesChange?.(show);
|
|
32
|
+
},
|
|
33
|
+
[onShowValuesChange]
|
|
34
|
+
);
|
|
35
|
+
const contextValue = useMemo(() => ({ setShowValues, showValues }), [setShowValues, showValues]);
|
|
36
|
+
return /* @__PURE__ */ jsx(EnvironmentVariablesContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx("div", { className: cn("rounded-lg border bg-background", className), ...props, children }) });
|
|
37
|
+
};
|
|
38
|
+
var EnvironmentVariablesHeader = ({
|
|
39
|
+
className,
|
|
40
|
+
children,
|
|
41
|
+
...props
|
|
42
|
+
}) => /* @__PURE__ */ jsx("div", { className: cn("flex items-center justify-between border-b px-4 py-3", className), ...props, children });
|
|
43
|
+
var EnvironmentVariablesTitle = ({
|
|
44
|
+
className,
|
|
45
|
+
children,
|
|
46
|
+
...props
|
|
47
|
+
}) => /* @__PURE__ */ jsx("h3", { className: cn("font-medium text-body", className), ...props, children: children ?? "Environment Variables" });
|
|
48
|
+
var EnvironmentVariablesToggle = ({
|
|
49
|
+
className,
|
|
50
|
+
...props
|
|
51
|
+
}) => {
|
|
52
|
+
const { t } = useLocale();
|
|
53
|
+
const { showValues, setShowValues } = useContext(EnvironmentVariablesContext);
|
|
54
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", className), children: [
|
|
55
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-meta", children: showValues ? /* @__PURE__ */ jsx(EyeIcon, { size: 14 }) : /* @__PURE__ */ jsx(EyeOffIcon, { size: 14 }) }),
|
|
56
|
+
/* @__PURE__ */ jsx(
|
|
57
|
+
Switch,
|
|
58
|
+
{
|
|
59
|
+
"aria-label": t("ai.environmentVariables.toggleVisibility"),
|
|
60
|
+
checked: showValues,
|
|
61
|
+
onCheckedChange: setShowValues,
|
|
62
|
+
...props
|
|
63
|
+
}
|
|
64
|
+
)
|
|
65
|
+
] });
|
|
66
|
+
};
|
|
67
|
+
var EnvironmentVariablesContent = ({
|
|
68
|
+
className,
|
|
69
|
+
children,
|
|
70
|
+
...props
|
|
71
|
+
}) => /* @__PURE__ */ jsx("div", { className: cn("divide-y", className), ...props, children });
|
|
72
|
+
var EnvironmentVariableContext = createContext({
|
|
73
|
+
name: "",
|
|
74
|
+
value: ""
|
|
75
|
+
});
|
|
76
|
+
var EnvironmentVariableGroup = ({
|
|
77
|
+
className,
|
|
78
|
+
children,
|
|
79
|
+
...props
|
|
80
|
+
}) => /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-2", className), ...props, children });
|
|
81
|
+
var EnvironmentVariableName = ({
|
|
82
|
+
className,
|
|
83
|
+
children,
|
|
84
|
+
...props
|
|
85
|
+
}) => {
|
|
86
|
+
const { name } = useContext(EnvironmentVariableContext);
|
|
87
|
+
return /* @__PURE__ */ jsx("span", { className: cn("font-mono text-body", className), ...props, children: children ?? name });
|
|
88
|
+
};
|
|
89
|
+
var EnvironmentVariableValue = ({
|
|
90
|
+
className,
|
|
91
|
+
children,
|
|
92
|
+
...props
|
|
93
|
+
}) => {
|
|
94
|
+
const { value } = useContext(EnvironmentVariableContext);
|
|
95
|
+
const { showValues } = useContext(EnvironmentVariablesContext);
|
|
96
|
+
const displayValue = showValues ? value : "\u2022".repeat(Math.min(value.length, 20));
|
|
97
|
+
return /* @__PURE__ */ jsx(
|
|
98
|
+
"span",
|
|
99
|
+
{
|
|
100
|
+
className: cn(
|
|
101
|
+
"font-mono text-muted-foreground text-body",
|
|
102
|
+
!showValues && "select-none",
|
|
103
|
+
className
|
|
104
|
+
),
|
|
105
|
+
...props,
|
|
106
|
+
children: children ?? displayValue
|
|
107
|
+
}
|
|
108
|
+
);
|
|
109
|
+
};
|
|
110
|
+
var EnvironmentVariable = ({
|
|
111
|
+
name,
|
|
112
|
+
value,
|
|
113
|
+
className,
|
|
114
|
+
children,
|
|
115
|
+
...props
|
|
116
|
+
}) => {
|
|
117
|
+
const envVarContextValue = useMemo(() => ({ name, value }), [name, value]);
|
|
118
|
+
return /* @__PURE__ */ jsx(EnvironmentVariableContext.Provider, { value: envVarContextValue, children: /* @__PURE__ */ jsx(
|
|
119
|
+
"div",
|
|
120
|
+
{
|
|
121
|
+
className: cn("flex items-center justify-between gap-4 px-4 py-3", className),
|
|
122
|
+
...props,
|
|
123
|
+
children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
124
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx(EnvironmentVariableName, {}) }),
|
|
125
|
+
/* @__PURE__ */ jsx(EnvironmentVariableValue, {})
|
|
126
|
+
] })
|
|
127
|
+
}
|
|
128
|
+
) });
|
|
129
|
+
};
|
|
130
|
+
var EnvironmentVariableCopyButton = ({
|
|
131
|
+
onCopy,
|
|
132
|
+
onError,
|
|
133
|
+
timeout,
|
|
134
|
+
copyFormat = "value",
|
|
135
|
+
children,
|
|
136
|
+
className,
|
|
137
|
+
"aria-label": ariaLabel,
|
|
138
|
+
...props
|
|
139
|
+
}) => {
|
|
140
|
+
const { t } = useLocale();
|
|
141
|
+
const { name, value } = useContext(EnvironmentVariableContext);
|
|
142
|
+
const { copied: isCopied, copy } = useCopyToClipboard({ resetAfterMs: timeout ?? 2e3 });
|
|
143
|
+
const getTextToCopy = useCallback(() => {
|
|
144
|
+
const formatMap = {
|
|
145
|
+
export: () => `export ${name}="${value}"`,
|
|
146
|
+
name: () => name,
|
|
147
|
+
value: () => value
|
|
148
|
+
};
|
|
149
|
+
return formatMap[copyFormat]();
|
|
150
|
+
}, [name, value, copyFormat]);
|
|
151
|
+
const copyToClipboard = useCallback(async () => {
|
|
152
|
+
const ok = await copy(getTextToCopy());
|
|
153
|
+
if (ok) {
|
|
154
|
+
onCopy?.();
|
|
155
|
+
} else {
|
|
156
|
+
onError?.(new Error("Clipboard API not available"));
|
|
157
|
+
}
|
|
158
|
+
}, [copy, getTextToCopy, onCopy, onError]);
|
|
159
|
+
const Icon = isCopied ? CheckIcon : CopyIcon;
|
|
160
|
+
return /* @__PURE__ */ jsx(
|
|
161
|
+
Button,
|
|
162
|
+
{
|
|
163
|
+
"aria-label": ariaLabel ?? t("copy"),
|
|
164
|
+
className: cn("size-6 shrink-0", className),
|
|
165
|
+
onClick: copyToClipboard,
|
|
166
|
+
size: "icon",
|
|
167
|
+
variant: "ghost",
|
|
168
|
+
...props,
|
|
169
|
+
children: children ?? /* @__PURE__ */ jsx(Icon, { size: 12 })
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
};
|
|
173
|
+
var EnvironmentVariableRequired = ({
|
|
174
|
+
className,
|
|
175
|
+
children,
|
|
176
|
+
...props
|
|
177
|
+
}) => /* @__PURE__ */ jsx(Badge, { className: cn("text-meta", className), variant: "secondary", ...props, children: children ?? "Required" });
|
|
178
|
+
|
|
179
|
+
export {
|
|
180
|
+
EnvironmentVariables,
|
|
181
|
+
EnvironmentVariablesHeader,
|
|
182
|
+
EnvironmentVariablesTitle,
|
|
183
|
+
EnvironmentVariablesToggle,
|
|
184
|
+
EnvironmentVariablesContent,
|
|
185
|
+
EnvironmentVariableGroup,
|
|
186
|
+
EnvironmentVariableName,
|
|
187
|
+
EnvironmentVariableValue,
|
|
188
|
+
EnvironmentVariable,
|
|
189
|
+
EnvironmentVariableCopyButton,
|
|
190
|
+
EnvironmentVariableRequired
|
|
191
|
+
};
|
|
192
|
+
//# sourceMappingURL=chunk-MLFMYCPH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/environment-variables.tsx"],"sourcesContent":["\"use client\";\n\nimport { Badge } from \"@elabs-ai/components-ui\";\nimport { Button } from \"@elabs-ai/components-ui\";\nimport { Switch } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { useCopyToClipboard, useLocale } from \"@elabs-ai/components-ui\";\nimport { CheckIcon, CopyIcon, EyeIcon, EyeOffIcon } from \"lucide-react\";\nimport type { ComponentProps, HTMLAttributes } from \"react\";\nimport { createContext, useCallback, useContext, useMemo, useState } from \"react\";\n\ninterface EnvironmentVariablesContextType {\n showValues: boolean;\n setShowValues: (show: boolean) => void;\n}\n\n// Default noop for context default value\n// oxlint-disable-next-line eslint(no-empty-function)\nconst noop = () => {};\n\nconst EnvironmentVariablesContext = createContext<EnvironmentVariablesContextType>({\n setShowValues: noop,\n showValues: false,\n});\n\nexport type EnvironmentVariablesProps = HTMLAttributes<HTMLDivElement> & {\n showValues?: boolean;\n defaultShowValues?: boolean;\n onShowValuesChange?: (show: boolean) => void;\n};\n\nexport const EnvironmentVariables = ({\n showValues: controlledShowValues,\n defaultShowValues = false,\n onShowValuesChange,\n className,\n children,\n ...props\n}: EnvironmentVariablesProps) => {\n const [internalShowValues, setInternalShowValues] = useState(defaultShowValues);\n const showValues = controlledShowValues ?? internalShowValues;\n\n const setShowValues = useCallback(\n (show: boolean) => {\n setInternalShowValues(show);\n onShowValuesChange?.(show);\n },\n [onShowValuesChange],\n );\n\n const contextValue = useMemo(() => ({ setShowValues, showValues }), [setShowValues, showValues]);\n\n return (\n <EnvironmentVariablesContext.Provider value={contextValue}>\n <div className={cn(\"rounded-lg border bg-background\", className)} {...props}>\n {children}\n </div>\n </EnvironmentVariablesContext.Provider>\n );\n};\n\nexport type EnvironmentVariablesHeaderProps = HTMLAttributes<HTMLDivElement>;\n\nexport const EnvironmentVariablesHeader = ({\n className,\n children,\n ...props\n}: EnvironmentVariablesHeaderProps) => (\n <div className={cn(\"flex items-center justify-between border-b px-4 py-3\", className)} {...props}>\n {children}\n </div>\n);\n\nexport type EnvironmentVariablesTitleProps = HTMLAttributes<HTMLHeadingElement>;\n\nexport const EnvironmentVariablesTitle = ({\n className,\n children,\n ...props\n}: EnvironmentVariablesTitleProps) => (\n <h3 className={cn(\"font-medium text-body\", className)} {...props}>\n {children ?? \"Environment Variables\"}\n </h3>\n);\n\nexport type EnvironmentVariablesToggleProps = ComponentProps<typeof Switch>;\n\nexport const EnvironmentVariablesToggle = ({\n className,\n ...props\n}: EnvironmentVariablesToggleProps) => {\n const { t } = useLocale();\n const { showValues, setShowValues } = useContext(EnvironmentVariablesContext);\n\n return (\n <div className={cn(\"flex items-center gap-2\", className)}>\n <span className=\"text-muted-foreground text-meta\">\n {showValues ? <EyeIcon size={14} /> : <EyeOffIcon size={14} />}\n </span>\n <Switch\n aria-label={t(\"ai.environmentVariables.toggleVisibility\")}\n checked={showValues}\n onCheckedChange={setShowValues}\n {...props}\n />\n </div>\n );\n};\n\nexport type EnvironmentVariablesContentProps = HTMLAttributes<HTMLDivElement>;\n\nexport const EnvironmentVariablesContent = ({\n className,\n children,\n ...props\n}: EnvironmentVariablesContentProps) => (\n <div className={cn(\"divide-y\", className)} {...props}>\n {children}\n </div>\n);\n\ninterface EnvironmentVariableContextType {\n name: string;\n value: string;\n}\n\nconst EnvironmentVariableContext = createContext<EnvironmentVariableContextType>({\n name: \"\",\n value: \"\",\n});\n\nexport type EnvironmentVariableGroupProps = HTMLAttributes<HTMLDivElement>;\n\nexport const EnvironmentVariableGroup = ({\n className,\n children,\n ...props\n}: EnvironmentVariableGroupProps) => (\n <div className={cn(\"flex items-center gap-2\", className)} {...props}>\n {children}\n </div>\n);\n\nexport type EnvironmentVariableNameProps = HTMLAttributes<HTMLSpanElement>;\n\nexport const EnvironmentVariableName = ({\n className,\n children,\n ...props\n}: EnvironmentVariableNameProps) => {\n const { name } = useContext(EnvironmentVariableContext);\n\n return (\n <span className={cn(\"font-mono text-body\", className)} {...props}>\n {children ?? name}\n </span>\n );\n};\n\nexport type EnvironmentVariableValueProps = HTMLAttributes<HTMLSpanElement>;\n\nexport const EnvironmentVariableValue = ({\n className,\n children,\n ...props\n}: EnvironmentVariableValueProps) => {\n const { value } = useContext(EnvironmentVariableContext);\n const { showValues } = useContext(EnvironmentVariablesContext);\n\n const displayValue = showValues ? value : \"•\".repeat(Math.min(value.length, 20));\n\n return (\n <span\n className={cn(\n \"font-mono text-muted-foreground text-body\",\n !showValues && \"select-none\",\n className,\n )}\n {...props}\n >\n {children ?? displayValue}\n </span>\n );\n};\n\nexport type EnvironmentVariableProps = HTMLAttributes<HTMLDivElement> & {\n name: string;\n value: string;\n};\n\nexport const EnvironmentVariable = ({\n name,\n value,\n className,\n children,\n ...props\n}: EnvironmentVariableProps) => {\n const envVarContextValue = useMemo(() => ({ name, value }), [name, value]);\n\n return (\n <EnvironmentVariableContext.Provider value={envVarContextValue}>\n <div\n className={cn(\"flex items-center justify-between gap-4 px-4 py-3\", className)}\n {...props}\n >\n {children ?? (\n <>\n <div className=\"flex items-center gap-2\">\n <EnvironmentVariableName />\n </div>\n <EnvironmentVariableValue />\n </>\n )}\n </div>\n </EnvironmentVariableContext.Provider>\n );\n};\n\nexport type EnvironmentVariableCopyButtonProps = ComponentProps<typeof Button> & {\n onCopy?: () => void;\n onError?: (error: Error) => void;\n timeout?: number;\n copyFormat?: \"name\" | \"value\" | \"export\";\n};\n\nexport const EnvironmentVariableCopyButton = ({\n onCopy,\n onError,\n timeout,\n copyFormat = \"value\",\n children,\n className,\n \"aria-label\": ariaLabel,\n ...props\n}: EnvironmentVariableCopyButtonProps) => {\n const { t } = useLocale();\n const { name, value } = useContext(EnvironmentVariableContext);\n // Shared implementation (`@elabs-ai/components-ui`) instead of a private\n // copy of the same copy-to-clipboard state machine (issue-workflow.md\n // dedupe finding) — see `CodeBlockCopyButton` for the reference usage.\n const { copied: isCopied, copy } = useCopyToClipboard({ resetAfterMs: timeout ?? 2000 });\n\n const getTextToCopy = useCallback((): string => {\n const formatMap = {\n export: () => `export ${name}=\"${value}\"`,\n name: () => name,\n value: () => value,\n };\n return formatMap[copyFormat]();\n }, [name, value, copyFormat]);\n\n const copyToClipboard = useCallback(async () => {\n const ok = await copy(getTextToCopy());\n if (ok) {\n onCopy?.();\n } else {\n onError?.(new Error(\"Clipboard API not available\"));\n }\n }, [copy, getTextToCopy, onCopy, onError]);\n\n const Icon = isCopied ? CheckIcon : CopyIcon;\n\n return (\n <Button\n aria-label={ariaLabel ?? t(\"copy\")}\n className={cn(\"size-6 shrink-0\", className)}\n onClick={copyToClipboard}\n size=\"icon\"\n variant=\"ghost\"\n {...props}\n >\n {children ?? <Icon size={12} />}\n </Button>\n );\n};\n\nexport type EnvironmentVariableRequiredProps = ComponentProps<typeof Badge>;\n\nexport const EnvironmentVariableRequired = ({\n className,\n children,\n ...props\n}: EnvironmentVariableRequiredProps) => (\n <Badge className={cn(\"text-meta\", className)} variant=\"secondary\" {...props}>\n {children ?? \"Required\"}\n </Badge>\n);\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/connection.tsx
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
var HALF = 0.5;
|
|
6
|
+
var Connection = ({ fromX, fromY, toX, toY }) => /* @__PURE__ */ jsxs("g", { children: [
|
|
7
|
+
/* @__PURE__ */ jsx(
|
|
8
|
+
"path",
|
|
9
|
+
{
|
|
10
|
+
className: "animated",
|
|
11
|
+
d: `M${fromX},${fromY} C ${fromX + (toX - fromX) * HALF},${fromY} ${fromX + (toX - fromX) * HALF},${toY} ${toX},${toY}`,
|
|
12
|
+
fill: "none",
|
|
13
|
+
stroke: "var(--color-ring)",
|
|
14
|
+
strokeWidth: 1
|
|
15
|
+
}
|
|
16
|
+
),
|
|
17
|
+
/* @__PURE__ */ jsx(
|
|
18
|
+
"circle",
|
|
19
|
+
{
|
|
20
|
+
cx: toX,
|
|
21
|
+
cy: toY,
|
|
22
|
+
fill: "var(--color-background)",
|
|
23
|
+
r: 3,
|
|
24
|
+
stroke: "var(--color-ring)",
|
|
25
|
+
strokeWidth: 1
|
|
26
|
+
}
|
|
27
|
+
)
|
|
28
|
+
] });
|
|
29
|
+
|
|
30
|
+
export {
|
|
31
|
+
Connection
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=chunk-MOK66734.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/connection.tsx"],"sourcesContent":["import type { ConnectionLineComponent } from \"@xyflow/react\";\n\nconst HALF = 0.5;\n\nexport const Connection: ConnectionLineComponent = ({ fromX, fromY, toX, toY }) => (\n <g>\n <path\n className=\"animated\"\n d={`M${fromX},${fromY} C ${fromX + (toX - fromX) * HALF},${fromY} ${fromX + (toX - fromX) * HALF},${toY} ${toX},${toY}`}\n fill=\"none\"\n stroke=\"var(--color-ring)\"\n strokeWidth={1}\n />\n <circle\n cx={toX}\n cy={toY}\n fill=\"var(--color-background)\"\n r={3}\n stroke=\"var(--color-ring)\"\n strokeWidth={1}\n />\n </g>\n);\n"],"mappings":";;;AAKE,SACE,KADF;AAHF,IAAM,OAAO;AAEN,IAAM,aAAsC,CAAC,EAAE,OAAO,OAAO,KAAK,IAAI,MAC3E,qBAAC,OACC;AAAA;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,GAAG,IAAI,KAAK,IAAI,KAAK,MAAM,SAAS,MAAM,SAAS,IAAI,IAAI,KAAK,IAAI,SAAS,MAAM,SAAS,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG;AAAA,MACrH,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAa;AAAA;AAAA,EACf;AAAA,EACA;AAAA,IAAC;AAAA;AAAA,MACC,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,MAAK;AAAA,MACL,GAAG;AAAA,MACH,QAAO;AAAA,MACP,aAAa;AAAA;AAAA,EACf;AAAA,GACF;","names":[]}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
Suggestion,
|
|
4
|
+
Suggestions
|
|
5
|
+
} from "./chunk-475UEU2Q.js";
|
|
6
|
+
import {
|
|
7
|
+
PromptInputEffort
|
|
8
|
+
} from "./chunk-P6YJAZFG.js";
|
|
9
|
+
import {
|
|
10
|
+
PromptInputMode
|
|
11
|
+
} from "./chunk-H42LRUQ4.js";
|
|
12
|
+
import {
|
|
13
|
+
PromptInputSlash,
|
|
14
|
+
PromptInputSlashTextarea
|
|
15
|
+
} from "./chunk-WMDSMSPL.js";
|
|
16
|
+
import {
|
|
17
|
+
PromptInput,
|
|
18
|
+
PromptInputBody,
|
|
19
|
+
PromptInputButton,
|
|
20
|
+
PromptInputFooter,
|
|
21
|
+
PromptInputSubmit,
|
|
22
|
+
PromptInputTextarea,
|
|
23
|
+
PromptInputTools
|
|
24
|
+
} from "./chunk-SSGJ6MEM.js";
|
|
25
|
+
|
|
26
|
+
// src/composer.tsx
|
|
27
|
+
import { useCallback, useRef, useState } from "react";
|
|
28
|
+
import { ArrowUp, Mic, Paperclip, Sparkles } from "lucide-react";
|
|
29
|
+
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
30
|
+
import {
|
|
31
|
+
cn,
|
|
32
|
+
Kbd,
|
|
33
|
+
MentionInput,
|
|
34
|
+
MentionInputContent,
|
|
35
|
+
MentionInputEmpty,
|
|
36
|
+
MentionInputItem,
|
|
37
|
+
MentionInputList,
|
|
38
|
+
MentionInputTextarea,
|
|
39
|
+
useLocale
|
|
40
|
+
} from "@elabs-ai/components-ui";
|
|
41
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
42
|
+
var EMPTY_MENTION_VALUE = { text: "", mentions: [] };
|
|
43
|
+
function Composer({
|
|
44
|
+
onSubmit,
|
|
45
|
+
placeholder,
|
|
46
|
+
status = "Awaiting your input",
|
|
47
|
+
modelPicker,
|
|
48
|
+
mode,
|
|
49
|
+
effort,
|
|
50
|
+
slashCommands,
|
|
51
|
+
onSlashCommand,
|
|
52
|
+
mentions,
|
|
53
|
+
tools,
|
|
54
|
+
sendStatus,
|
|
55
|
+
onStop,
|
|
56
|
+
submitProps,
|
|
57
|
+
shortcuts,
|
|
58
|
+
cancelShortcut,
|
|
59
|
+
suggestions,
|
|
60
|
+
onSuggestionClick,
|
|
61
|
+
showVoice = true,
|
|
62
|
+
showAttach = true,
|
|
63
|
+
tone = "surface",
|
|
64
|
+
className
|
|
65
|
+
}) {
|
|
66
|
+
const { t } = useLocale();
|
|
67
|
+
const textareaRef = useRef(null);
|
|
68
|
+
const [text, setText] = useState("");
|
|
69
|
+
const hasSlash = slashCommands !== void 0 && slashCommands.length > 0;
|
|
70
|
+
const [mentionValue, setMentionValue] = useControllableState({
|
|
71
|
+
prop: mentions?.value,
|
|
72
|
+
defaultProp: EMPTY_MENTION_VALUE,
|
|
73
|
+
onChange: mentions?.onValueChange
|
|
74
|
+
});
|
|
75
|
+
const busy = sendStatus === "submitted" || sendStatus === "streaming";
|
|
76
|
+
const canCancel = busy && Boolean(onStop);
|
|
77
|
+
const allShortcuts = [
|
|
78
|
+
...shortcuts ?? [],
|
|
79
|
+
...canCancel && cancelShortcut ? [cancelShortcut] : []
|
|
80
|
+
];
|
|
81
|
+
const handleSubmit = useCallback(
|
|
82
|
+
(message, event) => {
|
|
83
|
+
setText("");
|
|
84
|
+
const result = onSubmit?.(message, event);
|
|
85
|
+
if (mentions) setMentionValue(EMPTY_MENTION_VALUE);
|
|
86
|
+
return result;
|
|
87
|
+
},
|
|
88
|
+
[onSubmit, mentions, setMentionValue]
|
|
89
|
+
);
|
|
90
|
+
const resolvedPlaceholder = placeholder ?? t("ai.composer.placeholder");
|
|
91
|
+
return /* @__PURE__ */ jsxs("div", { className: "w-full", children: [
|
|
92
|
+
/* @__PURE__ */ jsxs(
|
|
93
|
+
"div",
|
|
94
|
+
{
|
|
95
|
+
className: cn(
|
|
96
|
+
"rounded-xl p-1.5 border",
|
|
97
|
+
tone === "card" ? "bg-surface-muted" : "bg-card shadow-sm",
|
|
98
|
+
className
|
|
99
|
+
),
|
|
100
|
+
children: [
|
|
101
|
+
status != null ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 px-3 py-1.5 text-meta text-muted-foreground", children: [
|
|
102
|
+
/* @__PURE__ */ jsx(Sparkles, { className: "size-3.5", "aria-hidden": "true" }),
|
|
103
|
+
/* @__PURE__ */ jsx("span", { children: status })
|
|
104
|
+
] }) : null,
|
|
105
|
+
/* @__PURE__ */ jsxs(
|
|
106
|
+
PromptInput,
|
|
107
|
+
{
|
|
108
|
+
onSubmit: handleSubmit,
|
|
109
|
+
surfaceClassName: "rounded-t-none rounded-b-lg",
|
|
110
|
+
tone,
|
|
111
|
+
children: [
|
|
112
|
+
/* @__PURE__ */ jsx(PromptInputBody, { children: hasSlash && slashCommands ? /* @__PURE__ */ jsx(
|
|
113
|
+
PromptInputSlash,
|
|
114
|
+
{
|
|
115
|
+
commands: slashCommands,
|
|
116
|
+
value: text,
|
|
117
|
+
textareaRef,
|
|
118
|
+
onValueChange: (next) => setText(next.text),
|
|
119
|
+
onSelect: onSlashCommand,
|
|
120
|
+
children: /* @__PURE__ */ jsx(
|
|
121
|
+
PromptInputSlashTextarea,
|
|
122
|
+
{
|
|
123
|
+
value: text,
|
|
124
|
+
onChange: (event) => setText(event.target.value),
|
|
125
|
+
placeholder: resolvedPlaceholder
|
|
126
|
+
}
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
) : mentions ? /* @__PURE__ */ jsxs(
|
|
130
|
+
MentionInput,
|
|
131
|
+
{
|
|
132
|
+
options: mentions.options,
|
|
133
|
+
value: mentionValue,
|
|
134
|
+
onValueChange: setMentionValue,
|
|
135
|
+
children: [
|
|
136
|
+
/* @__PURE__ */ jsx(MentionInputTextarea, { asChild: true, children: /* @__PURE__ */ jsx(PromptInputTextarea, { placeholder: resolvedPlaceholder }) }),
|
|
137
|
+
/* @__PURE__ */ jsxs(MentionInputContent, { children: [
|
|
138
|
+
/* @__PURE__ */ jsx(MentionInputList, { children: (option) => /* @__PURE__ */ jsx(MentionInputItem, { option }, option.id) }),
|
|
139
|
+
/* @__PURE__ */ jsx(MentionInputEmpty, {})
|
|
140
|
+
] })
|
|
141
|
+
]
|
|
142
|
+
}
|
|
143
|
+
) : /* @__PURE__ */ jsx(PromptInputTextarea, { placeholder: resolvedPlaceholder }) }),
|
|
144
|
+
/* @__PURE__ */ jsxs(PromptInputFooter, { children: [
|
|
145
|
+
/* @__PURE__ */ jsxs(PromptInputTools, { className: "flex-wrap gap-y-1", children: [
|
|
146
|
+
tools ?? (showAttach ? /* @__PURE__ */ jsx(PromptInputButton, { tooltip: "Attach files", children: /* @__PURE__ */ jsx(Paperclip, { className: "size-4" }) }) : null),
|
|
147
|
+
modelPicker,
|
|
148
|
+
mode ? /* @__PURE__ */ jsx(PromptInputMode, { ...mode }) : null,
|
|
149
|
+
effort ? /* @__PURE__ */ jsx(PromptInputEffort, { ...effort }) : null
|
|
150
|
+
] }),
|
|
151
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
|
|
152
|
+
showVoice ? /* @__PURE__ */ jsx(PromptInputButton, { tooltip: "Voice", children: /* @__PURE__ */ jsx(Mic, { className: "size-4" }) }) : null,
|
|
153
|
+
/* @__PURE__ */ jsx(
|
|
154
|
+
PromptInputSubmit,
|
|
155
|
+
{
|
|
156
|
+
status: sendStatus,
|
|
157
|
+
onStop,
|
|
158
|
+
sendIcon: /* @__PURE__ */ jsx(ArrowUp, { className: "size-4" }),
|
|
159
|
+
...submitProps,
|
|
160
|
+
className: cn("rounded-full", submitProps?.className)
|
|
161
|
+
}
|
|
162
|
+
)
|
|
163
|
+
] })
|
|
164
|
+
] })
|
|
165
|
+
]
|
|
166
|
+
}
|
|
167
|
+
),
|
|
168
|
+
allShortcuts.length > 0 ? /* @__PURE__ */ jsx(
|
|
169
|
+
"div",
|
|
170
|
+
{
|
|
171
|
+
className: "flex flex-wrap items-center gap-3 px-3 pt-1.5 text-meta text-muted-foreground",
|
|
172
|
+
"data-slot": "composer-shortcuts",
|
|
173
|
+
children: allShortcuts.map((shortcut, index) => /* @__PURE__ */ jsxs(
|
|
174
|
+
"span",
|
|
175
|
+
{
|
|
176
|
+
className: "inline-flex items-center gap-1.5",
|
|
177
|
+
children: [
|
|
178
|
+
/* @__PURE__ */ jsx(Kbd, { children: shortcut.keys }),
|
|
179
|
+
/* @__PURE__ */ jsx("span", { children: shortcut.label })
|
|
180
|
+
]
|
|
181
|
+
},
|
|
182
|
+
index
|
|
183
|
+
))
|
|
184
|
+
}
|
|
185
|
+
) : null
|
|
186
|
+
]
|
|
187
|
+
}
|
|
188
|
+
),
|
|
189
|
+
suggestions && suggestions.length > 0 ? /* @__PURE__ */ jsx(Suggestions, { className: "mt-4 justify-center", children: suggestions.map((s) => /* @__PURE__ */ jsx(Suggestion, { suggestion: s, onClick: () => onSuggestionClick?.(s) }, s)) }) : null
|
|
190
|
+
] });
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export {
|
|
194
|
+
Composer
|
|
195
|
+
};
|
|
196
|
+
//# sourceMappingURL=chunk-MXTAWPYM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/composer.tsx"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useRef, useState, type ComponentProps, type ReactNode } from \"react\";\nimport { ArrowUp, Mic, Paperclip, Sparkles } from \"lucide-react\";\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport {\n cn,\n Kbd,\n MentionInput,\n MentionInputContent,\n MentionInputEmpty,\n MentionInputItem,\n MentionInputList,\n MentionInputTextarea,\n useLocale,\n type MentionOption,\n type MentionValue,\n} from \"@elabs-ai/components-ui\";\n\nimport {\n PromptInput,\n PromptInputBody,\n PromptInputButton,\n PromptInputFooter,\n PromptInputSubmit,\n PromptInputTextarea,\n PromptInputTools,\n type PromptInputProps,\n} from \"./prompt-input\";\nimport { PromptInputEffort, type PromptInputEffortProps } from \"./prompt-input-effort\";\nimport { PromptInputMode, type PromptInputModeProps } from \"./prompt-input-mode\";\nimport {\n PromptInputSlash,\n PromptInputSlashTextarea,\n type PromptInputSlashProps,\n} from \"./prompt-input-slash\";\nimport { Suggestion, Suggestions } from \"./suggestion\";\n\n/**\n * The slice of `PromptInputModeProps` a `Composer` owns — the vocabulary and\n * the controlled/uncontrolled seam, never the DOM props of the wrapper div.\n *\n * `defaultValue` is deliberately absent: `PromptInputMode` has no uncontrolled\n * initial-value seam (its uncontrolled default is `modes[0]`), and the\n * `defaultValue` it inherits from `HTMLAttributes<HTMLDivElement>` is the DOM\n * attribute, which would type-check and then do nothing. Omit `value` for the\n * uncontrolled default; pass `value` + `onValueChange` to drive it.\n */\nexport type ComposerModeProps = Pick<\n PromptInputModeProps,\n \"modes\" | \"value\" | \"onValueChange\" | \"aria-label\"\n>;\n\n/**\n * The slice of `PromptInputEffortProps` a `Composer` owns. `aria-label` stays\n * REQUIRED, exactly as on the primitive: the name of the scale (\"Reasoning\n * effort\", \"Thinking budget\") is as much the consumer's vocabulary as its\n * levels are, so `Composer` has no default to invent either. `defaultValue` is\n * absent for the same reason it is on `ComposerModeProps`.\n */\nexport type ComposerEffortProps = Pick<\n PromptInputEffortProps,\n \"levels\" | \"value\" | \"onValueChange\" | \"aria-label\"\n>;\n\n/**\n * One shortcut-hint row entry: the physical key(s) plus what they do, shown\n * as a `Kbd` chip beside a plain-text label — never inside a control's own\n * name (see `ComposerProps.shortcuts`).\n */\nexport interface ComposerShortcut {\n /** Rendered inside a `Kbd` chip, e.g. `\"Enter\"`, `\"Shift+Enter\"`. */\n keys: string;\n /** What the key does, in a word or two, e.g. `\"send\"`, `\"newline\"`. */\n label: string;\n}\n\n/**\n * An `@`-mention roster for the composer field (`MentionInput` from\n * `@elabs-ai/components-ui`). The field keeps its own submit contract; the\n * mentions ride alongside the text in a `MentionValue`.\n *\n * Read the mentions on submit from `value` (controlled) or from\n * `onValueChange`, and resolve them with `serializeMentions(value)`\n * (`{ text, mentionedIds }`). `Composer` resets the value to empty after a\n * submit it accepts — through `onValueChange`, so a controlled caller's state\n * clears too.\n */\nexport interface ComposerMentions {\n /** Who (or what) can be mentioned. */\n options: MentionOption[];\n /** Controlled value. Omit for an uncontrolled roster. */\n value?: MentionValue;\n /** Fires on every edit, pick and post-submit reset. */\n onValueChange?: (value: MentionValue) => void;\n}\n\nconst EMPTY_MENTION_VALUE: MentionValue = { text: \"\", mentions: [] };\n\nexport interface ComposerBaseProps {\n /** Submit handler — receives the assembled message (text + attachments). */\n onSubmit?: PromptInputProps[\"onSubmit\"];\n /** Textarea placeholder. Default `\"Ask me anything…\"`. */\n placeholder?: string;\n /**\n * Muted status line shown above the input well. Default `\"Awaiting your\n * input\"`. Drive it from chat state (\"Thinking…\", \"Generating…\") or pass\n * `null` to hide the strip entirely.\n */\n status?: ReactNode;\n /**\n * The model control, rendered first in the tools cluster after `attach`.\n * Pass a `<ModelPicker>` from `@elabs-ai/components-ui` (it is sized to sit\n * in a composer footer) — or anything else. Default: nothing renders.\n *\n * This replaces the old `model` prop, which rendered a static, non-interactive\n * pill defaulted to a hard-coded model name. A composer that shows a model\n * name it cannot change is a lie about what the control does; the slot now\n * takes the real picker instead.\n */\n modelPicker?: ReactNode;\n /**\n * App-defined operating mode control — renders a `PromptInputMode` in the\n * tools cluster. Omitted, nothing renders. `brand-ui` ships no mode\n * vocabulary: `modes` is entirely yours.\n */\n mode?: ComposerModeProps;\n /**\n * Ordered reasoning-effort control — renders a `PromptInputEffort` in the\n * tools cluster. Omitted, nothing renders. `levels` is ordered low → high\n * and is entirely yours; `aria-label` names the scale.\n */\n effort?: ComposerEffortProps;\n /**\n * Override the DEFAULT tool buttons (today: the attach button) — e.g. to add\n * a web-search or connect-data control. Render `PromptInputButton`s /\n * `PromptInputActionMenu` here; when set, `showAttach` is ignored.\n *\n * The explicit `modelPicker` / `mode` / `effort` slots are NOT part of this\n * override — they render after whatever this puts in the cluster, so passing\n * `tools` can never silently swallow a control you asked for by name.\n */\n tools?: ReactNode;\n /** Send-button state, forwarded to `PromptInputSubmit` (ready/submitted/streaming/error). */\n sendStatus?: ComponentProps<typeof PromptInputSubmit>[\"status\"];\n /** Stop handler used while the send button shows the generating state. */\n onStop?: ComponentProps<typeof PromptInputSubmit>[\"onStop\"];\n /**\n * Keyboard-shortcut hints shown as a row beneath the input well — plain\n * `Kbd` + label pairs, e.g. `[{ keys: \"Enter\", label: \"send\" }]`. Omitted,\n * nothing renders (opt-in, like every other Composer slot); the row is\n * never invented, since the real bindings are the host app's.\n */\n shortcuts?: ComposerShortcut[];\n /**\n * A second, busy-only hint appended to `shortcuts` (#107) — shown ONLY\n * once the composer is actually generating (`sendStatus` is `\"submitted\"`\n * or `\"streaming\"`) AND a real `onStop` handler is set, so the hint never\n * describes an affordance that isn't there. Mirrors\n * `TerminalComposer`'s `canCancel = busy && Boolean(onStop)` shape.\n */\n cancelShortcut?: ComposerShortcut;\n /**\n * Extra props spread onto the send button — `disabled`, `aria-label`,\n * `variant`, `id`, `className`. `status` and `onStop` are excluded because\n * `Composer` owns them via `sendStatus` / `onStop` above. (A `data-*` key is\n * not assignable through this object: TypeScript only permits arbitrary\n * `data-*` on a JSX element directly, not on a typed props object. Reach for\n * `id` or `aria-label` as the test hook.)\n *\n * **`disabled` is the one that matters for correctness.** `PromptInput`'s\n * submit handler calls `form.reset()` as soon as it ACCEPTS a submit, so a\n * consumer that refuses the send inside `onSubmit` — an app doing async setup\n * on the first message, say — has already had the textarea cleared and the\n * user's text destroyed, with nothing to restore from. Disabling the control\n * is what actually prevents it: `PromptInputTextarea`'s Enter handler checks\n * `submitControl?.disabled` and bails before `requestSubmit()`, so the Enter\n * path is closed too, not just the click. It holds with a slash palette open\n * as well — the palette's own Enter handling only ever inserts a command.\n *\n * Leave it UNSET rather than passing `false` when you have no opinion —\n * `PromptInputSubmit` resolves `disabled ?? autoDisabled`, so a literal\n * `false` opts out of the library's own empty-composer guard.\n */\n submitProps?: Omit<ComponentProps<typeof PromptInputSubmit>, \"status\" | \"onStop\">;\n /**\n * The two-tone arrangement, forwarded to the `tone` prop of `PromptInput`.\n * `\"surface\"` (default, unchanged) is the original Composer look — an outer\n * `bg-card` frame around the standard muted `PromptInput` well — so every\n * existing usage is unaffected. `\"card\"` swaps to the tinted-outer/\n * distinct-inner \"double card\" (#254): an outer `bg-surface-muted` frame\n * around a `tone=\"card\"` well. The well fill relative to the frame is\n * theme-driven, not universally \"white\" — raised on light themes, recessed\n * on dark; see the `tone` prop doc on `PromptInput`.\n */\n tone?: PromptInputProps[\"tone\"];\n /** Optional suggestion chips rendered beneath the composer. */\n suggestions?: string[];\n /** Click handler for a suggestion chip. */\n onSuggestionClick?: (suggestion: string) => void;\n /** Show the voice button. Default `true`. */\n showVoice?: boolean;\n /** Show the attach button. Default `true`. */\n showAttach?: boolean;\n /** Extra classes for the outer card frame. */\n className?: string;\n}\n\n/**\n * The field enhancements that each take over the textarea — a slash palette OR\n * a mention roster, never both. The union makes the impossible combination a\n * type error instead of a silent precedence rule.\n */\nexport type ComposerFieldProps =\n | {\n /**\n * Slash-command palette. When set (and non-empty) the textarea becomes a\n * `PromptInputSlashTextarea` wrapped in a `PromptInputSlash`, so typing `/`\n * at the start of a line opens a filtered command list — nothing else about\n * the composer changes.\n *\n * Note this makes the textarea REACT-CONTROLLED (the palette needs to read\n * and splice the text), which is why `Composer` clears its own copy of the\n * text on submit: `PromptInput`'s `form.reset()` reaches the DOM node, not\n * React state.\n */\n slashCommands?: PromptInputSlashProps[\"commands\"];\n /** Fires with the chosen slash command (alongside the text splice). */\n onSlashCommand?: PromptInputSlashProps[\"onSelect\"];\n mentions?: never;\n }\n | {\n /** `@`-mention roster on the field — see `ComposerMentions`. */\n mentions?: ComposerMentions;\n slashCommands?: never;\n onSlashCommand?: never;\n };\n\nexport type ComposerProps = ComposerBaseProps & ComposerFieldProps;\n\n/**\n * Composer — the standard brand-ui AI chat input.\n *\n * A rounded two-tone \"double card\": a status strip wrapping a recessed\n * `PromptInput` well (sharp top, theme-rounded bottom), a tools cluster,\n * voice, and a circular send. Built on the real `PromptInput`, so it drops\n * into a `ChatShell` footer or stands alone as an empty-state composer. `tone`\n * (default `\"surface\"`, unchanged) picks the arrangement: `\"surface\"` keeps\n * the original outer `bg-card` frame around the standard muted well;\n * `\"card\"` (#254) swaps to an outer `bg-surface-muted` frame around a\n * `tone=\"card\"` well — the well fill is theme-driven (raised on light\n * themes, recessed on dark), not universally white; see the\n * `tone` prop doc on `PromptInput`. Semantic tokens only; theme-aware radii\n * (`rounded-xl` frame / `rounded-b-lg` well); reads in every theme.\n *\n * **Composer is the chat input. Every control the `PromptInput` family ships\n * is reachable from a `Composer` prop; drop to `PromptInput` only for a\n * bespoke shell.** `modelPicker`, `mode`, `effort`, `slashCommands` and\n * `mentions` are the slots that make that true — they render `ModelPicker`,\n * `PromptInputMode`, `PromptInputEffort`, `PromptInputSlash` and\n * `MentionInput` respectively,\n * in the footer order `attach · modelPicker · mode · effort │ voice · send`\n * (the same left-to-right arrangement `TerminalComposer` uses, so the chat and\n * console skins agree).\n */\nexport function Composer({\n onSubmit,\n placeholder,\n status = \"Awaiting your input\",\n modelPicker,\n mode,\n effort,\n slashCommands,\n onSlashCommand,\n mentions,\n tools,\n sendStatus,\n onStop,\n submitProps,\n shortcuts,\n cancelShortcut,\n suggestions,\n onSuggestionClick,\n showVoice = true,\n showAttach = true,\n tone = \"surface\",\n className,\n}: ComposerProps) {\n const { t } = useLocale();\n\n // Only read when `slashCommands` is set — the palette needs the live text and\n // a handle on the field to do its caret math. Without it the textarea stays\n // uncontrolled, exactly as before.\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const [text, setText] = useState(\"\");\n const hasSlash = slashCommands !== undefined && slashCommands.length > 0;\n // Always called (hook order); only read when `mentions` is set.\n const [mentionValue, setMentionValue] = useControllableState<MentionValue>({\n prop: mentions?.value,\n defaultProp: EMPTY_MENTION_VALUE,\n onChange: mentions?.onValueChange,\n });\n\n // #107: \"Composer shortcut hints change with a busy state\" — derived from\n // the existing canonical `sendStatus`, never a second boolean prop. The\n // cancel hint only ever joins the row once there is a real Stop affordance\n // it can describe (mirrors `TerminalComposer`'s `canCancel` derivation).\n const busy = sendStatus === \"submitted\" || sendStatus === \"streaming\";\n const canCancel = busy && Boolean(onStop);\n const allShortcuts = [\n ...(shortcuts ?? []),\n ...(canCancel && cancelShortcut ? [cancelShortcut] : []),\n ];\n\n const handleSubmit = useCallback<PromptInputProps[\"onSubmit\"]>(\n (message, event) => {\n // `PromptInput.handleSubmit` calls `form.reset()`, which clears the DOM\n // node but cannot touch React state — so the slash-mode textarea would\n // keep rendering the sent text straight back. Clearing here is a no-op in\n // the uncontrolled (non-slash) arrangement.\n setText(\"\");\n const result = onSubmit?.(message, event);\n // `form.reset()` cannot clear a value MentionInput controls either.\n if (mentions) setMentionValue(EMPTY_MENTION_VALUE);\n return result;\n },\n [onSubmit, mentions, setMentionValue],\n );\n\n const resolvedPlaceholder = placeholder ?? t(\"ai.composer.placeholder\");\n\n return (\n <div className=\"w-full\">\n <div\n className={cn(\n \"rounded-xl p-1.5 border\",\n tone === \"card\" ? \"bg-surface-muted\" : \"bg-card shadow-sm\",\n className,\n )}\n >\n {/* Muted status strip — sits in the outer frame above the input well. */}\n {status != null ? (\n <div className=\"flex items-center gap-1.5 px-3 py-1.5 text-meta text-muted-foreground\">\n <Sparkles className=\"size-3.5\" aria-hidden=\"true\" />\n <span>{status}</span>\n </div>\n ) : null}\n\n {/* Inner well — sharp top (nests under the strip), theme-rounded bottom. */}\n <PromptInput\n onSubmit={handleSubmit}\n surfaceClassName=\"rounded-t-none rounded-b-lg\"\n tone={tone}\n >\n <PromptInputBody>\n {hasSlash && slashCommands ? (\n <PromptInputSlash\n commands={slashCommands}\n value={text}\n textareaRef={textareaRef}\n onValueChange={(next) => setText(next.text)}\n onSelect={onSlashCommand}\n >\n {/* No `ref` here on purpose: PromptInputSlashTextarea merges the\n palette's own `textareaRef` in for us. */}\n <PromptInputSlashTextarea\n value={text}\n onChange={(event) => setText(event.target.value)}\n placeholder={resolvedPlaceholder}\n />\n </PromptInputSlash>\n ) : mentions ? (\n <MentionInput\n options={mentions.options}\n value={mentionValue}\n onValueChange={setMentionValue}\n >\n {/* `asChild` lends the mention behaviour to the composer's own\n textarea, so `name=\"message\"` — what PromptInput's submit\n reads — survives. */}\n <MentionInputTextarea asChild>\n <PromptInputTextarea placeholder={resolvedPlaceholder} />\n </MentionInputTextarea>\n <MentionInputContent>\n <MentionInputList>\n {(option) => <MentionInputItem key={option.id} option={option} />}\n </MentionInputList>\n <MentionInputEmpty />\n </MentionInputContent>\n </MentionInput>\n ) : (\n <PromptInputTextarea placeholder={resolvedPlaceholder} />\n )}\n </PromptInputBody>\n <PromptInputFooter>\n {/* `flex-wrap` so a full cluster (attach + picker + mode + effort)\n wraps instead of overflowing a narrow composer. */}\n <PromptInputTools className=\"flex-wrap gap-y-1\">\n {tools ??\n (showAttach ? (\n <PromptInputButton tooltip=\"Attach files\">\n <Paperclip className=\"size-4\" />\n </PromptInputButton>\n ) : null)}\n {modelPicker}\n {mode ? <PromptInputMode {...mode} /> : null}\n {effort ? <PromptInputEffort {...effort} /> : null}\n </PromptInputTools>\n <div className=\"flex shrink-0 items-center gap-1\">\n {showVoice ? (\n <PromptInputButton tooltip=\"Voice\">\n <Mic className=\"size-4\" />\n </PromptInputButton>\n ) : null}\n {/* `sendIcon` (not `children`) survives the send↔stop flip: the\n circular ArrowUp shows at rest AND once a follow-up is typed\n during a running turn (#351), while PromptInputSubmit's own\n status glyphs (spinner / stop square / error) still render\n whenever the control IS the Stop action. */}\n <PromptInputSubmit\n status={sendStatus}\n onStop={onStop}\n sendIcon={<ArrowUp className=\"size-4\" />}\n {...submitProps}\n // After the spread so a caller's `className` EXTENDS the round\n // shape instead of replacing it; every other key still wins.\n className={cn(\"rounded-full\", submitProps?.className)}\n />\n </div>\n </PromptInputFooter>\n </PromptInput>\n\n {/* #107: the hint row itself — plain SIBLING `Kbd` + label pairs, never\n nested inside `PromptInputSubmit` (which already names itself via its\n own `aria-label`), so the row cannot pollute any control's accessible\n name (the #153-style trap). */}\n {allShortcuts.length > 0 ? (\n <div\n className=\"flex flex-wrap items-center gap-3 px-3 pt-1.5 text-meta text-muted-foreground\"\n data-slot=\"composer-shortcuts\"\n >\n {allShortcuts.map((shortcut, index) => (\n <span\n className=\"inline-flex items-center gap-1.5\"\n // Shortcut rows are a fixed, non-reorderable list per render —\n // `keys` alone isn't guaranteed unique (a caller could offer the\n // same key for two purposes), so index is a stable, honest key.\n key={index}\n >\n <Kbd>{shortcut.keys}</Kbd>\n <span>{shortcut.label}</span>\n </span>\n ))}\n </div>\n ) : null}\n </div>\n\n {suggestions && suggestions.length > 0 ? (\n <Suggestions className=\"mt-4 justify-center\">\n {suggestions.map((s) => (\n <Suggestion key={s} suggestion={s} onClick={() => onSuggestionClick?.(s)} />\n ))}\n </Suggestions>\n ) : null}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,SAAS,aAAa,QAAQ,gBAAqD;AACnF,SAAS,SAAS,KAAK,WAAW,gBAAgB;AAClD,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AAqUG,SACE,KADF;AArPV,IAAM,sBAAoC,EAAE,MAAM,IAAI,UAAU,CAAC,EAAE;AAwK5D,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,OAAO;AAAA,EACP;AACF,GAAkB;AAChB,QAAM,EAAE,EAAE,IAAI,UAAU;AAKxB,QAAM,cAAc,OAA4B,IAAI;AACpD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,EAAE;AACnC,QAAM,WAAW,kBAAkB,UAAa,cAAc,SAAS;AAEvE,QAAM,CAAC,cAAc,eAAe,IAAI,qBAAmC;AAAA,IACzE,MAAM,UAAU;AAAA,IAChB,aAAa;AAAA,IACb,UAAU,UAAU;AAAA,EACtB,CAAC;AAMD,QAAM,OAAO,eAAe,eAAe,eAAe;AAC1D,QAAM,YAAY,QAAQ,QAAQ,MAAM;AACxC,QAAM,eAAe;AAAA,IACnB,GAAI,aAAa,CAAC;AAAA,IAClB,GAAI,aAAa,iBAAiB,CAAC,cAAc,IAAI,CAAC;AAAA,EACxD;AAEA,QAAM,eAAe;AAAA,IACnB,CAAC,SAAS,UAAU;AAKlB,cAAQ,EAAE;AACV,YAAM,SAAS,WAAW,SAAS,KAAK;AAExC,UAAI,SAAU,iBAAgB,mBAAmB;AACjD,aAAO;AAAA,IACT;AAAA,IACA,CAAC,UAAU,UAAU,eAAe;AAAA,EACtC;AAEA,QAAM,sBAAsB,eAAe,EAAE,yBAAyB;AAEtE,SACE,qBAAC,SAAI,WAAU,UACb;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,UACT;AAAA,UACA,SAAS,SAAS,qBAAqB;AAAA,UACvC;AAAA,QACF;AAAA,QAGC;AAAA,oBAAU,OACT,qBAAC,SAAI,WAAU,yEACb;AAAA,gCAAC,YAAS,WAAU,YAAW,eAAY,QAAO;AAAA,YAClD,oBAAC,UAAM,kBAAO;AAAA,aAChB,IACE;AAAA,UAGJ;AAAA,YAAC;AAAA;AAAA,cACC,UAAU;AAAA,cACV,kBAAiB;AAAA,cACjB;AAAA,cAEA;AAAA,oCAAC,mBACE,sBAAY,gBACX;AAAA,kBAAC;AAAA;AAAA,oBACC,UAAU;AAAA,oBACV,OAAO;AAAA,oBACP;AAAA,oBACA,eAAe,CAAC,SAAS,QAAQ,KAAK,IAAI;AAAA,oBAC1C,UAAU;AAAA,oBAIV;AAAA,sBAAC;AAAA;AAAA,wBACC,OAAO;AAAA,wBACP,UAAU,CAAC,UAAU,QAAQ,MAAM,OAAO,KAAK;AAAA,wBAC/C,aAAa;AAAA;AAAA,oBACf;AAAA;AAAA,gBACF,IACE,WACF;AAAA,kBAAC;AAAA;AAAA,oBACC,SAAS,SAAS;AAAA,oBAClB,OAAO;AAAA,oBACP,eAAe;AAAA,oBAKf;AAAA,0CAAC,wBAAqB,SAAO,MAC3B,8BAAC,uBAAoB,aAAa,qBAAqB,GACzD;AAAA,sBACA,qBAAC,uBACC;AAAA,4CAAC,oBACE,WAAC,WAAW,oBAAC,oBAAiC,UAAX,OAAO,EAAoB,GACjE;AAAA,wBACA,oBAAC,qBAAkB;AAAA,yBACrB;AAAA;AAAA;AAAA,gBACF,IAEA,oBAAC,uBAAoB,aAAa,qBAAqB,GAE3D;AAAA,gBACA,qBAAC,qBAGC;AAAA,uCAAC,oBAAiB,WAAU,qBACzB;AAAA,8BACE,aACC,oBAAC,qBAAkB,SAAQ,gBACzB,8BAAC,aAAU,WAAU,UAAS,GAChC,IACE;AAAA,oBACL;AAAA,oBACA,OAAO,oBAAC,mBAAiB,GAAG,MAAM,IAAK;AAAA,oBACvC,SAAS,oBAAC,qBAAmB,GAAG,QAAQ,IAAK;AAAA,qBAChD;AAAA,kBACA,qBAAC,SAAI,WAAU,oCACZ;AAAA,gCACC,oBAAC,qBAAkB,SAAQ,SACzB,8BAAC,OAAI,WAAU,UAAS,GAC1B,IACE;AAAA,oBAMJ;AAAA,sBAAC;AAAA;AAAA,wBACC,QAAQ;AAAA,wBACR;AAAA,wBACA,UAAU,oBAAC,WAAQ,WAAU,UAAS;AAAA,wBACrC,GAAG;AAAA,wBAGJ,WAAW,GAAG,gBAAgB,aAAa,SAAS;AAAA;AAAA,oBACtD;AAAA,qBACF;AAAA,mBACF;AAAA;AAAA;AAAA,UACF;AAAA,UAMC,aAAa,SAAS,IACrB;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,aAAU;AAAA,cAET,uBAAa,IAAI,CAAC,UAAU,UAC3B;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAU;AAAA,kBAMV;AAAA,wCAAC,OAAK,mBAAS,MAAK;AAAA,oBACpB,oBAAC,UAAM,mBAAS,OAAM;AAAA;AAAA;AAAA,gBAHjB;AAAA,cAIP,CACD;AAAA;AAAA,UACH,IACE;AAAA;AAAA;AAAA,IACN;AAAA,IAEC,eAAe,YAAY,SAAS,IACnC,oBAAC,eAAY,WAAU,uBACpB,sBAAY,IAAI,CAAC,MAChB,oBAAC,cAAmB,YAAY,GAAG,SAAS,MAAM,oBAAoB,CAAC,KAAtD,CAAyD,CAC3E,GACH,IACE;AAAA,KACN;AAEJ;","names":[]}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
PERSONA_SOURCES
|
|
4
|
+
} from "./chunk-YHUSW7D2.js";
|
|
5
|
+
import {
|
|
6
|
+
LazyEngineBoundary
|
|
7
|
+
} from "./chunk-S3ISPW3A.js";
|
|
8
|
+
|
|
9
|
+
// src/persona.tsx
|
|
10
|
+
import { cn } from "@elabs-ai/components-ui/lib/cn";
|
|
11
|
+
import { useLocale } from "@elabs-ai/components-ui";
|
|
12
|
+
import { lazy, memo, Suspense, useCallback, useState } from "react";
|
|
13
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
14
|
+
var PersonaRive = lazy(() => import("./_persona-rive.js"));
|
|
15
|
+
var PERSONA_STATE_KEYS = {
|
|
16
|
+
idle: "ai.persona.idle",
|
|
17
|
+
listening: "ai.persona.listening",
|
|
18
|
+
thinking: "ai.persona.thinking",
|
|
19
|
+
speaking: "ai.persona.speaking",
|
|
20
|
+
asleep: "ai.persona.asleep"
|
|
21
|
+
};
|
|
22
|
+
var PersonaFallback = ({ className }) => /* @__PURE__ */ jsx(
|
|
23
|
+
"div",
|
|
24
|
+
{
|
|
25
|
+
"aria-hidden": "true",
|
|
26
|
+
className: cn("grid size-16 shrink-0 place-items-center rounded-full bg-primary/10", className),
|
|
27
|
+
children: /* @__PURE__ */ jsx("span", { className: "size-6 animate-pulse rounded-full bg-primary/40 motion-reduce:animate-none" })
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
var Persona = memo(
|
|
31
|
+
({
|
|
32
|
+
className,
|
|
33
|
+
fallback,
|
|
34
|
+
onLoad,
|
|
35
|
+
onLoadError,
|
|
36
|
+
onPause,
|
|
37
|
+
onPlay,
|
|
38
|
+
onReady,
|
|
39
|
+
onStop,
|
|
40
|
+
src,
|
|
41
|
+
state = "idle",
|
|
42
|
+
statusLabel,
|
|
43
|
+
variant = "obsidian"
|
|
44
|
+
}) => {
|
|
45
|
+
const source = PERSONA_SOURCES[variant];
|
|
46
|
+
if (!source) {
|
|
47
|
+
throw new Error(`Invalid variant: ${variant}`);
|
|
48
|
+
}
|
|
49
|
+
const { t } = useLocale();
|
|
50
|
+
const [failed, setFailed] = useState(false);
|
|
51
|
+
const handleLoadError = useCallback(
|
|
52
|
+
(event) => {
|
|
53
|
+
setFailed(true);
|
|
54
|
+
onLoadError?.(event);
|
|
55
|
+
},
|
|
56
|
+
[onLoadError]
|
|
57
|
+
);
|
|
58
|
+
const placeholder = fallback ?? /* @__PURE__ */ jsx(PersonaFallback, { className });
|
|
59
|
+
const label = statusLabel === null ? null : statusLabel ?? t(PERSONA_STATE_KEYS[state]);
|
|
60
|
+
const visual = failed ? placeholder : (
|
|
61
|
+
// The Rive runtime is an optional peer (`@rive-app/react-webgl2`, issue
|
|
62
|
+
// #33) reached via `lazy()` — a REJECTED import throws during render,
|
|
63
|
+
// which `Suspense` alone cannot catch (it only covers the pending
|
|
64
|
+
// state). `LazyEngineBoundary` catches that throw and falls back to the
|
|
65
|
+
// same placeholder a load-time `onLoadError` already renders.
|
|
66
|
+
// `renderMissing` stays pure — `LazyEngineBoundary.componentDidCatch`
|
|
67
|
+
// already logs the error once, correctly; logging it again here would
|
|
68
|
+
// double-report on every render this fallback re-mounts under.
|
|
69
|
+
/* @__PURE__ */ jsx(LazyEngineBoundary, { renderMissing: () => placeholder, children: /* @__PURE__ */ jsx(Suspense, { fallback: placeholder, children: /* @__PURE__ */ jsx(
|
|
70
|
+
PersonaRive,
|
|
71
|
+
{
|
|
72
|
+
className,
|
|
73
|
+
onLoad,
|
|
74
|
+
onLoadError: handleLoadError,
|
|
75
|
+
onPause,
|
|
76
|
+
onPlay,
|
|
77
|
+
onReady,
|
|
78
|
+
onStop,
|
|
79
|
+
source,
|
|
80
|
+
src: src ?? source.source,
|
|
81
|
+
state
|
|
82
|
+
}
|
|
83
|
+
) }) })
|
|
84
|
+
);
|
|
85
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
86
|
+
visual,
|
|
87
|
+
label !== null && /* @__PURE__ */ jsx("span", { className: "sr-only", role: "status", "aria-live": "polite", children: label })
|
|
88
|
+
] });
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
Persona.displayName = "Persona";
|
|
92
|
+
|
|
93
|
+
export {
|
|
94
|
+
Persona
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=chunk-NCL2UZKI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/persona.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { useLocale } from \"@elabs-ai/components-ui\";\nimport type { FC, ReactNode } from \"react\";\nimport { lazy, memo, Suspense, useCallback, useState } from \"react\";\n\nimport { LazyEngineBoundary } from \"./_lazy-engine-boundary\";\nimport { PERSONA_SOURCES, type PersonaState, type PersonaVariant } from \"./persona-sources\";\n\nexport { PERSONA_SOURCES };\nexport type { PersonaState, PersonaVariant };\n\n/**\n * The Rive runtime lives behind a dynamic import — `@rive-app/react-webgl2`\n * declares no `sideEffects`, so a static import would put the whole WebGL2\n * runtime and its `.wasm` in every consumer's entry chunk, `Persona` rendered or\n * not. See ADR 0019.\n *\n * Issue #101: `@rive-app/react-webgl2` (and, transitively, `@rive-app/webgl2`,\n * which re-exports `RiveParameters`) is an OPTIONAL peer, so no PUBLIC export's\n * type may structurally reference it — doing so would name the peer's module\n * specifier in this package's generated root `.d.ts` and hand a\n * `skipLibCheck: false` consumer who has not installed the peer a `TS2307` just\n * for importing the barrel. `PersonaRiveEvent`/`PersonaRiveEventCallback` below\n * are an OWNED mirror of the peer's `Event`/`EventCallback` (from\n * `@rive-app/webgl2`'s `rive.d.ts`) — every one of `RiveParameters`'s\n * `onLoad`/`onLoadError`/`onPause`/`onPlay`/`onStop` callbacks share that exact\n * same `EventCallback` shape, so one owned type covers all five. The\n * conformance assertion in `_persona-rive.tsx` (which still imports the real\n * peer types — that module is reached only through `lazy()` and never sits in\n * the barrel's declaration graph) proves this mirror stays assignable to the\n * real peer type; a future Rive release that changes `Event`'s shape fails\n * `pnpm --filter @elabs-ai/components-ai typecheck` locally instead of\n * reaching a consumer as silent drift. Mirrors the identical pattern\n * `packages/terminal/src/interactive-terminal.tsx` already established for\n * `@xterm/xterm`'s `ITheme` (also issue #101).\n */\nconst PersonaRive = lazy(() => import(\"./_persona-rive\"));\n\n/**\n * Owned mirror of `@rive-app/webgl2`'s `Event` (the parameter type every\n * `RiveParameters` callback receives) — see the module doc comment above.\n * `data` is deliberately widened to `unknown` rather than replicating Rive's\n * `RiveEventPayload`/`LoopEvent`/`RiveFile` union: no callback in this package\n * (or, realistically, a consumer's) narrows it, and `unknown` remains a safe,\n * structurally-compatible supertype of the real union for the conformance\n * assertion in `_persona-rive.tsx`.\n */\nexport interface PersonaRiveEvent {\n type: string;\n data?: unknown;\n}\n\n/** Owned mirror of `@rive-app/webgl2`'s `EventCallback`. */\nexport type PersonaRiveEventCallback = (event: PersonaRiveEvent) => void;\n\n/**\n * Localized status announced when `state` changes, one key per `PersonaState`.\n * Typed as a `Record` (not a bare template string) so a `PersonaState` value\n * added later without a matching key here fails to typecheck.\n */\nconst PERSONA_STATE_KEYS: Record<PersonaState, string> = {\n idle: \"ai.persona.idle\",\n listening: \"ai.persona.listening\",\n thinking: \"ai.persona.thinking\",\n speaking: \"ai.persona.speaking\",\n asleep: \"ai.persona.asleep\",\n};\n\nexport interface PersonaProps {\n className?: string;\n /**\n * Rendered while the artwork loads, and permanently if it fails (blocked by a\n * `connect-src` CSP, offline, or a bad `src`). Defaults to a token-driven orb,\n * so a blocked fetch never leaves an empty box.\n */\n fallback?: ReactNode;\n onLoad?: PersonaRiveEventCallback;\n onLoadError?: PersonaRiveEventCallback;\n onPause?: PersonaRiveEventCallback;\n onPlay?: PersonaRiveEventCallback;\n onReady?: () => void;\n onStop?: PersonaRiveEventCallback;\n /**\n * Override the `.riv` artwork URL — point at a self-hosted copy when a CSP\n * blocks the default origin. Defaults to `PERSONA_SOURCES[variant].source`.\n * Mirrors the `mapStyle` override on `MapCanvas`.\n */\n src?: string;\n state: PersonaState;\n /**\n * Visually-hidden text announced when `state` changes. Defaults to a\n * localized label for the current `state`; pass `null` when the consuming\n * surface already renders its own `role=\"status\"` line, so AT is not told\n * twice.\n */\n statusLabel?: ReactNode | null;\n variant?: PersonaVariant;\n}\n\n/**\n * The offline/blocked stand-in: a token-driven orb.\n *\n * Opacity-only pulse (no transform), neutralised under reduced motion.\n */\nconst PersonaFallback = ({ className }: { className?: string }) => (\n <div\n aria-hidden=\"true\"\n className={cn(\"grid size-16 shrink-0 place-items-center rounded-full bg-primary/10\", className)}\n >\n <span className=\"size-6 animate-pulse rounded-full bg-primary/40 motion-reduce:animate-none\" />\n </div>\n);\n\nexport const Persona: FC<PersonaProps> = memo(\n ({\n className,\n fallback,\n onLoad,\n onLoadError,\n onPause,\n onPlay,\n onReady,\n onStop,\n src,\n state = \"idle\",\n statusLabel,\n variant = \"obsidian\",\n }) => {\n const source = PERSONA_SOURCES[variant];\n\n if (!source) {\n throw new Error(`Invalid variant: ${variant}`);\n }\n\n const { t } = useLocale();\n const [failed, setFailed] = useState(false);\n\n const handleLoadError = useCallback<PersonaRiveEventCallback>(\n (event) => {\n setFailed(true);\n onLoadError?.(event);\n },\n [onLoadError],\n );\n\n const placeholder = fallback ?? <PersonaFallback className={className} />;\n\n const label = statusLabel === null ? null : (statusLabel ?? t(PERSONA_STATE_KEYS[state]));\n\n const visual = failed ? (\n placeholder\n ) : (\n // The Rive runtime is an optional peer (`@rive-app/react-webgl2`, issue\n // #33) reached via `lazy()` — a REJECTED import throws during render,\n // which `Suspense` alone cannot catch (it only covers the pending\n // state). `LazyEngineBoundary` catches that throw and falls back to the\n // same placeholder a load-time `onLoadError` already renders.\n // `renderMissing` stays pure — `LazyEngineBoundary.componentDidCatch`\n // already logs the error once, correctly; logging it again here would\n // double-report on every render this fallback re-mounts under.\n <LazyEngineBoundary renderMissing={() => placeholder}>\n <Suspense fallback={placeholder}>\n <PersonaRive\n className={className}\n onLoad={onLoad}\n onLoadError={handleLoadError}\n onPause={onPause}\n onPlay={onPlay}\n onReady={onReady}\n onStop={onStop}\n source={source}\n src={src ?? source.source}\n state={state}\n />\n </Suspense>\n </LazyEngineBoundary>\n );\n\n return (\n <>\n {visual}\n {label !== null && (\n <span className=\"sr-only\" role=\"status\" aria-live=\"polite\">\n {label}\n </span>\n )}\n </>\n );\n },\n);\n\nPersona.displayName = \"Persona\";\n"],"mappings":";;;;;;;;;AAEA,SAAS,UAAU;AACnB,SAAS,iBAAiB;AAE1B,SAAS,MAAM,MAAM,UAAU,aAAa,gBAAgB;AA0GxD,SAsEE,UAtEF,KAsEE,YAtEF;AAzEJ,IAAM,cAAc,KAAK,MAAM,OAAO,oBAAiB,CAAC;AAwBxD,IAAM,qBAAmD;AAAA,EACvD,MAAM;AAAA,EACN,WAAW;AAAA,EACX,UAAU;AAAA,EACV,UAAU;AAAA,EACV,QAAQ;AACV;AAsCA,IAAM,kBAAkB,CAAC,EAAE,UAAU,MACnC;AAAA,EAAC;AAAA;AAAA,IACC,eAAY;AAAA,IACZ,WAAW,GAAG,uEAAuE,SAAS;AAAA,IAE9F,8BAAC,UAAK,WAAU,8EAA6E;AAAA;AAC/F;AAGK,IAAM,UAA4B;AAAA,EACvC,CAAC;AAAA,IACC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA,UAAU;AAAA,EACZ,MAAM;AACJ,UAAM,SAAS,gBAAgB,OAAO;AAEtC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,oBAAoB,OAAO,EAAE;AAAA,IAC/C;AAEA,UAAM,EAAE,EAAE,IAAI,UAAU;AACxB,UAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAE1C,UAAM,kBAAkB;AAAA,MACtB,CAAC,UAAU;AACT,kBAAU,IAAI;AACd,sBAAc,KAAK;AAAA,MACrB;AAAA,MACA,CAAC,WAAW;AAAA,IACd;AAEA,UAAM,cAAc,YAAY,oBAAC,mBAAgB,WAAsB;AAEvE,UAAM,QAAQ,gBAAgB,OAAO,OAAQ,eAAe,EAAE,mBAAmB,KAAK,CAAC;AAEvF,UAAM,SAAS,SACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUA,oBAAC,sBAAmB,eAAe,MAAM,aACvC,8BAAC,YAAS,UAAU,aAClB;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA,aAAa;AAAA,UACb;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,KAAK,OAAO,OAAO;AAAA,UACnB;AAAA;AAAA,MACF,GACF,GACF;AAAA;AAGF,WACE,iCACG;AAAA;AAAA,MACA,UAAU,QACT,oBAAC,UAAK,WAAU,WAAU,MAAK,UAAS,aAAU,UAC/C,iBACH;AAAA,OAEJ;AAAA,EAEJ;AACF;AAEA,QAAQ,cAAc;","names":[]}
|