@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,561 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
fieldLabel,
|
|
4
|
+
initialFormValues,
|
|
5
|
+
normalizeFormSpec,
|
|
6
|
+
optionLabel,
|
|
7
|
+
optionValue,
|
|
8
|
+
validateForm
|
|
9
|
+
} from "./chunk-HVXM2G5F.js";
|
|
10
|
+
|
|
11
|
+
// src/message-form.tsx
|
|
12
|
+
import {
|
|
13
|
+
createContext,
|
|
14
|
+
forwardRef,
|
|
15
|
+
use,
|
|
16
|
+
useCallback,
|
|
17
|
+
useId,
|
|
18
|
+
useMemo,
|
|
19
|
+
useState
|
|
20
|
+
} from "react";
|
|
21
|
+
import { Check } from "lucide-react";
|
|
22
|
+
import {
|
|
23
|
+
Badge,
|
|
24
|
+
Button,
|
|
25
|
+
Checkbox,
|
|
26
|
+
Input,
|
|
27
|
+
Label,
|
|
28
|
+
NumberInput,
|
|
29
|
+
Select,
|
|
30
|
+
SelectContent,
|
|
31
|
+
SelectItem,
|
|
32
|
+
SelectTrigger,
|
|
33
|
+
SelectValue,
|
|
34
|
+
Skeleton,
|
|
35
|
+
Spinner,
|
|
36
|
+
Textarea
|
|
37
|
+
} from "@elabs-ai/components-ui";
|
|
38
|
+
import { cn } from "@elabs-ai/components-ui/lib/cn";
|
|
39
|
+
import { useLocale } from "@elabs-ai/components-ui";
|
|
40
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
41
|
+
var MessageFormContext = createContext(null);
|
|
42
|
+
function useMessageFormContext() {
|
|
43
|
+
const ctx = use(MessageFormContext);
|
|
44
|
+
if (!ctx) {
|
|
45
|
+
throw new Error("MessageForm sub-components must be rendered inside <MessageFormProvider>.");
|
|
46
|
+
}
|
|
47
|
+
return ctx;
|
|
48
|
+
}
|
|
49
|
+
function controlId(formId, name) {
|
|
50
|
+
return `${formId}-field-${name}`;
|
|
51
|
+
}
|
|
52
|
+
function descId(formId, name) {
|
|
53
|
+
return `${formId}-desc-${name}`;
|
|
54
|
+
}
|
|
55
|
+
function errorId(formId, name) {
|
|
56
|
+
return `${formId}-error-${name}`;
|
|
57
|
+
}
|
|
58
|
+
function effectiveValue(field, values) {
|
|
59
|
+
const v = values[field.name];
|
|
60
|
+
if (v !== void 0) return v;
|
|
61
|
+
if (field.default !== void 0) return field.default;
|
|
62
|
+
if (field.type === "boolean") return false;
|
|
63
|
+
if (field.type === "multi-enum") return [];
|
|
64
|
+
return void 0;
|
|
65
|
+
}
|
|
66
|
+
function MessageFormProvider({
|
|
67
|
+
spec,
|
|
68
|
+
values: valuesProp,
|
|
69
|
+
onChange,
|
|
70
|
+
onSubmit,
|
|
71
|
+
disabled = false,
|
|
72
|
+
submitted = false,
|
|
73
|
+
submitting = false,
|
|
74
|
+
isStreaming,
|
|
75
|
+
streaming = false,
|
|
76
|
+
children
|
|
77
|
+
}) {
|
|
78
|
+
const resolvedStreaming = isStreaming ?? streaming;
|
|
79
|
+
const formId = useId();
|
|
80
|
+
const headingId = `${formId}-title`;
|
|
81
|
+
const isControlled = valuesProp !== void 0;
|
|
82
|
+
const [internalValues, setInternalValues] = useState(
|
|
83
|
+
() => initialFormValues(spec.fields)
|
|
84
|
+
);
|
|
85
|
+
const [attempted, setAttempted] = useState(false);
|
|
86
|
+
const resolvedValues = isControlled ? valuesProp : internalValues;
|
|
87
|
+
const setValue = useCallback(
|
|
88
|
+
(name, value2) => {
|
|
89
|
+
const base = isControlled ? valuesProp : internalValues;
|
|
90
|
+
const next = { ...base, [name]: value2 };
|
|
91
|
+
if (!isControlled) setInternalValues(next);
|
|
92
|
+
onChange?.(next);
|
|
93
|
+
},
|
|
94
|
+
[isControlled, valuesProp, internalValues, onChange]
|
|
95
|
+
);
|
|
96
|
+
const submit = useCallback(() => {
|
|
97
|
+
setAttempted(true);
|
|
98
|
+
const merged = { ...resolvedValues };
|
|
99
|
+
for (const field of spec.fields) merged[field.name] = effectiveValue(field, resolvedValues);
|
|
100
|
+
const errs = validateForm(spec.fields, merged);
|
|
101
|
+
const firstInvalid = spec.fields.find((f) => errs[f.name]);
|
|
102
|
+
if (firstInvalid) {
|
|
103
|
+
if (typeof document !== "undefined") {
|
|
104
|
+
const el = document.getElementById(controlId(formId, firstInvalid.name));
|
|
105
|
+
el?.focus();
|
|
106
|
+
}
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
onSubmit?.({ formName: spec.formName, values: merged });
|
|
110
|
+
}, [resolvedValues, spec.fields, spec.formName, formId, onSubmit]);
|
|
111
|
+
const reset = useCallback(() => {
|
|
112
|
+
setAttempted(false);
|
|
113
|
+
const seeded = initialFormValues(spec.fields);
|
|
114
|
+
if (!isControlled) setInternalValues(seeded);
|
|
115
|
+
onChange?.(seeded);
|
|
116
|
+
}, [isControlled, spec.fields, onChange]);
|
|
117
|
+
const errors = useMemo(() => {
|
|
118
|
+
if (!attempted) return {};
|
|
119
|
+
const merged = { ...resolvedValues };
|
|
120
|
+
for (const field of spec.fields) merged[field.name] = effectiveValue(field, resolvedValues);
|
|
121
|
+
return validateForm(spec.fields, merged);
|
|
122
|
+
}, [attempted, resolvedValues, spec.fields]);
|
|
123
|
+
const value = useMemo(
|
|
124
|
+
() => ({
|
|
125
|
+
spec,
|
|
126
|
+
values: resolvedValues,
|
|
127
|
+
errors,
|
|
128
|
+
setValue,
|
|
129
|
+
submit,
|
|
130
|
+
reset,
|
|
131
|
+
attempted,
|
|
132
|
+
submitted,
|
|
133
|
+
submitting,
|
|
134
|
+
disabled,
|
|
135
|
+
isStreaming: resolvedStreaming,
|
|
136
|
+
formId,
|
|
137
|
+
headingId
|
|
138
|
+
}),
|
|
139
|
+
[
|
|
140
|
+
spec,
|
|
141
|
+
resolvedValues,
|
|
142
|
+
errors,
|
|
143
|
+
setValue,
|
|
144
|
+
submit,
|
|
145
|
+
reset,
|
|
146
|
+
attempted,
|
|
147
|
+
submitted,
|
|
148
|
+
submitting,
|
|
149
|
+
disabled,
|
|
150
|
+
resolvedStreaming,
|
|
151
|
+
formId,
|
|
152
|
+
headingId
|
|
153
|
+
]
|
|
154
|
+
);
|
|
155
|
+
return /* @__PURE__ */ jsx(MessageFormContext.Provider, { value, children });
|
|
156
|
+
}
|
|
157
|
+
function StringControl({
|
|
158
|
+
field,
|
|
159
|
+
value,
|
|
160
|
+
invalid,
|
|
161
|
+
disabled,
|
|
162
|
+
readOnly,
|
|
163
|
+
id,
|
|
164
|
+
describedBy,
|
|
165
|
+
setValue
|
|
166
|
+
}) {
|
|
167
|
+
const text = value === void 0 ? "" : String(value);
|
|
168
|
+
const commonAria = {
|
|
169
|
+
id,
|
|
170
|
+
"aria-invalid": invalid || void 0,
|
|
171
|
+
"aria-describedby": describedBy,
|
|
172
|
+
"aria-required": field.required || void 0,
|
|
173
|
+
required: field.required
|
|
174
|
+
};
|
|
175
|
+
if (field.multiline) {
|
|
176
|
+
return /* @__PURE__ */ jsx(
|
|
177
|
+
Textarea,
|
|
178
|
+
{
|
|
179
|
+
...commonAria,
|
|
180
|
+
name: field.name,
|
|
181
|
+
value: text,
|
|
182
|
+
disabled,
|
|
183
|
+
readOnly,
|
|
184
|
+
maxLength: field.maxLength,
|
|
185
|
+
onChange: (e) => setValue(field.name, e.target.value)
|
|
186
|
+
}
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
const inputType = field.format === "email" ? "email" : field.format === "uri" ? "url" : field.format === "date" ? "date" : field.format === "date-time" ? "datetime-local" : "text";
|
|
190
|
+
const spellCheck = field.format === "email" || field.format === "uri" ? false : void 0;
|
|
191
|
+
const inputMode = field.format === "email" ? "email" : field.format === "uri" ? "url" : void 0;
|
|
192
|
+
return /* @__PURE__ */ jsx(
|
|
193
|
+
Input,
|
|
194
|
+
{
|
|
195
|
+
...commonAria,
|
|
196
|
+
type: inputType,
|
|
197
|
+
name: field.name,
|
|
198
|
+
value: text,
|
|
199
|
+
disabled,
|
|
200
|
+
readOnly,
|
|
201
|
+
minLength: field.minLength,
|
|
202
|
+
maxLength: field.maxLength,
|
|
203
|
+
spellCheck,
|
|
204
|
+
inputMode,
|
|
205
|
+
onChange: (e) => setValue(field.name, e.target.value)
|
|
206
|
+
}
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
function NumberControl({
|
|
210
|
+
field,
|
|
211
|
+
value,
|
|
212
|
+
invalid,
|
|
213
|
+
disabled,
|
|
214
|
+
readOnly,
|
|
215
|
+
id,
|
|
216
|
+
describedBy,
|
|
217
|
+
setValue
|
|
218
|
+
}) {
|
|
219
|
+
const num = typeof value === "number" ? value : null;
|
|
220
|
+
return /* @__PURE__ */ jsx(
|
|
221
|
+
NumberInput,
|
|
222
|
+
{
|
|
223
|
+
id,
|
|
224
|
+
name: field.name,
|
|
225
|
+
value: num,
|
|
226
|
+
min: field.min,
|
|
227
|
+
max: field.max,
|
|
228
|
+
step: field.type === "integer" ? 1 : void 0,
|
|
229
|
+
disabled,
|
|
230
|
+
readOnly,
|
|
231
|
+
"aria-invalid": invalid || void 0,
|
|
232
|
+
"aria-describedby": describedBy,
|
|
233
|
+
"aria-required": field.required || void 0,
|
|
234
|
+
onValueChange: (next) => setValue(field.name, next ?? void 0)
|
|
235
|
+
}
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
function BooleanControl({
|
|
239
|
+
field,
|
|
240
|
+
value,
|
|
241
|
+
disabled,
|
|
242
|
+
id,
|
|
243
|
+
describedBy,
|
|
244
|
+
setValue
|
|
245
|
+
}) {
|
|
246
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
247
|
+
/* @__PURE__ */ jsx(
|
|
248
|
+
Checkbox,
|
|
249
|
+
{
|
|
250
|
+
id,
|
|
251
|
+
name: field.name,
|
|
252
|
+
checked: value === true,
|
|
253
|
+
disabled,
|
|
254
|
+
"aria-describedby": describedBy,
|
|
255
|
+
"aria-required": field.required || void 0,
|
|
256
|
+
onCheckedChange: (checked) => setValue(field.name, checked === true)
|
|
257
|
+
}
|
|
258
|
+
),
|
|
259
|
+
/* @__PURE__ */ jsxs(Label, { htmlFor: id, className: "flex items-center gap-1 font-normal", children: [
|
|
260
|
+
fieldLabel(field),
|
|
261
|
+
field.required && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "text-destructive-text", children: "*" })
|
|
262
|
+
] })
|
|
263
|
+
] });
|
|
264
|
+
}
|
|
265
|
+
function EnumControl({
|
|
266
|
+
field,
|
|
267
|
+
value,
|
|
268
|
+
invalid,
|
|
269
|
+
disabled,
|
|
270
|
+
id,
|
|
271
|
+
describedBy,
|
|
272
|
+
setValue
|
|
273
|
+
}) {
|
|
274
|
+
const { t } = useLocale();
|
|
275
|
+
const current = typeof value === "string" && value.length > 0 ? value : void 0;
|
|
276
|
+
return /* @__PURE__ */ jsxs(Select, { value: current, disabled, onValueChange: (v) => setValue(field.name, v), children: [
|
|
277
|
+
/* @__PURE__ */ jsx(
|
|
278
|
+
SelectTrigger,
|
|
279
|
+
{
|
|
280
|
+
id,
|
|
281
|
+
"aria-invalid": invalid || void 0,
|
|
282
|
+
"aria-describedby": describedBy,
|
|
283
|
+
"aria-required": field.required || void 0,
|
|
284
|
+
children: /* @__PURE__ */ jsx(SelectValue, { placeholder: t("ai.messageForm.selectPlaceholder") })
|
|
285
|
+
}
|
|
286
|
+
),
|
|
287
|
+
/* @__PURE__ */ jsx(SelectContent, { children: field.options.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: optionValue(option), children: optionLabel(option) }, optionValue(option))) })
|
|
288
|
+
] });
|
|
289
|
+
}
|
|
290
|
+
function MultiEnumControl({
|
|
291
|
+
field,
|
|
292
|
+
value,
|
|
293
|
+
disabled,
|
|
294
|
+
id,
|
|
295
|
+
labelId,
|
|
296
|
+
describedBy,
|
|
297
|
+
setValue
|
|
298
|
+
}) {
|
|
299
|
+
const selected = Array.isArray(value) ? value : [];
|
|
300
|
+
const toggle = (optValue, checked) => {
|
|
301
|
+
const next = checked ? [...selected, optValue] : selected.filter((v) => v !== optValue);
|
|
302
|
+
setValue(field.name, next);
|
|
303
|
+
};
|
|
304
|
+
return (
|
|
305
|
+
// The group is the focus-first-error target (id + tabIndex=-1). It is named
|
|
306
|
+
// by the field's visible label via aria-labelledby — NOT aria-label — so no
|
|
307
|
+
// single checkbox ends up with two <label for> associations.
|
|
308
|
+
/* @__PURE__ */ jsx(
|
|
309
|
+
"div",
|
|
310
|
+
{
|
|
311
|
+
role: "group",
|
|
312
|
+
id,
|
|
313
|
+
tabIndex: -1,
|
|
314
|
+
"aria-labelledby": labelId,
|
|
315
|
+
"aria-describedby": describedBy,
|
|
316
|
+
className: "flex flex-col gap-2 focus:outline-none",
|
|
317
|
+
children: field.options.map((option) => {
|
|
318
|
+
const optValue = optionValue(option);
|
|
319
|
+
const optionId = `${id}-${optValue}`;
|
|
320
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
321
|
+
/* @__PURE__ */ jsx(
|
|
322
|
+
Checkbox,
|
|
323
|
+
{
|
|
324
|
+
id: optionId,
|
|
325
|
+
checked: selected.includes(optValue),
|
|
326
|
+
disabled,
|
|
327
|
+
onCheckedChange: (checked) => toggle(optValue, checked === true)
|
|
328
|
+
}
|
|
329
|
+
),
|
|
330
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: optionId, className: "font-normal", children: optionLabel(option) })
|
|
331
|
+
] }, optValue);
|
|
332
|
+
})
|
|
333
|
+
}
|
|
334
|
+
)
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
var MessageFormField = forwardRef(
|
|
338
|
+
function MessageFormField2({ name, className, ...props }, ref) {
|
|
339
|
+
const ctx = useMessageFormContext();
|
|
340
|
+
const field = ctx.spec.fields.find((f) => f.name === name);
|
|
341
|
+
if (!field) return null;
|
|
342
|
+
const id = controlId(ctx.formId, name);
|
|
343
|
+
const labelId = `${ctx.formId}-label-${name}`;
|
|
344
|
+
const value = effectiveValue(field, ctx.values);
|
|
345
|
+
const error = ctx.errors[name] ?? null;
|
|
346
|
+
const invalid = Boolean(error);
|
|
347
|
+
const controlDisabled = ctx.disabled || ctx.submitted || ctx.submitting;
|
|
348
|
+
const readOnly = ctx.submitted;
|
|
349
|
+
const description = field.description;
|
|
350
|
+
const hasDesc = Boolean(description);
|
|
351
|
+
const describedBy = [hasDesc ? descId(ctx.formId, name) : null, invalid ? errorId(ctx.formId, name) : null].filter(Boolean).join(" ") || void 0;
|
|
352
|
+
const controlProps = {
|
|
353
|
+
field,
|
|
354
|
+
value,
|
|
355
|
+
invalid,
|
|
356
|
+
disabled: controlDisabled,
|
|
357
|
+
readOnly,
|
|
358
|
+
id,
|
|
359
|
+
labelId,
|
|
360
|
+
describedBy,
|
|
361
|
+
setValue: ctx.setValue
|
|
362
|
+
};
|
|
363
|
+
const isBoolean = field.type === "boolean";
|
|
364
|
+
const isGroupField = field.type === "multi-enum";
|
|
365
|
+
return /* @__PURE__ */ jsxs("div", { ref, className: cn("flex flex-col gap-1.5", className), ...props, children: [
|
|
366
|
+
!isBoolean && /* @__PURE__ */ jsxs(
|
|
367
|
+
Label,
|
|
368
|
+
{
|
|
369
|
+
id: labelId,
|
|
370
|
+
htmlFor: isGroupField ? void 0 : id,
|
|
371
|
+
className: "flex items-center gap-1",
|
|
372
|
+
children: [
|
|
373
|
+
fieldLabel(field),
|
|
374
|
+
field.required && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "text-destructive-text", children: "*" })
|
|
375
|
+
]
|
|
376
|
+
}
|
|
377
|
+
),
|
|
378
|
+
field.type === "string" && /* @__PURE__ */ jsx(StringControl, { ...controlProps, field }),
|
|
379
|
+
(field.type === "number" || field.type === "integer") && /* @__PURE__ */ jsx(NumberControl, { ...controlProps, field }),
|
|
380
|
+
field.type === "boolean" && /* @__PURE__ */ jsx(BooleanControl, { ...controlProps, field }),
|
|
381
|
+
field.type === "enum" && /* @__PURE__ */ jsx(EnumControl, { ...controlProps, field }),
|
|
382
|
+
field.type === "multi-enum" && /* @__PURE__ */ jsx(MultiEnumControl, { ...controlProps, field }),
|
|
383
|
+
hasDesc && /* @__PURE__ */ jsx("p", { id: descId(ctx.formId, name), className: "text-caption text-muted-foreground", children: description }),
|
|
384
|
+
invalid && /* @__PURE__ */ jsx("p", { id: errorId(ctx.formId, name), className: "text-caption text-destructive-text", children: error })
|
|
385
|
+
] });
|
|
386
|
+
}
|
|
387
|
+
);
|
|
388
|
+
var MessageFormFields = forwardRef(
|
|
389
|
+
function MessageFormFields2({ className, ...props }, ref) {
|
|
390
|
+
const { spec, isStreaming } = useMessageFormContext();
|
|
391
|
+
if (spec.fields.length === 0 && isStreaming) {
|
|
392
|
+
return /* @__PURE__ */ jsxs("div", { ref, className: cn("flex flex-col gap-4", className), ...props, children: [
|
|
393
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", role: "status", "aria-live": "polite", children: "Loading form\u2026" }),
|
|
394
|
+
/* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "flex flex-col gap-4", children: [0, 1, 2].map((i) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
395
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-24" }),
|
|
396
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-9 w-full" })
|
|
397
|
+
] }, i)) })
|
|
398
|
+
] });
|
|
399
|
+
}
|
|
400
|
+
return /* @__PURE__ */ jsx("div", { ref, className: cn("flex flex-col gap-4", className), ...props, children: spec.fields.map((field) => /* @__PURE__ */ jsx(MessageFormField, { name: field.name }, field.name)) });
|
|
401
|
+
}
|
|
402
|
+
);
|
|
403
|
+
var MessageFormSubmit = forwardRef(
|
|
404
|
+
function MessageFormSubmit2({ label, className, ...props }, ref) {
|
|
405
|
+
const { spec, submitting, submitted, disabled } = useMessageFormContext();
|
|
406
|
+
if (submitted) {
|
|
407
|
+
return /* @__PURE__ */ jsx("div", { ref, className: cn("flex items-center", className), ...props, children: /* @__PURE__ */ jsxs(Badge, { variant: "success", "aria-live": "polite", children: [
|
|
408
|
+
/* @__PURE__ */ jsx(Check, { "aria-hidden": "true", className: "size-3" }),
|
|
409
|
+
"Submitted"
|
|
410
|
+
] }) });
|
|
411
|
+
}
|
|
412
|
+
const text = label ?? spec.submitLabel ?? "Submit";
|
|
413
|
+
return /* @__PURE__ */ jsx("div", { ref, className: cn("flex items-center", className), ...props, children: /* @__PURE__ */ jsxs(Button, { type: "submit", disabled: disabled || submitting, "aria-busy": submitting || void 0, children: [
|
|
414
|
+
submitting && /* @__PURE__ */ jsx(Spinner, { "aria-hidden": "true", className: "text-current" }),
|
|
415
|
+
submitting ? "Submitting\u2026" : text
|
|
416
|
+
] }) });
|
|
417
|
+
}
|
|
418
|
+
);
|
|
419
|
+
var MessageFormRoot = forwardRef(
|
|
420
|
+
function MessageFormRoot2({ className, children, ...props }, ref) {
|
|
421
|
+
const { t } = useLocale();
|
|
422
|
+
const { submit, headingId, spec, disabled, submitting } = useMessageFormContext();
|
|
423
|
+
const handleSubmit = (e) => {
|
|
424
|
+
e.preventDefault();
|
|
425
|
+
if (disabled || submitting) return;
|
|
426
|
+
submit();
|
|
427
|
+
};
|
|
428
|
+
return /* @__PURE__ */ jsx(
|
|
429
|
+
"form",
|
|
430
|
+
{
|
|
431
|
+
ref,
|
|
432
|
+
noValidate: true,
|
|
433
|
+
onSubmit: handleSubmit,
|
|
434
|
+
"aria-labelledby": spec.title ? headingId : void 0,
|
|
435
|
+
"aria-label": spec.title ? void 0 : spec.formName || t("ai.messageForm.label"),
|
|
436
|
+
className: cn("flex w-full flex-col gap-4", className),
|
|
437
|
+
...props,
|
|
438
|
+
children
|
|
439
|
+
}
|
|
440
|
+
);
|
|
441
|
+
}
|
|
442
|
+
);
|
|
443
|
+
var MessageFormTitle = forwardRef(
|
|
444
|
+
function MessageFormTitle2({ className, children, ...props }, ref) {
|
|
445
|
+
const { headingId, spec } = useMessageFormContext();
|
|
446
|
+
const content = children ?? spec.title;
|
|
447
|
+
if (!content) return null;
|
|
448
|
+
return /* @__PURE__ */ jsx(
|
|
449
|
+
"p",
|
|
450
|
+
{
|
|
451
|
+
ref,
|
|
452
|
+
id: headingId,
|
|
453
|
+
className: cn("text-subtitle text-foreground text-balance", className),
|
|
454
|
+
...props,
|
|
455
|
+
children: content
|
|
456
|
+
}
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
);
|
|
460
|
+
var MessageFormDescription = forwardRef(
|
|
461
|
+
function MessageFormDescription2({ className, children, ...props }, ref) {
|
|
462
|
+
const { spec } = useMessageFormContext();
|
|
463
|
+
const content = children ?? spec.description;
|
|
464
|
+
if (!content) return null;
|
|
465
|
+
return /* @__PURE__ */ jsx(
|
|
466
|
+
"p",
|
|
467
|
+
{
|
|
468
|
+
ref,
|
|
469
|
+
className: cn("text-body text-muted-foreground text-pretty", className),
|
|
470
|
+
...props,
|
|
471
|
+
children: content
|
|
472
|
+
}
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
);
|
|
476
|
+
var MessageFormFallback = forwardRef(
|
|
477
|
+
function MessageFormFallback2({ message = "This form could not be displayed.", className, ...props }, ref) {
|
|
478
|
+
return /* @__PURE__ */ jsx(
|
|
479
|
+
"div",
|
|
480
|
+
{
|
|
481
|
+
ref,
|
|
482
|
+
role: "status",
|
|
483
|
+
"aria-live": "polite",
|
|
484
|
+
className: cn(
|
|
485
|
+
// Sole structural cue is the border (no fill) — reads in every theme.
|
|
486
|
+
"flex items-center justify-center rounded-md border border-border-strong px-4 py-6 text-center text-body text-muted-foreground",
|
|
487
|
+
className
|
|
488
|
+
),
|
|
489
|
+
...props,
|
|
490
|
+
children: message
|
|
491
|
+
}
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
);
|
|
495
|
+
var MessageForm = forwardRef(function MessageForm2({
|
|
496
|
+
spec,
|
|
497
|
+
values,
|
|
498
|
+
onChange,
|
|
499
|
+
onSubmit,
|
|
500
|
+
submitLabel,
|
|
501
|
+
disabled,
|
|
502
|
+
submitted,
|
|
503
|
+
submitting,
|
|
504
|
+
isStreaming,
|
|
505
|
+
streaming,
|
|
506
|
+
className,
|
|
507
|
+
...props
|
|
508
|
+
}, ref) {
|
|
509
|
+
const resolvedStreaming = isStreaming ?? streaming;
|
|
510
|
+
const result = normalizeFormSpec(spec);
|
|
511
|
+
if (!result.ok) {
|
|
512
|
+
return /* @__PURE__ */ jsx(MessageFormFallback, { ref, message: result.reason, className, ...props });
|
|
513
|
+
}
|
|
514
|
+
const normalized = result.spec;
|
|
515
|
+
const empty = normalized.fields.length === 0;
|
|
516
|
+
if (empty && !resolvedStreaming) {
|
|
517
|
+
return /* @__PURE__ */ jsx(
|
|
518
|
+
MessageFormFallback,
|
|
519
|
+
{
|
|
520
|
+
ref,
|
|
521
|
+
message: "This form has no fields to fill in.",
|
|
522
|
+
className,
|
|
523
|
+
...props
|
|
524
|
+
}
|
|
525
|
+
);
|
|
526
|
+
}
|
|
527
|
+
return /* @__PURE__ */ jsx(
|
|
528
|
+
MessageFormProvider,
|
|
529
|
+
{
|
|
530
|
+
spec: normalized,
|
|
531
|
+
values,
|
|
532
|
+
onChange,
|
|
533
|
+
onSubmit,
|
|
534
|
+
disabled,
|
|
535
|
+
submitted,
|
|
536
|
+
submitting,
|
|
537
|
+
isStreaming: resolvedStreaming,
|
|
538
|
+
children: /* @__PURE__ */ jsx("div", { ref, className: cn("w-full", className), ...props, children: /* @__PURE__ */ jsxs(MessageFormRoot, { children: [
|
|
539
|
+
(normalized.title || normalized.description) && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
540
|
+
/* @__PURE__ */ jsx(MessageFormTitle, {}),
|
|
541
|
+
/* @__PURE__ */ jsx(MessageFormDescription, {})
|
|
542
|
+
] }),
|
|
543
|
+
/* @__PURE__ */ jsx(MessageFormFields, {}),
|
|
544
|
+
/* @__PURE__ */ jsx(MessageFormSubmit, { label: submitLabel })
|
|
545
|
+
] }) })
|
|
546
|
+
}
|
|
547
|
+
);
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
export {
|
|
551
|
+
MessageFormProvider,
|
|
552
|
+
MessageFormField,
|
|
553
|
+
MessageFormFields,
|
|
554
|
+
MessageFormSubmit,
|
|
555
|
+
MessageFormRoot,
|
|
556
|
+
MessageFormTitle,
|
|
557
|
+
MessageFormDescription,
|
|
558
|
+
MessageFormFallback,
|
|
559
|
+
MessageForm
|
|
560
|
+
};
|
|
561
|
+
//# sourceMappingURL=chunk-T56JFGXI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/message-form.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * MessageForm — a model-emittable form rendered inside a chat message.\n *\n * The model emits a serializable `FormSpec` (see `message-form-spec.ts`); the\n * user fills it; the app receives structured `{ formName, values }` on submit.\n *\n * Design bar (mirrors AutoChart + ChangeReview):\n * - Spec-driven, zod-validated. The model is the author; it never chooses look.\n * - Never throws on model output. A malformed spec → `MessageFormFallback`.\n * - Streaming-tolerant. Half-arrived fields are dropped (not fatal); an empty\n * spec while streaming shows a skeleton, never a crash.\n * - Compound + lifted state, controlled AND uncontrolled (the ChangeReview\n * pattern): `MessageFormProvider` owns the values; the parts read a context.\n * - Tokens only; keyboard-operable; inline errors; focus the first error on\n * submit; a submitted form renders inert with its values visible (a chat\n * message is a historical record).\n *\n * Composes `@elabs-ai/components-ui` inputs — it does NOT re-invent field primitives.\n *\n * Compound structure (named exports, the Card/CardHeader convention):\n * <MessageFormProvider> — lifted state (values + errors + actions)\n * <MessageFormRoot> — the <form> element (never nest inside another form)\n * <MessageFormFields> — every field, or place <MessageFormField> yourself\n * <MessageFormSubmit> — submit button / submitting spinner / submitted note\n */\n\nimport {\n createContext,\n forwardRef,\n use,\n useCallback,\n useId,\n useMemo,\n useState,\n type FormEvent,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\nimport { Check } from \"lucide-react\";\nimport {\n Badge,\n Button,\n Checkbox,\n Input,\n Label,\n NumberInput,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Skeleton,\n Spinner,\n Textarea,\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 fieldLabel,\n initialFormValues,\n normalizeFormSpec,\n optionLabel,\n optionValue,\n validateForm,\n type FieldSpec,\n type FormSpec,\n type FormSubmitState,\n type FormValue,\n type FormValues,\n type NormalizedFormSpec,\n} from \"./message-form-spec\";\n\n// ─── Context ────────────────────────────────────────────────────────────────\n\ninterface MessageFormContextValue {\n spec: NormalizedFormSpec;\n values: FormValues;\n /** Per-field error text, only populated after a submit attempt. */\n errors: Record<string, string | null>;\n setValue: (name: string, value: FormValue) => void;\n submit: () => void;\n reset: () => void;\n /** True once submit has been attempted (drives error visibility). */\n attempted: boolean;\n submitted: boolean;\n submitting: boolean;\n disabled: boolean;\n isStreaming: boolean;\n formId: string;\n headingId: string;\n}\n\nconst MessageFormContext = createContext<MessageFormContextValue | null>(null);\n\nfunction useMessageFormContext(): MessageFormContextValue {\n const ctx = use(MessageFormContext);\n if (!ctx) {\n throw new Error(\"MessageForm sub-components must be rendered inside <MessageFormProvider>.\");\n }\n return ctx;\n}\n\n/** Stable DOM id for a field's primary control (used for label + focus). */\nfunction controlId(formId: string, name: string): string {\n return `${formId}-field-${name}`;\n}\nfunction descId(formId: string, name: string): string {\n return `${formId}-desc-${name}`;\n}\nfunction errorId(formId: string, name: string): string {\n return `${formId}-error-${name}`;\n}\n\n/** The effective value for a field (state value, else its default). */\nfunction effectiveValue(field: FieldSpec, values: FormValues): FormValue {\n const v = values[field.name];\n if (v !== undefined) return v;\n if (field.default !== undefined) return field.default;\n if (field.type === \"boolean\") return false;\n if (field.type === \"multi-enum\") return [];\n return undefined;\n}\n\n// ─── Provider ───────────────────────────────────────────────────────────────\n\nexport interface MessageFormProviderProps {\n /** A validated/normalized spec (a plain `FormSpec` also satisfies this). */\n spec: NormalizedFormSpec;\n /**\n * Controlled values. When provided the component is controlled and `onChange`\n * is the only way to update state.\n */\n values?: FormValues;\n /** Called with the next full values object on any field change. */\n onChange?: (values: FormValues) => void;\n /** Called with `{ formName, values }` when a valid form is submitted. */\n onSubmit?: (state: FormSubmitState) => void;\n /** Disable every control (form is not interactable). */\n disabled?: boolean;\n /** Terminal submitted state: controls are inert, values visible, no submit. */\n submitted?: boolean;\n /** In-flight submit: controls disabled, the submit button shows a spinner. */\n submitting?: boolean;\n /** The spec is still streaming in (renders a skeleton when no fields yet). */\n isStreaming?: boolean;\n /** @deprecated Use `isStreaming`. */\n streaming?: boolean;\n children: ReactNode;\n}\n\n/**\n * Lifts the form values. Controlled (pass `values`) or uncontrolled.\n * Derives `isControlled = values !== undefined` and never flips modes.\n */\nexport function MessageFormProvider({\n spec,\n values: valuesProp,\n onChange,\n onSubmit,\n disabled = false,\n submitted = false,\n submitting = false,\n isStreaming,\n streaming = false,\n children,\n}: MessageFormProviderProps) {\n const resolvedStreaming = isStreaming ?? streaming;\n const formId = useId();\n const headingId = `${formId}-title`;\n\n const isControlled = valuesProp !== undefined;\n const [internalValues, setInternalValues] = useState<FormValues>(() =>\n initialFormValues(spec.fields),\n );\n const [attempted, setAttempted] = useState(false);\n\n const resolvedValues = isControlled ? (valuesProp as FormValues) : internalValues;\n\n const setValue = useCallback(\n (name: string, value: FormValue) => {\n const base = isControlled ? (valuesProp as FormValues) : internalValues;\n const next: FormValues = { ...base, [name]: value };\n if (!isControlled) setInternalValues(next);\n onChange?.(next);\n },\n [isControlled, valuesProp, internalValues, onChange],\n );\n\n const submit = useCallback(() => {\n setAttempted(true);\n // Build the effective values (defaults folded in) for validation + payload.\n const merged: FormValues = { ...resolvedValues };\n for (const field of spec.fields) merged[field.name] = effectiveValue(field, resolvedValues);\n\n const errs = validateForm(spec.fields, merged);\n const firstInvalid = spec.fields.find((f) => errs[f.name]);\n if (firstInvalid) {\n // Focus the first field with an error (a11y: don't leave the user hunting).\n if (typeof document !== \"undefined\") {\n const el = document.getElementById(controlId(formId, firstInvalid.name));\n el?.focus();\n }\n return;\n }\n onSubmit?.({ formName: spec.formName, values: merged });\n }, [resolvedValues, spec.fields, spec.formName, formId, onSubmit]);\n\n const reset = useCallback(() => {\n setAttempted(false);\n const seeded = initialFormValues(spec.fields);\n if (!isControlled) setInternalValues(seeded);\n onChange?.(seeded);\n }, [isControlled, spec.fields, onChange]);\n\n // Errors only surface after a submit attempt; then they live-update on change.\n const errors = useMemo<Record<string, string | null>>(() => {\n if (!attempted) return {};\n const merged: FormValues = { ...resolvedValues };\n for (const field of spec.fields) merged[field.name] = effectiveValue(field, resolvedValues);\n return validateForm(spec.fields, merged);\n }, [attempted, resolvedValues, spec.fields]);\n\n const value = useMemo<MessageFormContextValue>(\n () => ({\n spec,\n values: resolvedValues,\n errors,\n setValue,\n submit,\n reset,\n attempted,\n submitted,\n submitting,\n disabled,\n isStreaming: resolvedStreaming,\n formId,\n headingId,\n }),\n [\n spec,\n resolvedValues,\n errors,\n setValue,\n submit,\n reset,\n attempted,\n submitted,\n submitting,\n disabled,\n resolvedStreaming,\n formId,\n headingId,\n ],\n );\n\n return <MessageFormContext.Provider value={value}>{children}</MessageFormContext.Provider>;\n}\n\n// ─── Field control renderers ──────────────────────────────────────────────────\n\ninterface FieldControlProps {\n field: FieldSpec;\n value: FormValue;\n invalid: boolean;\n disabled: boolean;\n readOnly: boolean;\n id: string;\n /** Id of the field's visible label (used by grouped controls' aria-labelledby). */\n labelId: string;\n describedBy: string | undefined;\n setValue: (name: string, value: FormValue) => void;\n}\n\nfunction StringControl({\n field,\n value,\n invalid,\n disabled,\n readOnly,\n id,\n describedBy,\n setValue,\n}: FieldControlProps & { field: Extract<FieldSpec, { type: \"string\" }> }) {\n const text = value === undefined ? \"\" : String(value);\n const commonAria = {\n id,\n \"aria-invalid\": invalid || undefined,\n \"aria-describedby\": describedBy,\n \"aria-required\": field.required || undefined,\n required: field.required,\n } as const;\n\n if (field.multiline) {\n return (\n <Textarea\n {...commonAria}\n name={field.name}\n value={text}\n disabled={disabled}\n readOnly={readOnly}\n maxLength={field.maxLength}\n onChange={(e) => setValue(field.name, e.target.value)}\n />\n );\n }\n\n // Map the format hint → input type + autofill/keyboard hints.\n const inputType =\n field.format === \"email\"\n ? \"email\"\n : field.format === \"uri\"\n ? \"url\"\n : field.format === \"date\"\n ? \"date\"\n : field.format === \"date-time\"\n ? \"datetime-local\"\n : \"text\";\n const spellCheck = field.format === \"email\" || field.format === \"uri\" ? false : undefined;\n const inputMode = field.format === \"email\" ? \"email\" : field.format === \"uri\" ? \"url\" : undefined;\n\n return (\n <Input\n {...commonAria}\n type={inputType}\n name={field.name}\n value={text}\n disabled={disabled}\n readOnly={readOnly}\n minLength={field.minLength}\n maxLength={field.maxLength}\n spellCheck={spellCheck}\n inputMode={inputMode}\n onChange={(e) => setValue(field.name, e.target.value)}\n />\n );\n}\n\nfunction NumberControl({\n field,\n value,\n invalid,\n disabled,\n readOnly,\n id,\n describedBy,\n setValue,\n}: FieldControlProps & { field: Extract<FieldSpec, { type: \"number\" | \"integer\" }> }) {\n const num = typeof value === \"number\" ? value : null;\n return (\n <NumberInput\n id={id}\n name={field.name}\n value={num}\n min={field.min}\n max={field.max}\n step={field.type === \"integer\" ? 1 : undefined}\n disabled={disabled}\n readOnly={readOnly}\n aria-invalid={invalid || undefined}\n aria-describedby={describedBy}\n aria-required={field.required || undefined}\n onValueChange={(next) => setValue(field.name, next ?? undefined)}\n />\n );\n}\n\nfunction BooleanControl({\n field,\n value,\n disabled,\n id,\n describedBy,\n setValue,\n}: FieldControlProps & { field: Extract<FieldSpec, { type: \"boolean\" }> }) {\n // Checkbox + clickable label share ONE hit target (no dead zone).\n return (\n <div className=\"flex items-center gap-2\">\n <Checkbox\n id={id}\n name={field.name}\n checked={value === true}\n disabled={disabled}\n aria-describedby={describedBy}\n aria-required={field.required || undefined}\n onCheckedChange={(checked) => setValue(field.name, checked === true)}\n />\n <Label htmlFor={id} className=\"flex items-center gap-1 font-normal\">\n {fieldLabel(field)}\n {field.required && (\n <span aria-hidden=\"true\" className=\"text-destructive-text\">\n *\n </span>\n )}\n </Label>\n </div>\n );\n}\n\nfunction EnumControl({\n field,\n value,\n invalid,\n disabled,\n id,\n describedBy,\n setValue,\n}: FieldControlProps & { field: Extract<FieldSpec, { type: \"enum\" }> }) {\n const { t } = useLocale();\n const current = typeof value === \"string\" && value.length > 0 ? value : undefined;\n return (\n <Select value={current} disabled={disabled} onValueChange={(v) => setValue(field.name, v)}>\n <SelectTrigger\n id={id}\n aria-invalid={invalid || undefined}\n aria-describedby={describedBy}\n aria-required={field.required || undefined}\n >\n <SelectValue placeholder={t(\"ai.messageForm.selectPlaceholder\")} />\n </SelectTrigger>\n <SelectContent>\n {field.options.map((option) => (\n <SelectItem key={optionValue(option)} value={optionValue(option)}>\n {optionLabel(option)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n}\n\nfunction MultiEnumControl({\n field,\n value,\n disabled,\n id,\n labelId,\n describedBy,\n setValue,\n}: FieldControlProps & { field: Extract<FieldSpec, { type: \"multi-enum\" }> }) {\n const selected = Array.isArray(value) ? value : [];\n const toggle = (optValue: string, checked: boolean) => {\n const next = checked ? [...selected, optValue] : selected.filter((v) => v !== optValue);\n setValue(field.name, next);\n };\n return (\n // The group is the focus-first-error target (id + tabIndex=-1). It is named\n // by the field's visible label via aria-labelledby — NOT aria-label — so no\n // single checkbox ends up with two <label for> associations.\n <div\n role=\"group\"\n id={id}\n tabIndex={-1}\n aria-labelledby={labelId}\n aria-describedby={describedBy}\n className=\"flex flex-col gap-2 focus:outline-none\"\n >\n {field.options.map((option) => {\n const optValue = optionValue(option);\n const optionId = `${id}-${optValue}`;\n return (\n <div key={optValue} className=\"flex items-center gap-2\">\n <Checkbox\n id={optionId}\n checked={selected.includes(optValue)}\n disabled={disabled}\n onCheckedChange={(checked) => toggle(optValue, checked === true)}\n />\n <Label htmlFor={optionId} className=\"font-normal\">\n {optionLabel(option)}\n </Label>\n </div>\n );\n })}\n </div>\n );\n}\n\n// ─── Field ────────────────────────────────────────────────────────────────────\n\nexport interface MessageFormFieldProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** The field's `name` (its key in the spec + values). */\n name: string;\n}\n\n/**\n * Renders one field by name: label, control, description, inline error.\n * Boolean fields render their own inline label (checkbox + label), so the\n * standalone `<Label>` above is suppressed for them.\n */\nexport const MessageFormField = forwardRef<HTMLDivElement, MessageFormFieldProps>(\n function MessageFormField({ name, className, ...props }, ref) {\n const ctx = useMessageFormContext();\n const field = ctx.spec.fields.find((f) => f.name === name);\n if (!field) return null;\n\n const id = controlId(ctx.formId, name);\n const labelId = `${ctx.formId}-label-${name}`;\n const value = effectiveValue(field, ctx.values);\n const error = ctx.errors[name] ?? null;\n const invalid = Boolean(error);\n const controlDisabled = ctx.disabled || ctx.submitted || ctx.submitting;\n const readOnly = ctx.submitted;\n const description = field.description;\n const hasDesc = Boolean(description);\n const describedBy =\n [hasDesc ? descId(ctx.formId, name) : null, invalid ? errorId(ctx.formId, name) : null]\n .filter(Boolean)\n .join(\" \") || undefined;\n\n const controlProps: FieldControlProps = {\n field,\n value,\n invalid,\n disabled: controlDisabled,\n readOnly,\n id,\n labelId,\n describedBy,\n setValue: ctx.setValue,\n };\n\n const isBoolean = field.type === \"boolean\";\n // A multi-enum renders a checkbox group named via aria-labelledby, so its\n // label must NOT use htmlFor (which would associate with a single control).\n const isGroupField = field.type === \"multi-enum\";\n\n return (\n <div ref={ref} className={cn(\"flex flex-col gap-1.5\", className)} {...props}>\n {!isBoolean && (\n <Label\n id={labelId}\n htmlFor={isGroupField ? undefined : id}\n className=\"flex items-center gap-1\"\n >\n {fieldLabel(field)}\n {field.required && (\n <span aria-hidden=\"true\" className=\"text-destructive-text\">\n *\n </span>\n )}\n </Label>\n )}\n\n {field.type === \"string\" && <StringControl {...controlProps} field={field} />}\n {(field.type === \"number\" || field.type === \"integer\") && (\n <NumberControl {...controlProps} field={field} />\n )}\n {field.type === \"boolean\" && <BooleanControl {...controlProps} field={field} />}\n {field.type === \"enum\" && <EnumControl {...controlProps} field={field} />}\n {field.type === \"multi-enum\" && <MultiEnumControl {...controlProps} field={field} />}\n\n {hasDesc && (\n <p id={descId(ctx.formId, name)} className=\"text-caption text-muted-foreground\">\n {description}\n </p>\n )}\n {invalid && (\n <p id={errorId(ctx.formId, name)} className=\"text-caption text-destructive-text\">\n {error}\n </p>\n )}\n </div>\n );\n },\n);\n\n// ─── Fields (all) ─────────────────────────────────────────────────────────────\n\nexport type MessageFormFieldsProps = HTMLAttributes<HTMLDivElement>;\n\n/** Renders every field in the spec, in order. A skeleton while streaming empty. */\nexport const MessageFormFields = forwardRef<HTMLDivElement, MessageFormFieldsProps>(\n function MessageFormFields({ className, ...props }, ref) {\n const { spec, isStreaming } = useMessageFormContext();\n\n if (spec.fields.length === 0 && isStreaming) {\n return (\n <div ref={ref} className={cn(\"flex flex-col gap-4\", className)} {...props}>\n <span className=\"sr-only\" role=\"status\" aria-live=\"polite\">\n Loading form…\n </span>\n <div aria-hidden=\"true\" className=\"flex flex-col gap-4\">\n {[0, 1, 2].map((i) => (\n <div key={i} className=\"flex flex-col gap-1.5\">\n <Skeleton className=\"h-4 w-24\" />\n <Skeleton className=\"h-9 w-full\" />\n </div>\n ))}\n </div>\n </div>\n );\n }\n\n return (\n <div ref={ref} className={cn(\"flex flex-col gap-4\", className)} {...props}>\n {spec.fields.map((field) => (\n <MessageFormField key={field.name} name={field.name} />\n ))}\n </div>\n );\n },\n);\n\n// ─── Submit ───────────────────────────────────────────────────────────────────\n\nexport interface MessageFormSubmitProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** Submit button label (overrides `spec.submitLabel`). @default \"Submit\" */\n label?: string;\n}\n\n/**\n * The submit affordance. Enabled until the request starts (validation runs on\n * click), then a spinner. A submitted form shows an inert \"Submitted\" note.\n */\nexport const MessageFormSubmit = forwardRef<HTMLDivElement, MessageFormSubmitProps>(\n function MessageFormSubmit({ label, className, ...props }, ref) {\n const { spec, submitting, submitted, disabled } = useMessageFormContext();\n\n if (submitted) {\n return (\n <div ref={ref} className={cn(\"flex items-center\", className)} {...props}>\n <Badge variant=\"success\" aria-live=\"polite\">\n <Check aria-hidden=\"true\" className=\"size-3\" />\n Submitted\n </Badge>\n </div>\n );\n }\n\n const text = label ?? spec.submitLabel ?? \"Submit\";\n return (\n <div ref={ref} className={cn(\"flex items-center\", className)} {...props}>\n <Button type=\"submit\" disabled={disabled || submitting} aria-busy={submitting || undefined}>\n {submitting && <Spinner aria-hidden=\"true\" className=\"text-current\" />}\n {submitting ? \"Submitting…\" : text}\n </Button>\n </div>\n );\n },\n);\n\n// ─── Root (the <form> element) ────────────────────────────────────────────────\n\nexport type MessageFormRootProps = Omit<HTMLAttributes<HTMLFormElement>, \"onSubmit\">;\n\n/**\n * The `<form>` element wired to the context's `submit`. Never nest inside\n * another `<form>` — compose it as its own message-body block.\n */\nexport const MessageFormRoot = forwardRef<HTMLFormElement, MessageFormRootProps>(\n function MessageFormRoot({ className, children, ...props }, ref) {\n const { t } = useLocale();\n const { submit, headingId, spec, disabled, submitting } = useMessageFormContext();\n const handleSubmit = (e: FormEvent<HTMLFormElement>) => {\n e.preventDefault();\n if (disabled || submitting) return;\n submit();\n };\n return (\n <form\n ref={ref}\n noValidate\n onSubmit={handleSubmit}\n aria-labelledby={spec.title ? headingId : undefined}\n aria-label={spec.title ? undefined : spec.formName || t(\"ai.messageForm.label\")}\n className={cn(\"flex w-full flex-col gap-4\", className)}\n {...props}\n >\n {children}\n </form>\n );\n },\n);\n\n// ─── Title + Description ──────────────────────────────────────────────────────\n\nexport type MessageFormTitleProps = HTMLAttributes<HTMLParagraphElement>;\n\n/** The form heading. Its id is the `<form>`'s `aria-labelledby` target. */\nexport const MessageFormTitle = forwardRef<HTMLParagraphElement, MessageFormTitleProps>(\n function MessageFormTitle({ className, children, ...props }, ref) {\n const { headingId, spec } = useMessageFormContext();\n const content = children ?? spec.title;\n if (!content) return null;\n return (\n <p\n ref={ref}\n id={headingId}\n className={cn(\"text-subtitle text-foreground text-balance\", className)}\n {...props}\n >\n {content}\n </p>\n );\n },\n);\n\nexport type MessageFormDescriptionProps = HTMLAttributes<HTMLParagraphElement>;\n\n/** Supplemental description under the title. */\nexport const MessageFormDescription = forwardRef<HTMLParagraphElement, MessageFormDescriptionProps>(\n function MessageFormDescription({ className, children, ...props }, ref) {\n const { spec } = useMessageFormContext();\n const content = children ?? spec.description;\n if (!content) return null;\n return (\n <p\n ref={ref}\n className={cn(\"text-body text-muted-foreground text-pretty\", className)}\n {...props}\n >\n {content}\n </p>\n );\n },\n);\n\n// ─── Fallback ─────────────────────────────────────────────────────────────────\n\nexport interface MessageFormFallbackProps extends HTMLAttributes<HTMLDivElement> {\n /** Short human reason the form could not render. */\n message?: string;\n}\n\n/**\n * Shown when the spec is unusable. Mirrors `ChartFallback`: a calm, bordered\n * status box with a short reason — never a thrown error.\n */\nexport const MessageFormFallback = forwardRef<HTMLDivElement, MessageFormFallbackProps>(\n function MessageFormFallback(\n { message = \"This form 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 \"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// ─── Root convenience component ────────────────────────────────────────────────\n\nexport interface MessageFormProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n \"onSubmit\" | \"onChange\" | \"title\"\n> {\n /** The serializable form specification produced by an LLM tool-call. */\n spec: FormSpec | unknown;\n /** Controlled values (`{ [fieldName]: value }`). Omit for uncontrolled. */\n values?: FormValues;\n /** Called with the next full values object on any change. */\n onChange?: (values: FormValues) => void;\n /** Called with `{ formName, values }` on a valid submit. */\n onSubmit?: (state: FormSubmitState) => void;\n /** Submit button label (overrides `spec.submitLabel`). */\n submitLabel?: string;\n /** Disable every control. */\n disabled?: boolean;\n /** Terminal submitted state: inert, values visible, submit replaced. */\n submitted?: boolean;\n /** In-flight submit: controls disabled, spinner on submit. */\n submitting?: boolean;\n /** The spec is still streaming (renders a skeleton when no fields yet). */\n isStreaming?: boolean;\n /** @deprecated Use `isStreaming`. */\n streaming?: boolean;\n}\n\n/**\n * Convenience composition: `Provider → Root(form) → title/description → Fields →\n * Submit`. For a custom layout, compose `MessageFormProvider` + the parts.\n * A malformed spec renders `MessageFormFallback` (never throws).\n */\nexport const MessageForm = forwardRef<HTMLDivElement, MessageFormProps>(function MessageForm(\n {\n spec,\n values,\n onChange,\n onSubmit,\n submitLabel,\n disabled,\n submitted,\n submitting,\n isStreaming,\n streaming,\n className,\n ...props\n },\n ref,\n) {\n const resolvedStreaming = isStreaming ?? streaming;\n const result = normalizeFormSpec(spec);\n if (!result.ok) {\n return (\n <MessageFormFallback ref={ref} message={result.reason} className={className} {...props} />\n );\n }\n\n const normalized = result.spec;\n const empty = normalized.fields.length === 0;\n\n // Not streaming + no fields → the spec is structurally valid but useless.\n if (empty && !resolvedStreaming) {\n return (\n <MessageFormFallback\n ref={ref}\n message=\"This form has no fields to fill in.\"\n className={className}\n {...props}\n />\n );\n }\n\n return (\n <MessageFormProvider\n spec={normalized}\n values={values}\n onChange={onChange}\n onSubmit={onSubmit}\n disabled={disabled}\n submitted={submitted}\n submitting={submitting}\n isStreaming={resolvedStreaming}\n >\n <div ref={ref} className={cn(\"w-full\", className)} {...props}>\n <MessageFormRoot>\n {(normalized.title || normalized.description) && (\n <div className=\"flex flex-col gap-1\">\n <MessageFormTitle />\n <MessageFormDescription />\n </div>\n )}\n <MessageFormFields />\n <MessageFormSubmit label={submitLabel} />\n </MessageFormRoot>\n </div>\n </MessageFormProvider>\n );\n});\n"],"mappings":"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","names":["value","MessageFormField","MessageFormFields","MessageFormSubmit","MessageFormRoot","MessageFormTitle","MessageFormDescription","MessageFormFallback","MessageForm"]}
|