@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,382 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/context-panel.tsx
|
|
4
|
+
import {
|
|
5
|
+
Button,
|
|
6
|
+
Sheet,
|
|
7
|
+
SheetContent,
|
|
8
|
+
SheetDescription,
|
|
9
|
+
SheetHeader,
|
|
10
|
+
SheetTitle,
|
|
11
|
+
useCollapsiblePanel,
|
|
12
|
+
useIsMobile,
|
|
13
|
+
useLocale
|
|
14
|
+
} from "@elabs-ai/components-ui";
|
|
15
|
+
import { cn } from "@elabs-ai/components-ui/lib/cn";
|
|
16
|
+
import { ChevronLeftIcon, PanelRightIcon } from "lucide-react";
|
|
17
|
+
import {
|
|
18
|
+
createContext,
|
|
19
|
+
forwardRef,
|
|
20
|
+
use,
|
|
21
|
+
useCallback,
|
|
22
|
+
useEffect,
|
|
23
|
+
useId,
|
|
24
|
+
useMemo,
|
|
25
|
+
useRef,
|
|
26
|
+
useState
|
|
27
|
+
} from "react";
|
|
28
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
29
|
+
var CONTEXT_PANEL_COOKIE_NAME = "context_panel_state";
|
|
30
|
+
var CONTEXT_PANEL_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
|
|
31
|
+
var CONTEXT_PANEL_WIDTH = "20rem";
|
|
32
|
+
var CONTEXT_PANEL_WIDTH_MOBILE = "20rem";
|
|
33
|
+
var ContextPanelContext = createContext(null);
|
|
34
|
+
var ContextPanelInternalContext = createContext(null);
|
|
35
|
+
function useContextPanel() {
|
|
36
|
+
const context = use(ContextPanelContext);
|
|
37
|
+
if (!context) throw new Error("useContextPanel must be used within a ContextPanelProvider.");
|
|
38
|
+
return context;
|
|
39
|
+
}
|
|
40
|
+
function useAssetPreviewRenderer() {
|
|
41
|
+
return use(ContextPanelContext)?.meta.renderPreview;
|
|
42
|
+
}
|
|
43
|
+
function useContextPanelInternal() {
|
|
44
|
+
const context = use(ContextPanelInternalContext);
|
|
45
|
+
if (!context) {
|
|
46
|
+
throw new Error("ContextPanel components must be used within a ContextPanelProvider.");
|
|
47
|
+
}
|
|
48
|
+
return context;
|
|
49
|
+
}
|
|
50
|
+
function ContextPanelProvider({
|
|
51
|
+
children,
|
|
52
|
+
defaultOpen = true,
|
|
53
|
+
open: openProp,
|
|
54
|
+
onOpenChange,
|
|
55
|
+
view: viewProp,
|
|
56
|
+
onViewChange,
|
|
57
|
+
defaultView = "root",
|
|
58
|
+
selectedAsset: selectedAssetProp,
|
|
59
|
+
onSelectedAssetChange,
|
|
60
|
+
defaultSelectedAsset = null,
|
|
61
|
+
renderPreview
|
|
62
|
+
}) {
|
|
63
|
+
const isMobile = useIsMobile();
|
|
64
|
+
const [openMobile, setOpenMobile] = useState(false);
|
|
65
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);
|
|
66
|
+
const openControlled = openProp !== void 0;
|
|
67
|
+
const open = openControlled ? openProp : uncontrolledOpen;
|
|
68
|
+
const [uncontrolledView, setUncontrolledView] = useState(defaultView);
|
|
69
|
+
const viewControlled = viewProp !== void 0;
|
|
70
|
+
const view = viewControlled ? viewProp : uncontrolledView;
|
|
71
|
+
const [uncontrolledAsset, setUncontrolledAsset] = useState(
|
|
72
|
+
defaultSelectedAsset
|
|
73
|
+
);
|
|
74
|
+
const assetControlled = selectedAssetProp !== void 0;
|
|
75
|
+
const selectedAsset = assetControlled ? selectedAssetProp : uncontrolledAsset;
|
|
76
|
+
const panelId = useId();
|
|
77
|
+
const titleId = useId();
|
|
78
|
+
const returnFocusRef = useRef(null);
|
|
79
|
+
const detailFocusRef = useRef(null);
|
|
80
|
+
const setOpen = useCallback(
|
|
81
|
+
(value) => {
|
|
82
|
+
const next = typeof value === "function" ? value(open) : value;
|
|
83
|
+
if (!openControlled) setUncontrolledOpen(next);
|
|
84
|
+
onOpenChange?.(next);
|
|
85
|
+
if (typeof document !== "undefined") {
|
|
86
|
+
document.cookie = `${CONTEXT_PANEL_COOKIE_NAME}=${next}; path=/; max-age=${CONTEXT_PANEL_COOKIE_MAX_AGE}`;
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
[onOpenChange, open, openControlled]
|
|
90
|
+
);
|
|
91
|
+
const toggle = useCallback(() => {
|
|
92
|
+
if (isMobile) setOpenMobile((o) => !o);
|
|
93
|
+
else setOpen((o) => !o);
|
|
94
|
+
}, [isMobile, setOpen]);
|
|
95
|
+
const setView = useCallback(
|
|
96
|
+
(next) => {
|
|
97
|
+
if (!viewControlled) setUncontrolledView(next);
|
|
98
|
+
onViewChange?.(next);
|
|
99
|
+
},
|
|
100
|
+
[onViewChange, viewControlled]
|
|
101
|
+
);
|
|
102
|
+
const setSelectedAsset = useCallback(
|
|
103
|
+
(next) => {
|
|
104
|
+
if (!assetControlled) setUncontrolledAsset(next);
|
|
105
|
+
onSelectedAssetChange?.(next);
|
|
106
|
+
},
|
|
107
|
+
[assetControlled, onSelectedAssetChange]
|
|
108
|
+
);
|
|
109
|
+
const openDetail = useCallback(
|
|
110
|
+
(asset) => {
|
|
111
|
+
if (isMobile) setOpenMobile(true);
|
|
112
|
+
else if (!open) setOpen(true);
|
|
113
|
+
if (typeof document !== "undefined" && document.activeElement instanceof HTMLElement) {
|
|
114
|
+
returnFocusRef.current = document.activeElement;
|
|
115
|
+
}
|
|
116
|
+
setView("detail");
|
|
117
|
+
setSelectedAsset(asset);
|
|
118
|
+
requestAnimationFrame(() => detailFocusRef.current?.focus());
|
|
119
|
+
},
|
|
120
|
+
[isMobile, open, setOpen, setSelectedAsset, setView]
|
|
121
|
+
);
|
|
122
|
+
const back = useCallback(() => {
|
|
123
|
+
setView("root");
|
|
124
|
+
requestAnimationFrame(() => {
|
|
125
|
+
const target = returnFocusRef.current;
|
|
126
|
+
if (target?.isConnected) target.focus();
|
|
127
|
+
});
|
|
128
|
+
}, [setView]);
|
|
129
|
+
const contextValue = useMemo(
|
|
130
|
+
() => ({
|
|
131
|
+
state: { open, view, selectedAsset },
|
|
132
|
+
actions: { toggle, setOpen, openDetail, back },
|
|
133
|
+
meta: { isMobile, openMobile, setOpenMobile, renderPreview }
|
|
134
|
+
}),
|
|
135
|
+
[
|
|
136
|
+
back,
|
|
137
|
+
isMobile,
|
|
138
|
+
open,
|
|
139
|
+
openDetail,
|
|
140
|
+
openMobile,
|
|
141
|
+
renderPreview,
|
|
142
|
+
selectedAsset,
|
|
143
|
+
setOpen,
|
|
144
|
+
toggle,
|
|
145
|
+
view
|
|
146
|
+
]
|
|
147
|
+
);
|
|
148
|
+
const internalValue = useMemo(
|
|
149
|
+
() => ({ panelId, titleId, detailFocusRef }),
|
|
150
|
+
[panelId, titleId]
|
|
151
|
+
);
|
|
152
|
+
return /* @__PURE__ */ jsx(ContextPanelContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(ContextPanelInternalContext.Provider, { value: internalValue, children }) });
|
|
153
|
+
}
|
|
154
|
+
var ContextPanel = forwardRef(function ContextPanel2({ width = CONTEXT_PANEL_WIDTH, className, style, children, ...props }, ref) {
|
|
155
|
+
const { state, actions, meta } = useContextPanel();
|
|
156
|
+
const { panelId } = useContextPanelInternal();
|
|
157
|
+
const { t } = useLocale();
|
|
158
|
+
const panel = useCollapsiblePanel({
|
|
159
|
+
side: "right",
|
|
160
|
+
open: state.open,
|
|
161
|
+
onOpenChange: actions.setOpen,
|
|
162
|
+
widthClassName: "w-(--context-panel-width)",
|
|
163
|
+
spacerCollapsedClassName: "group-data-[state=collapsed]:w-0",
|
|
164
|
+
containerSlideClassNames: {
|
|
165
|
+
left: "left-0 group-data-[state=collapsed]:left-[calc(var(--context-panel-width)*-1)]",
|
|
166
|
+
right: "right-0 group-data-[state=collapsed]:right-[calc(var(--context-panel-width)*-1)]"
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
if (meta.isMobile) {
|
|
170
|
+
return /* @__PURE__ */ jsx(Sheet, { open: meta.openMobile, onOpenChange: meta.setOpenMobile, children: /* @__PURE__ */ jsxs(
|
|
171
|
+
SheetContent,
|
|
172
|
+
{
|
|
173
|
+
id: panelId,
|
|
174
|
+
side: "right",
|
|
175
|
+
"data-slot": "context-panel",
|
|
176
|
+
"data-mobile": "true",
|
|
177
|
+
className: "w-(--context-panel-width) gap-0 p-0",
|
|
178
|
+
style: { "--context-panel-width": CONTEXT_PANEL_WIDTH_MOBILE },
|
|
179
|
+
children: [
|
|
180
|
+
/* @__PURE__ */ jsxs(SheetHeader, { className: "sr-only", children: [
|
|
181
|
+
/* @__PURE__ */ jsx(SheetTitle, { children: t("ai.contextPanel.title") }),
|
|
182
|
+
/* @__PURE__ */ jsx(SheetDescription, { children: t("ai.contextPanel.description") })
|
|
183
|
+
] }),
|
|
184
|
+
/* @__PURE__ */ jsx("div", { className: "flex h-full w-full flex-col", children })
|
|
185
|
+
]
|
|
186
|
+
}
|
|
187
|
+
) });
|
|
188
|
+
}
|
|
189
|
+
return /* @__PURE__ */ jsxs(
|
|
190
|
+
"div",
|
|
191
|
+
{
|
|
192
|
+
ref,
|
|
193
|
+
id: panelId,
|
|
194
|
+
"data-slot": "context-panel",
|
|
195
|
+
inert: state.open ? void 0 : true,
|
|
196
|
+
className: cn("group relative hidden overflow-hidden md:block", className),
|
|
197
|
+
style: { "--context-panel-width": width, ...style },
|
|
198
|
+
...panel.attrs,
|
|
199
|
+
...props,
|
|
200
|
+
children: [
|
|
201
|
+
/* @__PURE__ */ jsx("div", { "data-slot": "context-panel-gap", className: panel.spacerClassName }),
|
|
202
|
+
/* @__PURE__ */ jsx(
|
|
203
|
+
"div",
|
|
204
|
+
{
|
|
205
|
+
"data-slot": "context-panel-container",
|
|
206
|
+
className: cn(panel.containerClassName, "absolute inset-y-0 flex h-full border-s"),
|
|
207
|
+
children: /* @__PURE__ */ jsx("div", { "data-slot": "context-panel-inner", className: "flex h-full w-full flex-col bg-card", children })
|
|
208
|
+
}
|
|
209
|
+
)
|
|
210
|
+
]
|
|
211
|
+
}
|
|
212
|
+
);
|
|
213
|
+
});
|
|
214
|
+
var ContextPanelTrigger = forwardRef(
|
|
215
|
+
function ContextPanelTrigger2({ className, onClick, children, ...props }, ref) {
|
|
216
|
+
const { t } = useLocale();
|
|
217
|
+
const { state, actions, meta } = useContextPanel();
|
|
218
|
+
const { panelId } = useContextPanelInternal();
|
|
219
|
+
const expanded = meta.isMobile ? meta.openMobile : state.open;
|
|
220
|
+
return /* @__PURE__ */ jsx(
|
|
221
|
+
Button,
|
|
222
|
+
{
|
|
223
|
+
ref,
|
|
224
|
+
"data-slot": "context-panel-trigger",
|
|
225
|
+
variant: "ghost",
|
|
226
|
+
size: "icon",
|
|
227
|
+
"aria-expanded": expanded,
|
|
228
|
+
"aria-controls": panelId,
|
|
229
|
+
"aria-label": t("ai.contextPanel.toggle"),
|
|
230
|
+
className: cn("size-7", className),
|
|
231
|
+
onClick: (event) => {
|
|
232
|
+
onClick?.(event);
|
|
233
|
+
actions.toggle();
|
|
234
|
+
},
|
|
235
|
+
...props,
|
|
236
|
+
children: children ?? /* @__PURE__ */ jsx(PanelRightIcon, { "aria-hidden": "true" })
|
|
237
|
+
}
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
);
|
|
241
|
+
var ContextPanelHeader = forwardRef(
|
|
242
|
+
function ContextPanelHeader2({ title = "Context", className, children, ...props }, ref) {
|
|
243
|
+
const { t } = useLocale();
|
|
244
|
+
const { state, actions } = useContextPanel();
|
|
245
|
+
const { titleId, detailFocusRef } = useContextPanelInternal();
|
|
246
|
+
const isDetail = state.view === "detail";
|
|
247
|
+
return /* @__PURE__ */ jsxs(
|
|
248
|
+
"div",
|
|
249
|
+
{
|
|
250
|
+
ref,
|
|
251
|
+
"data-slot": "context-panel-header",
|
|
252
|
+
className: cn("flex h-header shrink-0 items-center gap-2 border-b px-3", className),
|
|
253
|
+
...props,
|
|
254
|
+
children: [
|
|
255
|
+
isDetail ? /* @__PURE__ */ jsxs(
|
|
256
|
+
Button,
|
|
257
|
+
{
|
|
258
|
+
ref: (node) => {
|
|
259
|
+
detailFocusRef.current = node;
|
|
260
|
+
},
|
|
261
|
+
type: "button",
|
|
262
|
+
variant: "ghost",
|
|
263
|
+
size: "sm",
|
|
264
|
+
"data-slot": "context-panel-back",
|
|
265
|
+
"aria-label": t("ai.contextPanel.back"),
|
|
266
|
+
className: "gap-1 px-2 text-muted-foreground",
|
|
267
|
+
onClick: () => actions.back(),
|
|
268
|
+
children: [
|
|
269
|
+
/* @__PURE__ */ jsx(ChevronLeftIcon, { className: "size-4", "aria-hidden": "true", "data-rtl-flip": true }),
|
|
270
|
+
"Back"
|
|
271
|
+
]
|
|
272
|
+
}
|
|
273
|
+
) : null,
|
|
274
|
+
/* @__PURE__ */ jsx("h2", { id: titleId, className: "min-w-0 truncate text-title", children: isDetail ? state.selectedAsset?.name ?? title : title }),
|
|
275
|
+
children ? /* @__PURE__ */ jsx("div", { className: "ms-auto flex items-center gap-1", children }) : null
|
|
276
|
+
]
|
|
277
|
+
}
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
);
|
|
281
|
+
var ContextPanelBody = forwardRef(
|
|
282
|
+
function ContextPanelBody2({ root, detail, label = "Context", className, ...props }, ref) {
|
|
283
|
+
const { state } = useContextPanel();
|
|
284
|
+
const isDetail = state.view === "detail";
|
|
285
|
+
const [announcement, setAnnouncement] = useState("");
|
|
286
|
+
const previousView = useRef(state.view);
|
|
287
|
+
useEffect(() => {
|
|
288
|
+
if (previousView.current === state.view) return;
|
|
289
|
+
previousView.current = state.view;
|
|
290
|
+
setAnnouncement(
|
|
291
|
+
state.view === "detail" ? `Showing ${state.selectedAsset?.name ?? "asset detail"}` : "Back to context"
|
|
292
|
+
);
|
|
293
|
+
}, [state.selectedAsset, state.view]);
|
|
294
|
+
return /* @__PURE__ */ jsxs(
|
|
295
|
+
"div",
|
|
296
|
+
{
|
|
297
|
+
ref,
|
|
298
|
+
role: "region",
|
|
299
|
+
"aria-label": label,
|
|
300
|
+
"data-slot": "context-panel-body",
|
|
301
|
+
className: cn("relative min-h-0 flex-1 overflow-hidden", className),
|
|
302
|
+
...props,
|
|
303
|
+
children: [
|
|
304
|
+
/* @__PURE__ */ jsx("div", { "aria-live": "polite", className: "sr-only", children: announcement }),
|
|
305
|
+
/* @__PURE__ */ jsxs(
|
|
306
|
+
"div",
|
|
307
|
+
{
|
|
308
|
+
"data-slot": "context-panel-track",
|
|
309
|
+
className: "flex h-full w-[200%] transition-transform duration-base ease-standard motion-reduce:transition-none",
|
|
310
|
+
style: { transform: isDetail ? "translateX(-50%)" : "translateX(0)" },
|
|
311
|
+
children: [
|
|
312
|
+
/* @__PURE__ */ jsx(
|
|
313
|
+
"div",
|
|
314
|
+
{
|
|
315
|
+
"data-vt-pane": "root",
|
|
316
|
+
"aria-hidden": isDetail,
|
|
317
|
+
inert: isDetail ? true : void 0,
|
|
318
|
+
className: "flex h-full w-1/2 flex-col gap-5 overflow-y-auto p-4",
|
|
319
|
+
children: root
|
|
320
|
+
}
|
|
321
|
+
),
|
|
322
|
+
/* @__PURE__ */ jsx(
|
|
323
|
+
"div",
|
|
324
|
+
{
|
|
325
|
+
"data-vt-pane": "detail",
|
|
326
|
+
"aria-hidden": !isDetail,
|
|
327
|
+
inert: isDetail ? void 0 : true,
|
|
328
|
+
className: "h-full w-1/2 overflow-y-auto",
|
|
329
|
+
children: detail
|
|
330
|
+
}
|
|
331
|
+
)
|
|
332
|
+
]
|
|
333
|
+
}
|
|
334
|
+
)
|
|
335
|
+
]
|
|
336
|
+
}
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
);
|
|
340
|
+
var ContextPanelSection = forwardRef(
|
|
341
|
+
function ContextPanelSection2({ label, className, children, ...props }, ref) {
|
|
342
|
+
return /* @__PURE__ */ jsxs(
|
|
343
|
+
"section",
|
|
344
|
+
{
|
|
345
|
+
ref,
|
|
346
|
+
"data-slot": "context-panel-section",
|
|
347
|
+
className: cn("flex shrink-0 flex-col gap-2", className),
|
|
348
|
+
...props,
|
|
349
|
+
children: [
|
|
350
|
+
label ? /* @__PURE__ */ jsx("h3", { className: "text-meta text-muted-foreground", children: label }) : null,
|
|
351
|
+
children
|
|
352
|
+
]
|
|
353
|
+
}
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
);
|
|
357
|
+
var ContextPanelDetail = forwardRef(
|
|
358
|
+
function ContextPanelDetail2({ className, ...props }, ref) {
|
|
359
|
+
return /* @__PURE__ */ jsx(
|
|
360
|
+
"div",
|
|
361
|
+
{
|
|
362
|
+
ref,
|
|
363
|
+
"data-slot": "context-panel-detail",
|
|
364
|
+
className: cn("flex min-h-full flex-col p-4", className),
|
|
365
|
+
...props
|
|
366
|
+
}
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
);
|
|
370
|
+
|
|
371
|
+
export {
|
|
372
|
+
useContextPanel,
|
|
373
|
+
useAssetPreviewRenderer,
|
|
374
|
+
ContextPanelProvider,
|
|
375
|
+
ContextPanel,
|
|
376
|
+
ContextPanelTrigger,
|
|
377
|
+
ContextPanelHeader,
|
|
378
|
+
ContextPanelBody,
|
|
379
|
+
ContextPanelSection,
|
|
380
|
+
ContextPanelDetail
|
|
381
|
+
};
|
|
382
|
+
//# sourceMappingURL=chunk-NPUCMAG2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/context-panel.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * ContextPanel — the chat workspace's right context rail (#193, research 09).\n *\n * A compound, lifted-state component (doc-13): `ContextPanelProvider` lifts ALL\n * state ({ open, view, selectedAsset }) so an external trigger (e.g. an\n * app-header `ContextPanelTrigger`) can drive the panel from anywhere inside\n * the provider. The panel itself is ALWAYS MOUNTED and collapses via the\n * canonical `useCollapsiblePanel` width tween (one collapse implementation —\n * never a conditional mount, which can't animate). Root ↔ detail drill-in is a\n * v1 CSS two-pane translateX track behind the future `useViewTransition` seam\n * (research view-transitions/01-design.md §6.1): `openDetail`/`back` are\n * already shaped as `mutate`-callbacks and the panes carry stable\n * `data-vt-pane` identities, so the v2 swap is internal-only.\n *\n * ChatShell stays generic: compose `<ContextPanel>` as a SIBLING of\n * `<ChatShell>` under a workspace-wrapping `<ContextPanelProvider>` (the\n * Sidebar / SidebarInset relationship). Below the mobile breakpoint the panel\n * degrades to a `@elabs-ai/components-ui` `<Sheet side=\"right\">` driven by the same state.\n */\nimport {\n Button,\n Sheet,\n SheetContent,\n SheetDescription,\n SheetHeader,\n SheetTitle,\n useCollapsiblePanel,\n useIsMobile,\n useLocale,\n type FileSource,\n} from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { ChevronLeftIcon, PanelRightIcon } from \"lucide-react\";\nimport type { ComponentProps, CSSProperties, HTMLAttributes, ReactNode, RefObject } from \"react\";\nimport {\n createContext,\n forwardRef,\n use,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nconst CONTEXT_PANEL_COOKIE_NAME = \"context_panel_state\";\nconst CONTEXT_PANEL_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;\nconst CONTEXT_PANEL_WIDTH = \"20rem\";\nconst CONTEXT_PANEL_WIDTH_MOBILE = \"20rem\";\n\n/** Closed asset-type enum shared by the tree (`ProducedAssetTree`) and the preview (`AssetPreview`). */\nexport type ContextAssetType = \"markdown\" | \"code\" | \"sql\" | \"csv\" | \"image\";\n\n/** One produced asset — the unit the drill-in focuses (research 09 §B.1). */\nexport interface ContextAsset {\n id: string;\n name: string;\n path?: string;\n type: ContextAssetType;\n /** Inline content: source text — or, for `image`, the image src URL. */\n content?: string;\n /** Optional Shiki language for `code` assets (defaults to \"typescript\"). */\n language?: string;\n /**\n * The file itself, when the asset IS one — a `File`, a `Blob`, a URL, a\n * buffer. Carried so a `renderPreview` injection (below) can hand it to\n * something that opens files, such as `@elabs-ai/components-viewer`'s\n * `FileViewer`, without the asset first being turned into a string.\n *\n * `ContextAssetType` is deliberately NOT widened to cover PDFs, Office files\n * or video: this union describes what THIS package can draw, and every format\n * beyond it arrives through the injection seam rather than by growing a case\n * per format here (ADR 0024 §6).\n */\n source?: FileSource;\n /** MIME type, when known — helps a renderer that detects by media type. */\n mediaType?: string;\n}\n\n/**\n * Draw the body of an asset preview.\n *\n * Return `null` to decline and let `AssetPreview` fall through to its own\n * type-keyed rendering, which is what makes this additive: an injection that\n * handles PDFs only leaves markdown, code and CSV exactly as they were.\n */\nexport type AssetPreviewRenderer = (asset: ContextAsset) => ReactNode | null;\n\nexport type ContextPanelView = \"root\" | \"detail\";\n\nexport interface ContextPanelContextValue {\n /** Lifted state (doc-13 `state` / `actions` / `meta` interface). */\n state: {\n open: boolean;\n view: ContextPanelView;\n selectedAsset: ContextAsset | null;\n };\n actions: {\n /** Toggle the panel (the inline collapse on desktop, the Sheet on mobile). */\n toggle: () => void;\n setOpen: (open: boolean | ((open: boolean) => boolean)) => void;\n /** Drill into one asset (root → detail). Focus moves to the BACK control. */\n openDetail: (asset: ContextAsset) => void;\n /** Return to the root view; focus is restored to the originating row. */\n back: () => void;\n };\n meta: {\n isMobile: boolean;\n openMobile: boolean;\n setOpenMobile: (open: boolean) => void;\n /**\n * The injected preview renderer, if the provider was given one.\n * `AssetPreview` reads it from here so a page can teach the whole rail a\n * new format in one place instead of at every call site.\n */\n renderPreview?: AssetPreviewRenderer;\n };\n}\n\nconst ContextPanelContext = createContext<ContextPanelContextValue | null>(null);\n\ninterface ContextPanelInternalValue {\n panelId: string;\n titleId: string;\n /** The element focus moves to on `openDetail` (the BACK control). */\n detailFocusRef: RefObject<HTMLElement | null>;\n}\n\nconst ContextPanelInternalContext = createContext<ContextPanelInternalValue | null>(null);\n\nexport function useContextPanel(): ContextPanelContextValue {\n const context = use(ContextPanelContext);\n if (!context) throw new Error(\"useContextPanel must be used within a ContextPanelProvider.\");\n return context;\n}\n\n/**\n * The renderer injected into the surrounding `ContextPanelProvider`, if any.\n *\n * Unlike `useContextPanel()` this does NOT throw outside a provider:\n * `AssetPreview` is usable on its own (a preview pane in a page, a story), and\n * \"no provider\" simply means nobody injected anything.\n */\nexport function useAssetPreviewRenderer(): AssetPreviewRenderer | undefined {\n return use(ContextPanelContext)?.meta.renderPreview;\n}\n\nfunction useContextPanelInternal(): ContextPanelInternalValue {\n const context = use(ContextPanelInternalContext);\n if (!context) {\n throw new Error(\"ContextPanel components must be used within a ContextPanelProvider.\");\n }\n return context;\n}\n\nexport interface ContextPanelProviderProps {\n children: ReactNode;\n /** Uncontrolled initial open state. Default `true`. */\n defaultOpen?: boolean;\n /** Controlled open state (`isControlled = open !== undefined`, never flips). */\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Controlled view (root ↔ detail). */\n view?: ContextPanelView;\n onViewChange?: (view: ContextPanelView) => void;\n /** Uncontrolled initial view. Default `\"root\"`. */\n defaultView?: ContextPanelView;\n /** Controlled selected asset. */\n selectedAsset?: ContextAsset | null;\n onSelectedAssetChange?: (asset: ContextAsset | null) => void;\n /** Uncontrolled initial selected asset. Default `null`. */\n defaultSelectedAsset?: ContextAsset | null;\n /**\n * Draw an asset's preview body yourself.\n *\n * The seam that lets this package show formats it cannot parse — a PDF, a\n * spreadsheet, a video — without importing a domain sibling\n * (`@elabs-ai/components-ai` and\n * `@elabs-ai/components-viewer` are peers in the layer graph and\n * may never import each other). The consuming app owns the edge:\n *\n * ```tsx\n * <ContextPanelProvider\n * renderPreview={(asset) =>\n * asset.source ? <FileViewer source={asset.source} /> : null\n * }\n * >\n * ```\n *\n * Return `null` to decline, and the built-in type-keyed rendering runs\n * exactly as before — so an injection is additive, never a replacement.\n */\n renderPreview?: AssetPreviewRenderer;\n}\n\n/**\n * Lifts the panel state above the workspace so siblings outside the panel's\n * frame (the app-header trigger) can read/drive it — no prop-drilling, no\n * page-level `useState`, no conditional mount (research 09 §B.1/§C.2).\n */\nexport function ContextPanelProvider({\n children,\n defaultOpen = true,\n open: openProp,\n onOpenChange,\n view: viewProp,\n onViewChange,\n defaultView = \"root\",\n selectedAsset: selectedAssetProp,\n onSelectedAssetChange,\n defaultSelectedAsset = null,\n renderPreview,\n}: ContextPanelProviderProps) {\n const isMobile = useIsMobile();\n const [openMobile, setOpenMobile] = useState(false);\n\n // Controlled/uncontrolled per component-api.md: controlled iff the prop is\n // provided; the mode never flips mid-life.\n const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n const openControlled = openProp !== undefined;\n const open = openControlled ? openProp : uncontrolledOpen;\n\n const [uncontrolledView, setUncontrolledView] = useState<ContextPanelView>(defaultView);\n const viewControlled = viewProp !== undefined;\n const view = viewControlled ? viewProp : uncontrolledView;\n\n const [uncontrolledAsset, setUncontrolledAsset] = useState<ContextAsset | null>(\n defaultSelectedAsset,\n );\n const assetControlled = selectedAssetProp !== undefined;\n const selectedAsset = assetControlled ? selectedAssetProp : uncontrolledAsset;\n\n const panelId = useId();\n const titleId = useId();\n /** Where focus returns on `back()` — the originating tree row (09 §B.5). */\n const returnFocusRef = useRef<HTMLElement | null>(null);\n /** Where focus lands on `openDetail()` — the BACK control in the header. */\n const detailFocusRef = useRef<HTMLElement | null>(null);\n\n const setOpen = useCallback(\n (value: boolean | ((open: boolean) => boolean)) => {\n const next = typeof value === \"function\" ? value(open) : value;\n if (!openControlled) setUncontrolledOpen(next);\n onOpenChange?.(next);\n // Persistence: the SidebarProvider cookie pattern (research 09 §B.1).\n if (typeof document !== \"undefined\") {\n document.cookie = `${CONTEXT_PANEL_COOKIE_NAME}=${next}; path=/; max-age=${CONTEXT_PANEL_COOKIE_MAX_AGE}`;\n }\n },\n [onOpenChange, open, openControlled],\n );\n\n const toggle = useCallback(() => {\n if (isMobile) setOpenMobile((o) => !o);\n else setOpen((o) => !o);\n }, [isMobile, setOpen]);\n\n const setView = useCallback(\n (next: ContextPanelView) => {\n if (!viewControlled) setUncontrolledView(next);\n onViewChange?.(next);\n },\n [onViewChange, viewControlled],\n );\n\n const setSelectedAsset = useCallback(\n (next: ContextAsset | null) => {\n if (!assetControlled) setUncontrolledAsset(next);\n onSelectedAssetChange?.(next);\n },\n [assetControlled, onSelectedAssetChange],\n );\n\n const openDetail = useCallback(\n (asset: ContextAsset) => {\n // Drilling while collapsed auto-opens first (research 09 §G.1).\n if (isMobile) setOpenMobile(true);\n else if (!open) setOpen(true);\n // Stash the originating row so back() can restore focus (09 §B.5).\n if (typeof document !== \"undefined\" && document.activeElement instanceof HTMLElement) {\n returnFocusRef.current = document.activeElement;\n }\n // The v2 `useViewTransition` seam: this state change is the `mutate`\n // callback a future vt.run({ recipe: \"nav-forward\" }) will wrap (09 §B.3).\n setView(\"detail\");\n setSelectedAsset(asset);\n // Focus management is independent of the animation (VT guardrail §8):\n // land on the BACK control after the swap, never on transition end.\n requestAnimationFrame(() => detailFocusRef.current?.focus());\n },\n [isMobile, open, setOpen, setSelectedAsset, setView],\n );\n\n const back = useCallback(() => {\n // The v2 seam: the `mutate` a future vt.run({ recipe: \"nav-back\" }) wraps.\n setView(\"root\");\n requestAnimationFrame(() => {\n const target = returnFocusRef.current;\n if (target?.isConnected) target.focus();\n });\n }, [setView]);\n\n const contextValue = useMemo<ContextPanelContextValue>(\n () => ({\n state: { open, view, selectedAsset },\n actions: { toggle, setOpen, openDetail, back },\n meta: { isMobile, openMobile, setOpenMobile, renderPreview },\n }),\n [\n back,\n isMobile,\n open,\n openDetail,\n openMobile,\n renderPreview,\n selectedAsset,\n setOpen,\n toggle,\n view,\n ],\n );\n\n const internalValue = useMemo<ContextPanelInternalValue>(\n () => ({ panelId, titleId, detailFocusRef }),\n [panelId, titleId],\n );\n\n return (\n <ContextPanelContext.Provider value={contextValue}>\n <ContextPanelInternalContext.Provider value={internalValue}>\n {children}\n </ContextPanelInternalContext.Provider>\n </ContextPanelContext.Provider>\n );\n}\n\nexport interface ContextPanelProps extends ComponentProps<\"div\"> {\n /** Expanded panel width (any CSS length). Default `\"20rem\"`. */\n width?: string;\n}\n\n/**\n * The always-mounted shell. On desktop it animates its OWN width via the\n * canonical `useCollapsiblePanel` two-element tween — bounded to the SHELL\n * (a relative group + absolute container), not the viewport (09 §B.2). Below\n * the mobile breakpoint it renders a `Sheet side=\"right\"` with the same\n * children, driven by the same provider (09 §B.4).\n */\nexport const ContextPanel = forwardRef<HTMLDivElement, ContextPanelProps>(function ContextPanel(\n { width = CONTEXT_PANEL_WIDTH, className, style, children, ...props },\n ref,\n) {\n const { state, actions, meta } = useContextPanel();\n const { panelId } = useContextPanelInternal();\n const { t } = useLocale();\n\n const panel = useCollapsiblePanel({\n side: \"right\",\n open: state.open,\n onOpenChange: actions.setOpen,\n widthClassName: \"w-(--context-panel-width)\",\n spacerCollapsedClassName: \"group-data-[state=collapsed]:w-0\",\n containerSlideClassNames: {\n left: \"left-0 group-data-[state=collapsed]:left-[calc(var(--context-panel-width)*-1)]\",\n right: \"right-0 group-data-[state=collapsed]:right-[calc(var(--context-panel-width)*-1)]\",\n },\n });\n\n if (meta.isMobile) {\n return (\n <Sheet open={meta.openMobile} onOpenChange={meta.setOpenMobile}>\n <SheetContent\n id={panelId}\n side=\"right\"\n data-slot=\"context-panel\"\n data-mobile=\"true\"\n className=\"w-(--context-panel-width) gap-0 p-0\"\n style={{ \"--context-panel-width\": CONTEXT_PANEL_WIDTH_MOBILE } as CSSProperties}\n >\n <SheetHeader className=\"sr-only\">\n <SheetTitle>{t(\"ai.contextPanel.title\")}</SheetTitle>\n <SheetDescription>{t(\"ai.contextPanel.description\")}</SheetDescription>\n </SheetHeader>\n <div className=\"flex h-full w-full flex-col\">{children}</div>\n </SheetContent>\n </Sheet>\n );\n }\n\n return (\n <div\n ref={ref}\n id={panelId}\n data-slot=\"context-panel\"\n // Collapsed container is inert (09 §B.5 — Sidebar gets this free via\n // `hidden`; the right rail must do it explicitly).\n inert={state.open ? undefined : true}\n className={cn(\"group relative hidden overflow-hidden md:block\", className)}\n style={{ \"--context-panel-width\": width, ...style } as CSSProperties}\n {...panel.attrs}\n {...props}\n >\n <div data-slot=\"context-panel-gap\" className={panel.spacerClassName} />\n <div\n data-slot=\"context-panel-container\"\n // The deliberate Sidebar divergence (09 §B.2): bound to the shell, not\n // the viewport — `absolute` within the relative group, full height.\n className={cn(panel.containerClassName, \"absolute inset-y-0 flex h-full border-s\")}\n >\n {/* Detail-tier surface: raised `card`, robust across themes (#193). */}\n <div data-slot=\"context-panel-inner\" className=\"flex h-full w-full flex-col bg-card\">\n {children}\n </div>\n </div>\n </div>\n );\n});\n\nexport type ContextPanelTriggerProps = ComponentProps<typeof Button>;\n\n/** Toggle button — placeable ANYWHERE inside the provider (e.g. the app header). */\nexport const ContextPanelTrigger = forwardRef<HTMLButtonElement, ContextPanelTriggerProps>(\n function ContextPanelTrigger({ className, onClick, children, ...props }, ref) {\n const { t } = useLocale();\n const { state, actions, meta } = useContextPanel();\n const { panelId } = useContextPanelInternal();\n const expanded = meta.isMobile ? meta.openMobile : state.open;\n return (\n <Button\n ref={ref}\n data-slot=\"context-panel-trigger\"\n variant=\"ghost\"\n size=\"icon\"\n aria-expanded={expanded}\n aria-controls={panelId}\n aria-label={t(\"ai.contextPanel.toggle\")}\n className={cn(\"size-7\", className)}\n onClick={(event) => {\n onClick?.(event);\n actions.toggle();\n }}\n {...props}\n >\n {children ?? <PanelRightIcon aria-hidden=\"true\" />}\n </Button>\n );\n },\n);\n\nexport interface ContextPanelHeaderProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n /** Root-view title. Default `\"Context\"`. */\n title?: ReactNode;\n}\n\n/**\n * Title row. In the detail view it hosts the BACK control (a real button —\n * \"tab-panel swap\", not a breadcrumb) and shows the focused asset's name.\n */\nexport const ContextPanelHeader = forwardRef<HTMLDivElement, ContextPanelHeaderProps>(\n function ContextPanelHeader({ title = \"Context\", className, children, ...props }, ref) {\n const { t } = useLocale();\n const { state, actions } = useContextPanel();\n const { titleId, detailFocusRef } = useContextPanelInternal();\n const isDetail = state.view === \"detail\";\n return (\n <div\n ref={ref}\n data-slot=\"context-panel-header\"\n className={cn(\"flex h-header shrink-0 items-center gap-2 border-b px-3\", className)}\n {...props}\n >\n {isDetail ? (\n <Button\n ref={(node) => {\n detailFocusRef.current = node;\n }}\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n data-slot=\"context-panel-back\"\n aria-label={t(\"ai.contextPanel.back\")}\n className=\"gap-1 px-2 text-muted-foreground\"\n onClick={() => actions.back()}\n >\n <ChevronLeftIcon className=\"size-4\" aria-hidden=\"true\" data-rtl-flip />\n Back\n </Button>\n ) : null}\n <h2 id={titleId} className=\"min-w-0 truncate text-title\">\n {isDetail ? (state.selectedAsset?.name ?? title) : title}\n </h2>\n {children ? <div className=\"ms-auto flex items-center gap-1\">{children}</div> : null}\n </div>\n );\n },\n);\n\nexport interface ContextPanelBodyProps extends HTMLAttributes<HTMLDivElement> {\n /** Root view — the labelled sections (status / grounding / produced assets). */\n root: ReactNode;\n /** Detail view — typically `<ContextPanelDetail><AssetPreview …/></ContextPanelDetail>`. */\n detail: ReactNode;\n /** Accessible name of the region. Default `\"Context\"`. */\n label?: string;\n}\n\n/**\n * The two-view container that owns the drill-in. v1: a CSS-gated two-pane\n * translateX track (both panes mounted, transform-only, `duration-base` +\n * explicit `motion-reduce:` neutralizer). The off-screen pane is `aria-hidden`\n * AND `inert` so Tab can't land in it mid-slide (09 §B.3/§B.5). The panes'\n * `data-vt-pane` identities are the v2 `useViewTransition` seam.\n */\nexport const ContextPanelBody = forwardRef<HTMLDivElement, ContextPanelBodyProps>(\n function ContextPanelBody({ root, detail, label = \"Context\", className, ...props }, ref) {\n const { state } = useContextPanel();\n const isDetail = state.view === \"detail\";\n\n // Announce, don't steal focus mid-animation (09 §B.5). Skip the initial view.\n const [announcement, setAnnouncement] = useState(\"\");\n const previousView = useRef(state.view);\n useEffect(() => {\n if (previousView.current === state.view) return;\n previousView.current = state.view;\n setAnnouncement(\n state.view === \"detail\"\n ? `Showing ${state.selectedAsset?.name ?? \"asset detail\"}`\n : \"Back to context\",\n );\n }, [state.selectedAsset, state.view]);\n\n return (\n <div\n ref={ref}\n role=\"region\"\n aria-label={label}\n data-slot=\"context-panel-body\"\n className={cn(\"relative min-h-0 flex-1 overflow-hidden\", className)}\n {...props}\n >\n <div aria-live=\"polite\" className=\"sr-only\">\n {announcement}\n </div>\n <div\n data-slot=\"context-panel-track\"\n className=\"flex h-full w-[200%] transition-transform duration-base ease-standard motion-reduce:transition-none\"\n style={{ transform: isDetail ? \"translateX(-50%)\" : \"translateX(0)\" }}\n >\n <div\n data-vt-pane=\"root\"\n aria-hidden={isDetail}\n inert={isDetail ? true : undefined}\n className=\"flex h-full w-1/2 flex-col gap-5 overflow-y-auto p-4\"\n >\n {root}\n </div>\n <div\n data-vt-pane=\"detail\"\n aria-hidden={!isDetail}\n inert={isDetail ? undefined : true}\n className=\"h-full w-1/2 overflow-y-auto\"\n >\n {detail}\n </div>\n </div>\n </div>\n );\n },\n);\n\nexport interface ContextPanelSectionProps extends HTMLAttributes<HTMLElement> {\n /** Section label — a quiet `text-meta` heading, not a box (research 08). */\n label?: ReactNode;\n}\n\n/** A labelled root-view section (status / grounding / produced assets). */\nexport const ContextPanelSection = forwardRef<HTMLElement, ContextPanelSectionProps>(\n function ContextPanelSection({ label, className, children, ...props }, ref) {\n return (\n <section\n ref={ref}\n data-slot=\"context-panel-section\"\n className={cn(\"flex shrink-0 flex-col gap-2\", className)}\n {...props}\n >\n {label ? <h3 className=\"text-meta text-muted-foreground\">{label}</h3> : null}\n {children}\n </section>\n );\n },\n);\n\nexport type ContextPanelDetailProps = HTMLAttributes<HTMLDivElement>;\n\n/** The focused single-asset view — hosts `<AssetPreview>` (research 04 §5). */\nexport const ContextPanelDetail = forwardRef<HTMLDivElement, ContextPanelDetailProps>(\n function ContextPanelDetail({ className, ...props }, ref) {\n return (\n <div\n ref={ref}\n data-slot=\"context-panel-detail\"\n className={cn(\"flex min-h-full flex-col p-4\", className)}\n {...props}\n />\n );\n },\n);\n"],"mappings":"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","names":["ContextPanel","ContextPanelTrigger","ContextPanelHeader","ContextPanelBody","ContextPanelSection","ContextPanelDetail"]}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
LazyEngineBoundary
|
|
4
|
+
} from "./chunk-S3ISPW3A.js";
|
|
5
|
+
|
|
6
|
+
// src/audio-player.tsx
|
|
7
|
+
import { Skeleton, isOptionalPeerMissing, useLocale } from "@elabs-ai/components-ui";
|
|
8
|
+
import { cn } from "@elabs-ai/components-ui/lib/cn";
|
|
9
|
+
import { VolumeOffIcon } from "lucide-react";
|
|
10
|
+
import { lazy, Suspense } from "react";
|
|
11
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
var lazyPart = (pick) => lazy(() => import("./_audio-player-media-chrome.js").then((m) => ({ default: pick(m) })));
|
|
13
|
+
var AudioPlayerImpl = lazyPart((m) => m.AudioPlayer);
|
|
14
|
+
var AudioPlayerMissing = ({ className, error }) => {
|
|
15
|
+
const { t } = useLocale();
|
|
16
|
+
const isPeerMissing = isOptionalPeerMissing(error);
|
|
17
|
+
return /* @__PURE__ */ jsxs(
|
|
18
|
+
"div",
|
|
19
|
+
{
|
|
20
|
+
className: cn(
|
|
21
|
+
"flex h-10 w-full items-center gap-2 rounded-md border border-dashed border-border bg-muted/30 px-3 text-caption text-muted-foreground",
|
|
22
|
+
className
|
|
23
|
+
),
|
|
24
|
+
role: isPeerMissing ? "status" : "alert",
|
|
25
|
+
children: [
|
|
26
|
+
/* @__PURE__ */ jsx(VolumeOffIcon, { "aria-hidden": "true", className: "size-4 shrink-0" }),
|
|
27
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: isPeerMissing ? t("ai.error.engineMissingBody", {
|
|
28
|
+
feature: t("ai.audioPlayer.feature"),
|
|
29
|
+
packages: "media-chrome"
|
|
30
|
+
}) : t("ai.audioPlayer.renderError") })
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
var AudioPlayer = ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
36
|
+
LazyEngineBoundary,
|
|
37
|
+
{
|
|
38
|
+
renderMissing: (error) => /* @__PURE__ */ jsx(AudioPlayerMissing, { className, error }),
|
|
39
|
+
children: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(Skeleton, { className: cn("h-10 w-full rounded-md", className) }), children: /* @__PURE__ */ jsx(AudioPlayerImpl, { className, "data-slot": "audio-player", ...props }) })
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
var AudioPlayerElement = ({ ...props }) => (
|
|
43
|
+
// oxlint-disable-next-line eslint-plugin-jsx-a11y(media-has-caption) -- audio player captions are provided by consumer
|
|
44
|
+
/* @__PURE__ */ jsx(
|
|
45
|
+
"audio",
|
|
46
|
+
{
|
|
47
|
+
"data-slot": "audio-player-element",
|
|
48
|
+
slot: "media",
|
|
49
|
+
src: "src" in props ? props.src : `data:${props.data.mediaType};base64,${props.data.base64}`,
|
|
50
|
+
...props
|
|
51
|
+
}
|
|
52
|
+
)
|
|
53
|
+
);
|
|
54
|
+
var AudioPlayerControlBarImpl = lazyPart(
|
|
55
|
+
(m) => m.AudioPlayerControlBar
|
|
56
|
+
);
|
|
57
|
+
var AudioPlayerControlBar = (props) => /* @__PURE__ */ jsx(LazyEngineBoundary, { renderMissing: () => null, children: /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(AudioPlayerControlBarImpl, { "data-slot": "audio-player-control-bar", ...props }) }) });
|
|
58
|
+
var AudioPlayerPlayButtonImpl = lazyPart(
|
|
59
|
+
(m) => m.AudioPlayerPlayButton
|
|
60
|
+
);
|
|
61
|
+
var AudioPlayerPlayButton = (props) => /* @__PURE__ */ jsx(LazyEngineBoundary, { renderMissing: () => null, children: /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(AudioPlayerPlayButtonImpl, { "data-slot": "audio-player-play-button", ...props }) }) });
|
|
62
|
+
var AudioPlayerSeekBackwardButtonImpl = lazyPart(
|
|
63
|
+
(m) => m.AudioPlayerSeekBackwardButton
|
|
64
|
+
);
|
|
65
|
+
var AudioPlayerSeekBackwardButton = (props) => /* @__PURE__ */ jsx(LazyEngineBoundary, { renderMissing: () => null, children: /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(AudioPlayerSeekBackwardButtonImpl, { "data-slot": "audio-player-seek-backward-button", ...props }) }) });
|
|
66
|
+
var AudioPlayerSeekForwardButtonImpl = lazyPart(
|
|
67
|
+
(m) => m.AudioPlayerSeekForwardButton
|
|
68
|
+
);
|
|
69
|
+
var AudioPlayerSeekForwardButton = (props) => /* @__PURE__ */ jsx(LazyEngineBoundary, { renderMissing: () => null, children: /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(AudioPlayerSeekForwardButtonImpl, { "data-slot": "audio-player-seek-forward-button", ...props }) }) });
|
|
70
|
+
var AudioPlayerTimeDisplayImpl = lazyPart(
|
|
71
|
+
(m) => m.AudioPlayerTimeDisplay
|
|
72
|
+
);
|
|
73
|
+
var AudioPlayerTimeDisplay = (props) => /* @__PURE__ */ jsx(LazyEngineBoundary, { renderMissing: () => null, children: /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(AudioPlayerTimeDisplayImpl, { "data-slot": "audio-player-time-display", ...props }) }) });
|
|
74
|
+
var AudioPlayerTimeRangeImpl = lazyPart((m) => m.AudioPlayerTimeRange);
|
|
75
|
+
var AudioPlayerTimeRange = (props) => /* @__PURE__ */ jsx(LazyEngineBoundary, { renderMissing: () => null, children: /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(AudioPlayerTimeRangeImpl, { "data-slot": "audio-player-time-range", ...props }) }) });
|
|
76
|
+
var AudioPlayerDurationDisplayImpl = lazyPart(
|
|
77
|
+
(m) => m.AudioPlayerDurationDisplay
|
|
78
|
+
);
|
|
79
|
+
var AudioPlayerDurationDisplay = (props) => /* @__PURE__ */ jsx(LazyEngineBoundary, { renderMissing: () => null, children: /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(AudioPlayerDurationDisplayImpl, { "data-slot": "audio-player-duration-display", ...props }) }) });
|
|
80
|
+
var AudioPlayerMuteButtonImpl = lazyPart(
|
|
81
|
+
(m) => m.AudioPlayerMuteButton
|
|
82
|
+
);
|
|
83
|
+
var AudioPlayerMuteButton = (props) => /* @__PURE__ */ jsx(LazyEngineBoundary, { renderMissing: () => null, children: /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(AudioPlayerMuteButtonImpl, { "data-slot": "audio-player-mute-button", ...props }) }) });
|
|
84
|
+
var AudioPlayerVolumeRangeImpl = lazyPart(
|
|
85
|
+
(m) => m.AudioPlayerVolumeRange
|
|
86
|
+
);
|
|
87
|
+
var AudioPlayerVolumeRange = (props) => /* @__PURE__ */ jsx(LazyEngineBoundary, { renderMissing: () => null, children: /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(AudioPlayerVolumeRangeImpl, { "data-slot": "audio-player-volume-range", ...props }) }) });
|
|
88
|
+
|
|
89
|
+
export {
|
|
90
|
+
AudioPlayer,
|
|
91
|
+
AudioPlayerElement,
|
|
92
|
+
AudioPlayerControlBar,
|
|
93
|
+
AudioPlayerPlayButton,
|
|
94
|
+
AudioPlayerSeekBackwardButton,
|
|
95
|
+
AudioPlayerSeekForwardButton,
|
|
96
|
+
AudioPlayerTimeDisplay,
|
|
97
|
+
AudioPlayerTimeRange,
|
|
98
|
+
AudioPlayerDurationDisplay,
|
|
99
|
+
AudioPlayerMuteButton,
|
|
100
|
+
AudioPlayerVolumeRange
|
|
101
|
+
};
|
|
102
|
+
//# sourceMappingURL=chunk-NSCLRHES.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/audio-player.tsx"],"sourcesContent":["\"use client\";\n\nimport { Skeleton, isOptionalPeerMissing, useLocale } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport type { Experimental_SpeechResult as SpeechResult } from \"ai\";\nimport { VolumeOffIcon } from \"lucide-react\";\nimport type { ComponentProps, ComponentType, HTMLAttributes } from \"react\";\nimport { lazy, Suspense } from \"react\";\n\nimport { LazyEngineBoundary } from \"./_lazy-engine-boundary\";\n\n/**\n * media-chrome lives behind a dynamic import — it declares no `sideEffects`, so\n * a static import would put the whole custom-element library in every consumer's\n * entry chunk, `AudioPlayer` rendered or not. Every value import lives in\n * `_audio-player-media-chrome.tsx`. See ADR 0019 and `pnpm heavy-deps:check`.\n *\n * All ten parts resolve from the SAME module specifier, so they share one chunk:\n * once `AudioPlayer` has loaded it, the controls inside it resolve from cache.\n *\n * Issue #101: `media-chrome` is an OPTIONAL peer, so no PUBLIC export's type\n * may structurally reference `media-chrome/react`'s own types (previously\n * `ComponentProps<typeof MediaController>` and nine siblings, imported as\n * TYPE-only above) — doing so names `media-chrome/react`'s module specifier in\n * this package's generated root `.d.ts` and hands a `skipLibCheck: false`\n * consumer who has correctly omitted the peer a `TS2307` just for importing\n * the barrel — not just for using `AudioPlayer`. `AudioPlayerPartProps` below\n * is an OWNED base type: `media-chrome/react`'s wrapper\n * (`media-chrome/react`'s `createComponent`, from the `ce-la-react` helper it\n * is built on) types every part as `Omit<HTMLAttributes<I>, …> &\n * Partial<the element's own instance members>` — i.e. ordinary HTML attributes\n * plus a handful of optional custom attributes. `AudioPlayerPartProps` itself\n * stays ordinary HTML attributes only; the PRIMITIVE-typed (`string` /\n * `boolean` / `number`) extra instance members of `<media-controller>` and\n * `<media-seek-forward-button>` — the two elements measured by the round-2\n * validator — are mirrored one-by-one on `AudioPlayerProps` and\n * `AudioPlayerSeekForwardButtonProps` below (each a single declaration line\n * referencing nothing peer-owned, the same technique `seekOffset` already\n * used). What stays narrowed to `AudioPlayerPartProps` alone are the\n * PEER/COMPLEX-typed members (`MediaStore`, `AttributeTokenList`,\n * `MediaTooltip`, `TooltipPlacement`, DOM-element and `HTMLMediaElement`\n * callbacks, methods) and every member of the other eight parts — restoring\n * those would re-import the peer type graph this fix exists to avoid. See the\n * CHANGELOG's \"Breaking (types)\" entry for the exact narrowed set.\n * `AudioPlayerPartProps` is therefore NOT a full replica of media-chrome's\n * surface, only the base every part actually uses and re-exports (the same\n * scoping `TerminalColorTheme` uses for xterm's `ITheme` in\n * `packages/terminal/src/interactive-terminal.tsx`, also issue #101). The ten\n * conformance assertions at the bottom of `_audio-player-media-chrome.tsx`\n * (which still imports the real peer types — that module is reached only\n * through `lazy()` and never sits in the barrel's declaration graph) prove\n * every owned type here stays assignable to its real media-chrome counterpart;\n * a peer version bump that narrows a prop incompatibly fails\n * `pnpm --filter @elabs-ai/components-ai typecheck` locally instead of\n * reaching a consumer as silent drift.\n *\n * Deliberately no `ref` field: `ComponentProps<typeof MediaController>` (and\n * its nine siblings) included one via `RefAttributes<I>`, but `RefObject<T>`'s\n * mutable `current` makes ref types INVARIANT in `T` — a `Ref<HTMLElement>`\n * can never be assignable to a real element's own `Ref<MediaController>` (the\n * custom element subclass carries private/extra members `HTMLElement` lacks),\n * so keeping it would make every owned type fail its own conformance\n * assertion below. This IS a real-world break for a React 19 consumer: none\n * of the ten parts this package renders is wrapped in `forwardRef`, but\n * `MediaController` (and its siblings) are genuine `forwardRef` components,\n * and React 19's ref-as-prop carries a `ref` straight through an ordinary\n * function component's `{...props}` spread to the real underlying element —\n * see the CHANGELOG's \"Breaking (types)\" entry for the measured detail. It is\n * inert only under React 18.\n */\nexport type AudioPlayerPartProps = HTMLAttributes<HTMLElement>;\n\ntype MediaChromeModule = typeof import(\"./_audio-player-media-chrome\");\n\nconst lazyPart = <P,>(pick: (module: MediaChromeModule) => ComponentType<P>) =>\n lazy(() => import(\"./_audio-player-media-chrome\").then((m) => ({ default: pick(m) })));\n\n/**\n * The primitive-typed (`string`/`boolean`/`number`) extra instance members of\n * `media-chrome/react`'s `MediaController` — restored per issue #101's round-2\n * validation (R2): each is a single declaration line mirroring the real peer\n * type's name and shape, referencing nothing peer-owned, so it costs nothing\n * against the `.d.ts` leak this fix exists to prevent. Deliberately EXCLUDED:\n * `audio` (already narrowed out — `_audio-player-media-chrome.tsx`'s\n * conformance assertion Omits it from the real `ComponentProps`, since this\n * package renders its own `<AudioPlayerElement>` instead of passing one\n * through), and every PEER/COMPLEX-typed member (`mediaStore`, `hotkeys`\n * (`AttributeTokenList`), `media`/`fullscreenElement` (DOM elements),\n * `mediaStateReceivers`, `associatedElementSubscriptions`, every\n * `HTMLMediaElement` callback and every method) — those stay narrowed to\n * `AudioPlayerPartProps` alone; restoring them would re-import the peer type\n * graph. See `_audio-player-media-chrome.tsx`'s\n * `_AudioPlayerPropsConformance` assertion, which fails typecheck if this\n * interface ever drifts wider than the real element's own props.\n *\n * Doc comments below are inferred from each member's name and media-chrome's\n * public attribute-naming convention (`no*` = boolean opt-out of the\n * corresponding default-on behavior) — media-chrome ships no per-property doc\n * comments in its own `.d.ts` or README to copy from. Treat them as a reading\n * aid, not an authoritative spec; verify against media-chrome's source before\n * relying on exact semantics.\n */\nexport interface AudioPlayerProps extends AudioPlayerPartProps {\n /** Seconds of inactivity before controls hide; a string because it mirrors the HTML attribute value. */\n autohide?: string;\n /** Also autohide while the pointer is over the control elements themselves, not just the media. */\n autohideOverControls?: boolean;\n /** Breakpoint definitions (space-separated `name:width` pairs) driving `breakpointsComputed`. */\n breakpoints?: string;\n /** Whether the controller has computed its current breakpoint(s) at least once. */\n breakpointsComputed?: boolean;\n /** Fallback duration (seconds) to display before the real media duration is known. */\n defaultDuration?: number;\n /** Default stream type (\"on-demand\" or \"live\") before the media has resolved its own. */\n defaultStreamType?: string;\n /** Whether subtitles/captions are enabled by default. */\n defaultSubtitles?: boolean;\n /** Disables the controller's built-in tap/gesture handling (e.g. tap-to-play, double-tap-to-seek). */\n gesturesDisabled?: boolean;\n /** Whether hotkey keyboard control is currently active on the controller. */\n keyboardControl?: boolean;\n /** Space-separated list of hotkey names currently in use, for conflict detection with other listeners. */\n keysUsed?: string;\n /** Seconds behind the live edge still considered \"at\" live, for a live stream's seek range. */\n liveEdgeOffset?: number;\n /** Disables the controller's autohide-controls-on-inactivity behavior entirely. */\n noAutohide?: boolean;\n /** Disables automatically seeking back to the live edge after a manual seek on a live stream. */\n noAutoSeekToLive?: boolean;\n /** Opts out of the controller creating its own default internal media store. */\n noDefaultStore?: boolean;\n /** Disables the controller's built-in keyboard hotkeys entirely. */\n noHotkeys?: boolean;\n /** Opts out of remembering the user's mute preference across sessions. */\n noMutedPref?: boolean;\n /** Opts out of remembering the user's subtitles-language preference across sessions. */\n noSubtitlesLangPref?: boolean;\n /** Opts out of remembering the user's volume preference across sessions. */\n noVolumePref?: boolean;\n /** The language the controller resolved for its UI text, after applying any language preference. */\n resolvedLang?: string;\n /** Whether the user has interacted with the controller yet (affects autoplay-adjacent UI). */\n userInteractive?: boolean;\n}\n\nconst AudioPlayerImpl = lazyPart<AudioPlayerProps>((m) => m.AudioPlayer);\n\n/**\n * The settled-failure stand-in for the `LazyEngineBoundary` above — rendered\n * once the `media-chrome` load has genuinely failed, never while it is still\n * pending (that stays `Skeleton`, via the `Suspense fallback` below). A\n * loading skeleton left in place after a settled failure reads as \"still\n * loading, forever\" (loading-states.md) — this is a terminal state, so it\n * gets a real (if compact) notice instead, sized to the same `h-10` slot so\n * nothing shifts when the boundary trips.\n */\nconst AudioPlayerMissing = ({ className, error }: { className?: string; error: unknown }) => {\n const { t } = useLocale();\n const isPeerMissing = isOptionalPeerMissing(error);\n return (\n <div\n className={cn(\n \"flex h-10 w-full items-center gap-2 rounded-md border border-dashed border-border bg-muted/30 px-3 text-caption text-muted-foreground\",\n className,\n )}\n role={isPeerMissing ? \"status\" : \"alert\"}\n >\n <VolumeOffIcon aria-hidden=\"true\" className=\"size-4 shrink-0\" />\n <span className=\"truncate\">\n {isPeerMissing\n ? t(\"ai.error.engineMissingBody\", {\n feature: t(\"ai.audioPlayer.feature\"),\n packages: \"media-chrome\",\n })\n : t(\"ai.audioPlayer.renderError\")}\n </span>\n </div>\n );\n};\n\nexport const AudioPlayer = ({ className, ...props }: AudioPlayerProps) => (\n <LazyEngineBoundary\n renderMissing={(error) => <AudioPlayerMissing className={className} error={error} />}\n >\n <Suspense fallback={<Skeleton className={cn(\"h-10 w-full rounded-md\", className)} />}>\n <AudioPlayerImpl className={className} data-slot=\"audio-player\" {...props} />\n </Suspense>\n </LazyEngineBoundary>\n);\n\nexport type AudioPlayerElementProps = Omit<ComponentProps<\"audio\">, \"src\"> &\n (\n | {\n data: SpeechResult[\"audio\"];\n }\n | {\n src: string;\n }\n );\n\nexport const AudioPlayerElement = ({ ...props }: AudioPlayerElementProps) => (\n // oxlint-disable-next-line eslint-plugin-jsx-a11y(media-has-caption) -- audio player captions are provided by consumer\n <audio\n data-slot=\"audio-player-element\"\n slot=\"media\"\n src={\"src\" in props ? props.src : `data:${props.data.mediaType};base64,${props.data.base64}`}\n {...props}\n />\n);\n\nexport type AudioPlayerControlBarProps = AudioPlayerPartProps;\n\nconst AudioPlayerControlBarImpl = lazyPart<AudioPlayerControlBarProps>(\n (m) => m.AudioPlayerControlBar,\n);\n\nexport const AudioPlayerControlBar = (props: AudioPlayerControlBarProps) => (\n <LazyEngineBoundary renderMissing={() => null}>\n <Suspense fallback={null}>\n <AudioPlayerControlBarImpl data-slot=\"audio-player-control-bar\" {...props} />\n </Suspense>\n </LazyEngineBoundary>\n);\n\nexport type AudioPlayerPlayButtonProps = AudioPlayerPartProps;\n\nconst AudioPlayerPlayButtonImpl = lazyPart<AudioPlayerPlayButtonProps>(\n (m) => m.AudioPlayerPlayButton,\n);\n\nexport const AudioPlayerPlayButton = (props: AudioPlayerPlayButtonProps) => (\n <LazyEngineBoundary renderMissing={() => null}>\n <Suspense fallback={null}>\n <AudioPlayerPlayButtonImpl data-slot=\"audio-player-play-button\" {...props} />\n </Suspense>\n </LazyEngineBoundary>\n);\n\nexport interface AudioPlayerSeekBackwardButtonProps extends AudioPlayerPartProps {\n /** Skip distance in seconds. Mirrors the element's own default (10). */\n seekOffset?: number;\n}\n\nconst AudioPlayerSeekBackwardButtonImpl = lazyPart<AudioPlayerSeekBackwardButtonProps>(\n (m) => m.AudioPlayerSeekBackwardButton,\n);\n\nexport const AudioPlayerSeekBackwardButton = (props: AudioPlayerSeekBackwardButtonProps) => (\n <LazyEngineBoundary renderMissing={() => null}>\n <Suspense fallback={null}>\n <AudioPlayerSeekBackwardButtonImpl data-slot=\"audio-player-seek-backward-button\" {...props} />\n </Suspense>\n </LazyEngineBoundary>\n);\n\n/**\n * Primitive-typed extra members restored per issue #101's round-2 validation\n * (R2) — same technique and same inferred-from-naming caveat as\n * `AudioPlayerProps` above. Deliberately still narrowed out:\n * `keysUsed` (here typed `string[]`, unlike the controller's own `string`\n * member of the same name — an array is not primitive) and the DOM/method\n * members `disable`/`enable`/`handleClick`/`tooltipEl`/`tooltipPlacement`.\n */\nexport interface AudioPlayerSeekForwardButtonProps extends AudioPlayerPartProps {\n /** Whether the button is disabled. */\n disabled?: boolean;\n /** ID of the `<media-controller>` element this button controls, when it is not an ancestor. */\n mediaController?: string;\n /** The media's current playback time (seconds), as reflected by the controller's media store. */\n mediaCurrentTime?: number;\n /** Skip distance in seconds. Mirrors the element's own default (10). */\n seekOffset?: number;\n /** Suppresses the built-in hover tooltip on this button. */\n noTooltip?: boolean;\n /** Prevents the button's default click handling (for a consumer that wants to fully own the behavior). */\n preventClick?: boolean;\n}\n\nconst AudioPlayerSeekForwardButtonImpl = lazyPart<AudioPlayerSeekForwardButtonProps>(\n (m) => m.AudioPlayerSeekForwardButton,\n);\n\nexport const AudioPlayerSeekForwardButton = (props: AudioPlayerSeekForwardButtonProps) => (\n <LazyEngineBoundary renderMissing={() => null}>\n <Suspense fallback={null}>\n <AudioPlayerSeekForwardButtonImpl data-slot=\"audio-player-seek-forward-button\" {...props} />\n </Suspense>\n </LazyEngineBoundary>\n);\n\nexport type AudioPlayerTimeDisplayProps = AudioPlayerPartProps;\n\nconst AudioPlayerTimeDisplayImpl = lazyPart<AudioPlayerTimeDisplayProps>(\n (m) => m.AudioPlayerTimeDisplay,\n);\n\nexport const AudioPlayerTimeDisplay = (props: AudioPlayerTimeDisplayProps) => (\n <LazyEngineBoundary renderMissing={() => null}>\n <Suspense fallback={null}>\n <AudioPlayerTimeDisplayImpl data-slot=\"audio-player-time-display\" {...props} />\n </Suspense>\n </LazyEngineBoundary>\n);\n\nexport type AudioPlayerTimeRangeProps = AudioPlayerPartProps;\n\nconst AudioPlayerTimeRangeImpl = lazyPart<AudioPlayerTimeRangeProps>((m) => m.AudioPlayerTimeRange);\n\nexport const AudioPlayerTimeRange = (props: AudioPlayerTimeRangeProps) => (\n <LazyEngineBoundary renderMissing={() => null}>\n <Suspense fallback={null}>\n <AudioPlayerTimeRangeImpl data-slot=\"audio-player-time-range\" {...props} />\n </Suspense>\n </LazyEngineBoundary>\n);\n\nexport type AudioPlayerDurationDisplayProps = AudioPlayerPartProps;\n\nconst AudioPlayerDurationDisplayImpl = lazyPart<AudioPlayerDurationDisplayProps>(\n (m) => m.AudioPlayerDurationDisplay,\n);\n\nexport const AudioPlayerDurationDisplay = (props: AudioPlayerDurationDisplayProps) => (\n <LazyEngineBoundary renderMissing={() => null}>\n <Suspense fallback={null}>\n <AudioPlayerDurationDisplayImpl data-slot=\"audio-player-duration-display\" {...props} />\n </Suspense>\n </LazyEngineBoundary>\n);\n\nexport type AudioPlayerMuteButtonProps = AudioPlayerPartProps;\n\nconst AudioPlayerMuteButtonImpl = lazyPart<AudioPlayerMuteButtonProps>(\n (m) => m.AudioPlayerMuteButton,\n);\n\nexport const AudioPlayerMuteButton = (props: AudioPlayerMuteButtonProps) => (\n <LazyEngineBoundary renderMissing={() => null}>\n <Suspense fallback={null}>\n <AudioPlayerMuteButtonImpl data-slot=\"audio-player-mute-button\" {...props} />\n </Suspense>\n </LazyEngineBoundary>\n);\n\nexport type AudioPlayerVolumeRangeProps = AudioPlayerPartProps;\n\nconst AudioPlayerVolumeRangeImpl = lazyPart<AudioPlayerVolumeRangeProps>(\n (m) => m.AudioPlayerVolumeRange,\n);\n\nexport const AudioPlayerVolumeRange = (props: AudioPlayerVolumeRangeProps) => (\n <LazyEngineBoundary renderMissing={() => null}>\n <Suspense fallback={null}>\n <AudioPlayerVolumeRangeImpl data-slot=\"audio-player-volume-range\" {...props} />\n </Suspense>\n </LazyEngineBoundary>\n);\n"],"mappings":"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","names":[]}
|