@kitn.ai/ui 0.16.0 → 0.18.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 +55 -17
- package/dist/components/artifact.d.ts +39 -1
- package/dist/components/attachment-types.d.ts +12 -0
- package/dist/components/attachments.d.ts +2 -10
- package/dist/components/card.d.ts +27 -0
- package/dist/components/chain-of-thought.d.ts +78 -2
- package/dist/components/chat-scope-picker.d.ts +7 -0
- package/dist/components/chat-thread.d.ts +39 -16
- package/dist/components/choice-card.d.ts +27 -0
- package/dist/components/coachmark.d.ts +49 -0
- package/dist/components/composer-dom.d.ts +35 -0
- package/dist/components/composer-highlight.d.ts +48 -0
- package/dist/components/composer-history.d.ts +34 -0
- package/dist/components/composer.d.ts +86 -0
- package/dist/components/confirm-card.d.ts +17 -0
- package/dist/components/conversation-item.d.ts +9 -0
- package/dist/components/conversation-list.d.ts +36 -1
- package/dist/components/dismissed-stub.d.ts +22 -0
- package/dist/components/file-tree.d.ts +15 -0
- package/dist/components/form.d.ts +34 -0
- package/dist/components/markdown.d.ts +3 -0
- package/dist/components/message.d.ts +71 -2
- package/dist/components/model-switcher.d.ts +7 -0
- package/dist/components/prompt-input.d.ts +13 -4
- package/dist/components/prompt-suggestion.d.ts +9 -1
- package/dist/components/reasoning.d.ts +14 -1
- package/dist/components/response-compare-types.d.ts +66 -0
- package/dist/components/response-compare.d.ts +65 -0
- package/dist/components/screen.d.ts +46 -0
- package/dist/components/tasks-card.d.ts +50 -1
- package/dist/components/toast.d.ts +58 -0
- package/dist/components/tool-types.d.ts +10 -0
- package/dist/components/tool.d.ts +8 -8
- package/dist/components/use-card-resolution.d.ts +10 -6
- package/dist/components/voice-input.d.ts +27 -0
- package/dist/components/voice-output.d.ts +33 -0
- package/dist/core-C8fzo39E.js +12 -0
- package/dist/custom-elements.json +8472 -1691
- package/dist/elements/agent-card.d.ts +1 -0
- package/dist/elements/agent-card.js +1 -0
- package/dist/elements/artifact.js +1 -0
- package/dist/elements/attachments.js +1 -0
- package/dist/elements/autoloader.d.ts +2 -0
- package/dist/elements/autoloader.js +1 -0
- package/dist/elements/avatar.d.ts +1 -0
- package/dist/elements/avatar.js +1 -0
- package/dist/elements/badge.d.ts +1 -0
- package/dist/elements/badge.js +1 -0
- package/dist/elements/button.d.ts +1 -0
- package/dist/elements/button.js +1 -0
- package/dist/elements/card.js +1 -0
- package/dist/elements/cards.d.ts +1 -0
- package/dist/elements/cards.js +1 -0
- package/dist/elements/chain-of-thought.d.ts +0 -12
- package/dist/elements/chain-of-thought.js +1 -0
- package/dist/elements/chat-scope-picker.js +1 -0
- package/dist/elements/chat-types.d.ts +8 -2
- package/dist/elements/chat-workspace.js +1 -0
- package/dist/elements/chat.js +1 -0
- package/dist/elements/checkpoint.js +1 -0
- package/dist/elements/choice.js +1 -0
- package/dist/elements/chunks/Icon-DLLBeLG5.js +1 -0
- package/dist/elements/chunks/action-icons-UB4V5FNq.js +1 -0
- package/dist/elements/chunks/arrow-left-C-gwlUmx.js +1 -0
- package/dist/elements/chunks/attachments-CgbErf1r.js +1 -0
- package/dist/elements/chunks/badge-DTQpgB6N.js +1 -0
- package/dist/elements/chunks/bash-InADTalH.js +1 -0
- package/dist/elements/chunks/button-XDUM6lXs.js +1 -0
- package/dist/elements/chunks/card-CBlFZ-7I.js +1 -0
- package/dist/elements/chunks/card-routing-C986KuUA.js +1 -0
- package/dist/elements/chunks/chat-thread-BIhmqwNL.js +1 -0
- package/dist/elements/chunks/check-hGUoVIKb.js +1 -0
- package/dist/elements/chunks/chevron-down-DDoaSUtO.js +1 -0
- package/dist/elements/chunks/chevron-right-CdGEUakB.js +1 -0
- package/dist/elements/chunks/circle-BKAZdmzb.js +1 -0
- package/dist/elements/chunks/circle-check-CmYG-y3I.js +1 -0
- package/dist/elements/chunks/circle-x-DewgAEym.js +1 -0
- package/dist/elements/chunks/cn-CU7UAWzk.js +1 -0
- package/dist/elements/chunks/code-block-DedwxwFI.js +1 -0
- package/dist/elements/chunks/collapsible-FfgmTHtM.js +1 -0
- package/dist/elements/chunks/composer-Cfbw5HKT.js +65 -0
- package/dist/elements/chunks/context-DwJmxlRE.js +1 -0
- package/dist/elements/chunks/conversation-list-DsCQMfPq.js +1 -0
- package/dist/elements/chunks/core-AYMC6_lb.js +12 -0
- package/dist/elements/chunks/css-M7EaDHN_.js +1 -0
- package/dist/elements/chunks/default-input-BuqsoENC.js +1 -0
- package/dist/elements/chunks/define-rGsaWsLL.js +1 -0
- package/dist/elements/chunks/disclosure-CwoAkpMH.js +1 -0
- package/dist/elements/chunks/download-DJ06G3Bz.js +1 -0
- package/dist/elements/chunks/dropdown-BFg8ri_R.js +1 -0
- package/dist/elements/chunks/ellipsis-dlN6YvGw.js +1 -0
- package/dist/elements/chunks/engine-javascript-vq0WuIJl.js +141 -0
- package/dist/elements/chunks/external-link-DBX2lc_R.js +1 -0
- package/dist/elements/chunks/file-text-HfwUx4F9.js +1 -0
- package/dist/elements/chunks/file-tree-C6Toj71u.js +1 -0
- package/dist/elements/chunks/folder-MYuqa9Xp.js +1 -0
- package/dist/elements/chunks/github-dark-dimmed-DUshB20C.js +1 -0
- package/dist/elements/chunks/github-light-JYsPkUQd.js +1 -0
- package/dist/elements/chunks/hover-card-gE7iyXdW.js +1 -0
- package/dist/elements/chunks/html-CPZ3oZQ7.js +1 -0
- package/dist/elements/chunks/icon-Vqz4ivrY.js +1 -0
- package/dist/elements/chunks/index-BCRhi84a.js +1 -0
- package/dist/elements/chunks/info-B_toFS0l.js +1 -0
- package/dist/elements/chunks/input-gzbHYZvQ.js +1 -0
- package/dist/elements/chunks/javascript-C25yR2R2.js +1 -0
- package/dist/elements/chunks/json-DxJze_jm.js +1 -0
- package/dist/elements/chunks/kbd-n49c4KZm.js +1 -0
- package/dist/elements/chunks/link-CKPs9yM0.js +1 -0
- package/dist/elements/chunks/loader-q6MamGus.js +1 -0
- package/dist/elements/chunks/markdown-DBrcqq4S.js +64 -0
- package/dist/elements/chunks/message-CTqaYI0s.js +1 -0
- package/dist/elements/chunks/message-feedback-Cvzm03w0.js +1 -0
- package/dist/elements/chunks/message-square-CUg9eRCi.js +1 -0
- package/dist/elements/chunks/minimize-2-l2klxP6K.js +1 -0
- package/dist/elements/chunks/model-switcher-CmyjiHO1.js +1 -0
- package/dist/elements/chunks/overlay-C8sOYqjT.js +1 -0
- package/dist/elements/chunks/paperclip-42Ia7xHD.js +1 -0
- package/dist/elements/chunks/progress-bar-tzKMWAwO.js +1 -0
- package/dist/elements/chunks/prompt-suggestion-D3F6vP_A.js +1 -0
- package/dist/elements/chunks/reasoning-BJNmmyov.js +1 -0
- package/dist/elements/chunks/resizable-BRsk19qI.js +1 -0
- package/dist/elements/chunks/rotate-cw-BgcggLHC.js +1 -0
- package/dist/elements/chunks/scroll-area-CgGbFFbT.js +1 -0
- package/dist/elements/chunks/separator-8hM4GdHE.js +1 -0
- package/dist/elements/chunks/settings-CaUIYOg-.js +1 -0
- package/dist/elements/chunks/settings-group-CYjOVIZQ.js +1 -0
- package/dist/elements/chunks/share-BTYM3Ddt.js +1 -0
- package/dist/elements/chunks/skeleton-DsTYrPUe.js +1 -0
- package/dist/elements/chunks/slots-DkZ-Cmha.js +1 -0
- package/dist/elements/chunks/star-9R3LBQ9n.js +1 -0
- package/dist/elements/chunks/store-CYl5Y0_u.js +1 -0
- package/dist/elements/chunks/svelte--5p79yCD.js +1 -0
- package/dist/elements/chunks/text-shimmer-CaYGv8Se.js +1 -0
- package/dist/elements/chunks/textarea-NEr2SLcD.js +1 -0
- package/dist/elements/chunks/thumbs-up-DZYZkFfc.js +1 -0
- package/dist/elements/chunks/toast-store-ClxVZRcc.js +1 -0
- package/dist/elements/chunks/tool-CHZOmoe9.js +1 -0
- package/dist/elements/chunks/tooltip-WpHElELC.js +1 -0
- package/dist/elements/chunks/triangle-alert-BlS80PUg.js +1 -0
- package/dist/elements/chunks/tsx-B8rCNbgL.js +1 -0
- package/dist/elements/chunks/typescript-RycA9KXf.js +1 -0
- package/dist/elements/chunks/use-card-resolution-VSVoxDeJ.js +1 -0
- package/dist/elements/chunks/video-DxTPZqT8.js +1 -0
- package/dist/elements/chunks/vue-BmIZj4XD.js +1 -0
- package/dist/elements/chunks/x-C1qtndxn.js +1 -0
- package/dist/elements/coachmark.d.ts +1 -0
- package/dist/elements/coachmark.js +1 -0
- package/dist/elements/code-block.js +1 -0
- package/dist/elements/command.d.ts +1 -0
- package/dist/elements/command.js +1 -0
- package/dist/elements/compare.d.ts +1 -0
- package/dist/elements/compare.js +1 -0
- package/dist/elements/composer.d.ts +1 -0
- package/dist/elements/composer.js +1 -0
- package/dist/elements/confirm-card.js +1 -0
- package/dist/elements/context-meter.js +1 -0
- package/dist/elements/conversation-list.d.ts +1 -11
- package/dist/elements/conversation-list.js +1 -0
- package/dist/elements/default-input.d.ts +20 -9
- package/dist/elements/define.d.ts +11 -0
- package/dist/elements/dialog.d.ts +1 -0
- package/dist/elements/dialog.js +1 -0
- package/dist/elements/disclosure.d.ts +37 -0
- package/dist/elements/editable-label.d.ts +1 -0
- package/dist/elements/editable-label.js +1 -0
- package/dist/elements/embed.js +1 -0
- package/dist/elements/empty.js +1 -0
- package/dist/elements/feedback-bar.js +1 -0
- package/dist/elements/file-tree.js +1 -0
- package/dist/elements/file-upload.js +1 -0
- package/dist/elements/form.js +1 -0
- package/dist/elements/hover-card.d.ts +1 -0
- package/dist/elements/hover-card.js +1 -0
- package/dist/elements/icon.d.ts +1 -0
- package/dist/elements/icon.js +1 -0
- package/dist/elements/image.js +1 -0
- package/dist/elements/input.d.ts +1 -0
- package/dist/elements/input.js +1 -0
- package/dist/elements/kbd.d.ts +1 -0
- package/dist/elements/kbd.js +1 -0
- package/dist/elements/link-preview.js +1 -0
- package/dist/elements/loader.js +1 -0
- package/dist/elements/markdown.js +1 -0
- package/dist/elements/menu.d.ts +1 -0
- package/dist/elements/menu.js +1 -0
- package/dist/elements/message-skills.d.ts +0 -16
- package/dist/elements/message-skills.js +1 -0
- package/dist/elements/message.js +1 -0
- package/dist/elements/model-switcher.d.ts +1 -11
- package/dist/elements/model-switcher.js +1 -0
- package/dist/elements/nav.d.ts +1 -0
- package/dist/elements/nav.js +1 -0
- package/dist/elements/notice.d.ts +1 -0
- package/dist/elements/notice.js +1 -0
- package/dist/elements/pane-group.d.ts +1 -0
- package/dist/elements/pane-group.js +1 -0
- package/dist/elements/pane.d.ts +1 -0
- package/dist/elements/pane.js +1 -0
- package/dist/elements/popover.js +1 -0
- package/dist/elements/progress-bar.d.ts +1 -0
- package/dist/elements/progress-bar.js +1 -0
- package/dist/elements/prompt-dock.d.ts +1 -0
- package/dist/elements/prompt-dock.js +1 -0
- package/dist/elements/prompt-input.d.ts +1 -9
- package/dist/elements/prompt-input.js +1 -0
- package/dist/elements/prompt-suggestions.d.ts +0 -6
- package/dist/elements/prompt-suggestions.js +1 -0
- package/dist/elements/reasoning.js +1 -0
- package/dist/elements/register.d.ts +10 -0
- package/dist/elements/remote.js +1 -0
- package/dist/elements/resizable.d.ts +1 -17
- package/dist/elements/resizable.js +1 -0
- package/dist/elements/response-stream.js +14 -0
- package/dist/elements/screen.d.ts +1 -0
- package/dist/elements/screen.js +1 -0
- package/dist/elements/scroll-area.d.ts +1 -0
- package/dist/elements/scroll-area.js +1 -0
- package/dist/elements/scroll-button.js +1 -0
- package/dist/elements/search.d.ts +1 -0
- package/dist/elements/search.js +1 -0
- package/dist/elements/segmented.d.ts +1 -0
- package/dist/elements/segmented.js +1 -0
- package/dist/elements/separator.d.ts +1 -0
- package/dist/elements/separator.js +1 -0
- package/dist/elements/setting-item.d.ts +1 -0
- package/dist/elements/setting-item.js +1 -0
- package/dist/elements/settings-group.d.ts +1 -0
- package/dist/elements/settings-group.js +1 -0
- package/dist/elements/skeleton.d.ts +1 -0
- package/dist/elements/skeleton.js +1 -0
- package/dist/elements/slots.d.ts +176 -0
- package/dist/elements/source.d.ts +0 -17
- package/dist/elements/source.js +1 -0
- package/dist/elements/status.d.ts +1 -0
- package/dist/elements/status.js +1 -0
- package/dist/elements/switch.js +1 -0
- package/dist/elements/tabs.d.ts +1 -0
- package/dist/elements/tabs.js +1 -0
- package/dist/elements/tasks.js +1 -0
- package/dist/elements/text-shimmer.js +1 -0
- package/dist/elements/thinking-bar.js +1 -0
- package/dist/elements/toast.d.ts +1 -0
- package/dist/elements/toast.js +1 -0
- package/dist/elements/tool.js +1 -0
- package/dist/elements/tooltip.d.ts +1 -0
- package/dist/elements/tooltip.js +1 -0
- package/dist/elements/voice-input.js +1 -0
- package/dist/elements/voice-output.d.ts +1 -0
- package/dist/elements/voice-output.js +1 -0
- package/dist/elements.d.ts +772 -61
- package/dist/engine-javascript-C1x7zo1_.js +141 -0
- package/dist/index.d.ts +15 -2
- package/dist/index.js +14405 -9810
- package/dist/kai.es.js +1 -0
- package/dist/llms/llms-full.txt +1234 -107
- package/dist/llms/llms.txt +4 -4
- package/dist/mcp.es.js +217 -6
- package/dist/primitives/card-contract.d.ts +20 -4
- package/dist/primitives/card-recovery.d.ts +55 -0
- package/dist/primitives/composer-model.d.ts +22 -0
- package/dist/primitives/composer-triggers.d.ts +19 -0
- package/dist/primitives/create-kai-chat.d.ts +38 -0
- package/dist/primitives/message-feedback.d.ts +35 -0
- package/dist/primitives/toast-store.d.ts +118 -0
- package/dist/primitives/use-speech-recognition.d.ts +26 -0
- package/dist/react/index.d.ts +1166 -98
- package/dist/react/runtime.d.ts +9 -2
- package/dist/react/use-kai-chat.d.ts +41 -0
- package/dist/react.js +575 -186
- package/dist/register-impl-CYWGkgbI.js +141 -0
- package/dist/schemas/choice.schema.json +5 -0
- package/dist/schemas/tasks.schema.json +7 -2
- package/dist/state/index.d.ts +4 -0
- package/dist/state/messages.d.ts +11 -0
- package/dist/state/stream.d.ts +22 -0
- package/dist/state/suggestions.d.ts +4 -0
- package/dist/state.js +117 -0
- package/dist/theme.tokens.css +87 -0
- package/dist/types.d.ts +4 -0
- package/dist/ui/agent-card.d.ts +61 -0
- package/dist/ui/button.d.ts +5 -2
- package/dist/ui/card.d.ts +61 -0
- package/dist/ui/collapsible.d.ts +15 -1
- package/dist/ui/command.d.ts +33 -0
- package/dist/ui/dialog.d.ts +42 -0
- package/dist/ui/dropdown.d.ts +95 -1
- package/dist/ui/editable-label.d.ts +26 -0
- package/dist/ui/hover-card.d.ts +13 -1
- package/dist/ui/icon.d.ts +18 -0
- package/dist/ui/input.d.ts +33 -0
- package/dist/ui/kbd.d.ts +21 -0
- package/dist/ui/nav.d.ts +62 -0
- package/dist/ui/notice.d.ts +31 -0
- package/dist/ui/overlay.d.ts +12 -0
- package/dist/ui/pane-grid.d.ts +58 -0
- package/dist/ui/pane-group.d.ts +75 -0
- package/dist/ui/pane.d.ts +78 -0
- package/dist/ui/popover.d.ts +11 -1
- package/dist/ui/progress-bar.d.ts +23 -0
- package/dist/ui/prompt-dock.d.ts +96 -0
- package/dist/ui/resizable.d.ts +12 -0
- package/dist/ui/scroll-area.d.ts +4 -0
- package/dist/ui/segmented.d.ts +28 -0
- package/dist/ui/settings-group.d.ts +32 -0
- package/dist/ui/skeleton.d.ts +12 -0
- package/dist/ui/stat.d.ts +16 -0
- package/dist/ui/status.d.ts +13 -0
- package/dist/ui/switch.d.ts +8 -1
- package/dist/ui/tabs.d.ts +35 -0
- package/dist/ui/tooltip.d.ts +20 -1
- package/frameworks/react/index.tsx +1100 -163
- package/frameworks/react/runtime.tsx +30 -1
- package/frameworks/react/use-kai-chat.tsx +87 -0
- package/llms-full.txt +1234 -107
- package/llms.txt +4 -4
- package/package.json +36 -12
- package/src/agent-tooling/mcp/manifest.ts +14 -0
- package/src/agent-tooling/mcp/tools/debug.ts +194 -6
- package/src/agent-tooling/mcp/tools/reference.ts +32 -0
- package/src/agent-tooling/mcp/tools/scaffold.ts +162 -1
- package/src/components/artifact.tsx +98 -13
- package/src/components/attachment-types.ts +13 -0
- package/src/components/attachments.tsx +4 -14
- package/src/components/card.tsx +109 -15
- package/src/components/chain-of-thought.tsx +210 -1
- package/src/components/chat-scope-picker.tsx +13 -3
- package/src/components/chat-thread.tsx +238 -137
- package/src/components/choice-card.tsx +136 -15
- package/src/components/coachmark.tsx +245 -0
- package/src/components/component-meta.json +921 -108
- package/src/components/composer-dom.ts +159 -0
- package/src/components/composer-highlight.ts +242 -0
- package/src/components/composer-history.ts +82 -0
- package/src/components/composer.tsx +979 -0
- package/src/components/confirm-card.tsx +69 -2
- package/src/components/conversation-item.tsx +69 -7
- package/src/components/conversation-list.tsx +134 -37
- package/src/components/dismissed-stub.tsx +80 -0
- package/src/components/file-tree.tsx +197 -47
- package/src/components/form-widgets.tsx +9 -7
- package/src/components/form.tsx +161 -20
- package/src/components/image.tsx +3 -5
- package/src/components/link-preview.tsx +5 -4
- package/src/components/markdown.tsx +5 -2
- package/src/components/message.tsx +174 -14
- package/src/components/model-switcher.tsx +19 -4
- package/src/components/prompt-input.tsx +46 -75
- package/src/components/prompt-suggestion.tsx +48 -16
- package/src/components/reasoning.tsx +29 -6
- package/src/components/response-compare-types.ts +127 -0
- package/src/components/response-compare.tsx +460 -0
- package/src/components/screen.tsx +176 -0
- package/src/components/tasks-card.tsx +374 -23
- package/src/components/toast.tsx +486 -0
- package/src/components/tool-types.ts +10 -0
- package/src/components/tool.tsx +22 -16
- package/src/components/use-card-resolution.ts +24 -8
- package/src/components/voice-input.tsx +102 -19
- package/src/components/voice-output.tsx +202 -0
- package/src/elements/agent-card.tsx +67 -0
- package/src/elements/artifact.tsx +53 -4
- package/src/elements/attachments.tsx +1 -0
- package/src/elements/autoloader.ts +89 -0
- package/src/elements/avatar.tsx +33 -0
- package/src/elements/badge.tsx +32 -0
- package/src/elements/button.tsx +126 -0
- package/src/elements/card-media.jpg +0 -0
- package/src/elements/card.tsx +124 -31
- package/src/elements/cards.tsx +81 -7
- package/src/elements/chain-of-thought.tsx +77 -32
- package/src/elements/chat-scope-picker.tsx +35 -8
- package/src/elements/chat-types.ts +9 -2
- package/src/elements/chat-workspace.tsx +157 -43
- package/src/elements/chat.tsx +49 -25
- package/src/elements/choice.tsx +71 -19
- package/src/elements/coachmark.tsx +90 -0
- package/src/elements/command.tsx +209 -0
- package/src/elements/compare.tsx +110 -0
- package/src/elements/compiled.css +1 -1
- package/src/elements/composer.tsx +151 -0
- package/src/elements/confirm-card.tsx +36 -11
- package/src/elements/conversation-list.tsx +80 -11
- package/src/elements/default-input.tsx +75 -53
- package/src/elements/define.tsx +47 -6
- package/src/elements/dialog.tsx +98 -0
- package/src/elements/disclosure.ts +73 -0
- package/src/elements/editable-label.tsx +125 -0
- package/src/elements/element-manifest.json +310 -0
- package/src/elements/element-meta.json +5954 -1605
- package/src/elements/element-types.d.ts +771 -60
- package/src/elements/file-tree.tsx +12 -2
- package/src/elements/file-upload.tsx +1 -1
- package/src/elements/form.tsx +54 -11
- package/src/elements/hover-card.tsx +80 -0
- package/src/elements/icon-names.json +48 -0
- package/src/elements/icon.tsx +41 -0
- package/src/elements/input.tsx +203 -0
- package/src/elements/kbd.tsx +45 -0
- package/src/elements/menu.tsx +217 -0
- package/src/elements/message.tsx +84 -55
- package/src/elements/model-switcher.tsx +27 -1
- package/src/elements/nav.tsx +87 -0
- package/src/elements/notice.tsx +53 -0
- package/src/elements/pane-group.tsx +119 -0
- package/src/elements/pane.tsx +129 -0
- package/src/elements/popover.tsx +39 -17
- package/src/elements/progress-bar.tsx +39 -0
- package/src/elements/prompt-dock.tsx +81 -0
- package/src/elements/prompt-input.tsx +112 -63
- package/src/elements/prompt-suggestions.tsx +25 -9
- package/src/elements/reasoning.tsx +30 -9
- package/src/elements/register-impl.ts +41 -3
- package/src/elements/register.ts +20 -3
- package/src/elements/remote.tsx +4 -0
- package/src/elements/resizable.tsx +48 -11
- package/src/elements/screen.tsx +90 -0
- package/src/elements/scroll-area.tsx +33 -0
- package/src/elements/search.tsx +180 -0
- package/src/elements/segmented.tsx +135 -0
- package/src/elements/separator.tsx +36 -0
- package/src/elements/setting-item.tsx +50 -0
- package/src/elements/settings-group.tsx +37 -0
- package/src/elements/skeleton.tsx +45 -0
- package/src/elements/slots.ts +607 -0
- package/src/elements/source.tsx +13 -6
- package/src/elements/status.tsx +42 -0
- package/src/elements/styles.css +19 -0
- package/src/elements/switch.tsx +89 -14
- package/src/elements/tabs.tsx +95 -0
- package/src/elements/tasks.tsx +70 -14
- package/src/elements/toast.tsx +89 -0
- package/src/elements/tool.tsx +43 -9
- package/src/elements/tooltip.tsx +85 -0
- package/src/elements/video-poster.jpg +0 -0
- package/src/elements/voice-input.tsx +66 -16
- package/src/elements/voice-output.tsx +69 -0
- package/src/index.ts +35 -2
- package/src/primitives/card-contract.ts +14 -5
- package/src/primitives/card-recovery.ts +149 -0
- package/src/primitives/card-routing.ts +3 -0
- package/src/primitives/card-schemas/choice.schema.json +5 -0
- package/src/primitives/card-schemas/tasks.schema.json +7 -2
- package/src/primitives/composer-model.ts +49 -0
- package/src/primitives/composer-triggers.ts +35 -0
- package/src/primitives/create-kai-chat.ts +66 -0
- package/src/primitives/message-feedback.ts +123 -0
- package/src/primitives/toast-store.ts +276 -0
- package/src/primitives/use-speech-recognition.ts +135 -0
- package/src/state/index.ts +6 -0
- package/src/state/messages.ts +36 -0
- package/src/state/stream.ts +92 -0
- package/src/state/suggestions.ts +9 -0
- package/src/types.ts +4 -0
- package/src/ui/agent-card.tsx +212 -0
- package/src/ui/button.tsx +16 -5
- package/src/ui/card.tsx +245 -0
- package/src/ui/collapsible.tsx +30 -4
- package/src/ui/command.tsx +99 -0
- package/src/ui/dialog.tsx +217 -0
- package/src/ui/dropdown.tsx +375 -13
- package/src/ui/editable-label.tsx +112 -0
- package/src/ui/hover-card.tsx +28 -5
- package/src/ui/icon.tsx +110 -0
- package/src/ui/input.tsx +132 -0
- package/src/ui/kbd.tsx +118 -0
- package/src/ui/nav.tsx +282 -0
- package/src/ui/notice.tsx +84 -0
- package/src/ui/overlay.tsx +108 -2
- package/src/ui/pane-grid.tsx +116 -0
- package/src/ui/pane-group.tsx +280 -0
- package/src/ui/pane.tsx +193 -0
- package/src/ui/popover.tsx +16 -2
- package/src/ui/progress-bar.tsx +83 -0
- package/src/ui/prompt-dock.tsx +145 -0
- package/src/ui/resizable.tsx +69 -1
- package/src/ui/scroll-area.tsx +14 -3
- package/src/ui/segmented.tsx +109 -0
- package/src/ui/settings-group.tsx +67 -0
- package/src/ui/skeleton.tsx +62 -5
- package/src/ui/stat.tsx +41 -0
- package/src/ui/status.tsx +48 -0
- package/src/ui/switch.tsx +49 -23
- package/src/ui/tabs.tsx +168 -0
- package/src/ui/tooltip.tsx +57 -7
- package/theme.css +113 -0
- package/dist/components/slash-command.d.ts +0 -15
- package/dist/kitn-chat.es.js +0 -1
- package/dist/register-impl-wCsFPoh9.js +0 -77
- package/dist/register-ujhr1nBS.js +0 -1
- package/src/components/slash-command.tsx +0 -232
- package/src/elements/framework-usage.json +0 -563
- /package/dist/{kitn-chat-provider.d.ts → kai-provider.d.ts} +0 -0
- /package/dist/{kitn-chat-provider.es.js → kai-provider.es.js} +0 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { defineWebComponent } from './define';
|
|
2
|
+
import { Coachmark, type CoachmarkController } from '../components/coachmark';
|
|
3
|
+
import { wireDisclosure } from './disclosure';
|
|
4
|
+
|
|
5
|
+
interface Props extends Record<string, unknown> {
|
|
6
|
+
/** Drive/observe open state (Shoelace-style: settable + reflected to the `open`
|
|
7
|
+
* attribute; the element still self-manages). Set `el.open = true`, or
|
|
8
|
+
* `<kai-coachmark open>`; listen for `kai-open-change`. */
|
|
9
|
+
open?: boolean;
|
|
10
|
+
/** Initial open state on mount (uncontrolled seed). */
|
|
11
|
+
defaultOpen?: boolean;
|
|
12
|
+
/** The bold title. Named `headline` because `title` collides with the global
|
|
13
|
+
* `HTMLElement.title` attribute (it throws at registration). */
|
|
14
|
+
headline?: string;
|
|
15
|
+
/** A small badge pill beside the headline (e.g. "New"). */
|
|
16
|
+
badge?: string;
|
|
17
|
+
/** Floating placement relative to the anchor (default `bottom`). */
|
|
18
|
+
placement?: string;
|
|
19
|
+
/** Color tone: `primary` (default, theme accent), `info` (blue), `success`
|
|
20
|
+
* (green), `warning` (amber), or `error` (red) — reusing the kit's tool hues. */
|
|
21
|
+
tone?: 'primary' | 'info' | 'success' | 'warning' | 'error';
|
|
22
|
+
/** Render the arrow that points at the anchor (default `true`). Set
|
|
23
|
+
* `arrow="false"` for a plain bubble with no pointer. */
|
|
24
|
+
arrow?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Events fired by `<kai-coachmark>`. */
|
|
28
|
+
interface Events {
|
|
29
|
+
/** The × dismiss button was pressed. The consumer records that this hint was
|
|
30
|
+
* seen so it won't show again. */
|
|
31
|
+
'kai-dismiss': Record<string, never>;
|
|
32
|
+
/** The coachmark opened or closed (a method, the ×, or a driven `open`). */
|
|
33
|
+
'kai-open-change': { open: boolean };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* `<kai-coachmark>` — an anchored onboarding hint bubble with an arrow. It WRAPS
|
|
38
|
+
* a trigger (the default slot) and points a primary-colored bubble at it: a small
|
|
39
|
+
* `badge` pill, a bold `headline`, the `content` slot body, and a dismiss ×.
|
|
40
|
+
*
|
|
41
|
+
* ```html
|
|
42
|
+
* <kai-coachmark default-open headline="Cowork has a new home" badge="New">
|
|
43
|
+
* <button>Cowork</button>
|
|
44
|
+
* <span slot="content">Chat with Claude or switch to Cowork from here.</span>
|
|
45
|
+
* </kai-coachmark>
|
|
46
|
+
* <script type="module">
|
|
47
|
+
* document.querySelector('kai-coachmark')
|
|
48
|
+
* .addEventListener('kai-dismiss', () => localStorage.setItem('cowork-hint', 'seen'));
|
|
49
|
+
* </script>
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* Open state is the standard disclosure surface: settable+reflecting `open`,
|
|
53
|
+
* `kai-open-change`, and `show()`/`hide()`/`toggle()`; seed with `default-open`.
|
|
54
|
+
* Parts: `bubble` · `arrow` · `badge` · `title` · `dismiss`.
|
|
55
|
+
*/
|
|
56
|
+
defineWebComponent<Props, Events>('kai-coachmark', {
|
|
57
|
+
open: undefined,
|
|
58
|
+
defaultOpen: undefined,
|
|
59
|
+
headline: undefined,
|
|
60
|
+
badge: undefined,
|
|
61
|
+
placement: undefined,
|
|
62
|
+
tone: undefined,
|
|
63
|
+
arrow: true,
|
|
64
|
+
}, (props, ctx) => {
|
|
65
|
+
const { flag, dispatch } = ctx;
|
|
66
|
+
let api: CoachmarkController | undefined;
|
|
67
|
+
|
|
68
|
+
// The standard disclosure surface: settable+reflecting `open`, kai-open-change,
|
|
69
|
+
// show/hide/toggle. See ./disclosure. This is the SOLE emitter of kai-open-change.
|
|
70
|
+
wireDisclosure(ctx, () => api, () => props.open);
|
|
71
|
+
|
|
72
|
+
// headline/badge are scalar string props (NOT slots) — pass through directly so
|
|
73
|
+
// the component's own `Show when={…}` gating drives whether each region renders.
|
|
74
|
+
// The body is the `content` slot; an empty `<slot>` renders nothing.
|
|
75
|
+
return (
|
|
76
|
+
<Coachmark
|
|
77
|
+
defaultOpen={flag('defaultOpen')}
|
|
78
|
+
arrow={flag('arrow')}
|
|
79
|
+
placement={props.placement as never}
|
|
80
|
+
tone={props.tone as 'primary' | 'info' | 'success' | 'warning' | 'error' | undefined}
|
|
81
|
+
headline={props.headline as string | undefined}
|
|
82
|
+
badge={props.badge as string | undefined}
|
|
83
|
+
content={<slot name="content" />}
|
|
84
|
+
controllerRef={(a) => (api = a)}
|
|
85
|
+
onDismiss={() => dispatch('kai-dismiss', {})}
|
|
86
|
+
>
|
|
87
|
+
<slot />
|
|
88
|
+
</Coachmark>
|
|
89
|
+
);
|
|
90
|
+
});
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { createEffect, createMemo, createSignal, createUniqueId, on } from 'solid-js';
|
|
2
|
+
import { CommandList, type CommandGroup } from '../ui/command';
|
|
3
|
+
import { defineWebComponent } from './define';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A single command/mention item for `<kai-command>`.
|
|
7
|
+
*
|
|
8
|
+
* Set `items` as a JS property (array ref) — not an HTML attribute.
|
|
9
|
+
*/
|
|
10
|
+
export interface KaiCommandItem {
|
|
11
|
+
/** Unique identifier emitted in `kai-select`. */
|
|
12
|
+
id: string;
|
|
13
|
+
/** Display name shown in the list row. */
|
|
14
|
+
label: string;
|
|
15
|
+
/** Named icon (e.g. "search"), image URL / data-URI, or plain text. */
|
|
16
|
+
icon?: string;
|
|
17
|
+
/** Muted supplementary text (e.g. a file path or a short description). */
|
|
18
|
+
description?: string;
|
|
19
|
+
/** Optional keyboard shortcut shown as right-aligned key caps; uses the
|
|
20
|
+
* kai-kbd `keys` syntax (e.g. "Mod+K", "Alt+1"). */
|
|
21
|
+
shortcut?: string;
|
|
22
|
+
/** Group name that buckets this item under a section header. */
|
|
23
|
+
group?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface Props extends Record<string, unknown> {
|
|
27
|
+
/** Flat list of items. Set as a JS property — not an HTML attribute. */
|
|
28
|
+
items?: KaiCommandItem[];
|
|
29
|
+
/** Placeholder text for the search input. */
|
|
30
|
+
placeholder?: string;
|
|
31
|
+
/** Label shown when no items match the current query. */
|
|
32
|
+
emptyLabel?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface Events {
|
|
36
|
+
/** Fired when the user selects an item (click or Enter). */
|
|
37
|
+
'kai-select': { id: string };
|
|
38
|
+
/** Fired on every keystroke in the search input. */
|
|
39
|
+
'kai-query-change': { value: string };
|
|
40
|
+
/** Fired when the highlighted/active item changes — via Arrow keys or when
|
|
41
|
+
* filtering re-clamps the active row. `id` is the newly active item's id, or
|
|
42
|
+
* `undefined` when no item is active (e.g. the filtered list is empty). Lets a
|
|
43
|
+
* host preview the active item without committing a selection. */
|
|
44
|
+
'kai-active-change': { id: string | undefined };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* `<kai-command>` — a grouped, filterable command/mention palette.
|
|
49
|
+
*
|
|
50
|
+
* Set the `items` property in JavaScript (array, not attribute), listen for
|
|
51
|
+
* `kai-select` to know which item was picked, and `kai-query-change` to mirror
|
|
52
|
+
* the search query to your own logic (e.g. async server-side filtering).
|
|
53
|
+
*
|
|
54
|
+
* ```html
|
|
55
|
+
* <kai-command placeholder="Search…"></kai-command>
|
|
56
|
+
* <script type="module">
|
|
57
|
+
* import '@kitn.ai/ui/elements';
|
|
58
|
+
* const el = document.querySelector('kai-command');
|
|
59
|
+
* el.items = [
|
|
60
|
+
* { id: 'foo', label: 'Foo', icon: 'search', shortcut: 'Mod+K', group: 'Recent' },
|
|
61
|
+
* ];
|
|
62
|
+
* el.addEventListener('kai-select', (e) => console.log(e.detail.id));
|
|
63
|
+
* </script>
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
defineWebComponent<Props, Events>('kai-command', {
|
|
67
|
+
items: undefined,
|
|
68
|
+
placeholder: undefined,
|
|
69
|
+
emptyLabel: undefined,
|
|
70
|
+
}, (props, { dispatch, element, expose }) => {
|
|
71
|
+
const listboxId = createUniqueId();
|
|
72
|
+
const [query, setQuery] = createSignal('');
|
|
73
|
+
const [activeId, setActiveId] = createSignal<string | undefined>(undefined);
|
|
74
|
+
|
|
75
|
+
/** Items cast to the correct type; defaults to empty array. */
|
|
76
|
+
const allItems = () => (props.items as KaiCommandItem[] | undefined) ?? [];
|
|
77
|
+
|
|
78
|
+
/** Items filtered by the current query (label or description, case-insensitive). */
|
|
79
|
+
const filteredItems = createMemo<KaiCommandItem[]>(() => {
|
|
80
|
+
const q = query().toLowerCase();
|
|
81
|
+
if (!q) return allItems();
|
|
82
|
+
return allItems().filter(
|
|
83
|
+
(item) =>
|
|
84
|
+
item.label.toLowerCase().includes(q) ||
|
|
85
|
+
(item.description?.toLowerCase().includes(q) ?? false),
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
/** Filtered items grouped by `group`, preserving first-appearance order. */
|
|
90
|
+
const groupedItems = createMemo<CommandGroup[]>(() => {
|
|
91
|
+
const groups: CommandGroup[] = [];
|
|
92
|
+
for (const item of filteredItems()) {
|
|
93
|
+
let g = groups.find((x) => x.group === item.group);
|
|
94
|
+
if (!g) {
|
|
95
|
+
g = { group: item.group, items: [] };
|
|
96
|
+
groups.push(g);
|
|
97
|
+
}
|
|
98
|
+
g.items.push({ id: item.id, label: item.label, icon: item.icon, description: item.description, shortcut: item.shortcut });
|
|
99
|
+
}
|
|
100
|
+
return groups;
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
/** Flat ordered array of filtered item ids — used for keyboard navigation. */
|
|
104
|
+
const flatIds = createMemo<string[]>(() => filteredItems().map((item) => item.id));
|
|
105
|
+
|
|
106
|
+
/** Clamp/reset activeId when the filtered list changes. */
|
|
107
|
+
createEffect(() => {
|
|
108
|
+
const ids = flatIds();
|
|
109
|
+
const current = activeId();
|
|
110
|
+
if (!current || !ids.includes(current)) {
|
|
111
|
+
setActiveId(ids[0]);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
/** Mirror the active/highlighted item out as `kai-active-change` whenever it
|
|
116
|
+
* changes (Arrow keys or a filter-driven re-clamp). Skips the initial settle
|
|
117
|
+
* by only firing when the value actually differs from the previous one. */
|
|
118
|
+
createEffect(on(activeId, (id, prev) => {
|
|
119
|
+
if (id !== prev) dispatch('kai-active-change', { id });
|
|
120
|
+
}));
|
|
121
|
+
|
|
122
|
+
function select(id: string) {
|
|
123
|
+
dispatch('kai-select', { id });
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function handleInput(e: Event) {
|
|
127
|
+
const value = (e.currentTarget as HTMLInputElement).value;
|
|
128
|
+
setQuery(value);
|
|
129
|
+
dispatch('kai-query-change', { value });
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function handleKeyDown(e: KeyboardEvent) {
|
|
133
|
+
const ids = flatIds();
|
|
134
|
+
if (!ids.length) return;
|
|
135
|
+
|
|
136
|
+
const current = activeId();
|
|
137
|
+
const idx = current !== undefined ? ids.indexOf(current) : -1;
|
|
138
|
+
|
|
139
|
+
if (e.key === 'ArrowDown') {
|
|
140
|
+
e.preventDefault();
|
|
141
|
+
setActiveId(ids[(idx + 1) % ids.length]);
|
|
142
|
+
} else if (e.key === 'ArrowUp') {
|
|
143
|
+
e.preventDefault();
|
|
144
|
+
setActiveId(ids[(idx - 1 + ids.length) % ids.length]);
|
|
145
|
+
} else if (e.key === 'Enter') {
|
|
146
|
+
e.preventDefault();
|
|
147
|
+
const id = activeId();
|
|
148
|
+
if (id !== undefined) select(id);
|
|
149
|
+
} else if (e.key === 'Escape') {
|
|
150
|
+
e.preventDefault();
|
|
151
|
+
setQuery('');
|
|
152
|
+
dispatch('kai-query-change', { value: '' });
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ── Imperative API (instance methods on the host) ──────────────────────────
|
|
157
|
+
// Counterpart to the kai-* events: lets a host make the palette type-ready and
|
|
158
|
+
// reset its query without reaching into the shadow root.
|
|
159
|
+
expose({
|
|
160
|
+
/** Focus the search combobox input inside the shadow root so the palette is
|
|
161
|
+
* type-ready on demand (Shadow-DOM autofocus is unreliable, so hosts call
|
|
162
|
+
* this after opening the palette). */
|
|
163
|
+
focus: (options?: FocusOptions) =>
|
|
164
|
+
element.shadowRoot
|
|
165
|
+
?.querySelector<HTMLInputElement>('input[role="combobox"], input')
|
|
166
|
+
?.focus(options),
|
|
167
|
+
/** Blur the focused search input. */
|
|
168
|
+
blur: () =>
|
|
169
|
+
element.shadowRoot
|
|
170
|
+
?.querySelector<HTMLInputElement>('input[role="combobox"], input')
|
|
171
|
+
?.blur(),
|
|
172
|
+
/** Reset the search query to empty — re-showing all items — and fire
|
|
173
|
+
* `kai-query-change` with `''`. Mirrors the Escape-key behavior. */
|
|
174
|
+
clear: () => {
|
|
175
|
+
setQuery('');
|
|
176
|
+
dispatch('kai-query-change', { value: '' });
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
return (
|
|
181
|
+
<div class="flex flex-col overflow-hidden">
|
|
182
|
+
<div class="border-b border-border px-3 py-2">
|
|
183
|
+
<input
|
|
184
|
+
type="text"
|
|
185
|
+
role="combobox"
|
|
186
|
+
aria-expanded="true"
|
|
187
|
+
aria-haspopup="listbox"
|
|
188
|
+
aria-autocomplete="list"
|
|
189
|
+
aria-controls={listboxId}
|
|
190
|
+
value={query()}
|
|
191
|
+
placeholder={(props.placeholder as string | undefined) ?? 'Search…'}
|
|
192
|
+
class="w-full bg-transparent text-sm text-foreground placeholder:text-muted-foreground focus-visible:outline-none"
|
|
193
|
+
onInput={handleInput}
|
|
194
|
+
onKeyDown={handleKeyDown}
|
|
195
|
+
/>
|
|
196
|
+
</div>
|
|
197
|
+
<div class="overflow-y-auto max-h-[320px]">
|
|
198
|
+
<CommandList
|
|
199
|
+
id={listboxId}
|
|
200
|
+
ariaLabel="Results"
|
|
201
|
+
groups={groupedItems()}
|
|
202
|
+
activeId={activeId()}
|
|
203
|
+
onSelect={select}
|
|
204
|
+
emptyLabel={(props.emptyLabel as string | undefined) ?? 'No results'}
|
|
205
|
+
/>
|
|
206
|
+
</div>
|
|
207
|
+
</div>
|
|
208
|
+
);
|
|
209
|
+
});
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { defineWebComponent } from './define';
|
|
2
|
+
import { ChatConfig, useChatConfig, type ProseSize } from '../primitives/chat-config';
|
|
3
|
+
import { ResponseCompare, type CompareLayout } from '../components/response-compare';
|
|
4
|
+
import type {
|
|
5
|
+
ResponseCompareData,
|
|
6
|
+
CompareSelection,
|
|
7
|
+
ResponseCompareController,
|
|
8
|
+
} from '../components/response-compare';
|
|
9
|
+
|
|
10
|
+
interface Props extends Record<string, unknown> {
|
|
11
|
+
/** The compare definition (prompt + the two candidates). Set as a JS PROPERTY:
|
|
12
|
+
* `el.data = { prompt, candidates: [A, B], collapse? }`. Import
|
|
13
|
+
* `ResponseCompareData` from `@kitn.ai/ui` for the full shape. */
|
|
14
|
+
data?: Record<string, unknown>;
|
|
15
|
+
/** Stable id correlating every emitted event. Attribute: `compare-id`. */
|
|
16
|
+
compareId?: string;
|
|
17
|
+
/** Re-hydrate / control the user's pick. Set as a JS PROPERTY:
|
|
18
|
+
* `el.selection = { chosenId, rejectedIds }`. Renders the collapsed winner. */
|
|
19
|
+
selection?: Record<string, unknown>;
|
|
20
|
+
/** Layout: `'auto'` (default — columns when wide, tabs when narrow, by CONTAINER
|
|
21
|
+
* width) | `'columns'` (side-by-side) | `'tabs'` (pills to switch). Attribute: `layout`. */
|
|
22
|
+
layout?: CompareLayout;
|
|
23
|
+
/** Prose/text size for the rendered candidates. Attribute: `prose-size`. */
|
|
24
|
+
proseSize?: ProseSize;
|
|
25
|
+
/** Shiki theme for code blocks in the candidates. Attribute: `code-theme`. */
|
|
26
|
+
codeTheme?: string;
|
|
27
|
+
/** Whether code blocks are syntax-highlighted. Attribute: `code-highlight`. */
|
|
28
|
+
codeHighlight?: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface Events extends Record<string, unknown> {
|
|
32
|
+
/** The user committed a pick. `detail` = `{ chosenId, rejectedIds, at }`. */
|
|
33
|
+
'kai-compare-select': CompareSelection;
|
|
34
|
+
/** Both candidates have settled and the pick is live. */
|
|
35
|
+
'kai-ready': { compareId: string };
|
|
36
|
+
/** The definition was unusable. */
|
|
37
|
+
'kai-error': { compareId: string; message: string };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* `<kai-compare>` — a **dual-response comparison** (set via the `data` property):
|
|
42
|
+
* two assistant candidates for the same prompt, rendered side-by-side (or as tabs),
|
|
43
|
+
* each exactly like an assistant message (reasoning + tools + attachments +
|
|
44
|
+
* markdown). The user **picks** the better one — a COMMIT, not a Submit — which
|
|
45
|
+
* fires a non-bubbling **`kai-compare-select`** CustomEvent off the host
|
|
46
|
+
* (`{ chosenId, rejectedIds:[other], at }`) for the consumer to send a
|
|
47
|
+
* `(prompt, chosen, rejected)` preference pair. The card optimistically collapses
|
|
48
|
+
* to the chosen candidate. Single-shot.
|
|
49
|
+
*
|
|
50
|
+
* Both candidates can stream (push a fresh `data` reference per chunk); the pick is
|
|
51
|
+
* disabled with a per-column shimmer until BOTH settle, then `kai-ready` fires. The
|
|
52
|
+
* columns are a WAI-ARIA radiogroup with roving tabindex (Arrow keys move A↔B,
|
|
53
|
+
* Enter/Space picks). `kai-error` fires for a malformed definition. Isolated in
|
|
54
|
+
* Shadow DOM; theme-aware via the shared tokens.
|
|
55
|
+
*/
|
|
56
|
+
defineWebComponent<Props, Events>(
|
|
57
|
+
'kai-compare',
|
|
58
|
+
{
|
|
59
|
+
data: undefined,
|
|
60
|
+
compareId: undefined,
|
|
61
|
+
selection: undefined,
|
|
62
|
+
layout: 'auto',
|
|
63
|
+
proseSize: undefined,
|
|
64
|
+
codeTheme: undefined,
|
|
65
|
+
codeHighlight: undefined,
|
|
66
|
+
},
|
|
67
|
+
(props, { element, dispatch, expose }) => {
|
|
68
|
+
const compareId = (): string => props.compareId ?? (element.id || 'kai-compare');
|
|
69
|
+
// Inherit the shadow-root portal mount from the outer ChatConfig that
|
|
70
|
+
// defineWebComponent installs, so candidate-body overlays (hover cards,
|
|
71
|
+
// tooltips) stay inside the shadow root.
|
|
72
|
+
const outer = useChatConfig();
|
|
73
|
+
|
|
74
|
+
// ── Imperative API (instance methods on the host) ──────────────────────────
|
|
75
|
+
// Pattern C: ResponseCompare owns the pick + roving-focus state and hands up a
|
|
76
|
+
// controller; the facade captures it and exposes delegating methods. The
|
|
77
|
+
// component's own callbacks still fire (select → onSelect → kai-compare-select).
|
|
78
|
+
let controller: ResponseCompareController | undefined;
|
|
79
|
+
expose({
|
|
80
|
+
/** Programmatically commit a pick by candidate id — same path as the "Pick
|
|
81
|
+
* this" button: fires kai-compare-select and optimistically collapses
|
|
82
|
+
* (single-shot; inert while streaming or already resolved). `select` does
|
|
83
|
+
* NOT collide with the `selection` prop (distinct identifier). */
|
|
84
|
+
select: (candidateId: string) => controller?.select(candidateId),
|
|
85
|
+
/** Focus the current roving tab stop (the focused candidate's "Pick this"
|
|
86
|
+
* radio) so a consumer can move keyboard focus into the radiogroup. */
|
|
87
|
+
focus: (options?: FocusOptions) => controller?.focus(options),
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<ChatConfig
|
|
92
|
+
proseSize={props.proseSize}
|
|
93
|
+
codeTheme={props.codeTheme}
|
|
94
|
+
codeHighlight={props.codeHighlight}
|
|
95
|
+
portalMount={outer.portalMount()}
|
|
96
|
+
>
|
|
97
|
+
<ResponseCompare
|
|
98
|
+
data={props.data as ResponseCompareData | undefined}
|
|
99
|
+
compareId={compareId()}
|
|
100
|
+
selection={props.selection as CompareSelection | undefined}
|
|
101
|
+
layout={(props.layout as CompareLayout | undefined) ?? 'auto'}
|
|
102
|
+
controllerRef={(c) => (controller = c)}
|
|
103
|
+
onSelect={(sel) => dispatch('kai-compare-select', sel)}
|
|
104
|
+
onReady={() => dispatch('kai-ready', { compareId: compareId() })}
|
|
105
|
+
onError={(message) => dispatch('kai-error', { compareId: compareId(), message })}
|
|
106
|
+
/>
|
|
107
|
+
</ChatConfig>
|
|
108
|
+
);
|
|
109
|
+
},
|
|
110
|
+
);
|