@elabs-ai/components-ai 4.1.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/{_audio-player-media-chrome-T3XVXWRZ.js → _audio-player-media-chrome.js} +1 -1
- package/dist/_code-block-theme.js +12 -0
- package/dist/_code-block-theme.js.map +1 -0
- package/dist/{_flow-boundary-SHNWLQG5.js → _flow-boundary.js} +1 -1
- package/dist/_flow-boundary.js.map +1 -0
- package/dist/_flow-lazy.js +8 -0
- package/dist/_flow-lazy.js.map +1 -0
- package/dist/_lazy-boundary-conformance.js +2 -0
- package/dist/_lazy-boundary-conformance.js.map +1 -0
- package/dist/_lazy-cjk.js +13 -0
- package/dist/_lazy-cjk.js.map +1 -0
- package/dist/_lazy-engine-boundary.js +9 -0
- package/dist/_lazy-engine-boundary.js.map +1 -0
- package/dist/_lazy-math.js +13 -0
- package/dist/_lazy-math.js.map +1 -0
- package/dist/_lazy-mermaid.js +12 -0
- package/dist/_lazy-mermaid.js.map +1 -0
- package/dist/_mermaid-error-panel.js +9 -0
- package/dist/_mermaid-error-panel.js.map +1 -0
- package/dist/{_persona-rive-JEG44YHX.js → _persona-rive.js} +19 -24
- package/dist/_persona-rive.js.map +1 -0
- package/dist/_streamdown-i18n.js +21 -0
- package/dist/_streamdown-i18n.js.map +1 -0
- package/dist/_streamdown-safety.js +10 -0
- package/dist/_streamdown-safety.js.map +1 -0
- package/dist/_theme-scope-store.js +13 -0
- package/dist/_theme-scope-store.js.map +1 -0
- package/dist/a2ui/a2ui-surface.js +17 -0
- package/dist/a2ui/a2ui-surface.js.map +1 -0
- package/dist/a2ui/core/catalog.generated.js +10 -0
- package/dist/a2ui/core/catalog.generated.js.map +1 -0
- package/dist/a2ui/core/complete-json.js +10 -0
- package/dist/a2ui/core/complete-json.js.map +1 -0
- package/dist/a2ui/core/index.js +37 -0
- package/dist/a2ui/core/index.js.map +1 -0
- package/dist/a2ui/core/schema.js +11 -0
- package/dist/a2ui/core/schema.js.map +1 -0
- package/dist/a2ui/core/spec.js +10 -0
- package/dist/a2ui/core/spec.js.map +1 -0
- package/dist/a2ui/core/validate.js +16 -0
- package/dist/a2ui/core/validate.js.map +1 -0
- package/dist/a2ui/index.js +54 -0
- package/dist/a2ui/index.js.map +1 -0
- package/dist/a2ui/ui-catalog.js +18 -0
- package/dist/a2ui/ui-catalog.js.map +1 -0
- package/dist/agent-event.js +10 -0
- package/dist/agent-event.js.map +1 -0
- package/dist/agent-timeline.js +11 -0
- package/dist/agent-timeline.js.map +1 -0
- package/dist/agent.js +25 -0
- package/dist/agent.js.map +1 -0
- package/dist/artifact.js +23 -0
- package/dist/artifact.js.map +1 -0
- package/dist/asset-preview.js +22 -0
- package/dist/asset-preview.js.map +1 -0
- package/dist/attachments.js +33 -0
- package/dist/attachments.js.map +1 -0
- package/dist/audio-player.js +30 -0
- package/dist/audio-player.js.map +1 -0
- package/dist/audio-visualizer.js +9 -0
- package/dist/audio-visualizer.js.map +1 -0
- package/dist/canvas.js +10 -0
- package/dist/canvas.js.map +1 -0
- package/dist/chain-of-thought.js +22 -0
- package/dist/chain-of-thought.js.map +1 -0
- package/dist/chat-greeting.js +8 -0
- package/dist/chat-greeting.js.map +1 -0
- package/dist/chat-shell.js +9 -0
- package/dist/chat-shell.js.map +1 -0
- package/dist/checkpoint.js +13 -0
- package/dist/checkpoint.js.map +1 -0
- package/dist/chunk-2XOIG5TG.js +72 -0
- package/dist/chunk-2XOIG5TG.js.map +1 -0
- package/dist/chunk-34CQ2VHM.js +172 -0
- package/dist/chunk-34CQ2VHM.js.map +1 -0
- package/dist/chunk-3TDHPXZZ.js +60 -0
- package/dist/chunk-3TDHPXZZ.js.map +1 -0
- package/dist/chunk-3XNPMDZY.js +478 -0
- package/dist/chunk-3XNPMDZY.js.map +1 -0
- package/dist/chunk-3YPT3V7L.js +56 -0
- package/dist/chunk-3YPT3V7L.js.map +1 -0
- package/dist/chunk-475UEU2Q.js +87 -0
- package/dist/chunk-475UEU2Q.js.map +1 -0
- package/dist/chunk-4CBTII2I.js +95 -0
- package/dist/chunk-4CBTII2I.js.map +1 -0
- package/dist/chunk-4XRNIZMG.js +22 -0
- package/dist/chunk-4XRNIZMG.js.map +1 -0
- package/dist/chunk-5NNWUKK5.js +2 -0
- package/dist/chunk-5NNWUKK5.js.map +1 -0
- package/dist/chunk-5UOMU27Z.js +164 -0
- package/dist/chunk-5UOMU27Z.js.map +1 -0
- package/dist/chunk-5VGYZ62I.js +264 -0
- package/dist/chunk-5VGYZ62I.js.map +1 -0
- package/dist/chunk-6IQPH2OS.js +21 -0
- package/dist/chunk-6IQPH2OS.js.map +1 -0
- package/dist/chunk-6PB2MXCI.js +482 -0
- package/dist/chunk-6PB2MXCI.js.map +1 -0
- package/dist/chunk-7FD5CZEU.js +215 -0
- package/dist/chunk-7FD5CZEU.js.map +1 -0
- package/dist/chunk-7RL6KZDF.js +266 -0
- package/dist/chunk-7RL6KZDF.js.map +1 -0
- package/dist/chunk-ADOYAGGK.js +482 -0
- package/dist/chunk-ADOYAGGK.js.map +1 -0
- package/dist/chunk-AXMNJMMH.js +984 -0
- package/dist/chunk-AXMNJMMH.js.map +1 -0
- package/dist/chunk-BA3AEMOU.js +21 -0
- package/dist/chunk-BA3AEMOU.js.map +1 -0
- package/dist/chunk-BBHFOYML.js +336 -0
- package/dist/chunk-BBHFOYML.js.map +1 -0
- package/dist/chunk-BHUVISIY.js +221 -0
- package/dist/chunk-BHUVISIY.js.map +1 -0
- package/dist/chunk-BM2LWERA.js +100 -0
- package/dist/chunk-BM2LWERA.js.map +1 -0
- package/dist/chunk-CMOYXNPJ.js +211 -0
- package/dist/chunk-CMOYXNPJ.js.map +1 -0
- package/dist/chunk-CZP3RHC4.js +74 -0
- package/dist/chunk-CZP3RHC4.js.map +1 -0
- package/dist/chunk-DDG5JHQT.js +112 -0
- package/dist/chunk-DDG5JHQT.js.map +1 -0
- package/dist/chunk-DJODXO7I.js +38 -0
- package/dist/chunk-DJODXO7I.js.map +1 -0
- package/dist/chunk-DWJDJLPU.js +192 -0
- package/dist/chunk-DWJDJLPU.js.map +1 -0
- package/dist/chunk-DZW6LM22.js +45 -0
- package/dist/chunk-DZW6LM22.js.map +1 -0
- package/dist/chunk-ELGCZLZF.js +305 -0
- package/dist/chunk-ELGCZLZF.js.map +1 -0
- package/dist/chunk-EV3U6ZZB.js +209 -0
- package/dist/chunk-EV3U6ZZB.js.map +1 -0
- package/dist/chunk-EY7LVUKQ.js +87 -0
- package/dist/chunk-EY7LVUKQ.js.map +1 -0
- package/dist/chunk-F4C74F7M.js +230 -0
- package/dist/chunk-F4C74F7M.js.map +1 -0
- package/dist/chunk-FERYDFZA.js +108 -0
- package/dist/chunk-FERYDFZA.js.map +1 -0
- package/dist/chunk-FUIYG2DS.js +166 -0
- package/dist/chunk-FUIYG2DS.js.map +1 -0
- package/dist/chunk-GKYZT3LA.js +136 -0
- package/dist/chunk-GKYZT3LA.js.map +1 -0
- package/dist/chunk-H42LRUQ4.js +102 -0
- package/dist/chunk-H42LRUQ4.js.map +1 -0
- package/dist/chunk-HVXM2G5F.js +222 -0
- package/dist/chunk-HVXM2G5F.js.map +1 -0
- package/dist/chunk-I4RDAGVY.js +53 -0
- package/dist/chunk-I4RDAGVY.js.map +1 -0
- package/dist/chunk-IQJG4IDX.js +208 -0
- package/dist/chunk-IQJG4IDX.js.map +1 -0
- package/dist/chunk-IX2PXG4Y.js +144 -0
- package/dist/chunk-IX2PXG4Y.js.map +1 -0
- package/dist/chunk-IXICSOOP.js +287 -0
- package/dist/chunk-IXICSOOP.js.map +1 -0
- package/dist/chunk-JY5HSN4D.js +84 -0
- package/dist/chunk-JY5HSN4D.js.map +1 -0
- package/dist/chunk-LMNSBOBG.js +19 -0
- package/dist/chunk-LMNSBOBG.js.map +1 -0
- package/dist/chunk-MBI7D6IL.js +42 -0
- package/dist/chunk-MBI7D6IL.js.map +1 -0
- package/dist/chunk-MLFMYCPH.js +192 -0
- package/dist/chunk-MLFMYCPH.js.map +1 -0
- package/dist/chunk-MOK66734.js +33 -0
- package/dist/chunk-MOK66734.js.map +1 -0
- package/dist/chunk-MXTAWPYM.js +196 -0
- package/dist/chunk-MXTAWPYM.js.map +1 -0
- package/dist/chunk-NCL2UZKI.js +96 -0
- package/dist/chunk-NCL2UZKI.js.map +1 -0
- package/dist/chunk-NET4YLRY.js +107 -0
- package/dist/chunk-NET4YLRY.js.map +1 -0
- package/dist/chunk-NIG67CFM.js +329 -0
- package/dist/chunk-NIG67CFM.js.map +1 -0
- package/dist/chunk-NMVNNO3L.js +10 -0
- package/dist/chunk-NMVNNO3L.js.map +1 -0
- package/dist/chunk-NP7VID4K.js +2 -0
- package/dist/chunk-NP7VID4K.js.map +1 -0
- package/dist/chunk-NPUCMAG2.js +382 -0
- package/dist/chunk-NPUCMAG2.js.map +1 -0
- package/dist/chunk-NSCLRHES.js +102 -0
- package/dist/chunk-NSCLRHES.js.map +1 -0
- package/dist/chunk-OEUXHVFW.js +86 -0
- package/dist/chunk-OEUXHVFW.js.map +1 -0
- package/dist/chunk-ONBHFIMZ.js +137 -0
- package/dist/chunk-ONBHFIMZ.js.map +1 -0
- package/dist/chunk-OPH2HHL2.js +228 -0
- package/dist/chunk-OPH2HHL2.js.map +1 -0
- package/dist/chunk-OQERHIQP.js +287 -0
- package/dist/chunk-OQERHIQP.js.map +1 -0
- package/dist/chunk-P6YJAZFG.js +103 -0
- package/dist/chunk-P6YJAZFG.js.map +1 -0
- package/dist/chunk-PG7ERDOD.js +65 -0
- package/dist/chunk-PG7ERDOD.js.map +1 -0
- package/dist/chunk-PIB5JBMA.js +90 -0
- package/dist/chunk-PIB5JBMA.js.map +1 -0
- package/dist/chunk-PQ5BPIWQ.js +22 -0
- package/dist/chunk-PQ5BPIWQ.js.map +1 -0
- package/dist/chunk-PQBF6ZIQ.js +55 -0
- package/dist/chunk-PQBF6ZIQ.js.map +1 -0
- package/dist/chunk-PTWCTSZL.js +173 -0
- package/dist/chunk-PTWCTSZL.js.map +1 -0
- package/dist/chunk-QJUNPVOS.js +101 -0
- package/dist/chunk-QJUNPVOS.js.map +1 -0
- package/dist/chunk-QUDZOTRV.js +43 -0
- package/dist/chunk-QUDZOTRV.js.map +1 -0
- package/dist/chunk-RB7G65JC.js +213 -0
- package/dist/chunk-RB7G65JC.js.map +1 -0
- package/dist/chunk-RPHAOR7P.js +45 -0
- package/dist/chunk-RPHAOR7P.js.map +1 -0
- package/dist/chunk-RTCSH2AN.js +331 -0
- package/dist/chunk-RTCSH2AN.js.map +1 -0
- package/dist/chunk-S3ISPW3A.js +28 -0
- package/dist/chunk-S3ISPW3A.js.map +1 -0
- package/dist/chunk-SEVN656N.js +36 -0
- package/dist/chunk-SEVN656N.js.map +1 -0
- package/dist/chunk-SKVG672B.js +64 -0
- package/dist/chunk-SKVG672B.js.map +1 -0
- package/dist/chunk-SPQIU7GA.js +236 -0
- package/dist/chunk-SPQIU7GA.js.map +1 -0
- package/dist/chunk-SSGJ6MEM.js +1076 -0
- package/dist/chunk-SSGJ6MEM.js.map +1 -0
- package/dist/chunk-SSKZ2AED.js +118 -0
- package/dist/chunk-SSKZ2AED.js.map +1 -0
- package/dist/chunk-T56JFGXI.js +561 -0
- package/dist/chunk-T56JFGXI.js.map +1 -0
- package/dist/chunk-TCB6O74A.js +137 -0
- package/dist/chunk-TCB6O74A.js.map +1 -0
- package/dist/chunk-TTEYPO6X.js +57 -0
- package/dist/chunk-TTEYPO6X.js.map +1 -0
- package/dist/chunk-TWPHAJNM.js +462 -0
- package/dist/chunk-TWPHAJNM.js.map +1 -0
- package/dist/chunk-TXJJLP4O.js +336 -0
- package/dist/chunk-TXJJLP4O.js.map +1 -0
- package/dist/chunk-TZ6TB7VM.js +245 -0
- package/dist/chunk-TZ6TB7VM.js.map +1 -0
- package/dist/chunk-UBLKJJ7K.js +278 -0
- package/dist/chunk-UBLKJJ7K.js.map +1 -0
- package/dist/chunk-UCJ6IUFS.js +52 -0
- package/dist/chunk-UCJ6IUFS.js.map +1 -0
- package/dist/chunk-UCKFJ3QF.js +197 -0
- package/dist/chunk-UCKFJ3QF.js.map +1 -0
- package/dist/chunk-UPXSLILN.js +20 -0
- package/dist/chunk-UPXSLILN.js.map +1 -0
- package/dist/chunk-V4DORGWJ.js +92 -0
- package/dist/chunk-V4DORGWJ.js.map +1 -0
- package/dist/chunk-V6E5DYZD.js +80 -0
- package/dist/chunk-V6E5DYZD.js.map +1 -0
- package/dist/chunk-VLLYKF3P.js +96 -0
- package/dist/chunk-VLLYKF3P.js.map +1 -0
- package/dist/chunk-VLNBTOH6.js +43 -0
- package/dist/chunk-VLNBTOH6.js.map +1 -0
- package/dist/chunk-WMDSMSPL.js +303 -0
- package/dist/chunk-WMDSMSPL.js.map +1 -0
- package/dist/chunk-WU5BLGTF.js +149 -0
- package/dist/chunk-WU5BLGTF.js.map +1 -0
- package/dist/chunk-WYTZVSGK.js +245 -0
- package/dist/chunk-WYTZVSGK.js.map +1 -0
- package/dist/chunk-X47QMM6K.js +187 -0
- package/dist/chunk-X47QMM6K.js.map +1 -0
- package/dist/chunk-XNBKO32Y.js +174 -0
- package/dist/chunk-XNBKO32Y.js.map +1 -0
- package/dist/chunk-YHUSW7D2.js +40 -0
- package/dist/chunk-YHUSW7D2.js.map +1 -0
- package/dist/chunk-YSKD7UXX.js +126 -0
- package/dist/chunk-YSKD7UXX.js.map +1 -0
- package/dist/chunk-YYRDGWOU.js +72 -0
- package/dist/chunk-YYRDGWOU.js.map +1 -0
- package/dist/chunk-ZIGZMWM7.js +19 -0
- package/dist/chunk-ZIGZMWM7.js.map +1 -0
- package/dist/chunk-ZKRTUKNP.js +40 -0
- package/dist/chunk-ZKRTUKNP.js.map +1 -0
- package/dist/code-block.js +38 -0
- package/dist/code-block.js.map +1 -0
- package/dist/commit.js +51 -0
- package/dist/commit.js.map +1 -0
- package/dist/composer.js +15 -0
- package/dist/composer.js.map +1 -0
- package/dist/confirmation.js +53 -0
- package/dist/confirmation.js.map +1 -0
- package/dist/connection.js +8 -0
- package/dist/connection.js.map +1 -0
- package/dist/context-panel.js +25 -0
- package/dist/context-panel.js.map +1 -0
- package/dist/controls.js +10 -0
- package/dist/controls.js.map +1 -0
- package/dist/conversation.js +19 -0
- package/dist/conversation.js.map +1 -0
- package/dist/diff-view.js +15 -0
- package/dist/diff-view.js.map +1 -0
- package/dist/edge.js +10 -0
- package/dist/edge.js.map +1 -0
- package/dist/environment-variables.js +29 -0
- package/dist/environment-variables.js.map +1 -0
- package/dist/file-tree.js +23 -0
- package/dist/file-tree.js.map +1 -0
- package/dist/gallery.js +9 -0
- package/dist/gallery.js.map +1 -0
- package/dist/grouped-parts.js +21 -0
- package/dist/grouped-parts.js.map +1 -0
- package/dist/image.js +9 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +403 -108
- package/dist/index.js +671 -13205
- package/dist/index.js.map +1 -1
- package/dist/inline-citation.js +39 -0
- package/dist/inline-citation.js.map +1 -0
- package/dist/jsx-preview.js +17 -0
- package/dist/jsx-preview.js.map +1 -0
- package/dist/markdown-view.js +17 -0
- package/dist/markdown-view.js.map +1 -0
- package/dist/message-compare.js +12 -0
- package/dist/message-compare.js.map +1 -0
- package/dist/message-edit.js +19 -0
- package/dist/message-edit.js.map +1 -0
- package/dist/message-feedback.js +11 -0
- package/dist/message-feedback.js.map +1 -0
- package/dist/message-form-spec.js +38 -0
- package/dist/message-form-spec.js.map +1 -0
- package/dist/message-form.js +26 -0
- package/dist/message-form.js.map +1 -0
- package/dist/message-table-spec.js +26 -0
- package/dist/message-table-spec.js.map +1 -0
- package/dist/message-table.js +12 -0
- package/dist/message-table.js.map +1 -0
- package/dist/message.js +51 -0
- package/dist/message.js.map +1 -0
- package/dist/mic-selector.js +27 -0
- package/dist/mic-selector.js.map +1 -0
- package/dist/model-provider-logo.js +13 -0
- package/dist/model-provider-logo.js.map +1 -0
- package/dist/motion-config.js +9 -0
- package/dist/motion-config.js.map +1 -0
- package/dist/node.js +22 -0
- package/dist/node.js.map +1 -0
- package/dist/open-in-chat.js +31 -0
- package/dist/open-in-chat.js.map +1 -0
- package/dist/package-info.js +25 -0
- package/dist/package-info.js.map +1 -0
- package/dist/panel.js +10 -0
- package/dist/panel.js.map +1 -0
- package/dist/part-groups.js +18 -0
- package/dist/part-groups.js.map +1 -0
- package/dist/permission-mode-select.js +9 -0
- package/dist/permission-mode-select.js.map +1 -0
- package/dist/persona-sources.js +8 -0
- package/dist/persona-sources.js.map +1 -0
- package/dist/persona.js +14 -0
- package/dist/persona.js.map +1 -0
- package/dist/plan.js +32 -0
- package/dist/plan.js.map +1 -0
- package/dist/prompt-input-effort.js +9 -0
- package/dist/prompt-input-effort.js.map +1 -0
- package/dist/prompt-input-mode.js +10 -0
- package/dist/prompt-input-mode.js.map +1 -0
- package/dist/prompt-input-slash.js +12 -0
- package/dist/prompt-input-slash.js.map +1 -0
- package/dist/prompt-input.js +89 -0
- package/dist/prompt-input.js.map +1 -0
- package/dist/queue.js +37 -0
- package/dist/queue.js.map +1 -0
- package/dist/reasoning.js +23 -0
- package/dist/reasoning.js.map +1 -0
- package/dist/sandbox.js +28 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/schema-display.js +33 -0
- package/dist/schema-display.js.map +1 -0
- package/dist/selection-toolbar.js +11 -0
- package/dist/selection-toolbar.js.map +1 -0
- package/dist/session-header.js +9 -0
- package/dist/session-header.js.map +1 -0
- package/dist/session-status-bar.js +9 -0
- package/dist/session-status-bar.js.map +1 -0
- package/dist/shimmer.js +9 -0
- package/dist/shimmer.js.map +1 -0
- package/dist/snippet.js +17 -0
- package/dist/snippet.js.map +1 -0
- package/dist/sources.js +17 -0
- package/dist/sources.js.map +1 -0
- package/dist/speech-input.js +9 -0
- package/dist/speech-input.js.map +1 -0
- package/dist/stack-trace.js +27 -0
- package/dist/stack-trace.js.map +1 -0
- package/dist/suggestion.js +16 -0
- package/dist/suggestion.js.map +1 -0
- package/dist/task.js +18 -0
- package/dist/task.js.map +1 -0
- package/dist/test-results.js +43 -0
- package/dist/test-results.js.map +1 -0
- package/dist/token-usage.js +27 -0
- package/dist/token-usage.js.map +1 -0
- package/dist/tool-result-card.js +9 -0
- package/dist/tool-result-card.js.map +1 -0
- package/dist/tool.js +27 -0
- package/dist/tool.js.map +1 -0
- package/dist/toolbar.js +10 -0
- package/dist/toolbar.js.map +1 -0
- package/dist/transcription.js +11 -0
- package/dist/transcription.js.map +1 -0
- package/dist/turn-status.js +9 -0
- package/dist/turn-status.js.map +1 -0
- package/dist/use-audio-level.js +9 -0
- package/dist/use-audio-level.js.map +1 -0
- package/dist/voice-selector.js +47 -0
- package/dist/voice-selector.js.map +1 -0
- package/dist/web-preview.js +19 -0
- package/dist/web-preview.js.map +1 -0
- package/package.json +12 -10
- package/schemas/a2ui-surface.v1.schema.json +5425 -0
- package/src/__contract__/audio-visualizer.contract.test.tsx +49 -0
- package/src/__contract__/chat-shell.contract.test.tsx +49 -0
- package/src/__contract__/grouped-parts.contract.test.tsx +49 -0
- package/src/__contract__/image.contract.test.tsx +49 -0
- package/src/__contract__/markdown-view.contract.test.tsx +49 -0
- package/src/__contract__/message-feedback.contract.test.tsx +49 -0
- package/src/__contract__/message-form.contract.test.tsx +49 -0
- package/src/__contract__/message-table.contract.test.tsx +49 -0
- package/src/__contract__/model-provider-logo.contract.test.tsx +49 -0
- package/src/__contract__/persona.contract.test.tsx +49 -0
- package/src/__contract__/prompt-input-effort.contract.test.tsx +49 -0
- package/src/__contract__/prompt-input-mode.contract.test.tsx +49 -0
- package/src/_chat-shell-rail.tsx +4 -2
- package/src/_flow-boundary.tsx +2 -2
- package/src/_lazy-cjk.test.ts +43 -0
- package/src/_lazy-cjk.ts +73 -0
- package/src/_lazy-math.test.ts +63 -0
- package/src/_lazy-math.ts +90 -0
- package/src/_persona-rive.tsx +27 -41
- package/src/_streamdown-i18n.ts +73 -21
- package/src/_streamdown-safety.ts +2 -2
- package/src/_theme-scope-store.test.ts +83 -0
- package/src/_theme-scope-store.ts +103 -0
- package/src/a2ui/a2ui-surface.stories.tsx +662 -0
- package/src/a2ui/a2ui-surface.test.tsx +201 -0
- package/src/a2ui/a2ui-surface.tsx +354 -0
- package/src/a2ui/catalog.source.json +772 -0
- package/src/a2ui/core/a2ui-core.test.ts +178 -0
- package/src/a2ui/core/catalog.generated.ts +1006 -0
- package/src/a2ui/core/complete-json.ts +81 -0
- package/src/a2ui/core/index.ts +10 -0
- package/src/a2ui/core/schema.ts +111 -0
- package/src/a2ui/core/spec.ts +148 -0
- package/src/a2ui/core/validate.ts +266 -0
- package/src/a2ui/index.ts +7 -0
- package/src/a2ui/ui-catalog.tsx +225 -0
- package/src/a2ui/wave1-chart-spec.test.ts +87 -0
- package/src/a2ui/wave2-chart-spec.test.ts +108 -0
- package/src/agent-event.tsx +1 -1
- package/src/agent.tsx +18 -13
- package/src/agentic-workspace.stories.tsx +6 -45
- package/src/artifact.tsx +2 -2
- package/src/asset-preview.test.tsx +40 -0
- package/src/asset-preview.tsx +83 -12
- package/src/attachments.tsx +7 -4
- package/src/chat-shell.test.tsx +40 -10
- package/src/chat-shell.tsx +90 -44
- package/src/chat.stories.tsx +47 -42
- package/src/code-block.test.tsx +100 -1
- package/src/code-block.tsx +166 -103
- package/src/commit.tsx +30 -41
- package/src/composer.stories.tsx +4 -5
- package/src/composer.test.tsx +45 -0
- package/src/composer.tsx +104 -21
- package/src/confirmation.tsx +1 -1
- package/src/context-panel.stories.tsx +1 -1
- package/src/context-panel.tsx +2 -2
- package/src/conversation.stories.tsx +24 -0
- package/src/conversation.test.tsx +69 -0
- package/src/conversation.tsx +47 -8
- package/src/diff-view.stories.tsx +79 -0
- package/src/diff-view.test.tsx +52 -2
- package/src/diff-view.tsx +92 -36
- package/src/environment-variables.tsx +20 -37
- package/src/file-tree.test.tsx +21 -0
- package/src/file-tree.tsx +33 -16
- package/src/gallery.stories.tsx +42 -0
- package/src/gallery.tsx +2 -2
- package/src/grouped-parts.stories.tsx +23 -0
- package/src/grouped-parts.tsx +1 -1
- package/src/index.ts +1 -0
- package/src/inline-citation.tsx +5 -5
- package/src/jsx-preview.tsx +151 -43
- package/src/markdown-view.test.tsx +7 -3
- package/src/markdown-view.tsx +8 -1
- package/src/message-compare.stories.tsx +40 -0
- package/src/message-compare.tsx +2 -1
- package/src/message-form.stories.tsx +36 -3
- package/src/message-form.test.tsx +8 -2
- package/src/message-form.tsx +16 -8
- package/src/message-table.stories.tsx +26 -2
- package/src/message-table.test.tsx +7 -0
- package/src/message-table.tsx +9 -5
- package/src/message.test.tsx +73 -3
- package/src/message.tsx +36 -12
- package/src/model-provider-logo.test.tsx +57 -3
- package/src/model-provider-logo.tsx +45 -11
- package/src/open-in-chat.tsx +50 -29
- package/src/package-info.tsx +23 -20
- package/src/prompt-input-slash.stories.tsx +1 -1
- package/src/prompt-input.test.tsx +67 -1
- package/src/prompt-input.tsx +42 -4
- package/src/queue.tsx +4 -4
- package/src/reasoning.stories.tsx +27 -0
- package/src/reasoning.tsx +17 -6
- package/src/sandbox.tsx +3 -3
- package/src/schema-display.test.tsx +56 -0
- package/src/schema-display.tsx +68 -37
- package/src/session-header.stories.tsx +35 -1
- package/src/session-header.tsx +1 -1
- package/src/snippet.test.tsx +6 -2
- package/src/snippet.tsx +14 -34
- package/src/sources.stories.tsx +30 -0
- package/src/sources.tsx +4 -1
- package/src/speech-input.test.tsx +109 -0
- package/src/speech-input.tsx +31 -3
- package/src/stack-trace.tsx +20 -36
- package/src/streamdown-i18n.test.tsx +23 -0
- package/src/templates-ai-assistant.stories.tsx +151 -87
- package/src/test-results.tsx +47 -27
- package/src/token-usage.tsx +6 -6
- package/src/tool.stories.tsx +39 -0
- package/src/tool.test.tsx +65 -0
- package/src/tool.tsx +61 -25
- package/src/toolbar.tsx +0 -10
- package/src/transcription.tsx +1 -1
- package/src/voice-selector.tsx +5 -5
- package/src/web-preview.test.tsx +51 -1
- package/src/web-preview.tsx +39 -8
- package/dist/_flow-boundary-SHNWLQG5.js.map +0 -1
- package/dist/_persona-rive-JEG44YHX.js.map +0 -1
- /package/dist/{_audio-player-media-chrome-T3XVXWRZ.js.map → _audio-player-media-chrome.js.map} +0 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
EMPTY_CELL,
|
|
4
|
+
badgeToneForValue,
|
|
5
|
+
compareCellValues,
|
|
6
|
+
formatCellValue,
|
|
7
|
+
isEmptyCell,
|
|
8
|
+
isNumericFormat,
|
|
9
|
+
normalizeTableSpec
|
|
10
|
+
} from "./chunk-DWJDJLPU.js";
|
|
11
|
+
|
|
12
|
+
// src/message-table.tsx
|
|
13
|
+
import { forwardRef, useId, useMemo, useState } from "react";
|
|
14
|
+
import { ChevronDown, ChevronUp, ChevronsUpDown } from "lucide-react";
|
|
15
|
+
import {
|
|
16
|
+
Badge,
|
|
17
|
+
Skeleton,
|
|
18
|
+
Table,
|
|
19
|
+
TableBody,
|
|
20
|
+
TableCaption,
|
|
21
|
+
TableCell,
|
|
22
|
+
TableHead,
|
|
23
|
+
TableHeader,
|
|
24
|
+
TableRow
|
|
25
|
+
} from "@elabs-ai/components-ui";
|
|
26
|
+
import { cn } from "@elabs-ai/components-ui/lib/cn";
|
|
27
|
+
import { useLocale } from "@elabs-ai/components-ui";
|
|
28
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
29
|
+
var MessageTableFallback = forwardRef(
|
|
30
|
+
function MessageTableFallback2({ message = "This table could not be displayed.", className, ...props }, ref) {
|
|
31
|
+
return /* @__PURE__ */ jsx(
|
|
32
|
+
"div",
|
|
33
|
+
{
|
|
34
|
+
ref,
|
|
35
|
+
role: "status",
|
|
36
|
+
"aria-live": "polite",
|
|
37
|
+
className: cn(
|
|
38
|
+
// Sole structural cue is the border (no fill) — reads in every theme,
|
|
39
|
+
// incl. themes where surface-muted ≈ background. border-strong is
|
|
40
|
+
// contrast-guaranteed vs the background.
|
|
41
|
+
"flex items-center justify-center rounded-md border border-border-strong px-4 py-6 text-center text-body text-muted-foreground",
|
|
42
|
+
className
|
|
43
|
+
),
|
|
44
|
+
...props,
|
|
45
|
+
children: message
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
);
|
|
50
|
+
var MessageTable = forwardRef(function MessageTable2({
|
|
51
|
+
spec,
|
|
52
|
+
sortable = false,
|
|
53
|
+
sort: sortProp,
|
|
54
|
+
defaultSort = null,
|
|
55
|
+
onSortChange,
|
|
56
|
+
maxRows,
|
|
57
|
+
renderCell,
|
|
58
|
+
isStreaming,
|
|
59
|
+
streaming = false,
|
|
60
|
+
className,
|
|
61
|
+
...props
|
|
62
|
+
}, ref) {
|
|
63
|
+
const resolvedStreaming = isStreaming ?? streaming;
|
|
64
|
+
const { t } = useLocale();
|
|
65
|
+
const reactId = useId();
|
|
66
|
+
const isControlled = sortProp !== void 0;
|
|
67
|
+
const [internalSort, setInternalSort] = useState(defaultSort);
|
|
68
|
+
const resolvedSort = isControlled ? sortProp : internalSort;
|
|
69
|
+
const result = normalizeTableSpec(spec);
|
|
70
|
+
const normalized = result.ok ? result.spec : null;
|
|
71
|
+
const sortedRows = useMemo(() => {
|
|
72
|
+
if (!normalized || !resolvedSort) return normalized?.rows ?? [];
|
|
73
|
+
const column = normalized.columns.find((c) => c.key === resolvedSort.key);
|
|
74
|
+
if (!column) return normalized.rows;
|
|
75
|
+
const direction = resolvedSort.direction === "asc" ? 1 : -1;
|
|
76
|
+
return [...normalized.rows].sort(
|
|
77
|
+
(a, b) => direction * compareCellValues(a[column.key], b[column.key], column.format)
|
|
78
|
+
);
|
|
79
|
+
}, [normalized, resolvedSort]);
|
|
80
|
+
if (!result.ok) {
|
|
81
|
+
return /* @__PURE__ */ jsx(MessageTableFallback, { ref, message: result.reason, className, ...props });
|
|
82
|
+
}
|
|
83
|
+
const { columns, title, emptyText } = result.spec;
|
|
84
|
+
if (columns.length === 0) {
|
|
85
|
+
if (resolvedStreaming) {
|
|
86
|
+
return /* @__PURE__ */ jsxs("div", { ref, className: cn("w-full", className), ...props, children: [
|
|
87
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", role: "status", "aria-live": "polite", children: "Loading table\u2026" }),
|
|
88
|
+
/* @__PURE__ */ jsxs(
|
|
89
|
+
"div",
|
|
90
|
+
{
|
|
91
|
+
"aria-hidden": "true",
|
|
92
|
+
className: "flex flex-col gap-2 rounded-md border border-border p-3",
|
|
93
|
+
children: [
|
|
94
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-40" }),
|
|
95
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-full" }),
|
|
96
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-full" }),
|
|
97
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-3/4" })
|
|
98
|
+
]
|
|
99
|
+
}
|
|
100
|
+
)
|
|
101
|
+
] });
|
|
102
|
+
}
|
|
103
|
+
return /* @__PURE__ */ jsx(
|
|
104
|
+
MessageTableFallback,
|
|
105
|
+
{
|
|
106
|
+
ref,
|
|
107
|
+
message: "This table has no columns to display.",
|
|
108
|
+
className,
|
|
109
|
+
...props
|
|
110
|
+
}
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
const total = sortedRows.length;
|
|
114
|
+
const cappedRows = maxRows !== void 0 && maxRows >= 0 ? sortedRows.slice(0, maxRows) : sortedRows;
|
|
115
|
+
const truncatedCount = total - cappedRows.length;
|
|
116
|
+
const titleId = title ? `${reactId}-title` : void 0;
|
|
117
|
+
const setSort = (next) => {
|
|
118
|
+
if (!isControlled) setInternalSort(next);
|
|
119
|
+
onSortChange?.(next);
|
|
120
|
+
};
|
|
121
|
+
const toggleSort = (column) => {
|
|
122
|
+
if (resolvedSort?.key === column.key) {
|
|
123
|
+
setSort({ key: column.key, direction: resolvedSort.direction === "asc" ? "desc" : "asc" });
|
|
124
|
+
} else {
|
|
125
|
+
setSort({ key: column.key, direction: "asc" });
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
const renderCellContent = (column, row, rowIndex) => {
|
|
129
|
+
const value = row[column.key];
|
|
130
|
+
if (renderCell) {
|
|
131
|
+
const overridden = renderCell({ value, column, row, rowIndex });
|
|
132
|
+
if (overridden !== void 0) return overridden;
|
|
133
|
+
}
|
|
134
|
+
if (isEmptyCell(value)) {
|
|
135
|
+
return /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: EMPTY_CELL });
|
|
136
|
+
}
|
|
137
|
+
if (column.format === "badge") {
|
|
138
|
+
return /* @__PURE__ */ jsx(Badge, { variant: badgeToneForValue(value), children: String(value) });
|
|
139
|
+
}
|
|
140
|
+
return formatCellValue(value, column.format);
|
|
141
|
+
};
|
|
142
|
+
return /* @__PURE__ */ jsxs("div", { ref, className: cn("w-full", className), ...props, children: [
|
|
143
|
+
title && /* @__PURE__ */ jsx("p", { id: titleId, className: "mb-1 text-body font-semibold text-foreground text-balance", children: title }),
|
|
144
|
+
/* @__PURE__ */ jsxs("div", { className: "overflow-hidden rounded-md border border-border", children: [
|
|
145
|
+
resolvedStreaming && cappedRows.length === 0 && /* @__PURE__ */ jsx("span", { className: "sr-only", role: "status", "aria-live": "polite", children: "Loading table\u2026" }),
|
|
146
|
+
/* @__PURE__ */ jsxs(
|
|
147
|
+
Table,
|
|
148
|
+
{
|
|
149
|
+
"aria-labelledby": titleId,
|
|
150
|
+
"aria-label": title ? void 0 : t("ai.messageTable.label"),
|
|
151
|
+
"aria-busy": resolvedStreaming && cappedRows.length === 0 || void 0,
|
|
152
|
+
children: [
|
|
153
|
+
truncatedCount > 0 && /* @__PURE__ */ jsxs(TableCaption, { className: "mb-2 mt-3 px-3 text-caption", children: [
|
|
154
|
+
"Showing ",
|
|
155
|
+
cappedRows.length,
|
|
156
|
+
" of ",
|
|
157
|
+
total,
|
|
158
|
+
" rows"
|
|
159
|
+
] }),
|
|
160
|
+
/* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsx(TableRow, { children: columns.map((column) => {
|
|
161
|
+
const numeric = isNumericFormat(column.format);
|
|
162
|
+
const active = resolvedSort?.key === column.key;
|
|
163
|
+
const ariaSort = active ? resolvedSort?.direction === "asc" ? "ascending" : "descending" : sortable ? "none" : void 0;
|
|
164
|
+
const label = column.label ?? column.key;
|
|
165
|
+
return /* @__PURE__ */ jsx(
|
|
166
|
+
TableHead,
|
|
167
|
+
{
|
|
168
|
+
scope: "col",
|
|
169
|
+
"aria-sort": ariaSort,
|
|
170
|
+
className: cn(numeric && "text-end"),
|
|
171
|
+
children: sortable ? /* @__PURE__ */ jsxs(
|
|
172
|
+
"button",
|
|
173
|
+
{
|
|
174
|
+
type: "button",
|
|
175
|
+
onClick: () => toggleSort(column),
|
|
176
|
+
className: cn(
|
|
177
|
+
"inline-flex items-center gap-1 rounded-sm font-medium",
|
|
178
|
+
"focus-ring",
|
|
179
|
+
"hover:text-foreground transition-colors duration-fast ease-standard motion-reduce:transition-none",
|
|
180
|
+
numeric && "flex-row-reverse"
|
|
181
|
+
),
|
|
182
|
+
children: [
|
|
183
|
+
/* @__PURE__ */ jsx("span", { children: label }),
|
|
184
|
+
active ? resolvedSort?.direction === "asc" ? /* @__PURE__ */ jsx(ChevronUp, { "aria-hidden": "true", className: "size-3.5" }) : /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": "true", className: "size-3.5" }) : /* @__PURE__ */ jsx(ChevronsUpDown, { "aria-hidden": "true", className: "size-3.5 opacity-50" })
|
|
185
|
+
]
|
|
186
|
+
}
|
|
187
|
+
) : label
|
|
188
|
+
},
|
|
189
|
+
column.key
|
|
190
|
+
);
|
|
191
|
+
}) }) }),
|
|
192
|
+
/* @__PURE__ */ jsx(TableBody, { children: cappedRows.length === 0 && resolvedStreaming ? [0, 1, 2].map((i) => /* @__PURE__ */ jsx(TableRow, { "aria-hidden": "true", children: columns.map((column) => /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-full" }) }, column.key)) }, `skeleton-${i}`)) : cappedRows.length === 0 ? /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(
|
|
193
|
+
TableCell,
|
|
194
|
+
{
|
|
195
|
+
colSpan: columns.length,
|
|
196
|
+
className: "py-6 text-center text-muted-foreground",
|
|
197
|
+
children: emptyText ?? "No rows to display"
|
|
198
|
+
}
|
|
199
|
+
) }) : cappedRows.map((row, rowIndex) => /* @__PURE__ */ jsx(TableRow, { children: columns.map((column) => {
|
|
200
|
+
const numeric = isNumericFormat(column.format);
|
|
201
|
+
return /* @__PURE__ */ jsx(
|
|
202
|
+
TableCell,
|
|
203
|
+
{
|
|
204
|
+
className: cn(numeric && "text-end tabular-nums"),
|
|
205
|
+
children: renderCellContent(column, row, rowIndex)
|
|
206
|
+
},
|
|
207
|
+
column.key
|
|
208
|
+
);
|
|
209
|
+
}) }, rowIndex)) })
|
|
210
|
+
]
|
|
211
|
+
}
|
|
212
|
+
)
|
|
213
|
+
] })
|
|
214
|
+
] });
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
export {
|
|
218
|
+
MessageTableFallback,
|
|
219
|
+
MessageTable
|
|
220
|
+
};
|
|
221
|
+
//# sourceMappingURL=chunk-BHUVISIY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/message-table.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * MessageTable — a model-emittable data table rendered inside a chat message.\n *\n * The model emits a serializable, column-oriented `TableSpec` (see\n * `message-table-spec.ts`); MessageTable renders a lightweight table (NOT the\n * app-chrome `@elabs-ai/components-data` DataTable — this is message content).\n *\n * Design bar (mirrors AutoChart):\n * - Spec-driven, zod-validated; the model never chooses the look.\n * - Never throws. A malformed spec → `MessageTableFallback`; an unknown format\n * falls back to text; a missing cell renders an em-dash.\n * - Streaming-tolerant. Half-arrived columns/rows are dropped or render\n * progressively; a spec with columns but no rows yet shows skeleton rows.\n * - Tokens only; numeric columns are end-aligned + `tabular-nums`.\n * - Optional client-side sort (controlled OR uncontrolled) and an optional\n * per-cell `renderCell` override for consumer composition.\n *\n * Composes the `@elabs-ai/components-ui` `Table` primitive.\n */\n\nimport { forwardRef, useId, useMemo, useState, type HTMLAttributes, type ReactNode } from \"react\";\nimport { ChevronDown, ChevronUp, ChevronsUpDown } from \"lucide-react\";\nimport {\n Badge,\n Skeleton,\n Table,\n TableBody,\n TableCaption,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { useLocale } from \"@elabs-ai/components-ui\";\n\nimport {\n badgeToneForValue,\n compareCellValues,\n EMPTY_CELL,\n formatCellValue,\n isEmptyCell,\n isNumericFormat,\n normalizeTableSpec,\n type ColumnSpec,\n type TableRowData,\n type TableSpec,\n} from \"./message-table-spec\";\n\n// ─── Sort ─────────────────────────────────────────────────────────────────────\n\nexport interface TableSort {\n /** The sorted column's key. */\n key: string;\n direction: \"asc\" | \"desc\";\n}\n\n/** Per-cell render override — return `undefined` to fall back to default rendering. */\nexport type RenderCell = (args: {\n value: unknown;\n column: ColumnSpec;\n row: TableRowData;\n rowIndex: number;\n}) => ReactNode;\n\n// ─── Fallback ─────────────────────────────────────────────────────────────────\n\nexport interface MessageTableFallbackProps extends HTMLAttributes<HTMLDivElement> {\n /** Short human reason the table could not render. */\n message?: string;\n}\n\n/** Shown when the spec is unusable. Mirrors `ChartFallback` semantics. */\nexport const MessageTableFallback = forwardRef<HTMLDivElement, MessageTableFallbackProps>(\n function MessageTableFallback(\n { message = \"This table could not be displayed.\", className, ...props },\n ref,\n ) {\n return (\n <div\n ref={ref}\n role=\"status\"\n aria-live=\"polite\"\n className={cn(\n // Sole structural cue is the border (no fill) — reads in every theme,\n // incl. themes where surface-muted ≈ background. border-strong is\n // contrast-guaranteed vs the background.\n \"flex items-center justify-center rounded-md border border-border-strong px-4 py-6 text-center text-body text-muted-foreground\",\n className,\n )}\n {...props}\n >\n {message}\n </div>\n );\n },\n);\n\n// ─── MessageTable ─────────────────────────────────────────────────────────────\n\nexport interface MessageTableProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n /** The serializable table specification produced by an LLM tool-call. */\n spec: TableSpec | unknown;\n /** Enable click-to-sort column headers. @default false */\n sortable?: boolean;\n /** Controlled sort. When provided, `onSortChange` is the only way to update it. */\n sort?: TableSort | null;\n /** Uncontrolled initial sort. */\n defaultSort?: TableSort | null;\n /** Called with the next sort (or `null`) when a header is clicked. */\n onSortChange?: (sort: TableSort | null) => void;\n /** Cap the number of rendered rows; shows a \"Showing N of M rows\" notice. */\n maxRows?: number;\n /** Per-cell render override for custom composition. */\n renderCell?: RenderCell;\n /** The spec is still streaming (columns-but-no-rows shows skeleton rows). */\n isStreaming?: boolean;\n /** @deprecated Use `isStreaming`. */\n streaming?: boolean;\n}\n\n/**\n * MessageTable — renders a `TableSpec` as a lightweight message-body table.\n *\n * Intentionally bare: no toolbar, no expand chrome. Growing one here would be\n * `ChartFrame` re-implemented inside this package.\n *\n * **To make it expandable, wrap it in `ExpandDialog`**\n * (`@elabs-ai/components-ui`) — the shared two-pane expand surface,\n * the same one a chart opens. Do NOT hand-roll a lightbox or a full-screen\n * breakout; four of those already existed before the component was shared, and\n * each one taught users a different meaning for the same button.\n *\n * The context pane for a table is its SHAPE, not statistics: row count,\n * \"showing N of M\", column count, each column's declared `format`. A\n * model-emitted table's numerics may already be formatted strings, so min/max/avg\n * over them is wrong more often than right.\n */\nexport const MessageTable = forwardRef<HTMLDivElement, MessageTableProps>(function MessageTable(\n {\n spec,\n sortable = false,\n sort: sortProp,\n defaultSort = null,\n onSortChange,\n maxRows,\n renderCell,\n isStreaming,\n streaming = false,\n className,\n ...props\n },\n ref,\n) {\n const resolvedStreaming = isStreaming ?? streaming;\n const { t } = useLocale();\n const reactId = useId();\n const isControlled = sortProp !== undefined;\n const [internalSort, setInternalSort] = useState<TableSort | null>(defaultSort);\n const resolvedSort = isControlled ? (sortProp as TableSort | null) : internalSort;\n\n const result = normalizeTableSpec(spec);\n\n const normalized = result.ok ? result.spec : null;\n\n const sortedRows = useMemo<TableRowData[]>(() => {\n if (!normalized || !resolvedSort) return normalized?.rows ?? [];\n const column = normalized.columns.find((c) => c.key === resolvedSort.key);\n if (!column) return normalized.rows;\n const direction = resolvedSort.direction === \"asc\" ? 1 : -1;\n return [...normalized.rows].sort(\n (a, b) => direction * compareCellValues(a[column.key], b[column.key], column.format),\n );\n }, [normalized, resolvedSort]);\n\n if (!result.ok) {\n return (\n <MessageTableFallback ref={ref} message={result.reason} className={className} {...props} />\n );\n }\n\n const { columns, title, emptyText } = result.spec;\n\n // No columns: skeleton while streaming, otherwise a fallback.\n if (columns.length === 0) {\n if (resolvedStreaming) {\n return (\n <div ref={ref} className={cn(\"w-full\", className)} {...props}>\n <span className=\"sr-only\" role=\"status\" aria-live=\"polite\">\n Loading table…\n </span>\n <div\n aria-hidden=\"true\"\n className=\"flex flex-col gap-2 rounded-md border border-border p-3\"\n >\n <Skeleton className=\"h-5 w-40\" />\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-3/4\" />\n </div>\n </div>\n );\n }\n return (\n <MessageTableFallback\n ref={ref}\n message=\"This table has no columns to display.\"\n className={className}\n {...props}\n />\n );\n }\n\n const total = sortedRows.length;\n const cappedRows =\n maxRows !== undefined && maxRows >= 0 ? sortedRows.slice(0, maxRows) : sortedRows;\n const truncatedCount = total - cappedRows.length;\n\n const titleId = title ? `${reactId}-title` : undefined;\n\n const setSort = (next: TableSort | null) => {\n if (!isControlled) setInternalSort(next);\n onSortChange?.(next);\n };\n\n const toggleSort = (column: ColumnSpec) => {\n if (resolvedSort?.key === column.key) {\n setSort({ key: column.key, direction: resolvedSort.direction === \"asc\" ? \"desc\" : \"asc\" });\n } else {\n setSort({ key: column.key, direction: \"asc\" });\n }\n };\n\n const renderCellContent = (\n column: ColumnSpec,\n row: TableRowData,\n rowIndex: number,\n ): ReactNode => {\n const value = row[column.key];\n if (renderCell) {\n const overridden = renderCell({ value, column, row, rowIndex });\n if (overridden !== undefined) return overridden;\n }\n if (isEmptyCell(value)) {\n return <span className=\"text-muted-foreground\">{EMPTY_CELL}</span>;\n }\n if (column.format === \"badge\") {\n return <Badge variant={badgeToneForValue(value)}>{String(value)}</Badge>;\n }\n return formatCellValue(value, column.format);\n };\n\n return (\n <div ref={ref} className={cn(\"w-full\", className)} {...props}>\n {title && (\n <p id={titleId} className=\"mb-1 text-body font-semibold text-foreground text-balance\">\n {title}\n </p>\n )}\n <div className=\"overflow-hidden rounded-md border border-border\">\n {resolvedStreaming && cappedRows.length === 0 && (\n <span className=\"sr-only\" role=\"status\" aria-live=\"polite\">\n Loading table…\n </span>\n )}\n <Table\n aria-labelledby={titleId}\n aria-label={title ? undefined : t(\"ai.messageTable.label\")}\n aria-busy={(resolvedStreaming && cappedRows.length === 0) || undefined}\n >\n {truncatedCount > 0 && (\n <TableCaption className=\"mb-2 mt-3 px-3 text-caption\">\n Showing {cappedRows.length} of {total} rows\n </TableCaption>\n )}\n <TableHeader>\n <TableRow>\n {columns.map((column) => {\n const numeric = isNumericFormat(column.format);\n const active = resolvedSort?.key === column.key;\n const ariaSort = active\n ? resolvedSort?.direction === \"asc\"\n ? \"ascending\"\n : \"descending\"\n : sortable\n ? \"none\"\n : undefined;\n const label = column.label ?? column.key;\n return (\n <TableHead\n key={column.key}\n scope=\"col\"\n aria-sort={ariaSort}\n className={cn(numeric && \"text-end\")}\n >\n {sortable ? (\n <button\n type=\"button\"\n onClick={() => toggleSort(column)}\n className={cn(\n \"inline-flex items-center gap-1 rounded-sm font-medium\",\n \"focus-ring\",\n \"hover:text-foreground transition-colors duration-fast ease-standard motion-reduce:transition-none\",\n numeric && \"flex-row-reverse\",\n )}\n >\n <span>{label}</span>\n {active ? (\n resolvedSort?.direction === \"asc\" ? (\n <ChevronUp aria-hidden=\"true\" className=\"size-3.5\" />\n ) : (\n <ChevronDown aria-hidden=\"true\" className=\"size-3.5\" />\n )\n ) : (\n <ChevronsUpDown aria-hidden=\"true\" className=\"size-3.5 opacity-50\" />\n )}\n </button>\n ) : (\n label\n )}\n </TableHead>\n );\n })}\n </TableRow>\n </TableHeader>\n <TableBody>\n {cappedRows.length === 0 && resolvedStreaming ? (\n [0, 1, 2].map((i) => (\n <TableRow key={`skeleton-${i}`} aria-hidden=\"true\">\n {columns.map((column) => (\n <TableCell key={column.key}>\n <Skeleton className=\"h-4 w-full\" />\n </TableCell>\n ))}\n </TableRow>\n ))\n ) : cappedRows.length === 0 ? (\n <TableRow>\n <TableCell\n colSpan={columns.length}\n className=\"py-6 text-center text-muted-foreground\"\n >\n {emptyText ?? \"No rows to display\"}\n </TableCell>\n </TableRow>\n ) : (\n cappedRows.map((row, rowIndex) => (\n <TableRow key={rowIndex}>\n {columns.map((column) => {\n const numeric = isNumericFormat(column.format);\n return (\n <TableCell\n key={column.key}\n className={cn(numeric && \"text-end tabular-nums\")}\n >\n {renderCellContent(column, row, rowIndex)}\n </TableCell>\n );\n })}\n </TableRow>\n ))\n )}\n </TableBody>\n </Table>\n </div>\n </div>\n );\n});\n"],"mappings":"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","names":["MessageTableFallback","MessageTable"]}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
A2UI_COMMON_PROPS,
|
|
4
|
+
A2UI_VERSION
|
|
5
|
+
} from "./chunk-4XRNIZMG.js";
|
|
6
|
+
|
|
7
|
+
// src/a2ui/core/schema.ts
|
|
8
|
+
var A2UI_SURFACE_SCHEMA_ID = "https://github.com/mreimitz/elabs-components/packages/ai/schemas/a2ui-surface.v1.schema.json";
|
|
9
|
+
function propSchema(p) {
|
|
10
|
+
const base = {};
|
|
11
|
+
if (p.description) base.description = p.description;
|
|
12
|
+
if (p.default !== void 0) base.default = p.default;
|
|
13
|
+
if (p.enum) return { ...base, enum: p.enum };
|
|
14
|
+
switch (p.type) {
|
|
15
|
+
case "string":
|
|
16
|
+
case "number":
|
|
17
|
+
case "boolean":
|
|
18
|
+
case "array":
|
|
19
|
+
case "object":
|
|
20
|
+
return { ...base, type: p.type };
|
|
21
|
+
case "node":
|
|
22
|
+
return {
|
|
23
|
+
...base,
|
|
24
|
+
anyOf: [
|
|
25
|
+
{ type: "string" },
|
|
26
|
+
{ type: "number" },
|
|
27
|
+
{ $ref: "#/$defs/element" },
|
|
28
|
+
{ type: "array", items: { $ref: "#/$defs/node" } }
|
|
29
|
+
]
|
|
30
|
+
};
|
|
31
|
+
default:
|
|
32
|
+
return base;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function elementSchema(type, entry) {
|
|
36
|
+
const props = entry.builtin ? entry.props : { ...A2UI_COMMON_PROPS, ...entry.props };
|
|
37
|
+
const required = Object.entries(entry.props).filter(([, p]) => p.required).map(([name]) => name);
|
|
38
|
+
const properties = {
|
|
39
|
+
type: { const: type },
|
|
40
|
+
id: { type: "string" },
|
|
41
|
+
props: {
|
|
42
|
+
type: "object",
|
|
43
|
+
properties: Object.fromEntries(Object.entries(props).map(([n, p]) => [n, propSchema(p)])),
|
|
44
|
+
...required.length ? { required } : {},
|
|
45
|
+
additionalProperties: false
|
|
46
|
+
},
|
|
47
|
+
on: {
|
|
48
|
+
type: "object",
|
|
49
|
+
properties: Object.fromEntries(
|
|
50
|
+
Object.keys(entry.events).map((ev) => [ev, { $ref: "#/$defs/action" }])
|
|
51
|
+
),
|
|
52
|
+
additionalProperties: false
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
if (entry.children) properties.children = { type: "array", items: { $ref: "#/$defs/node" } };
|
|
56
|
+
return {
|
|
57
|
+
type: "object",
|
|
58
|
+
...entry.summary ? { description: entry.summary } : {},
|
|
59
|
+
properties,
|
|
60
|
+
required: required.length ? ["type", "props"] : ["type"],
|
|
61
|
+
additionalProperties: false
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function buildA2uiSurfaceSchema(catalog) {
|
|
65
|
+
const types = Object.keys(catalog).sort();
|
|
66
|
+
return {
|
|
67
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
68
|
+
$id: A2UI_SURFACE_SCHEMA_ID,
|
|
69
|
+
title: "A2UI surface v1 (brand-ui)",
|
|
70
|
+
description: "An agent-designed screen as data: a tree of brand-ui catalog nodes. Every `type` is a catalog entry, props are checked per type, and `on` binds catalog events to host actions. Text is a plain string child.",
|
|
71
|
+
type: "object",
|
|
72
|
+
properties: {
|
|
73
|
+
a2ui: { const: A2UI_VERSION },
|
|
74
|
+
title: { type: "string", description: "Accessible name of the surface region." },
|
|
75
|
+
root: { $ref: "#/$defs/node" }
|
|
76
|
+
},
|
|
77
|
+
required: ["a2ui", "root"],
|
|
78
|
+
additionalProperties: false,
|
|
79
|
+
$defs: {
|
|
80
|
+
action: {
|
|
81
|
+
type: "object",
|
|
82
|
+
properties: {
|
|
83
|
+
name: { type: "string", minLength: 1, description: "The host-side verb." },
|
|
84
|
+
payload: { description: "Free JSON attached to the action." }
|
|
85
|
+
},
|
|
86
|
+
required: ["name"],
|
|
87
|
+
additionalProperties: false
|
|
88
|
+
},
|
|
89
|
+
node: { anyOf: [{ type: "string" }, { $ref: "#/$defs/element" }] },
|
|
90
|
+
element: { oneOf: types.map((t) => ({ $ref: `#/$defs/${t}` })) },
|
|
91
|
+
...Object.fromEntries(types.map((t) => [t, elementSchema(t, catalog[t])]))
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export {
|
|
97
|
+
A2UI_SURFACE_SCHEMA_ID,
|
|
98
|
+
buildA2uiSurfaceSchema
|
|
99
|
+
};
|
|
100
|
+
//# sourceMappingURL=chunk-BM2LWERA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/a2ui/core/schema.ts"],"sourcesContent":["/**\n * schema.ts — the A2UI surface as a JSON Schema (draft 2020-12), built from the\n * catalog so editors, structured-output modes and JSON-Schema validators see the\n * SAME contract `validateA2uiSurface` enforces. Published as\n * `@elabs-ai/components-ai/a2ui/schema.json` and printed by `brand-ui a2ui schema`.\n */\nimport {\n A2UI_COMMON_PROPS,\n A2UI_VERSION,\n type A2uiCatalogSchema,\n type A2uiCatalogTypeSchema,\n type A2uiPropSchema,\n} from \"./spec\";\n\nexport const A2UI_SURFACE_SCHEMA_ID =\n \"https://github.com/mreimitz/elabs-components/packages/ai/schemas/a2ui-surface.v1.schema.json\";\n\ntype JsonSchema = Record<string, unknown>;\n\nfunction propSchema(p: A2uiPropSchema): JsonSchema {\n const base: JsonSchema = {};\n if (p.description) base.description = p.description;\n if (p.default !== undefined) base.default = p.default;\n if (p.enum) return { ...base, enum: p.enum };\n switch (p.type) {\n case \"string\":\n case \"number\":\n case \"boolean\":\n case \"array\":\n case \"object\":\n return { ...base, type: p.type };\n case \"node\":\n return {\n ...base,\n anyOf: [\n { type: \"string\" },\n { type: \"number\" },\n { $ref: \"#/$defs/element\" },\n { type: \"array\", items: { $ref: \"#/$defs/node\" } },\n ],\n };\n default:\n return base;\n }\n}\n\nfunction elementSchema(type: string, entry: A2uiCatalogTypeSchema): JsonSchema {\n const props = entry.builtin ? entry.props : { ...A2UI_COMMON_PROPS, ...entry.props };\n const required = Object.entries(entry.props)\n .filter(([, p]) => p.required)\n .map(([name]) => name);\n const properties: JsonSchema = {\n type: { const: type },\n id: { type: \"string\" },\n props: {\n type: \"object\",\n properties: Object.fromEntries(Object.entries(props).map(([n, p]) => [n, propSchema(p)])),\n ...(required.length ? { required } : {}),\n additionalProperties: false,\n },\n on: {\n type: \"object\",\n properties: Object.fromEntries(\n Object.keys(entry.events).map((ev) => [ev, { $ref: \"#/$defs/action\" }]),\n ),\n additionalProperties: false,\n },\n };\n if (entry.children) properties.children = { type: \"array\", items: { $ref: \"#/$defs/node\" } };\n return {\n type: \"object\",\n ...(entry.summary ? { description: entry.summary } : {}),\n properties,\n required: required.length ? [\"type\", \"props\"] : [\"type\"],\n additionalProperties: false,\n };\n}\n\n/** Build the JSON Schema document for `catalog`. Deterministic: sorted types. */\nexport function buildA2uiSurfaceSchema(catalog: A2uiCatalogSchema): JsonSchema {\n const types = Object.keys(catalog).sort();\n return {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n $id: A2UI_SURFACE_SCHEMA_ID,\n title: \"A2UI surface v1 (brand-ui)\",\n description:\n \"An agent-designed screen as data: a tree of brand-ui catalog nodes. Every `type` is a catalog entry, props are checked per type, and `on` binds catalog events to host actions. Text is a plain string child.\",\n type: \"object\",\n properties: {\n a2ui: { const: A2UI_VERSION },\n title: { type: \"string\", description: \"Accessible name of the surface region.\" },\n root: { $ref: \"#/$defs/node\" },\n },\n required: [\"a2ui\", \"root\"],\n additionalProperties: false,\n $defs: {\n action: {\n type: \"object\",\n properties: {\n name: { type: \"string\", minLength: 1, description: \"The host-side verb.\" },\n payload: { description: \"Free JSON attached to the action.\" },\n },\n required: [\"name\"],\n additionalProperties: false,\n },\n node: { anyOf: [{ type: \"string\" }, { $ref: \"#/$defs/element\" }] },\n element: { oneOf: types.map((t) => ({ $ref: `#/$defs/${t}` })) },\n ...Object.fromEntries(types.map((t) => [t, elementSchema(t, catalog[t]!)])),\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/inline-citation.tsx
|
|
4
|
+
import { Badge } from "@elabs-ai/components-ui";
|
|
5
|
+
import { Carousel, CarouselContent, CarouselItem } from "@elabs-ai/components-ui";
|
|
6
|
+
import { HoverCard, HoverCardContent, HoverCardTrigger } from "@elabs-ai/components-ui";
|
|
7
|
+
import { cn } from "@elabs-ai/components-ui/lib/cn";
|
|
8
|
+
import { useLocale } from "@elabs-ai/components-ui";
|
|
9
|
+
import { ArrowLeftIcon, ArrowRightIcon, BadgeCheckIcon } from "lucide-react";
|
|
10
|
+
import { createContext, useCallback, useContext, useEffect, useState } from "react";
|
|
11
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
var InlineCitation = ({ className, ...props }) => /* @__PURE__ */ jsx("span", { className: cn("group inline items-center gap-1", className), ...props });
|
|
13
|
+
var InlineCitationText = ({ className, ...props }) => /* @__PURE__ */ jsx("span", { className: cn("transition-colors group-hover:bg-accent", className), ...props });
|
|
14
|
+
var InlineCitationCard = (props) => /* @__PURE__ */ jsx(HoverCard, { closeDelay: 0, openDelay: 0, ...props });
|
|
15
|
+
var hostnameOrRaw = (value) => {
|
|
16
|
+
try {
|
|
17
|
+
return new URL(value).hostname || value;
|
|
18
|
+
} catch {
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
var inlineCitationSourceLabel = (source) => {
|
|
23
|
+
if (typeof source === "string") {
|
|
24
|
+
return hostnameOrRaw(source);
|
|
25
|
+
}
|
|
26
|
+
return source.label || (source.url ? hostnameOrRaw(source.url) : source.id || "unknown");
|
|
27
|
+
};
|
|
28
|
+
var InlineCitationCardTrigger = ({
|
|
29
|
+
sources,
|
|
30
|
+
className,
|
|
31
|
+
...props
|
|
32
|
+
}) => /* @__PURE__ */ jsx(HoverCardTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
33
|
+
Badge,
|
|
34
|
+
{
|
|
35
|
+
className: cn(
|
|
36
|
+
"ms-1 rounded-full border-success/40 bg-success/10 text-success-text",
|
|
37
|
+
className
|
|
38
|
+
),
|
|
39
|
+
variant: "outline",
|
|
40
|
+
...props,
|
|
41
|
+
children: [
|
|
42
|
+
/* @__PURE__ */ jsx(BadgeCheckIcon, { "aria-hidden": "true", className: "size-3" }),
|
|
43
|
+
sources[0] ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
44
|
+
inlineCitationSourceLabel(sources[0]),
|
|
45
|
+
" ",
|
|
46
|
+
sources.length > 1 && `+${sources.length - 1}`
|
|
47
|
+
] }) : "unknown"
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
) });
|
|
51
|
+
var EvidenceChip = InlineCitationCardTrigger;
|
|
52
|
+
var InlineCitationCardBody = ({ className, ...props }) => /* @__PURE__ */ jsx(HoverCardContent, { className: cn("relative w-80 p-0", className), ...props });
|
|
53
|
+
var CarouselApiContext = createContext(void 0);
|
|
54
|
+
var useCarouselApi = () => {
|
|
55
|
+
const context = useContext(CarouselApiContext);
|
|
56
|
+
return context;
|
|
57
|
+
};
|
|
58
|
+
var InlineCitationCarousel = ({
|
|
59
|
+
className,
|
|
60
|
+
children,
|
|
61
|
+
...props
|
|
62
|
+
}) => {
|
|
63
|
+
const [api, setApi] = useState();
|
|
64
|
+
return /* @__PURE__ */ jsx(CarouselApiContext.Provider, { value: api, children: /* @__PURE__ */ jsx(Carousel, { className: cn("w-full", className), setApi, ...props, children }) });
|
|
65
|
+
};
|
|
66
|
+
var InlineCitationCarouselContent = (props) => /* @__PURE__ */ jsx(CarouselContent, { ...props });
|
|
67
|
+
var InlineCitationCarouselItem = ({
|
|
68
|
+
className,
|
|
69
|
+
...props
|
|
70
|
+
}) => /* @__PURE__ */ jsx(CarouselItem, { className: cn("w-full space-y-2 p-4 ps-8", className), ...props });
|
|
71
|
+
var InlineCitationCarouselHeader = ({
|
|
72
|
+
className,
|
|
73
|
+
...props
|
|
74
|
+
}) => /* @__PURE__ */ jsx(
|
|
75
|
+
"div",
|
|
76
|
+
{
|
|
77
|
+
className: cn(
|
|
78
|
+
"flex items-center justify-between gap-2 rounded-t-md bg-secondary p-2",
|
|
79
|
+
className
|
|
80
|
+
),
|
|
81
|
+
...props
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
var InlineCitationCarouselIndex = ({
|
|
85
|
+
children,
|
|
86
|
+
className,
|
|
87
|
+
...props
|
|
88
|
+
}) => {
|
|
89
|
+
const api = useCarouselApi();
|
|
90
|
+
const [current, setCurrent] = useState(0);
|
|
91
|
+
const [count, setCount] = useState(0);
|
|
92
|
+
const syncState = useCallback(() => {
|
|
93
|
+
if (!api) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
setCount(api.scrollSnapList().length);
|
|
97
|
+
setCurrent(api.selectedScrollSnap() + 1);
|
|
98
|
+
}, [api]);
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
if (!api) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
syncState();
|
|
104
|
+
api.on("select", syncState);
|
|
105
|
+
return () => {
|
|
106
|
+
api.off("select", syncState);
|
|
107
|
+
};
|
|
108
|
+
}, [api, syncState]);
|
|
109
|
+
return /* @__PURE__ */ jsx(
|
|
110
|
+
"div",
|
|
111
|
+
{
|
|
112
|
+
className: cn(
|
|
113
|
+
"flex flex-1 items-center justify-end px-3 py-1 text-muted-foreground text-meta",
|
|
114
|
+
className
|
|
115
|
+
),
|
|
116
|
+
...props,
|
|
117
|
+
children: children ?? `${current}/${count}`
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
};
|
|
121
|
+
var InlineCitationCarouselPrev = ({
|
|
122
|
+
className,
|
|
123
|
+
...props
|
|
124
|
+
}) => {
|
|
125
|
+
const { t } = useLocale();
|
|
126
|
+
const api = useCarouselApi();
|
|
127
|
+
const handleClick = useCallback(() => {
|
|
128
|
+
if (api) {
|
|
129
|
+
api.scrollPrev();
|
|
130
|
+
}
|
|
131
|
+
}, [api]);
|
|
132
|
+
return /* @__PURE__ */ jsx(
|
|
133
|
+
"button",
|
|
134
|
+
{
|
|
135
|
+
"aria-label": t("previous"),
|
|
136
|
+
className: cn("shrink-0", className),
|
|
137
|
+
onClick: handleClick,
|
|
138
|
+
type: "button",
|
|
139
|
+
...props,
|
|
140
|
+
children: /* @__PURE__ */ jsx(ArrowLeftIcon, { className: "size-4 text-muted-foreground", "data-rtl-flip": true })
|
|
141
|
+
}
|
|
142
|
+
);
|
|
143
|
+
};
|
|
144
|
+
var InlineCitationCarouselNext = ({
|
|
145
|
+
className,
|
|
146
|
+
...props
|
|
147
|
+
}) => {
|
|
148
|
+
const { t } = useLocale();
|
|
149
|
+
const api = useCarouselApi();
|
|
150
|
+
const handleClick = useCallback(() => {
|
|
151
|
+
if (api) {
|
|
152
|
+
api.scrollNext();
|
|
153
|
+
}
|
|
154
|
+
}, [api]);
|
|
155
|
+
return /* @__PURE__ */ jsx(
|
|
156
|
+
"button",
|
|
157
|
+
{
|
|
158
|
+
"aria-label": t("next"),
|
|
159
|
+
className: cn("shrink-0", className),
|
|
160
|
+
onClick: handleClick,
|
|
161
|
+
type: "button",
|
|
162
|
+
...props,
|
|
163
|
+
children: /* @__PURE__ */ jsx(ArrowRightIcon, { className: "size-4 text-muted-foreground", "data-rtl-flip": true })
|
|
164
|
+
}
|
|
165
|
+
);
|
|
166
|
+
};
|
|
167
|
+
var InlineCitationSource = ({
|
|
168
|
+
title,
|
|
169
|
+
url,
|
|
170
|
+
description,
|
|
171
|
+
className,
|
|
172
|
+
children,
|
|
173
|
+
...props
|
|
174
|
+
}) => /* @__PURE__ */ jsxs("div", { className: cn("space-y-1", className), ...props, children: [
|
|
175
|
+
title && /* @__PURE__ */ jsx("h4", { className: "truncate font-medium text-body leading-tight", children: title }),
|
|
176
|
+
url && /* @__PURE__ */ jsx("p", { className: "truncate break-all text-muted-foreground text-meta", children: url }),
|
|
177
|
+
description && /* @__PURE__ */ jsx("p", { className: "line-clamp-3 text-muted-foreground text-body leading-relaxed", children: description }),
|
|
178
|
+
children
|
|
179
|
+
] });
|
|
180
|
+
var InlineCitationQuote = ({
|
|
181
|
+
children,
|
|
182
|
+
className,
|
|
183
|
+
...props
|
|
184
|
+
}) => /* @__PURE__ */ jsx(
|
|
185
|
+
"blockquote",
|
|
186
|
+
{
|
|
187
|
+
className: cn("border-muted border-s-2 ps-3 text-muted-foreground text-body italic", className),
|
|
188
|
+
...props,
|
|
189
|
+
children
|
|
190
|
+
}
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
export {
|
|
194
|
+
InlineCitation,
|
|
195
|
+
InlineCitationText,
|
|
196
|
+
InlineCitationCard,
|
|
197
|
+
inlineCitationSourceLabel,
|
|
198
|
+
InlineCitationCardTrigger,
|
|
199
|
+
EvidenceChip,
|
|
200
|
+
InlineCitationCardBody,
|
|
201
|
+
InlineCitationCarousel,
|
|
202
|
+
InlineCitationCarouselContent,
|
|
203
|
+
InlineCitationCarouselItem,
|
|
204
|
+
InlineCitationCarouselHeader,
|
|
205
|
+
InlineCitationCarouselIndex,
|
|
206
|
+
InlineCitationCarouselPrev,
|
|
207
|
+
InlineCitationCarouselNext,
|
|
208
|
+
InlineCitationSource,
|
|
209
|
+
InlineCitationQuote
|
|
210
|
+
};
|
|
211
|
+
//# sourceMappingURL=chunk-CMOYXNPJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/inline-citation.tsx"],"sourcesContent":["\"use client\";\n\nimport { Badge } from \"@elabs-ai/components-ui\";\nimport type { CarouselApi } from \"@elabs-ai/components-ui\";\nimport { Carousel, CarouselContent, CarouselItem } from \"@elabs-ai/components-ui\";\nimport { HoverCard, HoverCardContent, HoverCardTrigger } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { useLocale } from \"@elabs-ai/components-ui\";\nimport { ArrowLeftIcon, ArrowRightIcon, BadgeCheckIcon } from \"lucide-react\";\nimport type { ComponentProps } from \"react\";\nimport { createContext, useCallback, useContext, useEffect, useState } from \"react\";\n\nexport type InlineCitationProps = ComponentProps<\"span\">;\n\nexport const InlineCitation = ({ className, ...props }: InlineCitationProps) => (\n <span className={cn(\"group inline items-center gap-1\", className)} {...props} />\n);\n\nexport type InlineCitationTextProps = ComponentProps<\"span\">;\n\nexport const InlineCitationText = ({ className, ...props }: InlineCitationTextProps) => (\n <span className={cn(\"transition-colors group-hover:bg-accent\", className)} {...props} />\n);\n\nexport type InlineCitationCardProps = ComponentProps<typeof HoverCard>;\n\nexport const InlineCitationCard = (props: InlineCitationCardProps) => (\n <HoverCard closeDelay={0} openDelay={0} {...props} />\n);\n\n/**\n * A cited source: a bare string — a URL, or any opaque id / human label — or a\n * labelled object.\n *\n * Non-URL sources are first-class. An agent citing a warehouse table, a document\n * id, an uploaded file or a wiki page has no hostname to show, and must not have\n * to synthesize a fake URL to satisfy the chip.\n */\nexport type InlineCitationSourceRef =\n | string\n | {\n /** Opaque identifier, shown when there is no `label` and no `url`. */\n id?: string;\n /** Human-readable label — wins over any hostname derived from `url`. */\n label?: string;\n /** Optional link; its hostname is the fallback label. */\n url?: string;\n };\n\n/** The URL's hostname when `value` parses as one, else `value` itself. Never throws. */\nconst hostnameOrRaw = (value: string): string => {\n try {\n return new URL(value).hostname || value;\n } catch {\n return value;\n }\n};\n\n/**\n * The chip label for a source ref. Exported so consumers can render the same\n * label elsewhere (a footnote list, a tooltip) without re-deriving the rules.\n */\nexport const inlineCitationSourceLabel = (source: InlineCitationSourceRef): string => {\n if (typeof source === \"string\") {\n return hostnameOrRaw(source);\n }\n // `||` not `??` — an upstream field that is present but EMPTY (`label: \"\"`)\n // must still fall through, or the chip renders with no label at all.\n return source.label || (source.url ? hostnameOrRaw(source.url) : source.id || \"unknown\");\n};\n\nexport type InlineCitationCardTriggerProps = ComponentProps<typeof Badge> & {\n sources: InlineCitationSourceRef[];\n};\n\nexport const InlineCitationCardTrigger = ({\n sources,\n className,\n ...props\n}: InlineCitationCardTriggerProps) => (\n <HoverCardTrigger asChild>\n <Badge\n // The 08 §C.1 evidence channel: the green wash marks \"grounded\" — green\n // is reserved for evidence/answer/favourable (research 11 §B.4).\n className={cn(\n \"ms-1 rounded-full border-success/40 bg-success/10 text-success-text\",\n className,\n )}\n variant=\"outline\"\n {...props}\n >\n <BadgeCheckIcon aria-hidden=\"true\" className=\"size-3\" />\n {sources[0] ? (\n <>\n {inlineCitationSourceLabel(sources[0])} {sources.length > 1 && `+${sources.length - 1}`}\n </>\n ) : (\n \"unknown\"\n )}\n </Badge>\n </HoverCardTrigger>\n);\n\nexport type EvidenceChipProps = InlineCitationCardTriggerProps;\n\n/**\n * EvidenceChip — the named front door for the inline evidence interaction\n * (research 11 §B.4): the re-skinned `InlineCitationCardTrigger` (green\n * \"grounded\" wash). Use inside an `InlineCitationCard` (HoverCard) — it reuses\n * the citation carousel wholesale; it is not a new primitive.\n */\nexport const EvidenceChip = InlineCitationCardTrigger;\n\nexport type InlineCitationCardBodyProps = ComponentProps<\"div\">;\n\nexport const InlineCitationCardBody = ({ className, ...props }: InlineCitationCardBodyProps) => (\n <HoverCardContent className={cn(\"relative w-80 p-0\", className)} {...props} />\n);\n\nconst CarouselApiContext = createContext<CarouselApi | undefined>(undefined);\n\nconst useCarouselApi = () => {\n const context = useContext(CarouselApiContext);\n return context;\n};\n\nexport type InlineCitationCarouselProps = ComponentProps<typeof Carousel>;\n\nexport const InlineCitationCarousel = ({\n className,\n children,\n ...props\n}: InlineCitationCarouselProps) => {\n const [api, setApi] = useState<CarouselApi>();\n\n return (\n <CarouselApiContext.Provider value={api}>\n <Carousel className={cn(\"w-full\", className)} setApi={setApi} {...props}>\n {children}\n </Carousel>\n </CarouselApiContext.Provider>\n );\n};\n\nexport type InlineCitationCarouselContentProps = ComponentProps<\"div\">;\n\nexport const InlineCitationCarouselContent = (props: InlineCitationCarouselContentProps) => (\n <CarouselContent {...props} />\n);\n\nexport type InlineCitationCarouselItemProps = ComponentProps<\"div\">;\n\nexport const InlineCitationCarouselItem = ({\n className,\n ...props\n}: InlineCitationCarouselItemProps) => (\n <CarouselItem className={cn(\"w-full space-y-2 p-4 ps-8\", className)} {...props} />\n);\n\nexport type InlineCitationCarouselHeaderProps = ComponentProps<\"div\">;\n\nexport const InlineCitationCarouselHeader = ({\n className,\n ...props\n}: InlineCitationCarouselHeaderProps) => (\n <div\n className={cn(\n \"flex items-center justify-between gap-2 rounded-t-md bg-secondary p-2\",\n className,\n )}\n {...props}\n />\n);\n\nexport type InlineCitationCarouselIndexProps = ComponentProps<\"div\">;\n\nexport const InlineCitationCarouselIndex = ({\n children,\n className,\n ...props\n}: InlineCitationCarouselIndexProps) => {\n const api = useCarouselApi();\n const [current, setCurrent] = useState(0);\n const [count, setCount] = useState(0);\n\n const syncState = useCallback(() => {\n if (!api) {\n return;\n }\n setCount(api.scrollSnapList().length);\n setCurrent(api.selectedScrollSnap() + 1);\n }, [api]);\n\n useEffect(() => {\n if (!api) {\n return;\n }\n\n syncState();\n\n api.on(\"select\", syncState);\n\n return () => {\n api.off(\"select\", syncState);\n };\n }, [api, syncState]);\n\n return (\n <div\n className={cn(\n \"flex flex-1 items-center justify-end px-3 py-1 text-muted-foreground text-meta\",\n className,\n )}\n {...props}\n >\n {children ?? `${current}/${count}`}\n </div>\n );\n};\n\nexport type InlineCitationCarouselPrevProps = ComponentProps<\"button\">;\n\nexport const InlineCitationCarouselPrev = ({\n className,\n ...props\n}: InlineCitationCarouselPrevProps) => {\n const { t } = useLocale();\n const api = useCarouselApi();\n\n const handleClick = useCallback(() => {\n if (api) {\n api.scrollPrev();\n }\n }, [api]);\n\n return (\n <button\n aria-label={t(\"previous\")}\n className={cn(\"shrink-0\", className)}\n onClick={handleClick}\n type=\"button\"\n {...props}\n >\n <ArrowLeftIcon className=\"size-4 text-muted-foreground\" data-rtl-flip />\n </button>\n );\n};\n\nexport type InlineCitationCarouselNextProps = ComponentProps<\"button\">;\n\nexport const InlineCitationCarouselNext = ({\n className,\n ...props\n}: InlineCitationCarouselNextProps) => {\n const { t } = useLocale();\n const api = useCarouselApi();\n\n const handleClick = useCallback(() => {\n if (api) {\n api.scrollNext();\n }\n }, [api]);\n\n return (\n <button\n aria-label={t(\"next\")}\n className={cn(\"shrink-0\", className)}\n onClick={handleClick}\n type=\"button\"\n {...props}\n >\n <ArrowRightIcon className=\"size-4 text-muted-foreground\" data-rtl-flip />\n </button>\n );\n};\n\nexport type InlineCitationSourceProps = ComponentProps<\"div\"> & {\n title?: string;\n url?: string;\n description?: string;\n};\n\nexport const InlineCitationSource = ({\n title,\n url,\n description,\n className,\n children,\n ...props\n}: InlineCitationSourceProps) => (\n <div className={cn(\"space-y-1\", className)} {...props}>\n {title && <h4 className=\"truncate font-medium text-body leading-tight\">{title}</h4>}\n {url && <p className=\"truncate break-all text-muted-foreground text-meta\">{url}</p>}\n {description && (\n <p className=\"line-clamp-3 text-muted-foreground text-body leading-relaxed\">{description}</p>\n )}\n {children}\n </div>\n);\n\nexport type InlineCitationQuoteProps = ComponentProps<\"blockquote\">;\n\nexport const InlineCitationQuote = ({\n children,\n className,\n ...props\n}: InlineCitationQuoteProps) => (\n <blockquote\n className={cn(\"border-muted border-s-2 ps-3 text-muted-foreground text-body italic\", className)}\n {...props}\n >\n {children}\n </blockquote>\n);\n"],"mappings":"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","names":[]}
|