@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,137 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
AgentStep,
|
|
4
|
+
AgentTimeline
|
|
5
|
+
} from "./chunk-UCJ6IUFS.js";
|
|
6
|
+
|
|
7
|
+
// src/chain-of-thought.tsx
|
|
8
|
+
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
9
|
+
import { Badge } from "@elabs-ai/components-ui";
|
|
10
|
+
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@elabs-ai/components-ui";
|
|
11
|
+
import { cn } from "@elabs-ai/components-ui/lib/cn";
|
|
12
|
+
import { BrainIcon, ChevronDownIcon } from "lucide-react";
|
|
13
|
+
import { createContext, memo, useContext, useMemo } from "react";
|
|
14
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
15
|
+
var ChainOfThoughtContext = createContext(null);
|
|
16
|
+
var useChainOfThought = () => {
|
|
17
|
+
const context = useContext(ChainOfThoughtContext);
|
|
18
|
+
if (!context) {
|
|
19
|
+
throw new Error("ChainOfThought components must be used within ChainOfThought");
|
|
20
|
+
}
|
|
21
|
+
return context;
|
|
22
|
+
};
|
|
23
|
+
var ChainOfThought = memo(
|
|
24
|
+
({
|
|
25
|
+
className,
|
|
26
|
+
open,
|
|
27
|
+
defaultOpen = false,
|
|
28
|
+
onOpenChange,
|
|
29
|
+
children,
|
|
30
|
+
...props
|
|
31
|
+
}) => {
|
|
32
|
+
const [isOpen, setIsOpen] = useControllableState({
|
|
33
|
+
defaultProp: defaultOpen,
|
|
34
|
+
onChange: onOpenChange,
|
|
35
|
+
prop: open
|
|
36
|
+
});
|
|
37
|
+
const chainOfThoughtContext = useMemo(() => ({ isOpen, setIsOpen }), [isOpen, setIsOpen]);
|
|
38
|
+
return /* @__PURE__ */ jsx(ChainOfThoughtContext.Provider, { value: chainOfThoughtContext, children: /* @__PURE__ */ jsx("div", { className: cn("not-prose w-full space-y-4", className), ...props, children }) });
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
var ChainOfThoughtHeader = memo(
|
|
42
|
+
({ className, children, ...props }) => {
|
|
43
|
+
const { isOpen, setIsOpen } = useChainOfThought();
|
|
44
|
+
return /* @__PURE__ */ jsx(Collapsible, { onOpenChange: setIsOpen, open: isOpen, children: /* @__PURE__ */ jsxs(
|
|
45
|
+
CollapsibleTrigger,
|
|
46
|
+
{
|
|
47
|
+
className: cn(
|
|
48
|
+
"flex w-full items-center gap-2 text-body text-muted-foreground transition-colors hover:text-foreground",
|
|
49
|
+
className
|
|
50
|
+
),
|
|
51
|
+
...props,
|
|
52
|
+
children: [
|
|
53
|
+
/* @__PURE__ */ jsx(BrainIcon, { className: "size-4" }),
|
|
54
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 text-start", children: children ?? "Chain of Thought" }),
|
|
55
|
+
/* @__PURE__ */ jsx(
|
|
56
|
+
ChevronDownIcon,
|
|
57
|
+
{
|
|
58
|
+
className: cn("size-4 transition-transform", isOpen ? "rotate-180" : "rotate-0")
|
|
59
|
+
}
|
|
60
|
+
)
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
) });
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
var stepStatusToCanonical = {
|
|
67
|
+
active: "running",
|
|
68
|
+
complete: "complete",
|
|
69
|
+
pending: "pending"
|
|
70
|
+
};
|
|
71
|
+
var ChainOfThoughtStep = memo(
|
|
72
|
+
({ label, description, status = "complete", ...props }) => /* @__PURE__ */ jsx(
|
|
73
|
+
AgentStep,
|
|
74
|
+
{
|
|
75
|
+
hideBadge: true,
|
|
76
|
+
name: label,
|
|
77
|
+
status: stepStatusToCanonical[status],
|
|
78
|
+
summary: description,
|
|
79
|
+
...props
|
|
80
|
+
}
|
|
81
|
+
)
|
|
82
|
+
);
|
|
83
|
+
var ChainOfThoughtSearchResults = memo(
|
|
84
|
+
({ className, ...props }) => /* @__PURE__ */ jsx("div", { className: cn("flex flex-wrap items-center gap-2", className), ...props })
|
|
85
|
+
);
|
|
86
|
+
var ChainOfThoughtSearchResult = memo(
|
|
87
|
+
({ className, children, ...props }) => /* @__PURE__ */ jsx(
|
|
88
|
+
Badge,
|
|
89
|
+
{
|
|
90
|
+
className: cn("gap-1 px-2 py-0.5 text-meta font-normal", className),
|
|
91
|
+
variant: "secondary",
|
|
92
|
+
...props,
|
|
93
|
+
children
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
);
|
|
97
|
+
var ChainOfThoughtContent = memo(
|
|
98
|
+
({ className, children, ...props }) => {
|
|
99
|
+
const { isOpen } = useChainOfThought();
|
|
100
|
+
return /* @__PURE__ */ jsx(Collapsible, { open: isOpen, children: /* @__PURE__ */ jsx(
|
|
101
|
+
CollapsibleContent,
|
|
102
|
+
{
|
|
103
|
+
className: cn(
|
|
104
|
+
"mt-2 space-y-3",
|
|
105
|
+
"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-popover-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in data-[state=open]:[--tw-ease:var(--ease-entrance)] data-[state=closed]:[--tw-ease:var(--ease-exit)]",
|
|
106
|
+
className
|
|
107
|
+
),
|
|
108
|
+
...props,
|
|
109
|
+
children: /* @__PURE__ */ jsx(AgentTimeline, { children })
|
|
110
|
+
}
|
|
111
|
+
) });
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
var ChainOfThoughtImage = memo(
|
|
115
|
+
({ className, children, caption, ...props }) => /* @__PURE__ */ jsxs("div", { className: cn("mt-2 space-y-2", className), ...props, children: [
|
|
116
|
+
/* @__PURE__ */ jsx("div", { className: "relative flex max-h-[22rem] items-center justify-center overflow-hidden rounded-lg bg-muted p-3", children }),
|
|
117
|
+
caption && /* @__PURE__ */ jsx("p", { className: "text-meta text-muted-foreground", children: caption })
|
|
118
|
+
] })
|
|
119
|
+
);
|
|
120
|
+
ChainOfThought.displayName = "ChainOfThought";
|
|
121
|
+
ChainOfThoughtHeader.displayName = "ChainOfThoughtHeader";
|
|
122
|
+
ChainOfThoughtStep.displayName = "ChainOfThoughtStep";
|
|
123
|
+
ChainOfThoughtSearchResults.displayName = "ChainOfThoughtSearchResults";
|
|
124
|
+
ChainOfThoughtSearchResult.displayName = "ChainOfThoughtSearchResult";
|
|
125
|
+
ChainOfThoughtContent.displayName = "ChainOfThoughtContent";
|
|
126
|
+
ChainOfThoughtImage.displayName = "ChainOfThoughtImage";
|
|
127
|
+
|
|
128
|
+
export {
|
|
129
|
+
ChainOfThought,
|
|
130
|
+
ChainOfThoughtHeader,
|
|
131
|
+
ChainOfThoughtStep,
|
|
132
|
+
ChainOfThoughtSearchResults,
|
|
133
|
+
ChainOfThoughtSearchResult,
|
|
134
|
+
ChainOfThoughtContent,
|
|
135
|
+
ChainOfThoughtImage
|
|
136
|
+
};
|
|
137
|
+
//# sourceMappingURL=chunk-TCB6O74A.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/chain-of-thought.tsx"],"sourcesContent":["\"use client\";\n\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { Badge, type Status } from \"@elabs-ai/components-ui\";\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { BrainIcon, ChevronDownIcon } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\nimport type { ComponentProps } from \"react\";\nimport { createContext, memo, useContext, useMemo } from \"react\";\n\nimport { AgentStep, AgentTimeline, type AgentStepProps } from \"./agent-timeline\";\n\ninterface ChainOfThoughtContextValue {\n isOpen: boolean;\n setIsOpen: (open: boolean) => void;\n}\n\nconst ChainOfThoughtContext = createContext<ChainOfThoughtContextValue | null>(null);\n\nconst useChainOfThought = () => {\n const context = useContext(ChainOfThoughtContext);\n if (!context) {\n throw new Error(\"ChainOfThought components must be used within ChainOfThought\");\n }\n return context;\n};\n\nexport type ChainOfThoughtProps = ComponentProps<\"div\"> & {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n};\n\nexport const ChainOfThought = memo(\n ({\n className,\n open,\n defaultOpen = false,\n onOpenChange,\n children,\n ...props\n }: ChainOfThoughtProps) => {\n const [isOpen, setIsOpen] = useControllableState({\n defaultProp: defaultOpen,\n onChange: onOpenChange,\n prop: open,\n });\n\n const chainOfThoughtContext = useMemo(() => ({ isOpen, setIsOpen }), [isOpen, setIsOpen]);\n\n return (\n <ChainOfThoughtContext.Provider value={chainOfThoughtContext}>\n <div className={cn(\"not-prose w-full space-y-4\", className)} {...props}>\n {children}\n </div>\n </ChainOfThoughtContext.Provider>\n );\n },\n);\n\nexport type ChainOfThoughtHeaderProps = ComponentProps<typeof CollapsibleTrigger>;\n\nexport const ChainOfThoughtHeader = memo(\n ({ className, children, ...props }: ChainOfThoughtHeaderProps) => {\n const { isOpen, setIsOpen } = useChainOfThought();\n\n return (\n <Collapsible onOpenChange={setIsOpen} open={isOpen}>\n <CollapsibleTrigger\n className={cn(\n \"flex w-full items-center gap-2 text-body text-muted-foreground transition-colors hover:text-foreground\",\n className,\n )}\n {...props}\n >\n <BrainIcon className=\"size-4\" />\n <span className=\"flex-1 text-start\">{children ?? \"Chain of Thought\"}</span>\n <ChevronDownIcon\n className={cn(\"size-4 transition-transform\", isOpen ? \"rotate-180\" : \"rotate-0\")}\n />\n </CollapsibleTrigger>\n </Collapsible>\n );\n },\n);\n\nexport type ChainOfThoughtStepProps = Omit<\n AgentStepProps,\n \"name\" | \"summary\" | \"status\" | \"hideBadge\"\n> & {\n label: ReactNode;\n description?: ReactNode;\n status?: \"complete\" | \"active\" | \"pending\";\n};\n\n/**\n * Step status → the canonical 7-state vocabulary (#189, research 10 §B.1):\n * `active` is a running step.\n */\nconst stepStatusToCanonical: Record<NonNullable<ChainOfThoughtStepProps[\"status\"]>, Status> = {\n active: \"running\",\n complete: \"complete\",\n pending: \"pending\",\n};\n\n/**\n * @deprecated Compose `AgentStep` (agent-timeline.tsx) directly. Since #192\n * this is a thin alias mapping the legacy `label`/`description`/3-state\n * `status` props onto the canonical rail (`AgentTimeline` + `AgentStep`); the\n * pre-#192 hand-rolled connector + text-opacity status idiom is gone\n * (research 10 §B.3). The badge stays hidden here — the rail node carries the\n * status — keeping the quiet prose-rail look.\n */\nexport const ChainOfThoughtStep = memo(\n ({ label, description, status = \"complete\", ...props }: ChainOfThoughtStepProps) => (\n <AgentStep\n hideBadge\n name={label}\n status={stepStatusToCanonical[status]}\n summary={description}\n {...props}\n />\n ),\n);\n\nexport type ChainOfThoughtSearchResultsProps = ComponentProps<\"div\">;\n\nexport const ChainOfThoughtSearchResults = memo(\n ({ className, ...props }: ChainOfThoughtSearchResultsProps) => (\n <div className={cn(\"flex flex-wrap items-center gap-2\", className)} {...props} />\n ),\n);\n\nexport type ChainOfThoughtSearchResultProps = ComponentProps<typeof Badge>;\n\nexport const ChainOfThoughtSearchResult = memo(\n ({ className, children, ...props }: ChainOfThoughtSearchResultProps) => (\n <Badge\n className={cn(\"gap-1 px-2 py-0.5 text-meta font-normal\", className)}\n variant=\"secondary\"\n {...props}\n >\n {children}\n </Badge>\n ),\n);\n\nexport type ChainOfThoughtContentProps = ComponentProps<typeof CollapsibleContent>;\n\nexport const ChainOfThoughtContent = memo(\n ({ className, children, ...props }: ChainOfThoughtContentProps) => {\n const { isOpen } = useChainOfThought();\n\n return (\n <Collapsible open={isOpen}>\n <CollapsibleContent\n className={cn(\n \"mt-2 space-y-3\",\n \"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-popover-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in data-[state=open]:[--tw-ease:var(--ease-entrance)] data-[state=closed]:[--tw-ease:var(--ease-exit)]\",\n className,\n )}\n {...props}\n >\n <AgentTimeline>{children}</AgentTimeline>\n </CollapsibleContent>\n </Collapsible>\n );\n },\n);\n\nexport type ChainOfThoughtImageProps = ComponentProps<\"div\"> & {\n caption?: string;\n};\n\nexport const ChainOfThoughtImage = memo(\n ({ className, children, caption, ...props }: ChainOfThoughtImageProps) => (\n <div className={cn(\"mt-2 space-y-2\", className)} {...props}>\n <div className=\"relative flex max-h-[22rem] items-center justify-center overflow-hidden rounded-lg bg-muted p-3\">\n {children}\n </div>\n {caption && <p className=\"text-meta text-muted-foreground\">{caption}</p>}\n </div>\n ),\n);\n\nChainOfThought.displayName = \"ChainOfThought\";\nChainOfThoughtHeader.displayName = \"ChainOfThoughtHeader\";\nChainOfThoughtStep.displayName = \"ChainOfThoughtStep\";\nChainOfThoughtSearchResults.displayName = \"ChainOfThoughtSearchResults\";\nChainOfThoughtSearchResult.displayName = \"ChainOfThoughtSearchResult\";\nChainOfThoughtContent.displayName = \"ChainOfThoughtContent\";\nChainOfThoughtImage.displayName = \"ChainOfThoughtImage\";\n"],"mappings":";;;;;;;AAEA,SAAS,4BAA4B;AACrC,SAAS,aAA0B;AACnC,SAAS,aAAa,oBAAoB,0BAA0B;AACpE,SAAS,UAAU;AACnB,SAAS,WAAW,uBAAuB;AAG3C,SAAS,eAAe,MAAM,YAAY,eAAe;AA4CjD,cAgBA,YAhBA;AAnCR,IAAM,wBAAwB,cAAiD,IAAI;AAEnF,IAAM,oBAAoB,MAAM;AAC9B,QAAM,UAAU,WAAW,qBAAqB;AAChD,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,8DAA8D;AAAA,EAChF;AACA,SAAO;AACT;AAQO,IAAM,iBAAiB;AAAA,EAC5B,CAAC;AAAA,IACC;AAAA,IACA;AAAA,IACA,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,MAA2B;AACzB,UAAM,CAAC,QAAQ,SAAS,IAAI,qBAAqB;AAAA,MAC/C,aAAa;AAAA,MACb,UAAU;AAAA,MACV,MAAM;AAAA,IACR,CAAC;AAED,UAAM,wBAAwB,QAAQ,OAAO,EAAE,QAAQ,UAAU,IAAI,CAAC,QAAQ,SAAS,CAAC;AAExF,WACE,oBAAC,sBAAsB,UAAtB,EAA+B,OAAO,uBACrC,8BAAC,SAAI,WAAW,GAAG,8BAA8B,SAAS,GAAI,GAAG,OAC9D,UACH,GACF;AAAA,EAEJ;AACF;AAIO,IAAM,uBAAuB;AAAA,EAClC,CAAC,EAAE,WAAW,UAAU,GAAG,MAAM,MAAiC;AAChE,UAAM,EAAE,QAAQ,UAAU,IAAI,kBAAkB;AAEhD,WACE,oBAAC,eAAY,cAAc,WAAW,MAAM,QAC1C;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,UACT;AAAA,UACA;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QAEJ;AAAA,8BAAC,aAAU,WAAU,UAAS;AAAA,UAC9B,oBAAC,UAAK,WAAU,qBAAqB,sBAAY,oBAAmB;AAAA,UACpE;AAAA,YAAC;AAAA;AAAA,cACC,WAAW,GAAG,+BAA+B,SAAS,eAAe,UAAU;AAAA;AAAA,UACjF;AAAA;AAAA;AAAA,IACF,GACF;AAAA,EAEJ;AACF;AAeA,IAAM,wBAAwF;AAAA,EAC5F,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AACX;AAUO,IAAM,qBAAqB;AAAA,EAChC,CAAC,EAAE,OAAO,aAAa,SAAS,YAAY,GAAG,MAAM,MACnD;AAAA,IAAC;AAAA;AAAA,MACC,WAAS;AAAA,MACT,MAAM;AAAA,MACN,QAAQ,sBAAsB,MAAM;AAAA,MACpC,SAAS;AAAA,MACR,GAAG;AAAA;AAAA,EACN;AAEJ;AAIO,IAAM,8BAA8B;AAAA,EACzC,CAAC,EAAE,WAAW,GAAG,MAAM,MACrB,oBAAC,SAAI,WAAW,GAAG,qCAAqC,SAAS,GAAI,GAAG,OAAO;AAEnF;AAIO,IAAM,6BAA6B;AAAA,EACxC,CAAC,EAAE,WAAW,UAAU,GAAG,MAAM,MAC/B;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,2CAA2C,SAAS;AAAA,MAClE,SAAQ;AAAA,MACP,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ;AAIO,IAAM,wBAAwB;AAAA,EACnC,CAAC,EAAE,WAAW,UAAU,GAAG,MAAM,MAAkC;AACjE,UAAM,EAAE,OAAO,IAAI,kBAAkB;AAErC,WACE,oBAAC,eAAY,MAAM,QACjB;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QAEJ,8BAAC,iBAAe,UAAS;AAAA;AAAA,IAC3B,GACF;AAAA,EAEJ;AACF;AAMO,IAAM,sBAAsB;AAAA,EACjC,CAAC,EAAE,WAAW,UAAU,SAAS,GAAG,MAAM,MACxC,qBAAC,SAAI,WAAW,GAAG,kBAAkB,SAAS,GAAI,GAAG,OACnD;AAAA,wBAAC,SAAI,WAAU,mGACZ,UACH;AAAA,IACC,WAAW,oBAAC,OAAE,WAAU,mCAAmC,mBAAQ;AAAA,KACtE;AAEJ;AAEA,eAAe,cAAc;AAC7B,qBAAqB,cAAc;AACnC,mBAAmB,cAAc;AACjC,4BAA4B,cAAc;AAC1C,2BAA2B,cAAc;AACzC,sBAAsB,cAAc;AACpC,oBAAoB,cAAc;","names":[]}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/use-audio-level.ts
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
var DEFAULT_FFT_SIZE = 64;
|
|
6
|
+
var DEFAULT_SMOOTHING_TIME_CONSTANT = 0.6;
|
|
7
|
+
function resolveAudioContextConstructor() {
|
|
8
|
+
if (typeof window === "undefined") return null;
|
|
9
|
+
const w = window;
|
|
10
|
+
return w.AudioContext ?? w.webkitAudioContext ?? null;
|
|
11
|
+
}
|
|
12
|
+
function useAudioLevel(stream, options = {}) {
|
|
13
|
+
const { fftSize = DEFAULT_FFT_SIZE, smoothingTimeConstant = DEFAULT_SMOOTHING_TIME_CONSTANT } = options;
|
|
14
|
+
const [levels, setLevels] = useState([]);
|
|
15
|
+
const [level, setLevel] = useState(0);
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
if (!stream) {
|
|
18
|
+
setLevels([]);
|
|
19
|
+
setLevel(0);
|
|
20
|
+
return void 0;
|
|
21
|
+
}
|
|
22
|
+
const AudioContextConstructor = resolveAudioContextConstructor();
|
|
23
|
+
if (!AudioContextConstructor) {
|
|
24
|
+
return void 0;
|
|
25
|
+
}
|
|
26
|
+
const audioContext = new AudioContextConstructor();
|
|
27
|
+
const source = audioContext.createMediaStreamSource(stream);
|
|
28
|
+
const analyser = audioContext.createAnalyser();
|
|
29
|
+
analyser.fftSize = fftSize;
|
|
30
|
+
analyser.smoothingTimeConstant = smoothingTimeConstant;
|
|
31
|
+
source.connect(analyser);
|
|
32
|
+
const buffer = new Uint8Array(analyser.frequencyBinCount);
|
|
33
|
+
let rafId = 0;
|
|
34
|
+
const tick = () => {
|
|
35
|
+
analyser.getByteFrequencyData(buffer);
|
|
36
|
+
const normalized = Array.from(buffer, (value) => value / 255);
|
|
37
|
+
setLevels(normalized);
|
|
38
|
+
setLevel(normalized.reduce((sum, value) => sum + value, 0) / (normalized.length || 1));
|
|
39
|
+
rafId = requestAnimationFrame(tick);
|
|
40
|
+
};
|
|
41
|
+
rafId = requestAnimationFrame(tick);
|
|
42
|
+
return () => {
|
|
43
|
+
cancelAnimationFrame(rafId);
|
|
44
|
+
source.disconnect();
|
|
45
|
+
analyser.disconnect();
|
|
46
|
+
if (audioContext.state !== "closed") {
|
|
47
|
+
void audioContext.close();
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}, [stream, fftSize, smoothingTimeConstant]);
|
|
51
|
+
return { level, levels };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export {
|
|
55
|
+
useAudioLevel
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=chunk-TTEYPO6X.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/use-audio-level.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\n\n/**\n * The OPT-IN analyser-plumbing hook for `AudioVisualizer` (issue #21). It is a\n * separate export a consumer may ignore entirely — `AudioVisualizer` itself\n * never imports or calls this. brand-ui is a presentation layer (D5): this\n * hook never calls `getUserMedia` and never creates an `AudioContext` until a\n * `MediaStream` the CONSUMER already obtained is actually passed in.\n */\n\nexport interface UseAudioLevelOptions {\n /** `AnalyserNode.fftSize` — controls how many frequency bins `levels` has\n * (`fftSize / 2`). Must be a power of two in [32, 32768]. */\n fftSize?: number;\n /** `AnalyserNode.smoothingTimeConstant` (0–1) — the analyser's OWN frame-to-frame\n * smoothing, independent of `AudioVisualizer`'s reduced-motion smoothing. */\n smoothingTimeConstant?: number;\n}\n\nexport interface UseAudioLevelResult {\n /** Normalized 0–1 frequency-bin samples for the current frame — feed this\n * directly to `<AudioVisualizer levels={levels} />`. Empty while `stream`\n * is `null`/`undefined` or the Web Audio API is unavailable. */\n levels: number[];\n /** The mean of `levels` — a single 0–1 scalar for a simple level meter. */\n level: number;\n}\n\nconst DEFAULT_FFT_SIZE = 64;\nconst DEFAULT_SMOOTHING_TIME_CONSTANT = 0.6;\n\ntype AudioContextCtor = new () => AudioContext;\n\n/** Feature-detects the Web Audio API — absent under SSR, in a test runner\n * with no Web Audio shim, and in older Safari (`webkitAudioContext`). */\nfunction resolveAudioContextConstructor(): AudioContextCtor | null {\n if (typeof window === \"undefined\") return null;\n const w = window as typeof window & { webkitAudioContext?: AudioContextCtor };\n return w.AudioContext ?? w.webkitAudioContext ?? null;\n}\n\n/**\n * Polls a `MediaStream` the caller already obtained (their own `getUserMedia`\n * call — this hook never requests one) via a Web Audio `AnalyserNode`, on a\n * `requestAnimationFrame` loop, and returns normalized levels.\n *\n * Pass `null`/`undefined` for `stream` (e.g. before the user grants mic\n * permission) and the hook is a no-op returning empty levels — safe to call\n * unconditionally, including with no stream ever provided at all.\n */\nexport function useAudioLevel(\n stream: MediaStream | null | undefined,\n options: UseAudioLevelOptions = {},\n): UseAudioLevelResult {\n const { fftSize = DEFAULT_FFT_SIZE, smoothingTimeConstant = DEFAULT_SMOOTHING_TIME_CONSTANT } =\n options;\n const [levels, setLevels] = useState<number[]>([]);\n const [level, setLevel] = useState(0);\n\n useEffect(() => {\n if (!stream) {\n setLevels([]);\n setLevel(0);\n return undefined;\n }\n\n const AudioContextConstructor = resolveAudioContextConstructor();\n if (!AudioContextConstructor) {\n return undefined;\n }\n\n const audioContext = new AudioContextConstructor();\n const source = audioContext.createMediaStreamSource(stream);\n const analyser = audioContext.createAnalyser();\n analyser.fftSize = fftSize;\n analyser.smoothingTimeConstant = smoothingTimeConstant;\n source.connect(analyser);\n\n const buffer = new Uint8Array(analyser.frequencyBinCount);\n let rafId = 0;\n\n const tick = () => {\n analyser.getByteFrequencyData(buffer);\n const normalized = Array.from(buffer, (value) => value / 255);\n setLevels(normalized);\n setLevel(normalized.reduce((sum, value) => sum + value, 0) / (normalized.length || 1));\n rafId = requestAnimationFrame(tick);\n };\n rafId = requestAnimationFrame(tick);\n\n return () => {\n cancelAnimationFrame(rafId);\n source.disconnect();\n analyser.disconnect();\n if (audioContext.state !== \"closed\") {\n void audioContext.close();\n }\n };\n }, [stream, fftSize, smoothingTimeConstant]);\n\n return { level, levels };\n}\n"],"mappings":";;;AAEA,SAAS,WAAW,gBAAgB;AA4BpC,IAAM,mBAAmB;AACzB,IAAM,kCAAkC;AAMxC,SAAS,iCAA0D;AACjE,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,QAAM,IAAI;AACV,SAAO,EAAE,gBAAgB,EAAE,sBAAsB;AACnD;AAWO,SAAS,cACd,QACA,UAAgC,CAAC,GACZ;AACrB,QAAM,EAAE,UAAU,kBAAkB,wBAAwB,gCAAgC,IAC1F;AACF,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAmB,CAAC,CAAC;AACjD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,CAAC;AAEpC,YAAU,MAAM;AACd,QAAI,CAAC,QAAQ;AACX,gBAAU,CAAC,CAAC;AACZ,eAAS,CAAC;AACV,aAAO;AAAA,IACT;AAEA,UAAM,0BAA0B,+BAA+B;AAC/D,QAAI,CAAC,yBAAyB;AAC5B,aAAO;AAAA,IACT;AAEA,UAAM,eAAe,IAAI,wBAAwB;AACjD,UAAM,SAAS,aAAa,wBAAwB,MAAM;AAC1D,UAAM,WAAW,aAAa,eAAe;AAC7C,aAAS,UAAU;AACnB,aAAS,wBAAwB;AACjC,WAAO,QAAQ,QAAQ;AAEvB,UAAM,SAAS,IAAI,WAAW,SAAS,iBAAiB;AACxD,QAAI,QAAQ;AAEZ,UAAM,OAAO,MAAM;AACjB,eAAS,qBAAqB,MAAM;AACpC,YAAM,aAAa,MAAM,KAAK,QAAQ,CAAC,UAAU,QAAQ,GAAG;AAC5D,gBAAU,UAAU;AACpB,eAAS,WAAW,OAAO,CAAC,KAAK,UAAU,MAAM,OAAO,CAAC,KAAK,WAAW,UAAU,EAAE;AACrF,cAAQ,sBAAsB,IAAI;AAAA,IACpC;AACA,YAAQ,sBAAsB,IAAI;AAElC,WAAO,MAAM;AACX,2BAAqB,KAAK;AAC1B,aAAO,WAAW;AAClB,eAAS,WAAW;AACpB,UAAI,aAAa,UAAU,UAAU;AACnC,aAAK,aAAa,MAAM;AAAA,MAC1B;AAAA,IACF;AAAA,EACF,GAAG,CAAC,QAAQ,SAAS,qBAAqB,CAAC;AAE3C,SAAO,EAAE,OAAO,OAAO;AACzB;","names":[]}
|
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
Shimmer
|
|
4
|
+
} from "./chunk-3YPT3V7L.js";
|
|
5
|
+
import {
|
|
6
|
+
getThemeScope,
|
|
7
|
+
useThemeScopeRevision
|
|
8
|
+
} from "./chunk-3TDHPXZZ.js";
|
|
9
|
+
import {
|
|
10
|
+
buildCodeBlockTheme,
|
|
11
|
+
codeBlockThemeId,
|
|
12
|
+
getThemeScopeKey
|
|
13
|
+
} from "./chunk-SSKZ2AED.js";
|
|
14
|
+
|
|
15
|
+
// src/code-block.tsx
|
|
16
|
+
import { Button, useCopyToClipboard, useLocale } from "@elabs-ai/components-ui";
|
|
17
|
+
import {
|
|
18
|
+
Select,
|
|
19
|
+
SelectContent,
|
|
20
|
+
SelectItem,
|
|
21
|
+
SelectTrigger,
|
|
22
|
+
SelectValue
|
|
23
|
+
} from "@elabs-ai/components-ui";
|
|
24
|
+
import { cn } from "@elabs-ai/components-ui/lib/cn";
|
|
25
|
+
import { CheckIcon, CopyIcon } from "lucide-react";
|
|
26
|
+
import {
|
|
27
|
+
createContext,
|
|
28
|
+
memo,
|
|
29
|
+
useCallback,
|
|
30
|
+
useContext,
|
|
31
|
+
useEffect,
|
|
32
|
+
useLayoutEffect,
|
|
33
|
+
useMemo,
|
|
34
|
+
useReducer,
|
|
35
|
+
useRef,
|
|
36
|
+
useState
|
|
37
|
+
} from "react";
|
|
38
|
+
import { createHighlighter } from "shiki";
|
|
39
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
40
|
+
var isItalic = (fontStyle) => fontStyle && fontStyle & 1;
|
|
41
|
+
var isBold = (fontStyle) => fontStyle && fontStyle & 2;
|
|
42
|
+
var isUnderline = (fontStyle) => (
|
|
43
|
+
// oxlint-disable-next-line eslint(no-bitwise)
|
|
44
|
+
fontStyle && fontStyle & 4
|
|
45
|
+
);
|
|
46
|
+
var addKeysToTokens = (lines) => lines.map((line, lineIdx) => ({
|
|
47
|
+
key: `line-${lineIdx}`,
|
|
48
|
+
tokens: line.map((token, tokenIdx) => ({
|
|
49
|
+
key: `line-${lineIdx}-${tokenIdx}`,
|
|
50
|
+
token
|
|
51
|
+
}))
|
|
52
|
+
}));
|
|
53
|
+
var TokenSpan = ({ token }) => /* @__PURE__ */ jsx(
|
|
54
|
+
"span",
|
|
55
|
+
{
|
|
56
|
+
style: {
|
|
57
|
+
backgroundColor: token.bgColor,
|
|
58
|
+
color: token.color,
|
|
59
|
+
fontStyle: isItalic(token.fontStyle) ? "italic" : void 0,
|
|
60
|
+
fontWeight: isBold(token.fontStyle) ? "bold" : void 0,
|
|
61
|
+
textDecoration: isUnderline(token.fontStyle) ? "underline" : void 0,
|
|
62
|
+
...token.htmlStyle
|
|
63
|
+
},
|
|
64
|
+
children: token.content
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
var LINE_NUMBER_CLASSES = cn(
|
|
68
|
+
"block",
|
|
69
|
+
"before:content-[counter(line)]",
|
|
70
|
+
"before:inline-block",
|
|
71
|
+
"before:[counter-increment:line]",
|
|
72
|
+
"before:w-8",
|
|
73
|
+
"before:me-4",
|
|
74
|
+
"before:text-end",
|
|
75
|
+
"before:text-muted-foreground/50",
|
|
76
|
+
"before:font-mono",
|
|
77
|
+
"before:select-none"
|
|
78
|
+
);
|
|
79
|
+
var LineSpan = ({
|
|
80
|
+
keyedLine,
|
|
81
|
+
showLineNumbers
|
|
82
|
+
}) => /* @__PURE__ */ jsx("span", { className: showLineNumbers ? LINE_NUMBER_CLASSES : "block", children: keyedLine.tokens.length === 0 ? "\n" : keyedLine.tokens.map(({ token, key }) => /* @__PURE__ */ jsx(TokenSpan, { token }, key)) });
|
|
83
|
+
var CodeBlockContext = createContext({
|
|
84
|
+
code: ""
|
|
85
|
+
});
|
|
86
|
+
var highlighterCache = /* @__PURE__ */ new Map();
|
|
87
|
+
var MAX_TOKENS_CACHE_ENTRIES = 200;
|
|
88
|
+
var tokensCache = /* @__PURE__ */ new Map();
|
|
89
|
+
var tokensCacheGet = (key) => {
|
|
90
|
+
const value = tokensCache.get(key);
|
|
91
|
+
if (value === void 0) return void 0;
|
|
92
|
+
tokensCache.delete(key);
|
|
93
|
+
tokensCache.set(key, value);
|
|
94
|
+
return value;
|
|
95
|
+
};
|
|
96
|
+
var tokensCacheSet = (key, value) => {
|
|
97
|
+
tokensCache.delete(key);
|
|
98
|
+
tokensCache.set(key, value);
|
|
99
|
+
while (tokensCache.size > MAX_TOKENS_CACHE_ENTRIES) {
|
|
100
|
+
const oldestKey = tokensCache.keys().next().value;
|
|
101
|
+
if (oldestKey === void 0) break;
|
|
102
|
+
tokensCache.delete(oldestKey);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
var subscribers = /* @__PURE__ */ new Map();
|
|
106
|
+
var hashCode = (value) => {
|
|
107
|
+
let hash = 2166136261;
|
|
108
|
+
for (let i = 0; i < value.length; i++) {
|
|
109
|
+
hash ^= value.charCodeAt(i);
|
|
110
|
+
hash = Math.imul(hash, 16777619);
|
|
111
|
+
}
|
|
112
|
+
return (hash >>> 0).toString(36);
|
|
113
|
+
};
|
|
114
|
+
var getTokensCacheKey = (code, language, themeId) => `${themeId}:${language}:${code.length}:${hashCode(code)}`;
|
|
115
|
+
var getHighlighter = (language) => {
|
|
116
|
+
const cached = highlighterCache.get(language);
|
|
117
|
+
if (cached) {
|
|
118
|
+
return cached;
|
|
119
|
+
}
|
|
120
|
+
const highlighterPromise = createHighlighter({
|
|
121
|
+
langs: [language],
|
|
122
|
+
themes: []
|
|
123
|
+
});
|
|
124
|
+
highlighterCache.set(language, highlighterPromise);
|
|
125
|
+
return highlighterPromise;
|
|
126
|
+
};
|
|
127
|
+
var createRawTokens = (code) => ({
|
|
128
|
+
bg: "transparent",
|
|
129
|
+
fg: "inherit",
|
|
130
|
+
tokens: code.split("\n").map(
|
|
131
|
+
(line) => line === "" ? [] : [
|
|
132
|
+
{
|
|
133
|
+
color: "inherit",
|
|
134
|
+
content: line
|
|
135
|
+
}
|
|
136
|
+
]
|
|
137
|
+
)
|
|
138
|
+
});
|
|
139
|
+
var highlightCode = (code, language, callback, el, skipCache = false) => {
|
|
140
|
+
const themeId = codeBlockThemeId(getThemeScopeKey(el));
|
|
141
|
+
const tokensCacheKey = getTokensCacheKey(code, language, themeId);
|
|
142
|
+
const cached = tokensCacheGet(tokensCacheKey);
|
|
143
|
+
if (cached) {
|
|
144
|
+
return cached;
|
|
145
|
+
}
|
|
146
|
+
if (callback) {
|
|
147
|
+
if (!subscribers.has(tokensCacheKey)) {
|
|
148
|
+
subscribers.set(tokensCacheKey, /* @__PURE__ */ new Set());
|
|
149
|
+
}
|
|
150
|
+
subscribers.get(tokensCacheKey)?.add(callback);
|
|
151
|
+
}
|
|
152
|
+
getHighlighter(language).then((highlighter) => {
|
|
153
|
+
const availableLangs = highlighter.getLoadedLanguages();
|
|
154
|
+
const langToUse = availableLangs.includes(language) ? language : "text";
|
|
155
|
+
const result = highlighter.codeToTokens(code, {
|
|
156
|
+
lang: langToUse,
|
|
157
|
+
theme: buildCodeBlockTheme(el)
|
|
158
|
+
});
|
|
159
|
+
const tokenized = {
|
|
160
|
+
bg: result.bg ?? "transparent",
|
|
161
|
+
fg: result.fg ?? "inherit",
|
|
162
|
+
tokens: result.tokens
|
|
163
|
+
};
|
|
164
|
+
if (!skipCache) {
|
|
165
|
+
tokensCacheSet(tokensCacheKey, tokenized);
|
|
166
|
+
}
|
|
167
|
+
const subs = subscribers.get(tokensCacheKey);
|
|
168
|
+
if (subs) {
|
|
169
|
+
for (const sub of subs) {
|
|
170
|
+
sub(tokenized);
|
|
171
|
+
}
|
|
172
|
+
subscribers.delete(tokensCacheKey);
|
|
173
|
+
}
|
|
174
|
+
}).catch((error) => {
|
|
175
|
+
console.error("Failed to highlight code:", error);
|
|
176
|
+
subscribers.delete(tokensCacheKey);
|
|
177
|
+
});
|
|
178
|
+
return null;
|
|
179
|
+
};
|
|
180
|
+
var CodeBlockBody = memo(
|
|
181
|
+
({
|
|
182
|
+
tokenized,
|
|
183
|
+
showLineNumbers,
|
|
184
|
+
wrap,
|
|
185
|
+
className
|
|
186
|
+
}) => {
|
|
187
|
+
const preStyle = useMemo(
|
|
188
|
+
() => ({
|
|
189
|
+
backgroundColor: tokenized.bg,
|
|
190
|
+
color: tokenized.fg
|
|
191
|
+
}),
|
|
192
|
+
[tokenized.bg, tokenized.fg]
|
|
193
|
+
);
|
|
194
|
+
const keyedLines = useMemo(() => addKeysToTokens(tokenized.tokens), [tokenized.tokens]);
|
|
195
|
+
return /* @__PURE__ */ jsx(
|
|
196
|
+
"pre",
|
|
197
|
+
{
|
|
198
|
+
className: cn("m-0 p-4 text-body", wrap && "whitespace-pre-wrap break-words", className),
|
|
199
|
+
style: preStyle,
|
|
200
|
+
children: /* @__PURE__ */ jsx(
|
|
201
|
+
"code",
|
|
202
|
+
{
|
|
203
|
+
className: cn(
|
|
204
|
+
"font-mono text-body",
|
|
205
|
+
showLineNumbers && "[counter-increment:line_0] [counter-reset:line]"
|
|
206
|
+
),
|
|
207
|
+
children: keyedLines.map((keyedLine) => /* @__PURE__ */ jsx(LineSpan, { keyedLine, showLineNumbers }, keyedLine.key))
|
|
208
|
+
}
|
|
209
|
+
)
|
|
210
|
+
}
|
|
211
|
+
);
|
|
212
|
+
},
|
|
213
|
+
(prevProps, nextProps) => prevProps.tokenized === nextProps.tokenized && prevProps.showLineNumbers === nextProps.showLineNumbers && prevProps.wrap === nextProps.wrap && prevProps.className === nextProps.className
|
|
214
|
+
);
|
|
215
|
+
CodeBlockBody.displayName = "CodeBlockBody";
|
|
216
|
+
var CodeBlockContainer = ({
|
|
217
|
+
className,
|
|
218
|
+
language,
|
|
219
|
+
style,
|
|
220
|
+
...props
|
|
221
|
+
}) => /* @__PURE__ */ jsx(
|
|
222
|
+
"div",
|
|
223
|
+
{
|
|
224
|
+
className: cn(
|
|
225
|
+
"group relative w-full overflow-hidden rounded-md border bg-background text-foreground",
|
|
226
|
+
className
|
|
227
|
+
),
|
|
228
|
+
"data-language": language,
|
|
229
|
+
style: {
|
|
230
|
+
containIntrinsicSize: "auto 200px",
|
|
231
|
+
contentVisibility: "auto",
|
|
232
|
+
...style
|
|
233
|
+
},
|
|
234
|
+
...props
|
|
235
|
+
}
|
|
236
|
+
);
|
|
237
|
+
var CodeBlockHeader = ({
|
|
238
|
+
children,
|
|
239
|
+
className,
|
|
240
|
+
...props
|
|
241
|
+
}) => /* @__PURE__ */ jsx(
|
|
242
|
+
"div",
|
|
243
|
+
{
|
|
244
|
+
className: cn(
|
|
245
|
+
"flex items-center justify-between border-b bg-muted/80 px-3 py-2 text-muted-foreground text-meta",
|
|
246
|
+
className
|
|
247
|
+
),
|
|
248
|
+
...props,
|
|
249
|
+
children
|
|
250
|
+
}
|
|
251
|
+
);
|
|
252
|
+
var CodeBlockTitle = ({
|
|
253
|
+
children,
|
|
254
|
+
className,
|
|
255
|
+
...props
|
|
256
|
+
}) => /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-2", className), ...props, children });
|
|
257
|
+
var CodeBlockFilename = ({
|
|
258
|
+
children,
|
|
259
|
+
className,
|
|
260
|
+
...props
|
|
261
|
+
}) => /* @__PURE__ */ jsx("span", { className: cn("font-mono", className), ...props, children });
|
|
262
|
+
var CodeBlockActions = ({
|
|
263
|
+
children,
|
|
264
|
+
className,
|
|
265
|
+
...props
|
|
266
|
+
}) => /* @__PURE__ */ jsx("div", { className: cn("-my-1 -me-1 flex items-center gap-2", className), ...props, children });
|
|
267
|
+
var STREAM_HIGHLIGHT_THROTTLE_MS = 200;
|
|
268
|
+
var CodeBlockContent = ({
|
|
269
|
+
code,
|
|
270
|
+
language,
|
|
271
|
+
showLineNumbers = false,
|
|
272
|
+
wrap = false,
|
|
273
|
+
isStreaming = false
|
|
274
|
+
}) => {
|
|
275
|
+
const scopeRef = useRef(null);
|
|
276
|
+
const [, forceMountRerender] = useReducer((tick) => tick + 1, 0);
|
|
277
|
+
useLayoutEffect(() => {
|
|
278
|
+
forceMountRerender();
|
|
279
|
+
}, []);
|
|
280
|
+
const scopeEl = getThemeScope(scopeRef.current);
|
|
281
|
+
const themeRevision = useThemeScopeRevision(scopeRef.current);
|
|
282
|
+
const themeScopeKey = useMemo(
|
|
283
|
+
() => getThemeScopeKey(scopeEl),
|
|
284
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- themeRevision is the trigger; scopeEl's own identity already changes across the post-mount re-render above.
|
|
285
|
+
[themeRevision, scopeEl]
|
|
286
|
+
);
|
|
287
|
+
const rawTokens = useMemo(() => createRawTokens(code), [code]);
|
|
288
|
+
const themeId = codeBlockThemeId(themeScopeKey);
|
|
289
|
+
const tokensCacheKey = getTokensCacheKey(code, language, themeId);
|
|
290
|
+
const syncTokens = tokensCache.get(tokensCacheKey) ?? rawTokens;
|
|
291
|
+
const [asyncTokens, setAsyncTokens] = useState(null);
|
|
292
|
+
const asyncKeyRef = useRef({ code, language, themeScopeKey });
|
|
293
|
+
if (asyncKeyRef.current.code !== code || asyncKeyRef.current.language !== language || asyncKeyRef.current.themeScopeKey !== themeScopeKey) {
|
|
294
|
+
asyncKeyRef.current = { code, language, themeScopeKey };
|
|
295
|
+
setAsyncTokens(null);
|
|
296
|
+
}
|
|
297
|
+
const lastHighlightAtRef = useRef(0);
|
|
298
|
+
useEffect(() => {
|
|
299
|
+
let cancelled = false;
|
|
300
|
+
let timeoutId;
|
|
301
|
+
const runHighlight = () => {
|
|
302
|
+
lastHighlightAtRef.current = Date.now();
|
|
303
|
+
const cached = highlightCode(
|
|
304
|
+
code,
|
|
305
|
+
language,
|
|
306
|
+
(result) => {
|
|
307
|
+
if (!cancelled) {
|
|
308
|
+
setAsyncTokens(result);
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
scopeEl,
|
|
312
|
+
isStreaming
|
|
313
|
+
);
|
|
314
|
+
if (cached && !cancelled) {
|
|
315
|
+
setAsyncTokens(cached);
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
if (!isStreaming) {
|
|
319
|
+
runHighlight();
|
|
320
|
+
} else {
|
|
321
|
+
const elapsed = Date.now() - lastHighlightAtRef.current;
|
|
322
|
+
if (elapsed >= STREAM_HIGHLIGHT_THROTTLE_MS) {
|
|
323
|
+
runHighlight();
|
|
324
|
+
} else {
|
|
325
|
+
timeoutId = setTimeout(runHighlight, STREAM_HIGHLIGHT_THROTTLE_MS - elapsed);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return () => {
|
|
329
|
+
cancelled = true;
|
|
330
|
+
if (timeoutId !== void 0) {
|
|
331
|
+
clearTimeout(timeoutId);
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
}, [code, language, themeScopeKey, scopeEl, isStreaming]);
|
|
335
|
+
const tokenized = asyncTokens ?? syncTokens;
|
|
336
|
+
return /* @__PURE__ */ jsx(
|
|
337
|
+
"div",
|
|
338
|
+
{
|
|
339
|
+
ref: scopeRef,
|
|
340
|
+
className: cn(
|
|
341
|
+
"relative overflow-auto",
|
|
342
|
+
// Discoverable horizontal-scroll affordance in non-wrap mode, so a narrow
|
|
343
|
+
// embed doesn't silently clip long lines. Hidden when wrapping (no overflow).
|
|
344
|
+
!wrap && "[scrollbar-width:thin] [&::-webkit-scrollbar]:h-1.5 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-border"
|
|
345
|
+
),
|
|
346
|
+
children: /* @__PURE__ */ jsx(CodeBlockBody, { showLineNumbers, tokenized, wrap })
|
|
347
|
+
}
|
|
348
|
+
);
|
|
349
|
+
};
|
|
350
|
+
var CodeBlock = ({
|
|
351
|
+
code,
|
|
352
|
+
language,
|
|
353
|
+
showLineNumbers = false,
|
|
354
|
+
wrap = false,
|
|
355
|
+
isStreaming = false,
|
|
356
|
+
className,
|
|
357
|
+
children,
|
|
358
|
+
...props
|
|
359
|
+
}) => {
|
|
360
|
+
const contextValue = useMemo(() => ({ code }), [code]);
|
|
361
|
+
const { t } = useLocale();
|
|
362
|
+
return /* @__PURE__ */ jsx(CodeBlockContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs(CodeBlockContainer, { className, language, ...props, children: [
|
|
363
|
+
children,
|
|
364
|
+
/* @__PURE__ */ jsx(
|
|
365
|
+
CodeBlockContent,
|
|
366
|
+
{
|
|
367
|
+
code,
|
|
368
|
+
language,
|
|
369
|
+
showLineNumbers,
|
|
370
|
+
wrap,
|
|
371
|
+
isStreaming
|
|
372
|
+
}
|
|
373
|
+
),
|
|
374
|
+
isStreaming ? /* @__PURE__ */ jsx(
|
|
375
|
+
"div",
|
|
376
|
+
{
|
|
377
|
+
className: "flex items-center gap-2 border-t bg-muted/80 px-3 py-1.5 text-caption text-muted-foreground",
|
|
378
|
+
role: "status",
|
|
379
|
+
"aria-live": "polite",
|
|
380
|
+
children: /* @__PURE__ */ jsx(Shimmer, { children: t("ai.codeBlock.generating") })
|
|
381
|
+
}
|
|
382
|
+
) : null
|
|
383
|
+
] }) });
|
|
384
|
+
};
|
|
385
|
+
var CodeBlockCopyButton = ({
|
|
386
|
+
onCopy,
|
|
387
|
+
onError,
|
|
388
|
+
timeout,
|
|
389
|
+
children,
|
|
390
|
+
className,
|
|
391
|
+
...props
|
|
392
|
+
}) => {
|
|
393
|
+
const { t } = useLocale();
|
|
394
|
+
const { code } = useContext(CodeBlockContext);
|
|
395
|
+
const { copied: isCopied, copy } = useCopyToClipboard(
|
|
396
|
+
timeout === void 0 ? void 0 : { resetAfterMs: timeout }
|
|
397
|
+
);
|
|
398
|
+
const copyToClipboard = useCallback(async () => {
|
|
399
|
+
const ok = await copy(code);
|
|
400
|
+
if (ok) {
|
|
401
|
+
onCopy?.();
|
|
402
|
+
} else {
|
|
403
|
+
onError?.(new Error("Clipboard API not available"));
|
|
404
|
+
}
|
|
405
|
+
}, [copy, code, onCopy, onError]);
|
|
406
|
+
const Icon = isCopied ? CheckIcon : CopyIcon;
|
|
407
|
+
return /* @__PURE__ */ jsx(
|
|
408
|
+
Button,
|
|
409
|
+
{
|
|
410
|
+
"aria-label": t("copy"),
|
|
411
|
+
className: cn("shrink-0", className),
|
|
412
|
+
onClick: copyToClipboard,
|
|
413
|
+
size: "icon",
|
|
414
|
+
variant: "ghost",
|
|
415
|
+
...props,
|
|
416
|
+
children: children ?? /* @__PURE__ */ jsx(
|
|
417
|
+
"span",
|
|
418
|
+
{
|
|
419
|
+
className: "flex animate-in fade-in-0 zoom-in-95 duration-fast ease-entrance",
|
|
420
|
+
children: /* @__PURE__ */ jsx(Icon, { size: 14 })
|
|
421
|
+
},
|
|
422
|
+
isCopied ? "check" : "copy"
|
|
423
|
+
)
|
|
424
|
+
}
|
|
425
|
+
);
|
|
426
|
+
};
|
|
427
|
+
var CodeBlockLanguageSelector = (props) => /* @__PURE__ */ jsx(Select, { ...props });
|
|
428
|
+
var CodeBlockLanguageSelectorTrigger = ({
|
|
429
|
+
className,
|
|
430
|
+
...props
|
|
431
|
+
}) => /* @__PURE__ */ jsx(
|
|
432
|
+
SelectTrigger,
|
|
433
|
+
{
|
|
434
|
+
className: cn("h-7 border-none bg-transparent px-2 text-meta shadow-none", className),
|
|
435
|
+
size: "sm",
|
|
436
|
+
...props
|
|
437
|
+
}
|
|
438
|
+
);
|
|
439
|
+
var CodeBlockLanguageSelectorValue = (props) => /* @__PURE__ */ jsx(SelectValue, { ...props });
|
|
440
|
+
var CodeBlockLanguageSelectorContent = ({
|
|
441
|
+
align = "end",
|
|
442
|
+
...props
|
|
443
|
+
}) => /* @__PURE__ */ jsx(SelectContent, { align, ...props });
|
|
444
|
+
var CodeBlockLanguageSelectorItem = (props) => /* @__PURE__ */ jsx(SelectItem, { ...props });
|
|
445
|
+
|
|
446
|
+
export {
|
|
447
|
+
highlightCode,
|
|
448
|
+
CodeBlockContainer,
|
|
449
|
+
CodeBlockHeader,
|
|
450
|
+
CodeBlockTitle,
|
|
451
|
+
CodeBlockFilename,
|
|
452
|
+
CodeBlockActions,
|
|
453
|
+
CodeBlockContent,
|
|
454
|
+
CodeBlock,
|
|
455
|
+
CodeBlockCopyButton,
|
|
456
|
+
CodeBlockLanguageSelector,
|
|
457
|
+
CodeBlockLanguageSelectorTrigger,
|
|
458
|
+
CodeBlockLanguageSelectorValue,
|
|
459
|
+
CodeBlockLanguageSelectorContent,
|
|
460
|
+
CodeBlockLanguageSelectorItem
|
|
461
|
+
};
|
|
462
|
+
//# sourceMappingURL=chunk-TWPHAJNM.js.map
|