@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,287 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/token-usage.tsx
|
|
4
|
+
import { Button } from "@elabs-ai/components-ui";
|
|
5
|
+
import { HoverCard, HoverCardContent, HoverCardTrigger } from "@elabs-ai/components-ui";
|
|
6
|
+
import { Progress } from "@elabs-ai/components-ui";
|
|
7
|
+
import { useLocale } from "@elabs-ai/components-ui";
|
|
8
|
+
import { cn } from "@elabs-ai/components-ui/lib/cn";
|
|
9
|
+
import { createContext, useContext, useMemo } from "react";
|
|
10
|
+
import { getUsage } from "tokenlens";
|
|
11
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
var PERCENT_MAX = 100;
|
|
13
|
+
var ICON_RADIUS = 10;
|
|
14
|
+
var ICON_VIEWBOX = 24;
|
|
15
|
+
var ICON_CENTER = 12;
|
|
16
|
+
var ICON_STROKE_WIDTH = 2;
|
|
17
|
+
var TokenUsageContext = createContext(null);
|
|
18
|
+
var useTokenUsageValue = () => {
|
|
19
|
+
const context = useContext(TokenUsageContext);
|
|
20
|
+
if (!context) {
|
|
21
|
+
throw new Error("TokenUsage components must be used within TokenUsage");
|
|
22
|
+
}
|
|
23
|
+
return context;
|
|
24
|
+
};
|
|
25
|
+
var TokenUsage = ({
|
|
26
|
+
usedTokens,
|
|
27
|
+
maxTokens,
|
|
28
|
+
usage,
|
|
29
|
+
modelId,
|
|
30
|
+
...props
|
|
31
|
+
}) => {
|
|
32
|
+
const contextValue = useMemo(
|
|
33
|
+
() => ({ maxTokens, modelId, usage, usedTokens }),
|
|
34
|
+
[maxTokens, modelId, usage, usedTokens]
|
|
35
|
+
);
|
|
36
|
+
return /* @__PURE__ */ jsx(TokenUsageContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(HoverCard, { closeDelay: 0, openDelay: 0, ...props }) });
|
|
37
|
+
};
|
|
38
|
+
var TokenUsageIcon = () => {
|
|
39
|
+
const { t } = useLocale();
|
|
40
|
+
const { usedTokens, maxTokens } = useTokenUsageValue();
|
|
41
|
+
const circumference = 2 * Math.PI * ICON_RADIUS;
|
|
42
|
+
const usedPercent = usedTokens / maxTokens;
|
|
43
|
+
const dashOffset = circumference * (1 - usedPercent);
|
|
44
|
+
return /* @__PURE__ */ jsxs(
|
|
45
|
+
"svg",
|
|
46
|
+
{
|
|
47
|
+
"aria-label": t("ai.tokenUsage.usage"),
|
|
48
|
+
height: "20",
|
|
49
|
+
role: "img",
|
|
50
|
+
style: { color: "currentcolor" },
|
|
51
|
+
viewBox: `0 0 ${ICON_VIEWBOX} ${ICON_VIEWBOX}`,
|
|
52
|
+
width: "20",
|
|
53
|
+
children: [
|
|
54
|
+
/* @__PURE__ */ jsx(
|
|
55
|
+
"circle",
|
|
56
|
+
{
|
|
57
|
+
cx: ICON_CENTER,
|
|
58
|
+
cy: ICON_CENTER,
|
|
59
|
+
fill: "none",
|
|
60
|
+
opacity: "0.25",
|
|
61
|
+
r: ICON_RADIUS,
|
|
62
|
+
stroke: "currentColor",
|
|
63
|
+
strokeWidth: ICON_STROKE_WIDTH
|
|
64
|
+
}
|
|
65
|
+
),
|
|
66
|
+
/* @__PURE__ */ jsx(
|
|
67
|
+
"circle",
|
|
68
|
+
{
|
|
69
|
+
cx: ICON_CENTER,
|
|
70
|
+
cy: ICON_CENTER,
|
|
71
|
+
fill: "none",
|
|
72
|
+
opacity: "0.7",
|
|
73
|
+
r: ICON_RADIUS,
|
|
74
|
+
stroke: "currentColor",
|
|
75
|
+
strokeDasharray: `${circumference} ${circumference}`,
|
|
76
|
+
strokeDashoffset: dashOffset,
|
|
77
|
+
strokeLinecap: "round",
|
|
78
|
+
strokeWidth: ICON_STROKE_WIDTH,
|
|
79
|
+
style: { transform: "rotate(-90deg)", transformOrigin: "center" }
|
|
80
|
+
}
|
|
81
|
+
)
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
};
|
|
86
|
+
var TokenUsageTrigger = ({ children, ...props }) => {
|
|
87
|
+
const { formatNumber } = useLocale();
|
|
88
|
+
const { usedTokens, maxTokens } = useTokenUsageValue();
|
|
89
|
+
const usedPercent = usedTokens / maxTokens;
|
|
90
|
+
const renderedPercent = formatNumber(usedPercent, {
|
|
91
|
+
maximumFractionDigits: 1,
|
|
92
|
+
style: "percent"
|
|
93
|
+
});
|
|
94
|
+
return /* @__PURE__ */ jsx(HoverCardTrigger, { asChild: true, children: children ?? /* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", ...props, children: [
|
|
95
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-muted-foreground", children: renderedPercent }),
|
|
96
|
+
/* @__PURE__ */ jsx(TokenUsageIcon, {})
|
|
97
|
+
] }) });
|
|
98
|
+
};
|
|
99
|
+
var TokenUsageContent = ({ className, ...props }) => /* @__PURE__ */ jsx(HoverCardContent, { className: cn("min-w-60 divide-y overflow-hidden p-0", className), ...props });
|
|
100
|
+
var TokenUsageContentHeader = ({
|
|
101
|
+
children,
|
|
102
|
+
className,
|
|
103
|
+
...props
|
|
104
|
+
}) => {
|
|
105
|
+
const { formatNumber } = useLocale();
|
|
106
|
+
const { usedTokens, maxTokens } = useTokenUsageValue();
|
|
107
|
+
const usedPercent = usedTokens / maxTokens;
|
|
108
|
+
const displayPct = formatNumber(usedPercent, {
|
|
109
|
+
maximumFractionDigits: 1,
|
|
110
|
+
style: "percent"
|
|
111
|
+
});
|
|
112
|
+
const used = formatNumber(usedTokens, {
|
|
113
|
+
notation: "compact"
|
|
114
|
+
});
|
|
115
|
+
const total = formatNumber(maxTokens, {
|
|
116
|
+
notation: "compact"
|
|
117
|
+
});
|
|
118
|
+
return /* @__PURE__ */ jsx("div", { className: cn("w-full space-y-2 p-3", className), ...props, children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
119
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 text-meta", children: [
|
|
120
|
+
/* @__PURE__ */ jsx("p", { children: displayPct }),
|
|
121
|
+
/* @__PURE__ */ jsxs("p", { className: "font-mono text-muted-foreground", children: [
|
|
122
|
+
used,
|
|
123
|
+
" / ",
|
|
124
|
+
total
|
|
125
|
+
] })
|
|
126
|
+
] }),
|
|
127
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-2", children: /* @__PURE__ */ jsx(Progress, { className: "bg-muted", value: usedPercent * PERCENT_MAX }) })
|
|
128
|
+
] }) });
|
|
129
|
+
};
|
|
130
|
+
var TokenUsageContentBody = ({
|
|
131
|
+
children,
|
|
132
|
+
className,
|
|
133
|
+
...props
|
|
134
|
+
}) => /* @__PURE__ */ jsx("div", { className: cn("w-full p-3", className), ...props, children });
|
|
135
|
+
var TokenUsageContentFooter = ({
|
|
136
|
+
children,
|
|
137
|
+
className,
|
|
138
|
+
...props
|
|
139
|
+
}) => {
|
|
140
|
+
const { formatNumber, t } = useLocale();
|
|
141
|
+
const { modelId, usage } = useTokenUsageValue();
|
|
142
|
+
const costUSD = modelId ? getUsage({
|
|
143
|
+
modelId,
|
|
144
|
+
usage: {
|
|
145
|
+
input: usage?.inputTokens ?? 0,
|
|
146
|
+
output: usage?.outputTokens ?? 0
|
|
147
|
+
}
|
|
148
|
+
}).costUSD?.totalUSD : void 0;
|
|
149
|
+
const totalCost = formatNumber(costUSD ?? 0, {
|
|
150
|
+
currency: "USD",
|
|
151
|
+
style: "currency"
|
|
152
|
+
});
|
|
153
|
+
return /* @__PURE__ */ jsx(
|
|
154
|
+
"div",
|
|
155
|
+
{
|
|
156
|
+
className: cn(
|
|
157
|
+
"flex w-full items-center justify-between gap-3 bg-secondary p-3 text-meta",
|
|
158
|
+
className
|
|
159
|
+
),
|
|
160
|
+
...props,
|
|
161
|
+
children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
162
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("ai.tokenUsage.totalCost") }),
|
|
163
|
+
/* @__PURE__ */ jsx("span", { children: totalCost })
|
|
164
|
+
] })
|
|
165
|
+
}
|
|
166
|
+
);
|
|
167
|
+
};
|
|
168
|
+
var TokensWithCost = ({ tokens, costText }) => {
|
|
169
|
+
const { formatNumber } = useLocale();
|
|
170
|
+
return /* @__PURE__ */ jsxs("span", { children: [
|
|
171
|
+
tokens === void 0 ? "\u2014" : formatNumber(tokens, { notation: "compact" }),
|
|
172
|
+
costText ? /* @__PURE__ */ jsxs("span", { className: "ms-2 text-muted-foreground", children: [
|
|
173
|
+
"\u2022 ",
|
|
174
|
+
costText
|
|
175
|
+
] }) : null
|
|
176
|
+
] });
|
|
177
|
+
};
|
|
178
|
+
var TokenUsageInput = ({ className, children, ...props }) => {
|
|
179
|
+
const { formatNumber, t } = useLocale();
|
|
180
|
+
const { usage, modelId } = useTokenUsageValue();
|
|
181
|
+
const inputTokens = usage?.inputTokens ?? 0;
|
|
182
|
+
if (children) {
|
|
183
|
+
return children;
|
|
184
|
+
}
|
|
185
|
+
if (!inputTokens) {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
const inputCost = modelId ? getUsage({
|
|
189
|
+
modelId,
|
|
190
|
+
usage: { input: inputTokens, output: 0 }
|
|
191
|
+
}).costUSD?.totalUSD : void 0;
|
|
192
|
+
const inputCostText = formatNumber(inputCost ?? 0, {
|
|
193
|
+
currency: "USD",
|
|
194
|
+
style: "currency"
|
|
195
|
+
});
|
|
196
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between text-meta", className), ...props, children: [
|
|
197
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("ai.tokenUsage.input") }),
|
|
198
|
+
/* @__PURE__ */ jsx(TokensWithCost, { costText: inputCostText, tokens: inputTokens })
|
|
199
|
+
] });
|
|
200
|
+
};
|
|
201
|
+
var TokenUsageOutput = ({ className, children, ...props }) => {
|
|
202
|
+
const { formatNumber, t } = useLocale();
|
|
203
|
+
const { usage, modelId } = useTokenUsageValue();
|
|
204
|
+
const outputTokens = usage?.outputTokens ?? 0;
|
|
205
|
+
if (children) {
|
|
206
|
+
return children;
|
|
207
|
+
}
|
|
208
|
+
if (!outputTokens) {
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
const outputCost = modelId ? getUsage({
|
|
212
|
+
modelId,
|
|
213
|
+
usage: { input: 0, output: outputTokens }
|
|
214
|
+
}).costUSD?.totalUSD : void 0;
|
|
215
|
+
const outputCostText = formatNumber(outputCost ?? 0, {
|
|
216
|
+
currency: "USD",
|
|
217
|
+
style: "currency"
|
|
218
|
+
});
|
|
219
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between text-meta", className), ...props, children: [
|
|
220
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("ai.tokenUsage.output") }),
|
|
221
|
+
/* @__PURE__ */ jsx(TokensWithCost, { costText: outputCostText, tokens: outputTokens })
|
|
222
|
+
] });
|
|
223
|
+
};
|
|
224
|
+
var TokenUsageReasoning = ({
|
|
225
|
+
className,
|
|
226
|
+
children,
|
|
227
|
+
...props
|
|
228
|
+
}) => {
|
|
229
|
+
const { formatNumber, t } = useLocale();
|
|
230
|
+
const { usage, modelId } = useTokenUsageValue();
|
|
231
|
+
const reasoningTokens = usage?.outputTokenDetails?.reasoningTokens ?? 0;
|
|
232
|
+
if (children) {
|
|
233
|
+
return children;
|
|
234
|
+
}
|
|
235
|
+
if (!reasoningTokens) {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
const reasoningCost = modelId ? getUsage({
|
|
239
|
+
modelId,
|
|
240
|
+
usage: { reasoningTokens }
|
|
241
|
+
}).costUSD?.totalUSD : void 0;
|
|
242
|
+
const reasoningCostText = formatNumber(reasoningCost ?? 0, {
|
|
243
|
+
currency: "USD",
|
|
244
|
+
style: "currency"
|
|
245
|
+
});
|
|
246
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between text-meta", className), ...props, children: [
|
|
247
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("ai.tokenUsage.reasoning") }),
|
|
248
|
+
/* @__PURE__ */ jsx(TokensWithCost, { costText: reasoningCostText, tokens: reasoningTokens })
|
|
249
|
+
] });
|
|
250
|
+
};
|
|
251
|
+
var TokenUsageCache = ({ className, children, ...props }) => {
|
|
252
|
+
const { formatNumber, t } = useLocale();
|
|
253
|
+
const { usage, modelId } = useTokenUsageValue();
|
|
254
|
+
const cacheTokens = usage?.inputTokenDetails?.cacheReadTokens ?? 0;
|
|
255
|
+
if (children) {
|
|
256
|
+
return children;
|
|
257
|
+
}
|
|
258
|
+
if (!cacheTokens) {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
const cacheCost = modelId ? getUsage({
|
|
262
|
+
modelId,
|
|
263
|
+
usage: { cacheReads: cacheTokens, input: 0, output: 0 }
|
|
264
|
+
}).costUSD?.totalUSD : void 0;
|
|
265
|
+
const cacheCostText = formatNumber(cacheCost ?? 0, {
|
|
266
|
+
currency: "USD",
|
|
267
|
+
style: "currency"
|
|
268
|
+
});
|
|
269
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between text-meta", className), ...props, children: [
|
|
270
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("ai.tokenUsage.cache") }),
|
|
271
|
+
/* @__PURE__ */ jsx(TokensWithCost, { costText: cacheCostText, tokens: cacheTokens })
|
|
272
|
+
] });
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
export {
|
|
276
|
+
TokenUsage,
|
|
277
|
+
TokenUsageTrigger,
|
|
278
|
+
TokenUsageContent,
|
|
279
|
+
TokenUsageContentHeader,
|
|
280
|
+
TokenUsageContentBody,
|
|
281
|
+
TokenUsageContentFooter,
|
|
282
|
+
TokenUsageInput,
|
|
283
|
+
TokenUsageOutput,
|
|
284
|
+
TokenUsageReasoning,
|
|
285
|
+
TokenUsageCache
|
|
286
|
+
};
|
|
287
|
+
//# sourceMappingURL=chunk-OQERHIQP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/token-usage.tsx"],"sourcesContent":["\"use client\";\n\nimport { Button } from \"@elabs-ai/components-ui\";\nimport { HoverCard, HoverCardContent, HoverCardTrigger } from \"@elabs-ai/components-ui\";\nimport { Progress } from \"@elabs-ai/components-ui\";\nimport { useLocale } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport type { LanguageModelUsage } from \"ai\";\nimport type { ComponentProps } from \"react\";\nimport { createContext, useContext, useMemo } from \"react\";\nimport { getUsage } from \"tokenlens\";\n\nconst PERCENT_MAX = 100;\nconst ICON_RADIUS = 10;\nconst ICON_VIEWBOX = 24;\nconst ICON_CENTER = 12;\nconst ICON_STROKE_WIDTH = 2;\n\ntype ModelId = string;\n\ninterface TokenUsageSchema {\n usedTokens: number;\n maxTokens: number;\n usage?: LanguageModelUsage;\n modelId?: ModelId;\n}\n\nconst TokenUsageContext = createContext<TokenUsageSchema | null>(null);\n\nconst useTokenUsageValue = () => {\n const context = useContext(TokenUsageContext);\n\n if (!context) {\n throw new Error(\"TokenUsage components must be used within TokenUsage\");\n }\n\n return context;\n};\n\nexport type TokenUsageProps = ComponentProps<typeof HoverCard> & TokenUsageSchema;\n\nexport const TokenUsage = ({\n usedTokens,\n maxTokens,\n usage,\n modelId,\n ...props\n}: TokenUsageProps) => {\n const contextValue = useMemo(\n () => ({ maxTokens, modelId, usage, usedTokens }),\n [maxTokens, modelId, usage, usedTokens],\n );\n\n return (\n <TokenUsageContext.Provider value={contextValue}>\n <HoverCard closeDelay={0} openDelay={0} {...props} />\n </TokenUsageContext.Provider>\n );\n};\n\nconst TokenUsageIcon = () => {\n const { t } = useLocale();\n const { usedTokens, maxTokens } = useTokenUsageValue();\n const circumference = 2 * Math.PI * ICON_RADIUS;\n const usedPercent = usedTokens / maxTokens;\n const dashOffset = circumference * (1 - usedPercent);\n\n return (\n <svg\n aria-label={t(\"ai.tokenUsage.usage\")}\n height=\"20\"\n role=\"img\"\n style={{ color: \"currentcolor\" }}\n viewBox={`0 0 ${ICON_VIEWBOX} ${ICON_VIEWBOX}`}\n width=\"20\"\n >\n <circle\n cx={ICON_CENTER}\n cy={ICON_CENTER}\n fill=\"none\"\n opacity=\"0.25\"\n r={ICON_RADIUS}\n stroke=\"currentColor\"\n strokeWidth={ICON_STROKE_WIDTH}\n />\n <circle\n cx={ICON_CENTER}\n cy={ICON_CENTER}\n fill=\"none\"\n opacity=\"0.7\"\n r={ICON_RADIUS}\n stroke=\"currentColor\"\n strokeDasharray={`${circumference} ${circumference}`}\n strokeDashoffset={dashOffset}\n strokeLinecap=\"round\"\n strokeWidth={ICON_STROKE_WIDTH}\n style={{ transform: \"rotate(-90deg)\", transformOrigin: \"center\" }}\n />\n </svg>\n );\n};\n\nexport type TokenUsageTriggerProps = ComponentProps<typeof Button>;\n\nexport const TokenUsageTrigger = ({ children, ...props }: TokenUsageTriggerProps) => {\n const { formatNumber } = useLocale();\n const { usedTokens, maxTokens } = useTokenUsageValue();\n const usedPercent = usedTokens / maxTokens;\n const renderedPercent = formatNumber(usedPercent, {\n maximumFractionDigits: 1,\n style: \"percent\",\n });\n\n return (\n <HoverCardTrigger asChild>\n {children ?? (\n <Button type=\"button\" variant=\"ghost\" {...props}>\n <span className=\"font-medium text-muted-foreground\">{renderedPercent}</span>\n <TokenUsageIcon />\n </Button>\n )}\n </HoverCardTrigger>\n );\n};\n\nexport type TokenUsageContentProps = ComponentProps<typeof HoverCardContent>;\n\nexport const TokenUsageContent = ({ className, ...props }: TokenUsageContentProps) => (\n <HoverCardContent className={cn(\"min-w-60 divide-y overflow-hidden p-0\", className)} {...props} />\n);\n\nexport type TokenUsageContentHeaderProps = ComponentProps<\"div\">;\n\nexport const TokenUsageContentHeader = ({\n children,\n className,\n ...props\n}: TokenUsageContentHeaderProps) => {\n const { formatNumber } = useLocale();\n const { usedTokens, maxTokens } = useTokenUsageValue();\n const usedPercent = usedTokens / maxTokens;\n const displayPct = formatNumber(usedPercent, {\n maximumFractionDigits: 1,\n style: \"percent\",\n });\n const used = formatNumber(usedTokens, {\n notation: \"compact\",\n });\n const total = formatNumber(maxTokens, {\n notation: \"compact\",\n });\n\n return (\n <div className={cn(\"w-full space-y-2 p-3\", className)} {...props}>\n {children ?? (\n <>\n <div className=\"flex items-center justify-between gap-3 text-meta\">\n <p>{displayPct}</p>\n <p className=\"font-mono text-muted-foreground\">\n {used} / {total}\n </p>\n </div>\n <div className=\"space-y-2\">\n <Progress className=\"bg-muted\" value={usedPercent * PERCENT_MAX} />\n </div>\n </>\n )}\n </div>\n );\n};\n\nexport type TokenUsageContentBodyProps = ComponentProps<\"div\">;\n\nexport const TokenUsageContentBody = ({\n children,\n className,\n ...props\n}: TokenUsageContentBodyProps) => (\n <div className={cn(\"w-full p-3\", className)} {...props}>\n {children}\n </div>\n);\n\nexport type TokenUsageContentFooterProps = ComponentProps<\"div\">;\n\nexport const TokenUsageContentFooter = ({\n children,\n className,\n ...props\n}: TokenUsageContentFooterProps) => {\n const { formatNumber, t } = useLocale();\n const { modelId, usage } = useTokenUsageValue();\n const costUSD = modelId\n ? getUsage({\n modelId,\n usage: {\n input: usage?.inputTokens ?? 0,\n output: usage?.outputTokens ?? 0,\n },\n }).costUSD?.totalUSD\n : undefined;\n const totalCost = formatNumber(costUSD ?? 0, {\n currency: \"USD\",\n style: \"currency\",\n });\n\n return (\n <div\n className={cn(\n \"flex w-full items-center justify-between gap-3 bg-secondary p-3 text-meta\",\n className,\n )}\n {...props}\n >\n {children ?? (\n <>\n <span className=\"text-muted-foreground\">{t(\"ai.tokenUsage.totalCost\")}</span>\n <span>{totalCost}</span>\n </>\n )}\n </div>\n );\n};\n\nconst TokensWithCost = ({ tokens, costText }: { tokens?: number; costText?: string }) => {\n const { formatNumber } = useLocale();\n return (\n <span>\n {tokens === undefined ? \"—\" : formatNumber(tokens, { notation: \"compact\" })}\n {costText ? <span className=\"ms-2 text-muted-foreground\">• {costText}</span> : null}\n </span>\n );\n};\n\nexport type TokenUsageInputProps = ComponentProps<\"div\">;\n\nexport const TokenUsageInput = ({ className, children, ...props }: TokenUsageInputProps) => {\n const { formatNumber, t } = useLocale();\n const { usage, modelId } = useTokenUsageValue();\n const inputTokens = usage?.inputTokens ?? 0;\n\n if (children) {\n return children;\n }\n\n if (!inputTokens) {\n return null;\n }\n\n const inputCost = modelId\n ? getUsage({\n modelId,\n usage: { input: inputTokens, output: 0 },\n }).costUSD?.totalUSD\n : undefined;\n const inputCostText = formatNumber(inputCost ?? 0, {\n currency: \"USD\",\n style: \"currency\",\n });\n\n return (\n <div className={cn(\"flex items-center justify-between text-meta\", className)} {...props}>\n <span className=\"text-muted-foreground\">{t(\"ai.tokenUsage.input\")}</span>\n <TokensWithCost costText={inputCostText} tokens={inputTokens} />\n </div>\n );\n};\n\nexport type TokenUsageOutputProps = ComponentProps<\"div\">;\n\nexport const TokenUsageOutput = ({ className, children, ...props }: TokenUsageOutputProps) => {\n const { formatNumber, t } = useLocale();\n const { usage, modelId } = useTokenUsageValue();\n const outputTokens = usage?.outputTokens ?? 0;\n\n if (children) {\n return children;\n }\n\n if (!outputTokens) {\n return null;\n }\n\n const outputCost = modelId\n ? getUsage({\n modelId,\n usage: { input: 0, output: outputTokens },\n }).costUSD?.totalUSD\n : undefined;\n const outputCostText = formatNumber(outputCost ?? 0, {\n currency: \"USD\",\n style: \"currency\",\n });\n\n return (\n <div className={cn(\"flex items-center justify-between text-meta\", className)} {...props}>\n <span className=\"text-muted-foreground\">{t(\"ai.tokenUsage.output\")}</span>\n <TokensWithCost costText={outputCostText} tokens={outputTokens} />\n </div>\n );\n};\n\nexport type TokenUsageReasoningProps = ComponentProps<\"div\">;\n\nexport const TokenUsageReasoning = ({\n className,\n children,\n ...props\n}: TokenUsageReasoningProps) => {\n const { formatNumber, t } = useLocale();\n const { usage, modelId } = useTokenUsageValue();\n // `reasoningTokens` moved under `outputTokenDetails` in ai@7 (the flat,\n // deprecated top-level alias from ai@6 was removed).\n const reasoningTokens = usage?.outputTokenDetails?.reasoningTokens ?? 0;\n\n if (children) {\n return children;\n }\n\n if (!reasoningTokens) {\n return null;\n }\n\n const reasoningCost = modelId\n ? getUsage({\n modelId,\n usage: { reasoningTokens },\n }).costUSD?.totalUSD\n : undefined;\n const reasoningCostText = formatNumber(reasoningCost ?? 0, {\n currency: \"USD\",\n style: \"currency\",\n });\n\n return (\n <div className={cn(\"flex items-center justify-between text-meta\", className)} {...props}>\n <span className=\"text-muted-foreground\">{t(\"ai.tokenUsage.reasoning\")}</span>\n <TokensWithCost costText={reasoningCostText} tokens={reasoningTokens} />\n </div>\n );\n};\n\nexport type TokenUsageCacheProps = ComponentProps<\"div\">;\n\nexport const TokenUsageCache = ({ className, children, ...props }: TokenUsageCacheProps) => {\n const { formatNumber, t } = useLocale();\n const { usage, modelId } = useTokenUsageValue();\n // `cachedInputTokens` moved under `inputTokenDetails.cacheReadTokens` in\n // ai@7 (the flat, deprecated top-level alias from ai@6 was removed).\n const cacheTokens = usage?.inputTokenDetails?.cacheReadTokens ?? 0;\n\n if (children) {\n return children;\n }\n\n if (!cacheTokens) {\n return null;\n }\n\n const cacheCost = modelId\n ? getUsage({\n modelId,\n usage: { cacheReads: cacheTokens, input: 0, output: 0 },\n }).costUSD?.totalUSD\n : undefined;\n const cacheCostText = formatNumber(cacheCost ?? 0, {\n currency: \"USD\",\n style: \"currency\",\n });\n\n return (\n <div className={cn(\"flex items-center justify-between text-meta\", className)} {...props}>\n <span className=\"text-muted-foreground\">{t(\"ai.tokenUsage.cache\")}</span>\n <TokensWithCost costText={cacheCostText} tokens={cacheTokens} />\n </div>\n );\n};\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/prompt-input-effort.tsx
|
|
4
|
+
import { forwardRef } from "react";
|
|
5
|
+
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
6
|
+
import {
|
|
7
|
+
RadioGroup,
|
|
8
|
+
RadioGroupItem,
|
|
9
|
+
cn,
|
|
10
|
+
effortRungForIndex
|
|
11
|
+
} from "@elabs-ai/components-ui";
|
|
12
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
13
|
+
var PromptInputEffort = forwardRef(
|
|
14
|
+
function PromptInputEffort2({ levels, value, onValueChange, className, "aria-label": ariaLabel, ...props }, ref) {
|
|
15
|
+
const [selected, setSelected] = useControllableState({
|
|
16
|
+
defaultProp: levels[0]?.id ?? "",
|
|
17
|
+
onChange: onValueChange,
|
|
18
|
+
prop: value
|
|
19
|
+
});
|
|
20
|
+
const handleChange = (next) => {
|
|
21
|
+
if (!next) return;
|
|
22
|
+
setSelected(next);
|
|
23
|
+
};
|
|
24
|
+
const currentIndex = levels.findIndex((level) => level.id === selected);
|
|
25
|
+
const current = currentIndex >= 0 ? levels[currentIndex] : levels[0];
|
|
26
|
+
return /* @__PURE__ */ jsxs(
|
|
27
|
+
"div",
|
|
28
|
+
{
|
|
29
|
+
ref,
|
|
30
|
+
"data-slot": "prompt-input-effort",
|
|
31
|
+
className: cn("inline-flex items-center gap-2", className),
|
|
32
|
+
...props,
|
|
33
|
+
children: [
|
|
34
|
+
/* @__PURE__ */ jsx(
|
|
35
|
+
RadioGroup,
|
|
36
|
+
{
|
|
37
|
+
value: selected,
|
|
38
|
+
onValueChange: handleChange,
|
|
39
|
+
orientation: "horizontal",
|
|
40
|
+
"aria-label": ariaLabel,
|
|
41
|
+
"data-slot": "prompt-input-effort-scale",
|
|
42
|
+
className: "flex items-end gap-1",
|
|
43
|
+
children: levels.map((level, index) => {
|
|
44
|
+
const filled = currentIndex >= 0 && index <= currentIndex;
|
|
45
|
+
return (
|
|
46
|
+
// The visible bar (`-visual`) and the click/tap/focus target
|
|
47
|
+
// (the radio itself) are decoupled (WCAG 2.5.8, #161): the
|
|
48
|
+
// radio's authored size IS the ramp's meaning, so it can't
|
|
49
|
+
// simply grow to 24px without flattening the ramp. Instead the
|
|
50
|
+
// radio is stretched to fill this `size-6` (24px) frame —
|
|
51
|
+
// invisible, but a real >=24x24 hit box — while a separate,
|
|
52
|
+
// `aria-hidden` sibling paints the small bar at its authored
|
|
53
|
+
// `effortRungForIndex` size. Both are bottom-flush + centered
|
|
54
|
+
// so the radio's own checked-state indicator still lands on
|
|
55
|
+
// (and stays invisible against) the visible bar, exactly as
|
|
56
|
+
// when the radio painted the bar directly.
|
|
57
|
+
/* @__PURE__ */ jsxs(
|
|
58
|
+
"span",
|
|
59
|
+
{
|
|
60
|
+
"data-slot": "prompt-input-effort-item-frame",
|
|
61
|
+
className: "relative inline-flex size-6 shrink-0 items-end justify-center",
|
|
62
|
+
children: [
|
|
63
|
+
/* @__PURE__ */ jsx(
|
|
64
|
+
"span",
|
|
65
|
+
{
|
|
66
|
+
"aria-hidden": "true",
|
|
67
|
+
"data-slot": "prompt-input-effort-item-visual",
|
|
68
|
+
className: cn(
|
|
69
|
+
effortRungForIndex(index, levels.length),
|
|
70
|
+
"rounded-sm border",
|
|
71
|
+
filled ? "border-primary bg-primary" : "border-border-strong bg-transparent"
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
),
|
|
75
|
+
/* @__PURE__ */ jsx(
|
|
76
|
+
RadioGroupItem,
|
|
77
|
+
{
|
|
78
|
+
value: level.id,
|
|
79
|
+
"aria-label": level.label,
|
|
80
|
+
"data-slot": "prompt-input-effort-item",
|
|
81
|
+
"data-filled": filled ? "true" : "false",
|
|
82
|
+
className: "absolute inset-0 flex size-full items-end justify-center rounded-sm border-0 bg-transparent p-0 shadow-none"
|
|
83
|
+
}
|
|
84
|
+
)
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
level.id
|
|
88
|
+
)
|
|
89
|
+
);
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
),
|
|
93
|
+
/* @__PURE__ */ jsx("span", { className: "text-body", "data-slot": "prompt-input-effort-label", children: current?.label })
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
export {
|
|
101
|
+
PromptInputEffort
|
|
102
|
+
};
|
|
103
|
+
//# sourceMappingURL=chunk-P6YJAZFG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/prompt-input-effort.tsx"],"sourcesContent":["\"use client\";\n\nimport { forwardRef, type HTMLAttributes } from \"react\";\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport {\n RadioGroup,\n RadioGroupItem,\n cn,\n effortRungForIndex,\n type EffortLevel,\n} from \"@elabs-ai/components-ui\";\n\n// `EffortLevel` and the growing-square size ramp (`effortRungForIndex`,\n// formerly this file's private `SIZE_RUNGS`/`rungForIndex`) moved to\n// `@elabs-ai/components-ui` (`lib/operating-mode.ts`) — the terminal CLI\n// look-alike family's own effort chips (issue #117) reuse the same\n// vocabulary shape, and `@elabs-ai/components-ai`/\n// `@elabs-ai/components-terminal` are layer-2 DAG siblings that may not\n// import each other (T0; see\n// docs/decisions/2026-09-01-brainless-adoption-architecture.md § 4). Imported\n// above; NOT re-exported from here — a consumer imports `EffortLevel` from\n// `@elabs-ai/components-ui`.\n\nexport type PromptInputEffortProps = Omit<HTMLAttributes<HTMLDivElement>, \"onChange\"> & {\n /** Ordered low → high. The order IS the semantics — render in this order. */\n levels: EffortLevel[];\n /** Controlled selected level id. Omit for the uncontrolled default (`levels[0]`). */\n value?: string;\n /** Fires with the chosen level's id. */\n onValueChange?: (id: string) => void;\n /**\n * Accessible name for the whole scale (e.g. \"Reasoning effort\", \"Thinking\n * budget\") — required because the NAME of the scale is as much the\n * consumer's vocabulary as its levels are; this component has no default\n * to fall back to.\n */\n \"aria-label\": string;\n};\n\n/**\n * PromptInputEffort — an ORDERED reasoning-effort/budget control.\n *\n * Renders `levels` as a row of same-shape squares that GROW in size, low to\n * high — the size ramp encodes the order on its own, before any selection is\n * made. Selecting a level fills every square up to and including it (solid\n * fill + coloured border) and leaves the rest hollow (outline only): the\n * indicator's FILL is the second, non-colour channel required by a\n * greyscale-legibility read — the size ramp and the solid/hollow shape both\n * survive a greyscale render, so the level is recoverable without colour.\n * The current level's name is additionally rendered as text.\n *\n * Built on Radix (`RadioGroup`/`RadioGroupItem` from `@elabs-ai/components-ui`,\n * `role=\"radiogroup\"` of `role=\"radio\"`s) for arrow-key navigation, roving\n * focus and an accessible-name announcement on the checked item — no\n * hand-rolled key handling.\n */\nexport const PromptInputEffort = forwardRef<HTMLDivElement, PromptInputEffortProps>(\n function PromptInputEffort(\n { levels, value, onValueChange, className, \"aria-label\": ariaLabel, ...props },\n ref,\n ) {\n const [selected, setSelected] = useControllableState<string>({\n defaultProp: levels[0]?.id ?? \"\",\n onChange: onValueChange,\n prop: value,\n });\n\n const handleChange = (next: string) => {\n if (!next) return;\n setSelected(next);\n };\n\n const currentIndex = levels.findIndex((level) => level.id === selected);\n const current = currentIndex >= 0 ? levels[currentIndex] : levels[0];\n\n return (\n <div\n ref={ref}\n data-slot=\"prompt-input-effort\"\n className={cn(\"inline-flex items-center gap-2\", className)}\n {...props}\n >\n <RadioGroup\n value={selected}\n onValueChange={handleChange}\n orientation=\"horizontal\"\n aria-label={ariaLabel}\n data-slot=\"prompt-input-effort-scale\"\n className=\"flex items-end gap-1\"\n >\n {levels.map((level, index) => {\n const filled = currentIndex >= 0 && index <= currentIndex;\n return (\n // The visible bar (`-visual`) and the click/tap/focus target\n // (the radio itself) are decoupled (WCAG 2.5.8, #161): the\n // radio's authored size IS the ramp's meaning, so it can't\n // simply grow to 24px without flattening the ramp. Instead the\n // radio is stretched to fill this `size-6` (24px) frame —\n // invisible, but a real >=24x24 hit box — while a separate,\n // `aria-hidden` sibling paints the small bar at its authored\n // `effortRungForIndex` size. Both are bottom-flush + centered\n // so the radio's own checked-state indicator still lands on\n // (and stays invisible against) the visible bar, exactly as\n // when the radio painted the bar directly.\n <span\n key={level.id}\n data-slot=\"prompt-input-effort-item-frame\"\n className=\"relative inline-flex size-6 shrink-0 items-end justify-center\"\n >\n <span\n aria-hidden=\"true\"\n data-slot=\"prompt-input-effort-item-visual\"\n className={cn(\n effortRungForIndex(index, levels.length),\n \"rounded-sm border\",\n filled ? \"border-primary bg-primary\" : \"border-border-strong bg-transparent\",\n )}\n />\n <RadioGroupItem\n value={level.id}\n aria-label={level.label}\n data-slot=\"prompt-input-effort-item\"\n data-filled={filled ? \"true\" : \"false\"}\n className=\"absolute inset-0 flex size-full items-end justify-center rounded-sm border-0 bg-transparent p-0 shadow-none\"\n />\n </span>\n );\n })}\n </RadioGroup>\n <span className=\"text-body\" data-slot=\"prompt-input-effort-label\">\n {current?.label}\n </span>\n </div>\n );\n },\n);\n"],"mappings":";;;AAEA,SAAS,kBAAuC;AAChD,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AA8FO,SAKE,KALF;AAhDP,IAAM,oBAAoB;AAAA,EAC/B,SAASA,mBACP,EAAE,QAAQ,OAAO,eAAe,WAAW,cAAc,WAAW,GAAG,MAAM,GAC7E,KACA;AACA,UAAM,CAAC,UAAU,WAAW,IAAI,qBAA6B;AAAA,MAC3D,aAAa,OAAO,CAAC,GAAG,MAAM;AAAA,MAC9B,UAAU;AAAA,MACV,MAAM;AAAA,IACR,CAAC;AAED,UAAM,eAAe,CAAC,SAAiB;AACrC,UAAI,CAAC,KAAM;AACX,kBAAY,IAAI;AAAA,IAClB;AAEA,UAAM,eAAe,OAAO,UAAU,CAAC,UAAU,MAAM,OAAO,QAAQ;AACtE,UAAM,UAAU,gBAAgB,IAAI,OAAO,YAAY,IAAI,OAAO,CAAC;AAEnE,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,aAAU;AAAA,QACV,WAAW,GAAG,kCAAkC,SAAS;AAAA,QACxD,GAAG;AAAA,QAEJ;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,cACP,eAAe;AAAA,cACf,aAAY;AAAA,cACZ,cAAY;AAAA,cACZ,aAAU;AAAA,cACV,WAAU;AAAA,cAET,iBAAO,IAAI,CAAC,OAAO,UAAU;AAC5B,sBAAM,SAAS,gBAAgB,KAAK,SAAS;AAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAYE;AAAA,oBAAC;AAAA;AAAA,sBAEC,aAAU;AAAA,sBACV,WAAU;AAAA,sBAEV;AAAA;AAAA,0BAAC;AAAA;AAAA,4BACC,eAAY;AAAA,4BACZ,aAAU;AAAA,4BACV,WAAW;AAAA,8BACT,mBAAmB,OAAO,OAAO,MAAM;AAAA,8BACvC;AAAA,8BACA,SAAS,8BAA8B;AAAA,4BACzC;AAAA;AAAA,wBACF;AAAA,wBACA;AAAA,0BAAC;AAAA;AAAA,4BACC,OAAO,MAAM;AAAA,4BACb,cAAY,MAAM;AAAA,4BAClB,aAAU;AAAA,4BACV,eAAa,SAAS,SAAS;AAAA,4BAC/B,WAAU;AAAA;AAAA,wBACZ;AAAA;AAAA;AAAA,oBAnBK,MAAM;AAAA,kBAoBb;AAAA;AAAA,cAEJ,CAAC;AAAA;AAAA,UACH;AAAA,UACA,oBAAC,UAAK,WAAU,aAAY,aAAU,6BACnC,mBAAS,OACZ;AAAA;AAAA;AAAA,IACF;AAAA,EAEJ;AACF;","names":["PromptInputEffort"]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/_lazy-mermaid.ts
|
|
4
|
+
var DEFAULT_CONFIG = {
|
|
5
|
+
fontFamily: "monospace",
|
|
6
|
+
securityLevel: "strict",
|
|
7
|
+
startOnLoad: false,
|
|
8
|
+
suppressErrorRendering: true,
|
|
9
|
+
theme: "default"
|
|
10
|
+
};
|
|
11
|
+
var enginePromise;
|
|
12
|
+
var loadEngine = () => {
|
|
13
|
+
enginePromise ??= import("mermaid").then((m) => {
|
|
14
|
+
const engine = m.default;
|
|
15
|
+
if (typeof engine?.initialize !== "function" || typeof engine?.render !== "function") {
|
|
16
|
+
throw new Error("Cannot find module 'mermaid'");
|
|
17
|
+
}
|
|
18
|
+
return engine;
|
|
19
|
+
});
|
|
20
|
+
return enginePromise;
|
|
21
|
+
};
|
|
22
|
+
var preloadMermaid = () => {
|
|
23
|
+
void loadEngine();
|
|
24
|
+
};
|
|
25
|
+
var createLazyMermaidPlugin = (options = {}) => {
|
|
26
|
+
let initialized = false;
|
|
27
|
+
let config = { ...DEFAULT_CONFIG, ...options.config };
|
|
28
|
+
const instance = {
|
|
29
|
+
// Upstream calls `mermaid.initialize` synchronously here. We can't (the
|
|
30
|
+
// engine may not have loaded yet), so record the config and apply it inside
|
|
31
|
+
// `render`, which is the only place it can matter — Streamdown always calls
|
|
32
|
+
// `getMermaid()` immediately before awaiting `render()`.
|
|
33
|
+
initialize(next) {
|
|
34
|
+
config = { ...DEFAULT_CONFIG, ...options.config, ...next };
|
|
35
|
+
initialized = false;
|
|
36
|
+
},
|
|
37
|
+
async render(id, source) {
|
|
38
|
+
const engine = await loadEngine();
|
|
39
|
+
if (!initialized) {
|
|
40
|
+
engine.initialize(config);
|
|
41
|
+
initialized = true;
|
|
42
|
+
}
|
|
43
|
+
return engine.render(id, source);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
getMermaid(next) {
|
|
48
|
+
if (next) {
|
|
49
|
+
instance.initialize(next);
|
|
50
|
+
}
|
|
51
|
+
return instance;
|
|
52
|
+
},
|
|
53
|
+
language: "mermaid",
|
|
54
|
+
name: "mermaid",
|
|
55
|
+
type: "diagram"
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
var lazyMermaid = createLazyMermaidPlugin();
|
|
59
|
+
|
|
60
|
+
export {
|
|
61
|
+
preloadMermaid,
|
|
62
|
+
createLazyMermaidPlugin,
|
|
63
|
+
lazyMermaid
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=chunk-PG7ERDOD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/_lazy-mermaid.ts"],"sourcesContent":["/**\n * A drop-in replacement for `@streamdown/mermaid`'s `mermaid` plugin that loads\n * the Mermaid engine **on first diagram render** instead of at import time.\n *\n * Why this exists\n * ---------------\n * `@streamdown/mermaid`'s dist opens with a static `import n from \"mermaid\"`, and\n * neither it nor `mermaid`/`dompurify`/`d3` declares `sideEffects`, so a bundler\n * must keep the whole edge. `@elabs-ai/components-ai` imported that plugin from three modules\n * (`message`, `reasoning`, `markdown-view`), which put Mermaid + d3 + DOMPurify —\n * several MB — in the **entry chunk** of every consumer, including the vast\n * majority that never render a diagram.\n *\n * How it avoids a render flash\n * ----------------------------\n * `DiagramPlugin` is not the engine; it is a lazy accessor. Streamdown calls\n * `getMermaid()` only from inside its async diagram-render path (immediately\n * before `await instance.render(...)`), never at module or component init. So the\n * plugin object can be present from the very first frame — Streamdown always\n * treats a ```mermaid fence as a diagram — while the engine itself arrives with a\n * dynamic import inside `render()`. No content-sniffing, no plugin swap, no\n * suspense seam at the call sites, and no \"raw source flashes then becomes a\n * diagram\" transition.\n *\n * The upstream plugin is ~10 lines; its defaults and initialize-once semantics\n * are mirrored exactly below. The `DiagramPlugin` type is still imported (as a\n * type, so it erases) from `@streamdown/mermaid`, which keeps this honest against\n * the real contract at typecheck time.\n */\nimport type { DiagramPlugin, MermaidConfig, MermaidInstance } from \"@streamdown/mermaid\";\n\n/** Mirrors `@streamdown/mermaid`'s defaults — notably `securityLevel: \"strict\"`. */\nconst DEFAULT_CONFIG: MermaidConfig = {\n fontFamily: \"monospace\",\n securityLevel: \"strict\",\n startOnLoad: false,\n suppressErrorRendering: true,\n theme: \"default\",\n};\n\ntype MermaidModule = {\n initialize: (config: MermaidConfig) => void;\n render: (id: string, source: string) => Promise<{ svg: string }>;\n};\n\n/**\n * Module-level singleton: the engine is fetched at most once per app, however\n * many diagrams or Streamdown instances render.\n */\nlet enginePromise: Promise<MermaidModule> | undefined;\n\nconst loadEngine = (): Promise<MermaidModule> => {\n enginePromise ??= import(\"mermaid\").then((m) => {\n const engine = m.default as unknown as MermaidModule;\n // `mermaid` is an optional peer (issue #33), but its bytes are always\n // installed anyway: TWO of this package's own plain dependencies —\n // `streamdown` and `@streamdown/mermaid` — each declare `mermaid` as\n // their own plain, non-optional dependency (issue #94,\n // `pnpm optional-peers:check` proves and tracks this). So a hoisting\n // package manager (pnpm's default `node-linker=isolated` included, via\n // phantom resolution through the virtual store) may still make the real\n // bytes resolve even when a consumer never installed `mermaid`\n // themselves — this guard does not cover that case, only a bundler\n // whose optional-peer handling substitutes an EMPTY module (Vite's\n // production stub is `export default {}`) once the peer is genuinely\n // absent from the resolved tree. Without this guard that empty object\n // resolves successfully and the crash lands one call later, on\n // `engine.initialize is not a function` — a message\n // `isModuleNotFoundMessage` does not recognize, so it reaches the user\n // as \"Diagram couldn't be drawn\" with a Retry button that can never\n // succeed, instead of the actionable capability-gap panel.\n if (typeof engine?.initialize !== \"function\" || typeof engine?.render !== \"function\") {\n throw new Error(\"Cannot find module 'mermaid'\");\n }\n return engine;\n });\n return enginePromise;\n};\n\n/**\n * Start fetching the Mermaid engine ahead of time.\n *\n * Optional. Call it when you already know the surface will render diagrams (on\n * route entry, or when a conversation is known to contain them) so the first\n * diagram doesn't pay the import latency. Safe to call repeatedly; safe to\n * ignore — rendering a diagram loads the engine either way.\n */\nexport const preloadMermaid = (): void => {\n void loadEngine();\n};\n\n/**\n * Create a lazy Mermaid diagram plugin for Streamdown.\n *\n * @param options.config Mermaid config merged over the brand defaults.\n */\nexport const createLazyMermaidPlugin = (\n options: { config?: MermaidConfig } = {},\n): DiagramPlugin => {\n let initialized = false;\n let config: MermaidConfig = { ...DEFAULT_CONFIG, ...options.config };\n\n const instance: MermaidInstance = {\n // Upstream calls `mermaid.initialize` synchronously here. We can't (the\n // engine may not have loaded yet), so record the config and apply it inside\n // `render`, which is the only place it can matter — Streamdown always calls\n // `getMermaid()` immediately before awaiting `render()`.\n initialize(next: MermaidConfig) {\n config = { ...DEFAULT_CONFIG, ...options.config, ...next };\n initialized = false;\n },\n async render(id: string, source: string) {\n const engine = await loadEngine();\n if (!initialized) {\n engine.initialize(config);\n initialized = true;\n }\n return engine.render(id, source);\n },\n };\n\n return {\n getMermaid(next?: MermaidConfig) {\n if (next) {\n instance.initialize(next);\n }\n return instance;\n },\n language: \"mermaid\",\n name: \"mermaid\",\n type: \"diagram\",\n };\n};\n\n/**\n * The shared lazy Mermaid plugin — the `@elabs-ai/components-ai` replacement for\n * `@streamdown/mermaid`'s eager `mermaid` export. One instance for the whole\n * app, so the engine and its initialize-once state are shared.\n */\nexport const lazyMermaid: DiagramPlugin = createLazyMermaidPlugin();\n"],"mappings":";;;AAgCA,IAAM,iBAAgC;AAAA,EACpC,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,aAAa;AAAA,EACb,wBAAwB;AAAA,EACxB,OAAO;AACT;AAWA,IAAI;AAEJ,IAAM,aAAa,MAA8B;AAC/C,oBAAkB,OAAO,SAAS,EAAE,KAAK,CAAC,MAAM;AAC9C,UAAM,SAAS,EAAE;AAkBjB,QAAI,OAAO,QAAQ,eAAe,cAAc,OAAO,QAAQ,WAAW,YAAY;AACpF,YAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AACA,WAAO;AAAA,EACT,CAAC;AACD,SAAO;AACT;AAUO,IAAM,iBAAiB,MAAY;AACxC,OAAK,WAAW;AAClB;AAOO,IAAM,0BAA0B,CACrC,UAAsC,CAAC,MACrB;AAClB,MAAI,cAAc;AAClB,MAAI,SAAwB,EAAE,GAAG,gBAAgB,GAAG,QAAQ,OAAO;AAEnE,QAAM,WAA4B;AAAA;AAAA;AAAA;AAAA;AAAA,IAKhC,WAAW,MAAqB;AAC9B,eAAS,EAAE,GAAG,gBAAgB,GAAG,QAAQ,QAAQ,GAAG,KAAK;AACzD,oBAAc;AAAA,IAChB;AAAA,IACA,MAAM,OAAO,IAAY,QAAgB;AACvC,YAAM,SAAS,MAAM,WAAW;AAChC,UAAI,CAAC,aAAa;AAChB,eAAO,WAAW,MAAM;AACxB,sBAAc;AAAA,MAChB;AACA,aAAO,OAAO,OAAO,IAAI,MAAM;AAAA,IACjC;AAAA,EACF;AAEA,SAAO;AAAA,IACL,WAAW,MAAsB;AAC/B,UAAI,MAAM;AACR,iBAAS,WAAW,IAAI;AAAA,MAC1B;AACA,aAAO;AAAA,IACT;AAAA,IACA,UAAU;AAAA,IACV,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AACF;AAOO,IAAM,cAA6B,wBAAwB;","names":[]}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/transcription.tsx
|
|
4
|
+
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
5
|
+
import { cn } from "@elabs-ai/components-ui/lib/cn";
|
|
6
|
+
import { createContext, useCallback, useContext, useMemo } from "react";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
var TranscriptionContext = createContext(null);
|
|
9
|
+
var useTranscription = () => {
|
|
10
|
+
const context = useContext(TranscriptionContext);
|
|
11
|
+
if (!context) {
|
|
12
|
+
throw new Error("Transcription components must be used within Transcription");
|
|
13
|
+
}
|
|
14
|
+
return context;
|
|
15
|
+
};
|
|
16
|
+
var Transcription = ({
|
|
17
|
+
segments,
|
|
18
|
+
currentTime: externalCurrentTime,
|
|
19
|
+
onSeek,
|
|
20
|
+
className,
|
|
21
|
+
children,
|
|
22
|
+
...props
|
|
23
|
+
}) => {
|
|
24
|
+
const [currentTime, setCurrentTime] = useControllableState({
|
|
25
|
+
defaultProp: 0,
|
|
26
|
+
onChange: onSeek,
|
|
27
|
+
prop: externalCurrentTime
|
|
28
|
+
});
|
|
29
|
+
const contextValue = useMemo(
|
|
30
|
+
() => ({ currentTime, onSeek, onTimeUpdate: setCurrentTime, segments }),
|
|
31
|
+
[currentTime, onSeek, setCurrentTime, segments]
|
|
32
|
+
);
|
|
33
|
+
return /* @__PURE__ */ jsx(TranscriptionContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
|
|
34
|
+
"div",
|
|
35
|
+
{
|
|
36
|
+
className: cn("flex flex-wrap gap-1 text-body leading-relaxed", className),
|
|
37
|
+
"data-slot": "transcription",
|
|
38
|
+
...props,
|
|
39
|
+
children: segments.filter((segment) => segment.text.trim()).map((segment, index) => children(segment, index))
|
|
40
|
+
}
|
|
41
|
+
) });
|
|
42
|
+
};
|
|
43
|
+
var TranscriptionSegment = ({
|
|
44
|
+
segment,
|
|
45
|
+
index,
|
|
46
|
+
className,
|
|
47
|
+
onClick,
|
|
48
|
+
...props
|
|
49
|
+
}) => {
|
|
50
|
+
const { currentTime, onSeek } = useTranscription();
|
|
51
|
+
const isActive = currentTime >= segment.startSecond && currentTime < segment.endSecond;
|
|
52
|
+
const isPast = currentTime >= segment.endSecond;
|
|
53
|
+
const handleClick = useCallback(
|
|
54
|
+
(event) => {
|
|
55
|
+
if (onSeek) {
|
|
56
|
+
onSeek(segment.startSecond);
|
|
57
|
+
}
|
|
58
|
+
onClick?.(event);
|
|
59
|
+
},
|
|
60
|
+
[onSeek, segment.startSecond, onClick]
|
|
61
|
+
);
|
|
62
|
+
return /* @__PURE__ */ jsx(
|
|
63
|
+
"button",
|
|
64
|
+
{
|
|
65
|
+
className: cn(
|
|
66
|
+
"inline text-start",
|
|
67
|
+
// #399 — the active word is transcript TEXT: `-text` rung, not the fill.
|
|
68
|
+
isActive && "text-primary-text",
|
|
69
|
+
isPast && "text-muted-foreground",
|
|
70
|
+
!(isActive || isPast) && "text-muted-foreground/60",
|
|
71
|
+
onSeek && "cursor-pointer hover:text-foreground",
|
|
72
|
+
!onSeek && "cursor-default",
|
|
73
|
+
className
|
|
74
|
+
),
|
|
75
|
+
"data-active": isActive,
|
|
76
|
+
"data-index": index,
|
|
77
|
+
"data-slot": "transcription-segment",
|
|
78
|
+
onClick: handleClick,
|
|
79
|
+
type: "button",
|
|
80
|
+
...props,
|
|
81
|
+
children: segment.text
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export {
|
|
87
|
+
Transcription,
|
|
88
|
+
TranscriptionSegment
|
|
89
|
+
};
|
|
90
|
+
//# sourceMappingURL=chunk-PIB5JBMA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/transcription.tsx"],"sourcesContent":["\"use client\";\n\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport type { Experimental_TranscriptionResult as TranscriptionResult } from \"ai\";\nimport type { ComponentProps, ReactNode } from \"react\";\nimport { createContext, useCallback, useContext, useMemo } from \"react\";\n\ntype TranscriptionSegment = TranscriptionResult[\"segments\"][number];\n\ninterface TranscriptionContextValue {\n segments: TranscriptionSegment[];\n currentTime: number;\n onTimeUpdate: (time: number) => void;\n onSeek?: (time: number) => void;\n}\n\nconst TranscriptionContext = createContext<TranscriptionContextValue | null>(null);\n\nconst useTranscription = () => {\n const context = useContext(TranscriptionContext);\n if (!context) {\n throw new Error(\"Transcription components must be used within Transcription\");\n }\n return context;\n};\n\nexport type TranscriptionProps = Omit<ComponentProps<\"div\">, \"children\"> & {\n segments: TranscriptionSegment[];\n currentTime?: number;\n onSeek?: (time: number) => void;\n children: (segment: TranscriptionSegment, index: number) => ReactNode;\n};\n\nexport const Transcription = ({\n segments,\n currentTime: externalCurrentTime,\n onSeek,\n className,\n children,\n ...props\n}: TranscriptionProps) => {\n const [currentTime, setCurrentTime] = useControllableState({\n defaultProp: 0,\n onChange: onSeek,\n prop: externalCurrentTime,\n });\n\n const contextValue = useMemo(\n () => ({ currentTime, onSeek, onTimeUpdate: setCurrentTime, segments }),\n [currentTime, onSeek, setCurrentTime, segments],\n );\n\n return (\n <TranscriptionContext.Provider value={contextValue}>\n <div\n className={cn(\"flex flex-wrap gap-1 text-body leading-relaxed\", className)}\n data-slot=\"transcription\"\n {...props}\n >\n {segments\n .filter((segment) => segment.text.trim())\n .map((segment, index) => children(segment, index))}\n </div>\n </TranscriptionContext.Provider>\n );\n};\n\nexport type TranscriptionSegmentProps = ComponentProps<\"button\"> & {\n segment: TranscriptionSegment;\n index: number;\n};\n\nexport const TranscriptionSegment = ({\n segment,\n index,\n className,\n onClick,\n ...props\n}: TranscriptionSegmentProps) => {\n const { currentTime, onSeek } = useTranscription();\n\n const isActive = currentTime >= segment.startSecond && currentTime < segment.endSecond;\n const isPast = currentTime >= segment.endSecond;\n\n const handleClick = useCallback(\n (event: React.MouseEvent<HTMLButtonElement>) => {\n if (onSeek) {\n onSeek(segment.startSecond);\n }\n onClick?.(event);\n },\n [onSeek, segment.startSecond, onClick],\n );\n\n return (\n <button\n className={cn(\n \"inline text-start\",\n // #399 — the active word is transcript TEXT: `-text` rung, not the fill.\n isActive && \"text-primary-text\",\n isPast && \"text-muted-foreground\",\n !(isActive || isPast) && \"text-muted-foreground/60\",\n onSeek && \"cursor-pointer hover:text-foreground\",\n !onSeek && \"cursor-default\",\n className,\n )}\n data-active={isActive}\n data-index={index}\n data-slot=\"transcription-segment\"\n onClick={handleClick}\n type=\"button\"\n {...props}\n >\n {segment.text}\n </button>\n );\n};\n"],"mappings":";;;AAEA,SAAS,4BAA4B;AACrC,SAAS,UAAU;AAGnB,SAAS,eAAe,aAAa,YAAY,eAAe;AAiD1D;AAtCN,IAAM,uBAAuB,cAAgD,IAAI;AAEjF,IAAM,mBAAmB,MAAM;AAC7B,QAAM,UAAU,WAAW,oBAAoB;AAC/C,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,4DAA4D;AAAA,EAC9E;AACA,SAAO;AACT;AASO,IAAM,gBAAgB,CAAC;AAAA,EAC5B;AAAA,EACA,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAA0B;AACxB,QAAM,CAAC,aAAa,cAAc,IAAI,qBAAqB;AAAA,IACzD,aAAa;AAAA,IACb,UAAU;AAAA,IACV,MAAM;AAAA,EACR,CAAC;AAED,QAAM,eAAe;AAAA,IACnB,OAAO,EAAE,aAAa,QAAQ,cAAc,gBAAgB,SAAS;AAAA,IACrE,CAAC,aAAa,QAAQ,gBAAgB,QAAQ;AAAA,EAChD;AAEA,SACE,oBAAC,qBAAqB,UAArB,EAA8B,OAAO,cACpC;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,kDAAkD,SAAS;AAAA,MACzE,aAAU;AAAA,MACT,GAAG;AAAA,MAEH,mBACE,OAAO,CAAC,YAAY,QAAQ,KAAK,KAAK,CAAC,EACvC,IAAI,CAAC,SAAS,UAAU,SAAS,SAAS,KAAK,CAAC;AAAA;AAAA,EACrD,GACF;AAEJ;AAOO,IAAM,uBAAuB,CAAC;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAiC;AAC/B,QAAM,EAAE,aAAa,OAAO,IAAI,iBAAiB;AAEjD,QAAM,WAAW,eAAe,QAAQ,eAAe,cAAc,QAAQ;AAC7E,QAAM,SAAS,eAAe,QAAQ;AAEtC,QAAM,cAAc;AAAA,IAClB,CAAC,UAA+C;AAC9C,UAAI,QAAQ;AACV,eAAO,QAAQ,WAAW;AAAA,MAC5B;AACA,gBAAU,KAAK;AAAA,IACjB;AAAA,IACA,CAAC,QAAQ,QAAQ,aAAa,OAAO;AAAA,EACvC;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA;AAAA,QAEA,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,EAAE,YAAY,WAAW;AAAA,QACzB,UAAU;AAAA,QACV,CAAC,UAAU;AAAA,QACX;AAAA,MACF;AAAA,MACA,eAAa;AAAA,MACb,cAAY;AAAA,MACZ,aAAU;AAAA,MACV,SAAS;AAAA,MACT,MAAK;AAAA,MACJ,GAAG;AAAA,MAEH,kBAAQ;AAAA;AAAA,EACX;AAEJ;","names":[]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/motion-config.tsx
|
|
4
|
+
import { useReducedMotion } from "@elabs-ai/components-tokens";
|
|
5
|
+
import { MotionConfig } from "motion/react";
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
var DEFAULT_MOTION_TRANSITION = {
|
|
8
|
+
duration: 0.18,
|
|
9
|
+
ease: [0.2, 0, 0, 1]
|
|
10
|
+
};
|
|
11
|
+
function BrandMotionConfig({
|
|
12
|
+
children,
|
|
13
|
+
transition = DEFAULT_MOTION_TRANSITION
|
|
14
|
+
}) {
|
|
15
|
+
const reducedMotion = useReducedMotion();
|
|
16
|
+
return /* @__PURE__ */ jsx(MotionConfig, { reducedMotion: reducedMotion ? "always" : "never", transition, children });
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export {
|
|
20
|
+
BrandMotionConfig
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=chunk-PQ5BPIWQ.js.map
|