@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,28 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/_lazy-engine-boundary.tsx
|
|
4
|
+
import { Component } from "react";
|
|
5
|
+
var LazyEngineBoundary = class extends Component {
|
|
6
|
+
state = { error: null };
|
|
7
|
+
static getDerivedStateFromError(error) {
|
|
8
|
+
return { error: { value: error } };
|
|
9
|
+
}
|
|
10
|
+
componentDidCatch(error, info) {
|
|
11
|
+
console.error(
|
|
12
|
+
"[@elabs-ai/components-ai] a lazy engine failed to load:",
|
|
13
|
+
error,
|
|
14
|
+
info.componentStack
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
render() {
|
|
18
|
+
if (this.state.error) {
|
|
19
|
+
return this.props.renderMissing(this.state.error.value);
|
|
20
|
+
}
|
|
21
|
+
return this.props.children;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export {
|
|
26
|
+
LazyEngineBoundary
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=chunk-S3ISPW3A.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/_lazy-engine-boundary.tsx"],"sourcesContent":["\"use client\";\n\nimport { Component, type ErrorInfo, type ReactNode } from \"react\";\n\nexport interface LazyEngineBoundaryProps {\n children: ReactNode;\n /**\n * Called once a wrapped `lazy()` import rejects (an optional peer that is\n * not installed, or any other load-time failure). Return what to render in\n * its place — the boundary owns no default visual, since the right\n * stand-in differs by surface (an orb placeholder for `Persona`, `null`\n * for an `AudioPlayer` sub-control).\n */\n renderMissing: (error: unknown) => ReactNode;\n}\n\ninterface LazyEngineBoundaryState {\n // Wrapped in an object so `{ value: undefined }` (a boundary that caught\n // an error whose value happens to be `undefined`) is distinguishable from\n // \"nothing caught yet\" (`error: null`).\n error: { value: unknown } | null;\n}\n\n/**\n * Catches a `React.lazy()` load failure — an optional peer dependency that is\n * not installed (issue #33), or any other dynamic-import rejection — and\n * renders a caller-supplied fallback instead of unmounting the tree.\n *\n * `Suspense` alone does not do this: it only covers the PENDING state. A\n * REJECTED lazy import throws during render, and with no boundary above it\n * that throw propagates to the nearest ancestor boundary React DOES find —\n * by default, the whole app. This is the one place in `@elabs-ai/components-ai`\n * that needs a real render-phase error boundary; Mermaid and the interactive\n * terminal fail via an awaited promise instead (Streamdown's `errorComponent`\n * and a `.catch()` on the mount effect, respectively), which don't need one.\n */\nexport class LazyEngineBoundary extends Component<\n LazyEngineBoundaryProps,\n LazyEngineBoundaryState\n> {\n override state: LazyEngineBoundaryState = { error: null };\n\n static getDerivedStateFromError(error: unknown): LazyEngineBoundaryState {\n return { error: { value: error } };\n }\n\n override componentDidCatch(error: unknown, info: ErrorInfo): void {\n console.error(\n \"[@elabs-ai/components-ai] a lazy engine failed to load:\",\n error,\n info.componentStack,\n );\n }\n\n override render(): ReactNode {\n if (this.state.error) {\n return this.props.renderMissing(this.state.error.value);\n }\n return this.props.children;\n }\n}\n"],"mappings":";;;AAEA,SAAS,iBAAiD;AAkCnD,IAAM,qBAAN,cAAiC,UAGtC;AAAA,EACS,QAAiC,EAAE,OAAO,KAAK;AAAA,EAExD,OAAO,yBAAyB,OAAyC;AACvE,WAAO,EAAE,OAAO,EAAE,OAAO,MAAM,EAAE;AAAA,EACnC;AAAA,EAES,kBAAkB,OAAgB,MAAuB;AAChE,YAAQ;AAAA,MACN;AAAA,MACA;AAAA,MACA,KAAK;AAAA,IACP;AAAA,EACF;AAAA,EAES,SAAoB;AAC3B,QAAI,KAAK,MAAM,OAAO;AACpB,aAAO,KAAK,MAAM,cAAc,KAAK,MAAM,MAAM,KAAK;AAAA,IACxD;AACA,WAAO,KAAK,MAAM;AAAA,EACpB;AACF;","names":[]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/_mermaid-error-panel.tsx
|
|
4
|
+
import { Button, StatePanel, isModuleNotFoundMessage, useLocale } from "@elabs-ai/components-ui";
|
|
5
|
+
import { EyeOffIcon } from "lucide-react";
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
function MermaidErrorPanel({ error, retry }) {
|
|
8
|
+
const { t } = useLocale();
|
|
9
|
+
if (isModuleNotFoundMessage(error)) {
|
|
10
|
+
const feature = t("ai.mermaid.feature");
|
|
11
|
+
return /* @__PURE__ */ jsx("div", { className: "my-4", role: "status", "aria-live": "polite", children: /* @__PURE__ */ jsx(
|
|
12
|
+
StatePanel,
|
|
13
|
+
{
|
|
14
|
+
kind: "empty",
|
|
15
|
+
className: "border-solid",
|
|
16
|
+
icon: /* @__PURE__ */ jsx(EyeOffIcon, { "aria-hidden": "true" }),
|
|
17
|
+
title: t("ai.error.engineMissing", { feature }),
|
|
18
|
+
description: t("ai.error.engineMissingBody", { feature, packages: "mermaid" })
|
|
19
|
+
}
|
|
20
|
+
) });
|
|
21
|
+
}
|
|
22
|
+
return /* @__PURE__ */ jsx("div", { className: "my-4", children: /* @__PURE__ */ jsx(
|
|
23
|
+
StatePanel,
|
|
24
|
+
{
|
|
25
|
+
kind: "error",
|
|
26
|
+
title: t("ai.mermaid.renderError"),
|
|
27
|
+
description: error,
|
|
28
|
+
actions: /* @__PURE__ */ jsx(Button, { size: "sm", variant: "outline", onClick: retry, children: t("ai.error.retry") })
|
|
29
|
+
}
|
|
30
|
+
) });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
MermaidErrorPanel
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=chunk-SEVN656N.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/_mermaid-error-panel.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * The `errorComponent` Streamdown renders in place of a Mermaid diagram that\n * failed (issue #33). Streamdown hands back the render failure as a plain\n * STRING (`MermaidErrorComponentProps.error`, already reduced from whatever\n * was thrown), so this distinguishes two different failures by matching that\n * string rather than the original error object:\n *\n * - **The optional `mermaid` peer is not installed.** This is a CAPABILITY\n * GAP, not something wrong with the diagram or the app — the same class as\n * `@elabs-ai/components-viewer`'s `parser-missing`\n * (@.claude/rules/viewer-components.md \"A capability gap is not a\n * failure\"). Renders the neutral `StatePanel kind=\"empty\"`, naming the\n * package to install, announced `role=\"status\"`, with no retry action\n * (re-installing a dependency does not happen by clicking a button in the\n * page).\n * - **Anything else is a genuine render/syntax failure** — a real error, so\n * it gets `StatePanel kind=\"error\"` (`role=\"alert\"`, set internally by\n * `StatePanel`) wired to Streamdown's own `retry()`, which increments the\n * render attempt and re-runs the diagram.\n */\nimport { Button, StatePanel, isModuleNotFoundMessage, useLocale } from \"@elabs-ai/components-ui\";\nimport { EyeOffIcon } from \"lucide-react\";\n\nexport interface MermaidErrorPanelProps {\n chart: string;\n error: string;\n retry: () => void;\n}\n\nexport function MermaidErrorPanel({ error, retry }: MermaidErrorPanelProps) {\n const { t } = useLocale();\n\n if (isModuleNotFoundMessage(error)) {\n const feature = t(\"ai.mermaid.feature\");\n return (\n <div className=\"my-4\" role=\"status\" aria-live=\"polite\">\n <StatePanel\n kind=\"empty\"\n // A dashed edge invites a drop; this panel accepts nothing. Solid —\n // mirrors `@elabs-ai/components-viewer`'s `FileViewerError`.\n className=\"border-solid\"\n icon={<EyeOffIcon aria-hidden=\"true\" />}\n title={t(\"ai.error.engineMissing\", { feature })}\n description={t(\"ai.error.engineMissingBody\", { feature, packages: \"mermaid\" })}\n />\n </div>\n );\n }\n\n return (\n <div className=\"my-4\">\n <StatePanel\n kind=\"error\"\n title={t(\"ai.mermaid.renderError\")}\n description={error}\n actions={\n <Button size=\"sm\" variant=\"outline\" onClick={retry}>\n {t(\"ai.error.retry\")}\n </Button>\n }\n />\n </div>\n );\n}\n"],"mappings":";;;AAsBA,SAAS,QAAQ,YAAY,yBAAyB,iBAAiB;AACvE,SAAS,kBAAkB;AAoBX;AAZT,SAAS,kBAAkB,EAAE,OAAO,MAAM,GAA2B;AAC1E,QAAM,EAAE,EAAE,IAAI,UAAU;AAExB,MAAI,wBAAwB,KAAK,GAAG;AAClC,UAAM,UAAU,EAAE,oBAAoB;AACtC,WACE,oBAAC,SAAI,WAAU,QAAO,MAAK,UAAS,aAAU,UAC5C;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QAGL,WAAU;AAAA,QACV,MAAM,oBAAC,cAAW,eAAY,QAAO;AAAA,QACrC,OAAO,EAAE,0BAA0B,EAAE,QAAQ,CAAC;AAAA,QAC9C,aAAa,EAAE,8BAA8B,EAAE,SAAS,UAAU,UAAU,CAAC;AAAA;AAAA,IAC/E,GACF;AAAA,EAEJ;AAEA,SACE,oBAAC,SAAI,WAAU,QACb;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,OAAO,EAAE,wBAAwB;AAAA,MACjC,aAAa;AAAA,MACb,SACE,oBAAC,UAAO,MAAK,MAAK,SAAQ,WAAU,SAAS,OAC1C,YAAE,gBAAgB,GACrB;AAAA;AAAA,EAEJ,GACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/a2ui/core/complete-json.ts
|
|
4
|
+
function completeJson(text) {
|
|
5
|
+
const stack = [];
|
|
6
|
+
let inString = false;
|
|
7
|
+
let escaped = false;
|
|
8
|
+
let lastGood = 0;
|
|
9
|
+
let lastNonWs = "";
|
|
10
|
+
for (let i = 0; i < text.length; i++) {
|
|
11
|
+
const ch = text[i];
|
|
12
|
+
if (inString) {
|
|
13
|
+
if (escaped) escaped = false;
|
|
14
|
+
else if (ch === "\\") escaped = true;
|
|
15
|
+
else if (ch === '"') {
|
|
16
|
+
inString = false;
|
|
17
|
+
lastNonWs = ch;
|
|
18
|
+
lastGood = i + 1;
|
|
19
|
+
}
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if (ch === '"') {
|
|
23
|
+
inString = true;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (ch === "{" || ch === "[") stack.push(ch === "{" ? "}" : "]");
|
|
27
|
+
else if (ch === "}" || ch === "]") stack.pop();
|
|
28
|
+
if (!/\s/.test(ch)) {
|
|
29
|
+
lastNonWs = ch;
|
|
30
|
+
lastGood = i + 1;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
let out = text;
|
|
34
|
+
if (inString) {
|
|
35
|
+
const top = stack[stack.length - 1];
|
|
36
|
+
if (top === "}" && (lastNonWs === "{" || lastNonWs === ",")) out = text.slice(0, lastGood);
|
|
37
|
+
else out = escaped ? `${text.slice(0, -1)}"` : `${text}"`;
|
|
38
|
+
lastNonWs = out.trimEnd().slice(-1);
|
|
39
|
+
}
|
|
40
|
+
out = out.trimEnd();
|
|
41
|
+
if (lastNonWs === ",") out = out.slice(0, -1);
|
|
42
|
+
else if (lastNonWs === ":") out = `${out}null`;
|
|
43
|
+
else if (lastNonWs === '"' && stack[stack.length - 1] === "}") {
|
|
44
|
+
const m = /(?:^|[{,])\s*"(?:[^"\\]|\\.)*"$/.exec(out);
|
|
45
|
+
if (m) out = out.slice(0, m.index + (out[m.index] === "{" || out[m.index] === "," ? 1 : 0));
|
|
46
|
+
}
|
|
47
|
+
out = out.replace(/,\s*$/, "");
|
|
48
|
+
return out + stack.reverse().join("");
|
|
49
|
+
}
|
|
50
|
+
function parseSurfaceJson(text, partial = false) {
|
|
51
|
+
const trimmed = text.trim();
|
|
52
|
+
if (!trimmed) return null;
|
|
53
|
+
try {
|
|
54
|
+
return JSON.parse(partial ? completeJson(trimmed) : trimmed);
|
|
55
|
+
} catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export {
|
|
61
|
+
completeJson,
|
|
62
|
+
parseSurfaceJson
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=chunk-SKVG672B.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/a2ui/core/complete-json.ts"],"sourcesContent":["/**\n * complete-json.ts — close a PARTIAL JSON document so a streaming surface can be\n * parsed and drawn before the model has finished (the A2UI counterpart of\n * `JSXPreview`'s `completeJsxTag`).\n *\n * Strategy: one linear scan tracking the bracket stack, string state and escape\n * state; then (1) close an open string, (2) drop a dangling `,` or supply `null`\n * for a dangling `\"key\":`, (3) close every open bracket in reverse. The result is\n * always syntactically valid JSON for any prefix of a valid document that has\n * passed its first `{`. Semantic gaps (a half-typed prop value, a node without\n * its `type` yet) are the validator's business — the renderer prunes what does\n * not validate while streaming and keeps the last good tree.\n */\nexport function completeJson(text: string): string {\n const stack: string[] = [];\n let inString = false;\n let escaped = false;\n // Index just after the last STRUCTURALLY complete token, so a half-typed key\n // (`{\"ty`) can be cut rather than closed into `{\"ty\":null}`.\n let lastGood = 0;\n let lastNonWs = \"\";\n\n for (let i = 0; i < text.length; i++) {\n const ch = text[i] as string;\n if (inString) {\n if (escaped) escaped = false;\n else if (ch === \"\\\\\") escaped = true;\n else if (ch === '\"') {\n inString = false;\n lastNonWs = ch;\n lastGood = i + 1;\n }\n continue;\n }\n if (ch === '\"') {\n inString = true;\n continue;\n }\n if (ch === \"{\" || ch === \"[\") stack.push(ch === \"{\" ? \"}\" : \"]\");\n else if (ch === \"}\" || ch === \"]\") stack.pop();\n if (!/\\s/.test(ch)) {\n lastNonWs = ch;\n lastGood = i + 1;\n }\n }\n\n let out = text;\n if (inString) {\n // Inside a value string → close it. Inside a KEY (the string follows `{` or\n // `,` inside an object) → cut it: a key without a value is not renderable.\n const top = stack[stack.length - 1];\n if (top === \"}\" && (lastNonWs === \"{\" || lastNonWs === \",\")) out = text.slice(0, lastGood);\n else out = escaped ? `${text.slice(0, -1)}\"` : `${text}\"`;\n lastNonWs = out.trimEnd().slice(-1);\n }\n out = out.trimEnd();\n if (lastNonWs === \",\") out = out.slice(0, -1);\n else if (lastNonWs === \":\") out = `${out}null`;\n // A `\"key\"` with no colon yet (`{\"type\"`) is also unfinished — cut it.\n else if (lastNonWs === '\"' && stack[stack.length - 1] === \"}\") {\n const m = /(?:^|[{,])\\s*\"(?:[^\"\\\\]|\\\\.)*\"$/.exec(out);\n if (m) out = out.slice(0, m.index + (out[m.index] === \"{\" || out[m.index] === \",\" ? 1 : 0));\n }\n out = out.replace(/,\\s*$/, \"\");\n return out + stack.reverse().join(\"\");\n}\n\n/**\n * Parse `text`, completing it first when `partial`. Returns `null` (never throws)\n * when even the completed text is not JSON — the caller treats that as \"no tree\n * yet\".\n */\nexport function parseSurfaceJson(text: string, partial = false): unknown | null {\n const trimmed = text.trim();\n if (!trimmed) return null;\n try {\n return JSON.parse(partial ? completeJson(trimmed) : trimmed);\n } catch {\n return null;\n }\n}\n"],"mappings":";;;AAaO,SAAS,aAAa,MAAsB;AACjD,QAAM,QAAkB,CAAC;AACzB,MAAI,WAAW;AACf,MAAI,UAAU;AAGd,MAAI,WAAW;AACf,MAAI,YAAY;AAEhB,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,KAAK,KAAK,CAAC;AACjB,QAAI,UAAU;AACZ,UAAI,QAAS,WAAU;AAAA,eACd,OAAO,KAAM,WAAU;AAAA,eACvB,OAAO,KAAK;AACnB,mBAAW;AACX,oBAAY;AACZ,mBAAW,IAAI;AAAA,MACjB;AACA;AAAA,IACF;AACA,QAAI,OAAO,KAAK;AACd,iBAAW;AACX;AAAA,IACF;AACA,QAAI,OAAO,OAAO,OAAO,IAAK,OAAM,KAAK,OAAO,MAAM,MAAM,GAAG;AAAA,aACtD,OAAO,OAAO,OAAO,IAAK,OAAM,IAAI;AAC7C,QAAI,CAAC,KAAK,KAAK,EAAE,GAAG;AAClB,kBAAY;AACZ,iBAAW,IAAI;AAAA,IACjB;AAAA,EACF;AAEA,MAAI,MAAM;AACV,MAAI,UAAU;AAGZ,UAAM,MAAM,MAAM,MAAM,SAAS,CAAC;AAClC,QAAI,QAAQ,QAAQ,cAAc,OAAO,cAAc,KAAM,OAAM,KAAK,MAAM,GAAG,QAAQ;AAAA,QACpF,OAAM,UAAU,GAAG,KAAK,MAAM,GAAG,EAAE,CAAC,MAAM,GAAG,IAAI;AACtD,gBAAY,IAAI,QAAQ,EAAE,MAAM,EAAE;AAAA,EACpC;AACA,QAAM,IAAI,QAAQ;AAClB,MAAI,cAAc,IAAK,OAAM,IAAI,MAAM,GAAG,EAAE;AAAA,WACnC,cAAc,IAAK,OAAM,GAAG,GAAG;AAAA,WAE/B,cAAc,OAAO,MAAM,MAAM,SAAS,CAAC,MAAM,KAAK;AAC7D,UAAM,IAAI,kCAAkC,KAAK,GAAG;AACpD,QAAI,EAAG,OAAM,IAAI,MAAM,GAAG,EAAE,SAAS,IAAI,EAAE,KAAK,MAAM,OAAO,IAAI,EAAE,KAAK,MAAM,MAAM,IAAI,EAAE;AAAA,EAC5F;AACA,QAAM,IAAI,QAAQ,SAAS,EAAE;AAC7B,SAAO,MAAM,MAAM,QAAQ,EAAE,KAAK,EAAE;AACtC;AAOO,SAAS,iBAAiB,MAAc,UAAU,OAAuB;AAC9E,QAAM,UAAU,KAAK,KAAK;AAC1B,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI;AACF,WAAO,KAAK,MAAM,UAAU,aAAa,OAAO,IAAI,OAAO;AAAA,EAC7D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
parseSurfaceJson
|
|
4
|
+
} from "./chunk-SKVG672B.js";
|
|
5
|
+
import {
|
|
6
|
+
invalidNodePaths,
|
|
7
|
+
isA2uiElement,
|
|
8
|
+
validateA2uiSurface
|
|
9
|
+
} from "./chunk-7FD5CZEU.js";
|
|
10
|
+
import {
|
|
11
|
+
catalogSchema,
|
|
12
|
+
uiCatalog
|
|
13
|
+
} from "./chunk-XNBKO32Y.js";
|
|
14
|
+
|
|
15
|
+
// src/a2ui/a2ui-surface.tsx
|
|
16
|
+
import { Skeleton, useLocale } from "@elabs-ai/components-ui";
|
|
17
|
+
import { cn } from "@elabs-ai/components-ui/lib/cn";
|
|
18
|
+
import { AlertCircle } from "lucide-react";
|
|
19
|
+
import { createElement, forwardRef, memo, useEffect, useMemo, useRef, useState } from "react";
|
|
20
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
21
|
+
var GAP = {
|
|
22
|
+
none: "gap-0",
|
|
23
|
+
xs: "gap-1",
|
|
24
|
+
sm: "gap-2",
|
|
25
|
+
md: "gap-4",
|
|
26
|
+
lg: "gap-6"
|
|
27
|
+
};
|
|
28
|
+
var ALIGN = {
|
|
29
|
+
start: "items-start",
|
|
30
|
+
center: "items-center",
|
|
31
|
+
end: "items-end",
|
|
32
|
+
stretch: "items-stretch"
|
|
33
|
+
};
|
|
34
|
+
var JUSTIFY = {
|
|
35
|
+
start: "justify-start",
|
|
36
|
+
center: "justify-center",
|
|
37
|
+
end: "justify-end",
|
|
38
|
+
between: "justify-between"
|
|
39
|
+
};
|
|
40
|
+
var COLUMNS = {
|
|
41
|
+
1: "grid-cols-1",
|
|
42
|
+
2: "grid-cols-1 sm:grid-cols-2",
|
|
43
|
+
3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
|
|
44
|
+
4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4"
|
|
45
|
+
};
|
|
46
|
+
function builtinClass(type, props) {
|
|
47
|
+
const gap = GAP[String(props.gap ?? "md")] ?? GAP.md;
|
|
48
|
+
if (type === "Grid") {
|
|
49
|
+
return cn("grid", COLUMNS[Number(props.columns ?? 2)] ?? COLUMNS[2], gap);
|
|
50
|
+
}
|
|
51
|
+
return cn(
|
|
52
|
+
"flex min-w-0",
|
|
53
|
+
props.direction === "row" ? "flex-row" : "flex-col",
|
|
54
|
+
props.wrap ? "flex-wrap" : "",
|
|
55
|
+
ALIGN[String(props.align ?? "stretch")],
|
|
56
|
+
JUSTIFY[String(props.justify ?? "start")],
|
|
57
|
+
gap
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
var isEvent = (v) => typeof v === "object" && v !== null && "nativeEvent" in v && "target" in v;
|
|
61
|
+
function eventValue(args) {
|
|
62
|
+
const first = args[0];
|
|
63
|
+
if (isEvent(first)) {
|
|
64
|
+
const target = first.target;
|
|
65
|
+
if (target && typeof target.type === "string" && target.type === "checkbox")
|
|
66
|
+
return target.checked;
|
|
67
|
+
return target && "value" in target ? target.value : void 0;
|
|
68
|
+
}
|
|
69
|
+
return first;
|
|
70
|
+
}
|
|
71
|
+
function renderPropValue(value, path, ctx) {
|
|
72
|
+
if (Array.isArray(value) && value.some(isA2uiElement)) {
|
|
73
|
+
return value.map((item, i) => renderNode(item, `${path}[${i}]`, ctx));
|
|
74
|
+
}
|
|
75
|
+
if (isA2uiElement(value)) return renderNode(value, path, ctx);
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
function renderNode(node, path, ctx) {
|
|
79
|
+
if (typeof node === "string" || typeof node === "number") return node;
|
|
80
|
+
if (ctx.invalid.has(path)) return null;
|
|
81
|
+
const entry = ctx.catalog[node.type];
|
|
82
|
+
if (!entry) return null;
|
|
83
|
+
const props = {};
|
|
84
|
+
for (const [name, value] of Object.entries(node.props ?? {})) {
|
|
85
|
+
const schema = entry.schema.props[name];
|
|
86
|
+
props[name] = schema?.type === "node" ? renderPropValue(value, `${path}.props.${name}`, ctx) : value;
|
|
87
|
+
}
|
|
88
|
+
for (const [event, action] of Object.entries(node.on ?? {})) {
|
|
89
|
+
const handlerName = entry.schema.events[event];
|
|
90
|
+
if (!handlerName) continue;
|
|
91
|
+
props[handlerName] = (...args) => {
|
|
92
|
+
const value = event === "click" ? void 0 : eventValue(args);
|
|
93
|
+
ctx.onAction?.(action, { event, value, node, path });
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const children = entry.schema.children ? (node.children ?? []).map((child, i) => renderNode(child, `${path}.children[${i}]`, ctx)) : void 0;
|
|
97
|
+
const key = path;
|
|
98
|
+
const dataAttrs = {
|
|
99
|
+
"data-a2ui-type": node.type,
|
|
100
|
+
...node.id ? { "data-a2ui-id": node.id } : {}
|
|
101
|
+
};
|
|
102
|
+
if (entry.schema.builtin) {
|
|
103
|
+
return createElement(
|
|
104
|
+
"div",
|
|
105
|
+
{ key, className: builtinClass(node.type, props), ...dataAttrs },
|
|
106
|
+
...children ?? []
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
return createElement(
|
|
110
|
+
entry.component,
|
|
111
|
+
{ key, ...props, ...dataAttrs },
|
|
112
|
+
...children ?? []
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
var SurfaceTree = memo(function SurfaceTree2({
|
|
116
|
+
spec,
|
|
117
|
+
catalog,
|
|
118
|
+
invalid,
|
|
119
|
+
onAction
|
|
120
|
+
}) {
|
|
121
|
+
return /* @__PURE__ */ jsx(Fragment, { children: renderNode(spec.root, "root", { catalog, invalid, onAction }) });
|
|
122
|
+
});
|
|
123
|
+
var A2uiSurface = forwardRef(function A2uiSurface2({
|
|
124
|
+
surface,
|
|
125
|
+
catalog = uiCatalog,
|
|
126
|
+
onAction,
|
|
127
|
+
isStreaming = false,
|
|
128
|
+
loading = false,
|
|
129
|
+
onError,
|
|
130
|
+
skeleton,
|
|
131
|
+
className,
|
|
132
|
+
...props
|
|
133
|
+
}, ref) {
|
|
134
|
+
const { t } = useLocale();
|
|
135
|
+
const schema = useMemo(() => catalogSchema(catalog), [catalog]);
|
|
136
|
+
const parsed = useMemo(() => {
|
|
137
|
+
if (loading || surface == null) return { value: null, incomplete: false };
|
|
138
|
+
if (typeof surface !== "string") return { value: surface, incomplete: false };
|
|
139
|
+
const complete = parseSurfaceJson(surface, false);
|
|
140
|
+
if (complete !== null) return { value: complete, incomplete: false };
|
|
141
|
+
const partial = parseSurfaceJson(surface, true);
|
|
142
|
+
return { value: partial, incomplete: surface.trim() !== "" };
|
|
143
|
+
}, [surface, loading]);
|
|
144
|
+
const validation = useMemo(
|
|
145
|
+
() => parsed.value === null ? null : validateA2uiSurface(parsed.value, schema),
|
|
146
|
+
[parsed.value, schema]
|
|
147
|
+
);
|
|
148
|
+
const pending = loading || isStreaming || parsed.incomplete;
|
|
149
|
+
const empty = surface == null || typeof surface === "string" && surface.trim() === "";
|
|
150
|
+
const invalid = useMemo(
|
|
151
|
+
() => validation && !validation.ok && pending ? invalidNodePaths(validation.errors) : /* @__PURE__ */ new Set(),
|
|
152
|
+
[validation, pending]
|
|
153
|
+
);
|
|
154
|
+
const drawable = validation?.spec && (validation.ok || pending && !invalid.has("root")) ? validation.spec : null;
|
|
155
|
+
const lastGoodRef = useRef(null);
|
|
156
|
+
if (drawable) lastGoodRef.current = drawable;
|
|
157
|
+
const shown = drawable ?? (pending ? lastGoodRef.current : null);
|
|
158
|
+
const [hasRendered, setHasRendered] = useState(false);
|
|
159
|
+
useEffect(() => {
|
|
160
|
+
if (shown && !hasRendered) setHasRendered(true);
|
|
161
|
+
}, [shown, hasRendered]);
|
|
162
|
+
const status = loading ? "pending" : empty ? hasRendered ? "ready" : "idle" : pending ? "pending" : validation && !validation.ok ? "error" : "ready";
|
|
163
|
+
const reportedRef = useRef(null);
|
|
164
|
+
useEffect(() => {
|
|
165
|
+
if (status !== "error" || !validation || validation.ok) return;
|
|
166
|
+
const key = JSON.stringify(validation.errors);
|
|
167
|
+
if (reportedRef.current === key) return;
|
|
168
|
+
reportedRef.current = key;
|
|
169
|
+
onError?.(validation.errors);
|
|
170
|
+
}, [status, validation, onError]);
|
|
171
|
+
const showSkeleton = status === "pending" && !shown;
|
|
172
|
+
const title = shown?.title;
|
|
173
|
+
return /* @__PURE__ */ jsxs(
|
|
174
|
+
"div",
|
|
175
|
+
{
|
|
176
|
+
ref,
|
|
177
|
+
"data-slot": "a2ui-surface",
|
|
178
|
+
"data-status": status,
|
|
179
|
+
className: cn("relative min-w-0", className),
|
|
180
|
+
...title ? { role: "group", "aria-label": title } : {},
|
|
181
|
+
...props,
|
|
182
|
+
children: [
|
|
183
|
+
showSkeleton ? /* @__PURE__ */ jsxs(
|
|
184
|
+
"div",
|
|
185
|
+
{
|
|
186
|
+
"data-slot": "a2ui-surface-skeleton",
|
|
187
|
+
role: "status",
|
|
188
|
+
"aria-live": "polite",
|
|
189
|
+
className: "space-y-2",
|
|
190
|
+
children: [
|
|
191
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: t("ai.a2ui.loading") }),
|
|
192
|
+
skeleton ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
193
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-6 w-1/3" }),
|
|
194
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
|
|
195
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-16" }),
|
|
196
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-16" }),
|
|
197
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-16" })
|
|
198
|
+
] }),
|
|
199
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-24 w-full" })
|
|
200
|
+
] })
|
|
201
|
+
]
|
|
202
|
+
}
|
|
203
|
+
) : null,
|
|
204
|
+
shown ? /* @__PURE__ */ jsx(SurfaceTree, { spec: shown, catalog, invalid, onAction }) : null,
|
|
205
|
+
status === "error" && validation && !validation.ok ? /* @__PURE__ */ jsxs(
|
|
206
|
+
"div",
|
|
207
|
+
{
|
|
208
|
+
"data-slot": "a2ui-surface-error",
|
|
209
|
+
role: "alert",
|
|
210
|
+
className: "flex gap-2 rounded-md bg-destructive/10 p-3 text-body text-destructive-text",
|
|
211
|
+
children: [
|
|
212
|
+
/* @__PURE__ */ jsx(AlertCircle, { className: "mt-0.5 size-4 shrink-0", "aria-hidden": "true" }),
|
|
213
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-1", children: [
|
|
214
|
+
/* @__PURE__ */ jsx("p", { className: "font-medium", children: t("ai.a2ui.invalid") }),
|
|
215
|
+
/* @__PURE__ */ jsxs("ul", { className: "space-y-0.5 text-caption", children: [
|
|
216
|
+
validation.errors.slice(0, 8).map((e) => /* @__PURE__ */ jsxs("li", { className: "break-words", children: [
|
|
217
|
+
/* @__PURE__ */ jsx("code", { className: "text-code", children: e.path || "root" }),
|
|
218
|
+
" \u2014 ",
|
|
219
|
+
e.message
|
|
220
|
+
] }, `${e.path}:${e.code}`)),
|
|
221
|
+
validation.errors.length > 8 ? /* @__PURE__ */ jsx("li", { children: t("ai.a2ui.moreErrors", { count: validation.errors.length - 8 }) }) : null
|
|
222
|
+
] })
|
|
223
|
+
] })
|
|
224
|
+
]
|
|
225
|
+
}
|
|
226
|
+
) : null
|
|
227
|
+
]
|
|
228
|
+
}
|
|
229
|
+
);
|
|
230
|
+
});
|
|
231
|
+
A2uiSurface.displayName = "A2uiSurface";
|
|
232
|
+
|
|
233
|
+
export {
|
|
234
|
+
A2uiSurface
|
|
235
|
+
};
|
|
236
|
+
//# sourceMappingURL=chunk-SPQIU7GA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/a2ui/a2ui-surface.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * A2uiSurface — render an agent-DESIGNED screen from data (D2's safe generative\n * path). The agent emits an `A2uiSurfaceSpec` (JSON: a tree of catalog nodes);\n * this component validates it against the catalog and draws it with the real\n * components — never `eval`, never arbitrary tags, never agent styling.\n *\n * Readiness follows the house model (loading-states): `loading` → skeleton;\n * `isStreaming` (or a string surface that is still incomplete JSON) → build up,\n * pruning only the nodes that do not validate YET and suppressing errors; a\n * settled surface that fails validation → `role=\"alert\"` with every problem and\n * `onError`. Interaction is data too: a node's `on.<event>` names a host action\n * that arrives at `onAction` — the app decides what \"approve\" means (D5).\n */\nimport { Skeleton, useLocale } from \"@elabs-ai/components-ui\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\nimport { AlertCircle } from \"lucide-react\";\nimport type { ComponentProps, ReactNode, SyntheticEvent } from \"react\";\nimport { createElement, forwardRef, memo, useEffect, useMemo, useRef, useState } from \"react\";\n\nimport { completeJson, parseSurfaceJson } from \"./core/complete-json\";\nimport type {\n A2uiAction,\n A2uiElement,\n A2uiError,\n A2uiNode,\n A2uiPropValue,\n A2uiSurfaceSpec,\n} from \"./core/spec\";\nimport { invalidNodePaths, isA2uiElement, validateA2uiSurface } from \"./core/validate\";\nimport { catalogSchema, uiCatalog, type A2uiCatalog } from \"./ui-catalog\";\n\nexport type A2uiSurfaceStatus = \"idle\" | \"pending\" | \"ready\" | \"error\";\n\n/** What `onAction` receives besides the action the agent named. */\nexport interface A2uiActionContext {\n /** The catalog event that fired (`click`, `change`, …). */\n event: string;\n /** The control's value for `change` events (text, checked, selected value…). */\n value?: unknown;\n /** The node that carried the binding, and its path in the spec. */\n node: A2uiElement;\n path: string;\n}\n\nexport type A2uiActionHandler = (action: A2uiAction, context: A2uiActionContext) => void;\n\nexport type A2uiSurfaceProps = Omit<ComponentProps<\"div\">, \"children\" | \"onError\"> & {\n /** The agent's surface: a parsed spec, or its JSON text (may be a streaming prefix). */\n surface: A2uiSurfaceSpec | string | null | undefined;\n /** Which types render, and how. Defaults to the shipped `uiCatalog`. */\n catalog?: A2uiCatalog;\n /** Receives every `on.<event>` binding the user triggers. */\n onAction?: A2uiActionHandler;\n /** Content is arriving incrementally — build up, suppress transient errors. */\n isStreaming?: boolean;\n /** No surface yet (fetch-then-show) — forces the skeleton. */\n loading?: boolean;\n /** Fires once per settled, invalid surface with the validation errors. */\n onError?: (errors: A2uiError[]) => void;\n /** Replace the default skeleton (shown before the first paint while pending). */\n skeleton?: ReactNode;\n};\n\n// ---------------------------------------------------------------------------\n// Builtins — the two layout nodes the surface draws itself, on tokens only.\n// ---------------------------------------------------------------------------\nconst GAP: Record<string, string> = {\n none: \"gap-0\",\n xs: \"gap-1\",\n sm: \"gap-2\",\n md: \"gap-4\",\n lg: \"gap-6\",\n};\nconst ALIGN: Record<string, string> = {\n start: \"items-start\",\n center: \"items-center\",\n end: \"items-end\",\n stretch: \"items-stretch\",\n};\nconst JUSTIFY: Record<string, string> = {\n start: \"justify-start\",\n center: \"justify-center\",\n end: \"justify-end\",\n between: \"justify-between\",\n};\nconst COLUMNS: Record<number, string> = {\n 1: \"grid-cols-1\",\n 2: \"grid-cols-1 sm:grid-cols-2\",\n 3: \"grid-cols-1 sm:grid-cols-2 lg:grid-cols-3\",\n 4: \"grid-cols-1 sm:grid-cols-2 lg:grid-cols-4\",\n};\n\nfunction builtinClass(type: string, props: Record<string, unknown>): string {\n const gap = GAP[String(props.gap ?? \"md\")] ?? GAP.md;\n if (type === \"Grid\") {\n return cn(\"grid\", COLUMNS[Number(props.columns ?? 2)] ?? COLUMNS[2], gap);\n }\n return cn(\n \"flex min-w-0\",\n props.direction === \"row\" ? \"flex-row\" : \"flex-col\",\n props.wrap ? \"flex-wrap\" : \"\",\n ALIGN[String(props.align ?? \"stretch\")],\n JUSTIFY[String(props.justify ?? \"start\")],\n gap,\n );\n}\n\n// ---------------------------------------------------------------------------\n// Tree rendering\n// ---------------------------------------------------------------------------\ninterface RenderCtx {\n catalog: A2uiCatalog;\n invalid: Set<string>;\n onAction?: A2uiActionHandler;\n}\n\nconst isEvent = (v: unknown): v is SyntheticEvent =>\n typeof v === \"object\" && v !== null && \"nativeEvent\" in v && \"target\" in v;\n\n/** The value a `change`-style handler carries: the control's value, or the handler's first arg. */\nfunction eventValue(args: unknown[]): unknown {\n const first = args[0];\n if (isEvent(first)) {\n const target = first.target as HTMLInputElement | null;\n if (target && typeof target.type === \"string\" && target.type === \"checkbox\")\n return target.checked;\n return target && \"value\" in target ? target.value : undefined;\n }\n return first;\n}\n\nfunction renderPropValue(value: A2uiPropValue, path: string, ctx: RenderCtx): unknown {\n if (Array.isArray(value) && value.some(isA2uiElement)) {\n return value.map((item, i) => renderNode(item as A2uiNode, `${path}[${i}]`, ctx));\n }\n if (isA2uiElement(value)) return renderNode(value, path, ctx);\n return value;\n}\n\nfunction renderNode(node: A2uiNode, path: string, ctx: RenderCtx): ReactNode {\n if (typeof node === \"string\" || typeof node === \"number\") return node;\n if (ctx.invalid.has(path)) return null;\n const entry = ctx.catalog[node.type];\n if (!entry) return null;\n const props: Record<string, unknown> = {};\n for (const [name, value] of Object.entries(node.props ?? {})) {\n const schema = entry.schema.props[name];\n props[name] =\n schema?.type === \"node\" ? renderPropValue(value, `${path}.props.${name}`, ctx) : value;\n }\n for (const [event, action] of Object.entries(node.on ?? {})) {\n const handlerName = entry.schema.events[event];\n if (!handlerName) continue;\n props[handlerName] = (...args: unknown[]) => {\n // A control's value travels only with `change`-style events; a click\n // carries no value (a button's `target.value` is an empty string).\n const value = event === \"click\" ? undefined : eventValue(args);\n ctx.onAction?.(action, { event, value, node, path });\n };\n }\n const children = entry.schema.children\n ? (node.children ?? []).map((child, i) => renderNode(child, `${path}.children[${i}]`, ctx))\n : undefined;\n const key = path;\n const dataAttrs = {\n \"data-a2ui-type\": node.type,\n ...(node.id ? { \"data-a2ui-id\": node.id } : {}),\n };\n if (entry.schema.builtin) {\n return createElement(\n \"div\",\n { key, className: builtinClass(node.type, props), ...dataAttrs },\n ...(children ?? []),\n );\n }\n return createElement(\n entry.component as never,\n { key, ...props, ...dataAttrs },\n ...(children ?? []),\n );\n}\n\n/** A memoised subtree so a streaming parent re-render does not redraw settled siblings. */\nconst SurfaceTree = memo(function SurfaceTree({\n spec,\n catalog,\n invalid,\n onAction,\n}: {\n spec: A2uiSurfaceSpec;\n catalog: A2uiCatalog;\n invalid: Set<string>;\n onAction?: A2uiActionHandler;\n}) {\n return <>{renderNode(spec.root, \"root\", { catalog, invalid, onAction })}</>;\n});\n\n// ---------------------------------------------------------------------------\n// The surface\n// ---------------------------------------------------------------------------\nexport const A2uiSurface = forwardRef<HTMLDivElement, A2uiSurfaceProps>(function A2uiSurface(\n {\n surface,\n catalog = uiCatalog,\n onAction,\n isStreaming = false,\n loading = false,\n onError,\n skeleton,\n className,\n ...props\n },\n ref,\n) {\n const { t } = useLocale();\n const schema = useMemo(() => catalogSchema(catalog), [catalog]);\n\n // Parse (completing a streaming prefix), then validate. A string that is not\n // yet valid JSON even after completion is \"incomplete\", not invalid.\n const parsed = useMemo(() => {\n if (loading || surface == null) return { value: null, incomplete: false };\n if (typeof surface !== \"string\") return { value: surface, incomplete: false };\n const complete = parseSurfaceJson(surface, false);\n if (complete !== null) return { value: complete, incomplete: false };\n const partial = parseSurfaceJson(surface, true);\n return { value: partial, incomplete: surface.trim() !== \"\" };\n }, [surface, loading]);\n\n const validation = useMemo(\n () => (parsed.value === null ? null : validateA2uiSurface(parsed.value, schema)),\n [parsed.value, schema],\n );\n\n const pending = loading || isStreaming || parsed.incomplete;\n const empty = surface == null || (typeof surface === \"string\" && surface.trim() === \"\");\n\n // While pending, prune the failing subtrees and draw the rest; a settled\n // surface is all-or-nothing.\n const invalid = useMemo(\n () =>\n validation && !validation.ok && pending\n ? invalidNodePaths(validation.errors)\n : new Set<string>(),\n [validation, pending],\n );\n const drawable =\n validation?.spec && (validation.ok || (pending && !invalid.has(\"root\")))\n ? validation.spec\n : null;\n\n // The last tree that painted, so an unparsable streaming chunk (mid-token) or\n // a momentarily root-invalid prefix keeps the previous frame on screen.\n const lastGoodRef = useRef<A2uiSurfaceSpec | null>(null);\n if (drawable) lastGoodRef.current = drawable;\n const shown = drawable ?? (pending ? lastGoodRef.current : null);\n const [hasRendered, setHasRendered] = useState(false);\n useEffect(() => {\n if (shown && !hasRendered) setHasRendered(true);\n }, [shown, hasRendered]);\n\n const status: A2uiSurfaceStatus = loading\n ? \"pending\"\n : empty\n ? hasRendered\n ? \"ready\"\n : \"idle\"\n : pending\n ? \"pending\"\n : validation && !validation.ok\n ? \"error\"\n : \"ready\";\n\n // Terminal errors only — once per settled, invalid surface.\n // Keyed by the error LIST, not the input's identity, so a parent re-render\n // that passes an equal object literal does not report the same failure twice.\n const reportedRef = useRef<string | null>(null);\n useEffect(() => {\n if (status !== \"error\" || !validation || validation.ok) return;\n const key = JSON.stringify(validation.errors);\n if (reportedRef.current === key) return;\n reportedRef.current = key;\n onError?.(validation.errors);\n }, [status, validation, onError]);\n\n const showSkeleton = status === \"pending\" && !shown;\n const title = shown?.title;\n\n return (\n <div\n ref={ref}\n data-slot=\"a2ui-surface\"\n data-status={status}\n className={cn(\"relative min-w-0\", className)}\n {...(title ? { role: \"group\", \"aria-label\": title } : {})}\n {...props}\n >\n {showSkeleton ? (\n <div\n data-slot=\"a2ui-surface-skeleton\"\n role=\"status\"\n aria-live=\"polite\"\n className=\"space-y-2\"\n >\n <span className=\"sr-only\">{t(\"ai.a2ui.loading\")}</span>\n {skeleton ?? (\n <>\n <Skeleton className=\"h-6 w-1/3\" />\n <div className=\"grid grid-cols-3 gap-2\">\n <Skeleton className=\"h-16\" />\n <Skeleton className=\"h-16\" />\n <Skeleton className=\"h-16\" />\n </div>\n <Skeleton className=\"h-24 w-full\" />\n </>\n )}\n </div>\n ) : null}\n {shown ? (\n <SurfaceTree spec={shown} catalog={catalog} invalid={invalid} onAction={onAction} />\n ) : null}\n {status === \"error\" && validation && !validation.ok ? (\n <div\n data-slot=\"a2ui-surface-error\"\n role=\"alert\"\n // The status wash is the one separation gesture (surface-separation);\n // `-text` is the AA ink rung on a wash (status-rung).\n className=\"flex gap-2 rounded-md bg-destructive/10 p-3 text-body text-destructive-text\"\n >\n <AlertCircle className=\"mt-0.5 size-4 shrink-0\" aria-hidden=\"true\" />\n <div className=\"min-w-0 space-y-1\">\n <p className=\"font-medium\">{t(\"ai.a2ui.invalid\")}</p>\n <ul className=\"space-y-0.5 text-caption\">\n {validation.errors.slice(0, 8).map((e) => (\n <li key={`${e.path}:${e.code}`} className=\"break-words\">\n <code className=\"text-code\">{e.path || \"root\"}</code> — {e.message}\n </li>\n ))}\n {validation.errors.length > 8 ? (\n <li>{t(\"ai.a2ui.moreErrors\", { count: validation.errors.length - 8 })}</li>\n ) : null}\n </ul>\n </div>\n </div>\n ) : null}\n </div>\n );\n});\n\nA2uiSurface.displayName = \"A2uiSurface\";\n\n/** Re-exported so a host can pre-complete a streaming prefix itself (e.g. for a raw-JSON view). */\nexport { completeJson };\n"],"mappings":"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","names":["SurfaceTree","A2uiSurface"]}
|