@kitn.ai/ui 0.17.0 → 0.18.1
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 +28 -5
- 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 +37 -12
- package/dist/components/choice-card.d.ts +26 -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/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 +12 -0
- 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.d.ts +14 -0
- package/dist/components/screen.d.ts +46 -0
- package/dist/components/tasks-card.d.ts +49 -1
- package/dist/components/toast.d.ts +12 -2
- package/dist/components/tool-types.d.ts +10 -0
- package/dist/components/tool.d.ts +8 -8
- 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 +8392 -1860
- package/dist/elements/agent-card.d.ts +1 -0
- package/dist/elements/agent-card.js +1 -0
- package/dist/elements/artifact.js +1 -1
- package/dist/elements/attachments.js +1 -1
- package/dist/elements/autoloader.js +1 -1
- 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 -1
- package/dist/elements/cards.js +1 -1
- package/dist/elements/chain-of-thought.js +1 -1
- package/dist/elements/chat-scope-picker.js +1 -1
- package/dist/elements/chat-types.d.ts +47 -0
- package/dist/elements/chat-workspace.js +1 -1
- package/dist/elements/chat.js +1 -1
- package/dist/elements/checkpoint.js +1 -1
- package/dist/elements/choice.js +1 -1
- package/dist/elements/chunks/Icon-C2LTALdM.js +1 -0
- package/dist/elements/chunks/action-icons-Dtl8Ox5D.js +1 -0
- package/dist/elements/chunks/arrow-left-GbBceGBE.js +1 -0
- package/dist/elements/chunks/attachments-DLJcWCDV.js +1 -0
- package/dist/elements/chunks/badge-BTNZTODL.js +1 -0
- package/dist/elements/chunks/button-DBDZebGr.js +1 -0
- package/dist/elements/chunks/card-YfCyI4fH.js +1 -0
- package/dist/elements/chunks/chat-thread-Dz2qbzvI.js +1 -0
- package/dist/elements/chunks/check-fhmRksq_.js +1 -0
- package/dist/elements/chunks/chevron-down-DcRg1aRU.js +1 -0
- package/dist/elements/chunks/chevron-right-ChzBcNJ-.js +1 -0
- package/dist/elements/chunks/circle-B4fTe9v6.js +1 -0
- package/dist/elements/chunks/circle-check-CJV-3Rem.js +1 -0
- package/dist/elements/chunks/circle-x-pDtzlghQ.js +1 -0
- package/dist/elements/chunks/cn-CU7UAWzk.js +1 -0
- package/dist/elements/chunks/code-block-DZ6mz6vs.js +1 -0
- package/dist/elements/chunks/collapsible-CWUAShMC.js +1 -0
- package/dist/elements/chunks/composer-BZyPU6gD.js +65 -0
- package/dist/elements/chunks/context-Cx6eQA_G.js +1 -0
- package/dist/elements/chunks/conversation-list-C4xTQSpT.js +1 -0
- package/dist/elements/chunks/default-input-BZcwyKcP.js +1 -0
- package/dist/elements/chunks/define-CNSKFZCd.js +1 -0
- package/dist/elements/chunks/disclosure-BcBs--Jf.js +1 -0
- package/dist/elements/chunks/download-BDQwcFav.js +1 -0
- package/dist/elements/chunks/dropdown-wgs8xCJZ.js +1 -0
- package/dist/elements/chunks/ellipsis-CUiEJ6R1.js +1 -0
- package/dist/elements/chunks/external-link-DJUmC7g2.js +1 -0
- package/dist/elements/chunks/file-text-DOYfYvrh.js +1 -0
- package/dist/elements/chunks/file-tree-DQzNQrbr.js +1 -0
- package/dist/elements/chunks/folder-DBDUBANz.js +1 -0
- package/dist/elements/chunks/hover-card-BQGdGAQ3.js +1 -0
- package/dist/elements/chunks/icon-CAyRqVrg.js +1 -0
- package/dist/elements/chunks/{index-CTBEJeo6.js → index-BCRhi84a.js} +1 -1
- package/dist/elements/chunks/info-DBQl-m6e.js +1 -0
- package/dist/elements/chunks/input-DZD67EvW.js +1 -0
- package/dist/elements/chunks/kbd-DbyVrlnU.js +1 -0
- package/dist/elements/chunks/link-vko7AttA.js +1 -0
- package/dist/elements/chunks/loader-Cg6rO8tQ.js +1 -0
- package/dist/elements/chunks/{markdown-CMTGx9r8.js → markdown-n3Xbj3PR.js} +9 -9
- package/dist/elements/chunks/message-CgKytiSB.js +1 -0
- package/dist/elements/chunks/message-feedback-Ds3-US0e.js +1 -0
- package/dist/elements/chunks/message-square-MmRkvc-M.js +1 -0
- package/dist/elements/chunks/minimize-2-3kCdE0q3.js +1 -0
- package/dist/elements/chunks/model-switcher-BMtXGwLU.js +1 -0
- package/dist/elements/chunks/overlay-B1-MBI6h.js +1 -0
- package/dist/elements/chunks/paperclip-DDEfmkHc.js +1 -0
- package/dist/elements/chunks/progress-bar-Dwbiyv3s.js +1 -0
- package/dist/elements/chunks/prompt-suggestion-9lvgFcEa.js +1 -0
- package/dist/elements/chunks/reasoning-DzHWsdAJ.js +1 -0
- package/dist/elements/chunks/resizable-Bq_eHxUm.js +1 -0
- package/dist/elements/chunks/rotate-cw-jpisOdOV.js +1 -0
- package/dist/elements/chunks/scroll-area-g5Ze3K6f.js +1 -0
- package/dist/elements/chunks/separator-Bmjc5XyX.js +1 -0
- package/dist/elements/chunks/settings-Cz1bMJP9.js +1 -0
- package/dist/elements/chunks/settings-group-9imY3kRA.js +1 -0
- package/dist/elements/chunks/share-BdenF0wQ.js +1 -0
- package/dist/elements/chunks/skeleton-Pjc5jiaY.js +1 -0
- package/dist/elements/chunks/slots-DkZ-Cmha.js +1 -0
- package/dist/elements/chunks/star-DY6z1UUH.js +1 -0
- package/dist/elements/chunks/store-th4VyJXM.js +1 -0
- package/dist/elements/chunks/text-shimmer-CEi-tlXr.js +1 -0
- package/dist/elements/chunks/textarea-CboigarR.js +1 -0
- package/dist/elements/chunks/thumbs-up-BR33KLfA.js +1 -0
- package/dist/elements/chunks/toast-store-BEMda0fv.js +1 -0
- package/dist/elements/chunks/tool-TMued3WO.js +1 -0
- package/dist/elements/chunks/tooltip-Cft_Rxiw.js +1 -0
- package/dist/elements/chunks/triangle-alert-B07fX3Q8.js +1 -0
- package/dist/elements/chunks/use-card-resolution-M36zVciB.js +1 -0
- package/dist/elements/chunks/video-MKp3LmNT.js +1 -0
- package/dist/elements/chunks/x-Ckwicf6g.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 -1
- package/dist/elements/command.d.ts +1 -0
- package/dist/elements/command.js +1 -0
- package/dist/elements/compare.js +1 -1
- package/dist/elements/composer.d.ts +1 -0
- package/dist/elements/composer.js +1 -0
- package/dist/elements/confirm-card.js +1 -1
- package/dist/elements/context-meter.js +1 -1
- package/dist/elements/conversation-list.js +1 -1
- package/dist/elements/css.d.ts +1 -0
- package/dist/elements/default-input.d.ts +51 -0
- package/dist/elements/define.d.ts +53 -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 -1
- package/dist/elements/empty.js +1 -1
- package/dist/elements/feedback-bar.js +1 -1
- package/dist/elements/file-tree.js +1 -1
- package/dist/elements/file-upload.js +1 -1
- package/dist/elements/form.js +1 -1
- 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 -1
- 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 -1
- package/dist/elements/loader.js +1 -1
- package/dist/elements/markdown.js +1 -1
- package/dist/elements/menu.d.ts +1 -0
- package/dist/elements/menu.js +1 -0
- package/dist/elements/message-skills.js +1 -1
- package/dist/elements/message.js +1 -1
- package/dist/elements/model-switcher.js +1 -1
- 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 -1
- 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.js +1 -1
- package/dist/elements/prompt-suggestions.js +1 -1
- package/dist/elements/reasoning.js +1 -1
- package/dist/elements/register-impl.d.ts +0 -0
- package/dist/elements/register.d.ts +13 -0
- package/dist/elements/remote.d.ts +1 -0
- package/dist/elements/remote.js +1 -0
- package/dist/elements/resizable.js +1 -1
- package/dist/elements/response-stream.js +2 -2
- 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 -1
- 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.js +1 -1
- package/dist/elements/status.d.ts +1 -0
- package/dist/elements/status.js +1 -0
- package/dist/elements/switch.js +1 -1
- package/dist/elements/tabs.d.ts +1 -0
- package/dist/elements/tabs.js +1 -0
- package/dist/elements/tasks.js +1 -1
- package/dist/elements/text-shimmer.js +1 -1
- package/dist/elements/thinking-bar.js +1 -1
- package/dist/elements/toast.js +1 -1
- package/dist/elements/tool.js +1 -1
- package/dist/elements/tooltip.d.ts +1 -0
- package/dist/elements/tooltip.js +1 -0
- package/dist/elements/voice-input.js +1 -1
- package/dist/elements/voice-output.d.ts +1 -0
- package/dist/elements/voice-output.js +1 -0
- package/dist/elements.d.ts +733 -58
- package/dist/engine-javascript-C1x7zo1_.js +141 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +8255 -5703
- package/dist/kai.es.js +1 -0
- package/dist/llms/llms-full.txt +1146 -64
- package/dist/llms/llms.txt +4 -4
- package/dist/mcp.es.js +62 -7
- 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/toast-store.d.ts +32 -2
- package/dist/primitives/use-speech-recognition.d.ts +26 -0
- package/dist/react/index.d.ts +1085 -97
- package/dist/react/runtime.d.ts +9 -2
- package/dist/react/use-kai-chat.d.ts +41 -0
- package/dist/react.js +572 -193
- package/dist/register-impl-cKscku5m.js +141 -0
- package/dist/schemas/tasks.schema.json +2 -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 +77 -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 +19 -1
- package/frameworks/react/index.tsx +1042 -157
- package/frameworks/react/runtime.tsx +30 -1
- package/frameworks/react/use-kai-chat.tsx +87 -0
- package/llms-full.txt +1146 -64
- package/llms.txt +4 -4
- package/package.json +31 -10
- package/src/agent-tooling/mcp/manifest.ts +14 -0
- package/src/agent-tooling/mcp/tools/debug.ts +11 -7
- package/src/agent-tooling/mcp/tools/reference.ts +32 -0
- package/src/agent-tooling/mcp/tools/scaffold.ts +30 -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 +225 -116
- package/src/components/choice-card.tsx +103 -11
- package/src/components/coachmark.tsx +249 -0
- package/src/components/component-meta.json +699 -110
- 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 +54 -1
- package/src/components/conversation-item.tsx +69 -7
- package/src/components/conversation-list.tsx +134 -37
- package/src/components/file-tree.tsx +197 -47
- package/src/components/form-widgets.tsx +9 -7
- package/src/components/form.tsx +140 -17
- 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 +23 -4
- 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.tsx +31 -2
- package/src/components/screen.tsx +176 -0
- package/src/components/tasks-card.tsx +341 -21
- package/src/components/toast.tsx +119 -31
- package/src/components/tool-types.ts +10 -0
- package/src/components/tool.tsx +22 -16
- 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/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 +2 -2
- package/src/elements/chat-workspace.tsx +153 -41
- package/src/elements/chat.tsx +45 -23
- 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 +24 -2
- package/src/elements/compiled.css +2 -2
- 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 +87 -7
- 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 +129 -1
- package/src/elements/element-meta.json +5562 -1336
- package/src/elements/element-types.d.ts +732 -57
- 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 +58 -11
- 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 +38 -3
- package/src/elements/register.ts +11 -3
- 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/switch.tsx +89 -14
- package/src/elements/tabs.tsx +95 -0
- package/src/elements/tasks.tsx +70 -14
- package/src/elements/toast.tsx +17 -2
- 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 +5 -2
- package/src/primitives/card-schemas/tasks.schema.json +2 -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/toast-store.ts +43 -2
- 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 +218 -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 +117 -0
- package/src/ui/pane-group.tsx +291 -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 +52 -8
- package/theme.css +113 -0
- package/dist/components/slash-command.d.ts +0 -15
- package/dist/elements/chunks/Icon-D_Zmwmwh.js +0 -1
- package/dist/elements/chunks/action-icons-PVfIvcuG.js +0 -1
- package/dist/elements/chunks/attachments-Dp6vqtrc.js +0 -1
- package/dist/elements/chunks/button-CKyYD9G4.js +0 -1
- package/dist/elements/chunks/card-Cjho-PYk.js +0 -1
- package/dist/elements/chunks/chat-thread-RT808iPf.js +0 -1
- package/dist/elements/chunks/check-CDYaMYrM.js +0 -1
- package/dist/elements/chunks/chevron-down-3SBiq8HF.js +0 -1
- package/dist/elements/chunks/chevron-right-k2UFlIVK.js +0 -1
- package/dist/elements/chunks/cn-Dogu6PbV.js +0 -1
- package/dist/elements/chunks/code-block-BYUmfFSd.js +0 -1
- package/dist/elements/chunks/collapsible-BiNwdOn6.js +0 -1
- package/dist/elements/chunks/context-18g6oi4J.js +0 -1
- package/dist/elements/chunks/conversation-list-D9Y0NVdo.js +0 -1
- package/dist/elements/chunks/default-input-CSAoYYMd.js +0 -1
- package/dist/elements/chunks/download-D8K0Je8r.js +0 -1
- package/dist/elements/chunks/dropdown-bUs2iTia.js +0 -1
- package/dist/elements/chunks/external-link-6mA0wxab.js +0 -1
- package/dist/elements/chunks/file-text-DnaYk3Dm.js +0 -1
- package/dist/elements/chunks/file-tree-CgtRLlxK.js +0 -1
- package/dist/elements/chunks/hover-card-CIGw62gP.js +0 -1
- package/dist/elements/chunks/link-BlGSeoPy.js +0 -1
- package/dist/elements/chunks/loader-DvhR4qa0.js +0 -1
- package/dist/elements/chunks/message-CDZwXjhL.js +0 -1
- package/dist/elements/chunks/message-feedback-CYx81QiA.js +0 -1
- package/dist/elements/chunks/model-switcher-O_tUhoOT.js +0 -1
- package/dist/elements/chunks/overlay-DydXYMQW.js +0 -1
- package/dist/elements/chunks/prompt-suggestion-ldlWV5kd.js +0 -1
- package/dist/elements/chunks/reasoning-2PUnHlmr.js +0 -1
- package/dist/elements/chunks/resizable-B5WNbSeb.js +0 -1
- package/dist/elements/chunks/star-t9tI-P0q.js +0 -1
- package/dist/elements/chunks/store-C6rIooZz.js +0 -1
- package/dist/elements/chunks/text-shimmer-uh9V_KUh.js +0 -1
- package/dist/elements/chunks/textarea-3nm6Ia9U.js +0 -1
- package/dist/elements/chunks/thumbs-up-BBtguGld.js +0 -1
- package/dist/elements/chunks/toast-store-D8cL3fWl.js +0 -1
- package/dist/elements/chunks/tool-GJ3vwp1U.js +0 -1
- package/dist/elements/chunks/tooltip-DwKAz4XR.js +0 -1
- package/dist/elements/chunks/triangle-alert-Ct1zt2JL.js +0 -1
- package/dist/elements/chunks/use-card-resolution-D-_0Alzy.js +0 -1
- package/dist/elements/chunks/video-mVYiM99-.js +0 -1
- package/dist/elements/chunks/x-CzxL27Ch.js +0 -1
- package/dist/kitn-chat.es.js +0 -1
- package/dist/register-JyTglR6m.js +0 -1
- package/dist/register-impl-C6wlSsts.js +0 -77
- package/src/components/slash-command.tsx +0 -232
- package/src/elements/framework-usage.json +0 -588
- /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
|
@@ -2,12 +2,14 @@ import { defineWebComponent } from './define';
|
|
|
2
2
|
import { FileTree, type FileTreeFile } from '../components/file-tree';
|
|
3
3
|
|
|
4
4
|
interface Props extends Record<string, unknown> {
|
|
5
|
-
/** The files to render. Set as a JS property (array of `{ path, url?, code?, language?, type? }`). */
|
|
5
|
+
/** The files to render. Set as a JS property (array of `{ path, url?, code?, language?, type?, additions?, deletions?, status? }`). */
|
|
6
6
|
files: FileTreeFile[];
|
|
7
7
|
/** Selected file path — highlighted in the tree. */
|
|
8
8
|
activeFile?: string;
|
|
9
9
|
/** Folder paths expanded initially. Omit to start with all folders open. */
|
|
10
10
|
defaultExpanded?: string[];
|
|
11
|
+
/** Show a changed-files summary header (file count + summed `+/-` + Collapse-all). Attribute: `summary`. Off by default. */
|
|
12
|
+
summary?: boolean;
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
interface Events extends Record<string, unknown> {
|
|
@@ -19,12 +21,19 @@ interface Events extends Record<string, unknown> {
|
|
|
19
21
|
* `<kai-file-tree>` — a collapsible, keyboard-navigable file explorer built from a
|
|
20
22
|
* flat list of `/`-delimited paths (folders are derived). ARIA `tree`/`treeitem`.
|
|
21
23
|
* Selecting a file fires a `select` event (`detail.path`). Fills its container.
|
|
24
|
+
*
|
|
25
|
+
* For a changed-files / diff view, give each file `additions`/`deletions`/`status`
|
|
26
|
+
* (rendered as trailing `+N`/`-N` stats and a colored status letter), and set the
|
|
27
|
+
* `summary` attribute for a header with the changed-file count, summed `+/-`, and a
|
|
28
|
+
* Collapse-all toggle. Restyle the diff bits via `::part(summary | status |
|
|
29
|
+
* stat-additions | stat-deletions)`.
|
|
22
30
|
*/
|
|
23
31
|
defineWebComponent<Props, Events>('kai-file-tree', {
|
|
24
32
|
files: [],
|
|
25
33
|
activeFile: undefined,
|
|
26
34
|
defaultExpanded: undefined,
|
|
27
|
-
|
|
35
|
+
summary: false,
|
|
36
|
+
}, (props, { dispatch, flag }) => (
|
|
28
37
|
<>
|
|
29
38
|
{/* Fill the container + own the scroll (see resizable.tsx fill technique:
|
|
30
39
|
a definite `1fr` grid cell scoped to a wrapper, NOT :host, so the facade's
|
|
@@ -44,6 +53,7 @@ defineWebComponent<Props, Events>('kai-file-tree', {
|
|
|
44
53
|
files={props.files}
|
|
45
54
|
activeFile={props.activeFile}
|
|
46
55
|
defaultExpanded={props.defaultExpanded}
|
|
56
|
+
summary={flag('summary')}
|
|
47
57
|
onSelect={(path) => dispatch('kai-select', { path })}
|
|
48
58
|
/>
|
|
49
59
|
</div>
|
|
@@ -36,7 +36,7 @@ defineWebComponent<Props, Events>('kai-file-upload', {
|
|
|
36
36
|
disabled={flag('disabled')}
|
|
37
37
|
onFilesAdded={(files) => dispatch('kai-files-added', { files })}
|
|
38
38
|
>
|
|
39
|
-
<FileUploadTrigger class="border-border bg-
|
|
39
|
+
<FileUploadTrigger class="border-border bg-surface hover:bg-muted/60 text-muted-foreground flex w-full cursor-pointer flex-col items-center justify-center gap-2 rounded-xl border border-dashed px-6 py-8 text-sm transition-colors">
|
|
40
40
|
<Upload class="size-5" />
|
|
41
41
|
<slot>{props.label}</slot>
|
|
42
42
|
</FileUploadTrigger>
|
package/src/elements/form.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineWebComponent } from './define';
|
|
2
|
-
import { Form, type FormDefinition } from '../components/form';
|
|
2
|
+
import { Form, type FormController, type FormDefinition } from '../components/form';
|
|
3
3
|
import type { CardResolution } from '../primitives/card-contract';
|
|
4
4
|
|
|
5
5
|
interface Props extends Record<string, unknown> {
|
|
@@ -15,6 +15,20 @@ interface Props extends Record<string, unknown> {
|
|
|
15
15
|
/** Set when the user resolved this card; renders the read-only view. Property:
|
|
16
16
|
* `el.resolution = { kind:'submit', data:{…} }`. */
|
|
17
17
|
resolution?: Record<string, unknown>;
|
|
18
|
+
/** Controlled field values (JS property). When set, it wins over local edits. */
|
|
19
|
+
values?: Record<string, unknown>;
|
|
20
|
+
/** Initial values overlaying the schema defaults (uncontrolled seed; JS property). */
|
|
21
|
+
defaultValues?: Record<string, unknown>;
|
|
22
|
+
/** Disable all fields + submit. Attribute: `disabled`. */
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Events fired by `<kai-form>`. (Resolution still flows up the bubbling `kai-card`
|
|
27
|
+
* contract event — `kai-values-change` is the live change signal, distinct from the
|
|
28
|
+
* terminal submit.) */
|
|
29
|
+
interface Events {
|
|
30
|
+
/** The form's values changed on input — current coerced values + validity. */
|
|
31
|
+
'kai-values-change': { values: Record<string, unknown>; valid: boolean };
|
|
18
32
|
}
|
|
19
33
|
|
|
20
34
|
/**
|
|
@@ -27,17 +41,46 @@ interface Props extends Record<string, unknown> {
|
|
|
27
41
|
* else the bubbling `kai-card` event (so a bare `<kai-form>` works without a host).
|
|
28
42
|
* Isolated in Shadow DOM; theme-aware via the shared kit tokens.
|
|
29
43
|
*/
|
|
30
|
-
defineWebComponent<Props>('kai-form', {
|
|
44
|
+
defineWebComponent<Props, Events>('kai-form', {
|
|
31
45
|
data: undefined,
|
|
32
46
|
cardId: undefined,
|
|
33
47
|
heading: undefined,
|
|
34
48
|
resolution: undefined,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
49
|
+
values: undefined,
|
|
50
|
+
defaultValues: undefined,
|
|
51
|
+
disabled: false,
|
|
52
|
+
}, (props, { element, dispatch, flag, expose }) => {
|
|
53
|
+
// Pattern C: the Form component owns the value store + validation and hands up a
|
|
54
|
+
// controller; the facade captures it and exposes delegating instance methods.
|
|
55
|
+
let controller: FormController | undefined;
|
|
56
|
+
expose({
|
|
57
|
+
/** Focus the first control, or the first INVALID control after a failed validation. */
|
|
58
|
+
focus: (options?: FocusOptions) => controller?.focus(options),
|
|
59
|
+
/** Validate + submit programmatically — focus the first invalid field on failure,
|
|
60
|
+
* else emit the `submit` CardEvent and resolve. Named `send`, not `submit`. */
|
|
61
|
+
send: () => controller?.send(),
|
|
62
|
+
/** Run client-side validation now and return `{ valid, errors? }` WITHOUT submitting. */
|
|
63
|
+
validate: () => controller?.validate() ?? { valid: false },
|
|
64
|
+
/** Re-seed the form from each field's `default` and clear errors. */
|
|
65
|
+
reset: () => controller?.reset(),
|
|
66
|
+
/** Trigger the dismiss path (emit `dismiss` + collapse to the re-openable stub). */
|
|
67
|
+
dismiss: () => controller?.dismiss(),
|
|
68
|
+
/** Re-open a dismissed card from its stub (emit `reopen`). */
|
|
69
|
+
reopen: () => controller?.reopen(),
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<Form
|
|
74
|
+
data={props.data as FormDefinition | undefined}
|
|
75
|
+
cardId={props.cardId ?? (element.id || 'kai-form')}
|
|
76
|
+
heading={props.heading}
|
|
77
|
+
resolution={props.resolution as CardResolution | undefined}
|
|
78
|
+
values={props.values as Record<string, unknown> | undefined}
|
|
79
|
+
defaultValues={props.defaultValues as Record<string, unknown> | undefined}
|
|
80
|
+
disabled={flag('disabled')}
|
|
81
|
+
onValuesChange={(payload) => dispatch('kai-values-change', payload)}
|
|
82
|
+
controllerRef={(c) => (controller = c)}
|
|
83
|
+
hostElement={element}
|
|
84
|
+
/>
|
|
85
|
+
);
|
|
86
|
+
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { type Placement } from '@floating-ui/dom';
|
|
2
|
+
import { HoverCardRoot, HoverCardTrigger, HoverCardContent, type HoverCardController } from '../ui/hover-card';
|
|
3
|
+
import { defineWebComponent } from './define';
|
|
4
|
+
import { wireDisclosure } from './disclosure';
|
|
5
|
+
|
|
6
|
+
interface Props extends Record<string, unknown> {
|
|
7
|
+
/** Delay (ms) before the card opens on hover. Defaults to 0 (focus opens it
|
|
8
|
+
* immediately too). */
|
|
9
|
+
openDelay?: number;
|
|
10
|
+
/** Delay (ms) before it closes after the pointer leaves. Defaults to 300. */
|
|
11
|
+
closeDelay?: number;
|
|
12
|
+
/** Preferred placement: `'top' | 'bottom' | 'left' | 'right'` (+ optional
|
|
13
|
+
* `-start`/`-end`). Defaults to `'bottom'`; flips to stay in view. */
|
|
14
|
+
placement?: string;
|
|
15
|
+
/** Drive/observe open state (Shoelace-style: settable + reflected to the `open`
|
|
16
|
+
* attribute, the element still self-manages on hover). Set `el.open = true`,
|
|
17
|
+
* or `<kai-hover-card open>`; listen for `kai-open-change`. */
|
|
18
|
+
open?: boolean;
|
|
19
|
+
/** Initial open state on mount (uncontrolled seed). */
|
|
20
|
+
defaultOpen?: boolean;
|
|
21
|
+
/** Suppress the hover behavior entirely without unmounting. */
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Events fired by `<kai-hover-card>`. */
|
|
26
|
+
interface Events {
|
|
27
|
+
/** The card opened or closed (by hover/focus, outside-click, or a method). */
|
|
28
|
+
'kai-open-change': { open: boolean };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* `<kai-hover-card>` — reveals RICH content on hover/focus of a trigger (the
|
|
33
|
+
* markup-carrying sibling of the text-only `<kai-tooltip>`). Put the trigger as
|
|
34
|
+
* default light-DOM content and the card body in `slot="card"`. The card is
|
|
35
|
+
* portaled + positioned inside the shadow root, with a transparent hover bridge
|
|
36
|
+
* so the pointer can travel into it.
|
|
37
|
+
*
|
|
38
|
+
* ```html
|
|
39
|
+
* <kai-hover-card>
|
|
40
|
+
* <a href="#">@acme</a>
|
|
41
|
+
* <div slot="card">
|
|
42
|
+
* <strong>Acme Corp</strong>
|
|
43
|
+
* <p>Workspace · 24 members</p>
|
|
44
|
+
* </div>
|
|
45
|
+
* </kai-hover-card>
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
defineWebComponent<Props, Events>('kai-hover-card', {
|
|
49
|
+
openDelay: undefined,
|
|
50
|
+
closeDelay: undefined,
|
|
51
|
+
placement: undefined,
|
|
52
|
+
open: undefined,
|
|
53
|
+
defaultOpen: undefined,
|
|
54
|
+
disabled: undefined,
|
|
55
|
+
}, (props, ctx) => {
|
|
56
|
+
const { flag } = ctx;
|
|
57
|
+
let api: HoverCardController | undefined;
|
|
58
|
+
|
|
59
|
+
// The standard overlay surface: settable+reflecting `open`, kai-open-change,
|
|
60
|
+
// show/hide/toggle, disabled-gating. See ./disclosure.
|
|
61
|
+
wireDisclosure(ctx, () => api, () => props.open);
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<>
|
|
65
|
+
<style>{':host{display:inline-block}'}</style>
|
|
66
|
+
<HoverCardRoot
|
|
67
|
+
openDelay={props.openDelay != null ? Number(props.openDelay) : undefined}
|
|
68
|
+
closeDelay={props.closeDelay != null ? Number(props.closeDelay) : undefined}
|
|
69
|
+
defaultOpen={flag('defaultOpen')}
|
|
70
|
+
disabled={flag('disabled')}
|
|
71
|
+
controllerRef={(a) => (api = a)}
|
|
72
|
+
>
|
|
73
|
+
<HoverCardTrigger><slot /></HoverCardTrigger>
|
|
74
|
+
<HoverCardContent placement={(props.placement as Placement | undefined) ?? undefined}>
|
|
75
|
+
<slot name="card" />
|
|
76
|
+
</HoverCardContent>
|
|
77
|
+
</HoverCardRoot>
|
|
78
|
+
</>
|
|
79
|
+
);
|
|
80
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
[
|
|
2
|
+
"archive",
|
|
3
|
+
"arrow-left",
|
|
4
|
+
"arrow-up",
|
|
5
|
+
"audio-lines",
|
|
6
|
+
"book-open",
|
|
7
|
+
"bookmark",
|
|
8
|
+
"box",
|
|
9
|
+
"briefcase",
|
|
10
|
+
"chevron-down",
|
|
11
|
+
"chevron-left",
|
|
12
|
+
"circle",
|
|
13
|
+
"clock",
|
|
14
|
+
"code",
|
|
15
|
+
"copy",
|
|
16
|
+
"ellipsis",
|
|
17
|
+
"external-link",
|
|
18
|
+
"file-text",
|
|
19
|
+
"flag",
|
|
20
|
+
"folder",
|
|
21
|
+
"git-branch",
|
|
22
|
+
"git-pull-request",
|
|
23
|
+
"github",
|
|
24
|
+
"globe",
|
|
25
|
+
"home",
|
|
26
|
+
"image",
|
|
27
|
+
"list-filter",
|
|
28
|
+
"lock",
|
|
29
|
+
"message-circle",
|
|
30
|
+
"message-square",
|
|
31
|
+
"mic",
|
|
32
|
+
"monitor",
|
|
33
|
+
"more-horizontal",
|
|
34
|
+
"panel-left",
|
|
35
|
+
"paperclip",
|
|
36
|
+
"pencil",
|
|
37
|
+
"plus",
|
|
38
|
+
"rotate-cw",
|
|
39
|
+
"search",
|
|
40
|
+
"settings",
|
|
41
|
+
"share",
|
|
42
|
+
"sliders-horizontal",
|
|
43
|
+
"smile",
|
|
44
|
+
"sparkles",
|
|
45
|
+
"square-pen",
|
|
46
|
+
"workflow",
|
|
47
|
+
"x"
|
|
48
|
+
]
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { renderIcon } from '../ui/icon';
|
|
2
|
+
import { cn } from '../utils/cn';
|
|
3
|
+
import { defineWebComponent } from './define';
|
|
4
|
+
|
|
5
|
+
const SIZE: Record<string, string> = { sm: 'size-3.5', md: 'size-4', lg: 'size-5' };
|
|
6
|
+
|
|
7
|
+
interface Props extends Record<string, unknown> {
|
|
8
|
+
/** A curated icon name (e.g. `"mic"`, `"globe"`), an image URL/data-URI, or
|
|
9
|
+
* plain text. */
|
|
10
|
+
name?: string;
|
|
11
|
+
/** Size token: `sm` | `md` (default) | `lg`. */
|
|
12
|
+
size?: 'sm' | 'md' | 'lg';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* `<kai-icon>` — render one of the kit's curated icons (inline SVG) in your own
|
|
17
|
+
* markup, so surrounding UI can match the kit without pulling in an icon library.
|
|
18
|
+
* `name` also accepts a URL/data-URI or text. Renders in the theme's foreground by
|
|
19
|
+
* default; recolor with `kai-icon::part(icon){ color: … }`.
|
|
20
|
+
*
|
|
21
|
+
* Scope: the kit's small, *curated* icon set — not a general icon library. For
|
|
22
|
+
* anything outside it, drop your own inline SVG into an element's `icon` slot.
|
|
23
|
+
*
|
|
24
|
+
* ```html
|
|
25
|
+
* <kai-icon name="globe"></kai-icon>
|
|
26
|
+
* <kai-icon name="sparkles" size="lg"></kai-icon>
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
defineWebComponent<Props>('kai-icon', {
|
|
30
|
+
name: '',
|
|
31
|
+
size: 'md',
|
|
32
|
+
}, (props) => (
|
|
33
|
+
<>
|
|
34
|
+
{/* Base sets `:host{display:block}`; an inline icon must flow with surrounding
|
|
35
|
+
text (and not force a line break), so inline-flex like kai-button. */}
|
|
36
|
+
<style>{':host{display:inline-flex}'}</style>
|
|
37
|
+
<span part="icon" class={cn('inline-flex shrink-0', SIZE[props.size ?? 'md'] ?? SIZE.md)}>
|
|
38
|
+
{renderIcon(props.name, { class: 'size-full', imgClass: 'size-full', spanClass: 'size-full' })}
|
|
39
|
+
</span>
|
|
40
|
+
</>
|
|
41
|
+
));
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { createEffect, createSignal, onCleanup, onMount, untrack } from 'solid-js';
|
|
2
|
+
import { defineWebComponent } from './define';
|
|
3
|
+
import { Input, type InputProps } from '../ui/input';
|
|
4
|
+
|
|
5
|
+
interface Props extends Record<string, unknown> {
|
|
6
|
+
/** Native input type: `text` (default) · `email` · `url` · `search` · `tel` ·
|
|
7
|
+
* `password` · `number`. Single-line only. */
|
|
8
|
+
type?: string;
|
|
9
|
+
/** Controlled value — settable and reflected to the `value` attribute. `el.value
|
|
10
|
+
* = 'hi'` drives it (no event); typing updates it and fires `kai-input`. Read
|
|
11
|
+
* `el.value` for live state. */
|
|
12
|
+
value?: string;
|
|
13
|
+
/** Placeholder shown when empty. */
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
/** Field label, linked to the input. */
|
|
16
|
+
label?: string;
|
|
17
|
+
/** Helper text below the control. */
|
|
18
|
+
hint?: string;
|
|
19
|
+
/** Error text; flips the field invalid (`aria-invalid` + destructive border). */
|
|
20
|
+
error?: string;
|
|
21
|
+
/** Control density: `sm` or `md`. Defaults to `md`. */
|
|
22
|
+
size?: 'sm' | 'md';
|
|
23
|
+
/** Disable interaction. */
|
|
24
|
+
disabled?: boolean;
|
|
25
|
+
/** Make the input read-only. */
|
|
26
|
+
readonly?: boolean;
|
|
27
|
+
/** Mark the input required. */
|
|
28
|
+
required?: boolean;
|
|
29
|
+
/** Force the invalid state without an `error` string. */
|
|
30
|
+
invalid?: boolean;
|
|
31
|
+
/** Form-control name. */
|
|
32
|
+
name?: string;
|
|
33
|
+
/** Autofill hint forwarded to the inner input (e.g. `email`, `current-password`). */
|
|
34
|
+
autocomplete?: string;
|
|
35
|
+
/** Virtual-keyboard hint forwarded to the inner input (e.g. `numeric`, `email`). */
|
|
36
|
+
inputmode?: string;
|
|
37
|
+
// NOTE: `autocapitalize` is forwarded too, but NOT as a declared prop — see the
|
|
38
|
+
// attribute read in the facade body (it is a global reflected HTMLElement IDL
|
|
39
|
+
// attribute and would break the element constructor as a component-register prop).
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Events fired by `<kai-input>`. */
|
|
43
|
+
interface Events {
|
|
44
|
+
/** The value changed per keystroke. */
|
|
45
|
+
'kai-input': { value: string };
|
|
46
|
+
/** The value was committed (blur). */
|
|
47
|
+
'kai-change': { value: string };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Named slots whose occupancy gates an affix. An empty `<slot>` is always a
|
|
51
|
+
* truthy node, so the facade tracks which are actually filled and only hands a
|
|
52
|
+
* `<slot>` to the primitive when content is assigned — otherwise the primitive
|
|
53
|
+
* would switch to the affix-row layout for an empty slot. */
|
|
54
|
+
const SLOT_NAMES = ['leading', 'trailing'] as const;
|
|
55
|
+
type SlotName = (typeof SLOT_NAMES)[number];
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* `<kai-input>` — the kit's single-line text field. Drive/read the value with the
|
|
59
|
+
* `value` property (settable + reflected to the `value` attribute, so
|
|
60
|
+
* `:host([value])` and `el.value` see live state); listen for `kai-input` (per
|
|
61
|
+
* keystroke) and `kai-change` (commit/blur). A `label`, `hint`, and `error` wrap
|
|
62
|
+
* the control; `leading`/`trailing` slots take an icon, unit, or inline button.
|
|
63
|
+
*
|
|
64
|
+
* ```html
|
|
65
|
+
* <kai-input label="Workspace" placeholder="Acme Inc."></kai-input>
|
|
66
|
+
* <script type="module">
|
|
67
|
+
* import '@kitn.ai/ui/elements';
|
|
68
|
+
* const field = document.querySelector('kai-input');
|
|
69
|
+
* field.addEventListener('kai-input', (e) => console.log(e.detail.value));
|
|
70
|
+
* field.value = 'Acme'; // drive it (no event — the host already knows)
|
|
71
|
+
* field.focus(); // focus the inner input
|
|
72
|
+
* </script>
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* Methods: `focus()`, `select()`, `clear()`. Restyle via `::part(field)`,
|
|
76
|
+
* `::part(input)`, `::part(label)`, `::part(hint)`.
|
|
77
|
+
*/
|
|
78
|
+
defineWebComponent<Props, Events>('kai-input', {
|
|
79
|
+
type: 'text',
|
|
80
|
+
value: undefined,
|
|
81
|
+
placeholder: undefined,
|
|
82
|
+
label: undefined,
|
|
83
|
+
hint: undefined,
|
|
84
|
+
error: undefined,
|
|
85
|
+
size: 'md',
|
|
86
|
+
disabled: undefined,
|
|
87
|
+
readonly: undefined,
|
|
88
|
+
required: undefined,
|
|
89
|
+
invalid: undefined,
|
|
90
|
+
name: undefined,
|
|
91
|
+
autocomplete: undefined,
|
|
92
|
+
inputmode: undefined,
|
|
93
|
+
}, (props, ctx) => {
|
|
94
|
+
const { element, dispatch, flag, expose } = ctx;
|
|
95
|
+
|
|
96
|
+
// Lift the value into the facade and drive Input CONTROLLED so the host can read
|
|
97
|
+
// it (`el.value` / `:host([value])`) and set it after mount. Seed from the
|
|
98
|
+
// `value` property/attribute present on mount.
|
|
99
|
+
const [value, setValue] = createSignal(
|
|
100
|
+
(props.value as string | undefined) ?? element.getAttribute('value') ?? '',
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
// Coerce any value coming through the `value` setter (a JS assignment, or the
|
|
104
|
+
// write-back from `attributeChangedCallback`) to a string — falling back to the
|
|
105
|
+
// live attribute when nullish so the reflect write-back equals the signal and
|
|
106
|
+
// the equality guards absorb it (no attr⇄prop feedback loop; mirrors kai-segmented).
|
|
107
|
+
const coerce = (v: unknown): string =>
|
|
108
|
+
v == null ? (element.getAttribute('value') ?? '') : String(v);
|
|
109
|
+
|
|
110
|
+
// Set the value WITHOUT firing an event (programmatic / reflect write-back).
|
|
111
|
+
const setQuiet = (next: string) => { if (untrack(value) !== next) setValue(next); };
|
|
112
|
+
|
|
113
|
+
// Override `value` so reads return LIVE state and host writes (`el.value = …`)
|
|
114
|
+
// drive it WITHOUT firing events — distinct from the typing path.
|
|
115
|
+
Object.defineProperty(element, 'value', {
|
|
116
|
+
get: () => value(),
|
|
117
|
+
set: (v: unknown) => setQuiet(coerce(v)),
|
|
118
|
+
configurable: true,
|
|
119
|
+
enumerable: true,
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// Reflect internal value → the `[value]` host attribute (for `:host([value])`).
|
|
123
|
+
// The guard against the live attribute keeps the write-back the reflect triggers
|
|
124
|
+
// (attributeChangedCallback → setter) from looping.
|
|
125
|
+
createEffect(() => {
|
|
126
|
+
const v = value();
|
|
127
|
+
if (v) {
|
|
128
|
+
if (element.getAttribute('value') !== v) element.setAttribute('value', v);
|
|
129
|
+
} else if (element.hasAttribute('value')) {
|
|
130
|
+
element.removeAttribute('value');
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// `autocapitalize` is forwarded by reading the host attribute rather than as a
|
|
135
|
+
// declared prop: it is a global reflected HTMLElement IDL attribute (lowercase,
|
|
136
|
+
// like the reserved `lang`/`title`), so component-register's constructor
|
|
137
|
+
// `this.autocapitalize = undefined` would reflect an attribute and throw
|
|
138
|
+
// "must not have attributes". Seeded now; kept in sync by the observer in onMount.
|
|
139
|
+
const [autocapitalize, setAutocapitalize] = createSignal<string | undefined>(
|
|
140
|
+
element.getAttribute('autocapitalize') ?? undefined,
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
// Track which affix slots are filled; re-read on child mutations so late/streamed
|
|
144
|
+
// content lights up its affix. An empty slot is never passed to the primitive.
|
|
145
|
+
const [filled, setFilled] = createSignal<Record<SlotName, boolean>>({ leading: false, trailing: false });
|
|
146
|
+
onMount(() => {
|
|
147
|
+
const read = () => {
|
|
148
|
+
const next = {} as Record<SlotName, boolean>;
|
|
149
|
+
for (const name of SLOT_NAMES) next[name] = !!element.querySelector(`:scope > [slot="${name}"]`);
|
|
150
|
+
setFilled(next);
|
|
151
|
+
};
|
|
152
|
+
read();
|
|
153
|
+
const observer = new MutationObserver(read);
|
|
154
|
+
observer.observe(element, { childList: true, subtree: false });
|
|
155
|
+
onCleanup(() => observer.disconnect());
|
|
156
|
+
|
|
157
|
+
// Keep the forwarded `autocapitalize` in sync with the host attribute.
|
|
158
|
+
const syncAutocapitalize = () => setAutocapitalize(element.getAttribute('autocapitalize') ?? undefined);
|
|
159
|
+
syncAutocapitalize();
|
|
160
|
+
const attrObserver = new MutationObserver(syncAutocapitalize);
|
|
161
|
+
attrObserver.observe(element, { attributes: true, attributeFilter: ['autocapitalize'] });
|
|
162
|
+
onCleanup(() => attrObserver.disconnect());
|
|
163
|
+
});
|
|
164
|
+
const region = (name: SlotName) => (filled()[name] ? <slot name={name} /> : undefined);
|
|
165
|
+
|
|
166
|
+
const innerInput = () => element.shadowRoot?.querySelector<HTMLInputElement>('input') ?? null;
|
|
167
|
+
|
|
168
|
+
expose({
|
|
169
|
+
/** Focus the inner input (the host can't reach into the shadow root). */
|
|
170
|
+
focus: (options?: FocusOptions) => innerInput()?.focus(options),
|
|
171
|
+
/** Select the inner input's text. */
|
|
172
|
+
select: () => innerInput()?.select(),
|
|
173
|
+
/** Empty the value and fire `kai-change` with `''`. */
|
|
174
|
+
clear: () => { setValue(''); dispatch('kai-change', { value: '' }); },
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
return (
|
|
178
|
+
<>
|
|
179
|
+
<style>{':host{display:block}'}</style>
|
|
180
|
+
<Input
|
|
181
|
+
type={(props.type as string) ?? 'text'}
|
|
182
|
+
value={value()}
|
|
183
|
+
placeholder={props.placeholder as string | undefined}
|
|
184
|
+
label={props.label as string | undefined}
|
|
185
|
+
hint={props.hint as string | undefined}
|
|
186
|
+
error={props.error as string | undefined}
|
|
187
|
+
size={(props.size as 'sm' | 'md' | undefined) ?? 'md'}
|
|
188
|
+
invalid={flag('invalid')}
|
|
189
|
+
disabled={flag('disabled')}
|
|
190
|
+
readonly={flag('readonly')}
|
|
191
|
+
required={flag('required')}
|
|
192
|
+
name={props.name as string | undefined}
|
|
193
|
+
autocomplete={props.autocomplete as InputProps['autocomplete']}
|
|
194
|
+
inputmode={props.inputmode as InputProps['inputmode']}
|
|
195
|
+
autocapitalize={autocapitalize() as InputProps['autocapitalize']}
|
|
196
|
+
leading={region('leading')}
|
|
197
|
+
trailing={region('trailing')}
|
|
198
|
+
onValueInput={(v) => { setValue(v); dispatch('kai-input', { value: v }); }}
|
|
199
|
+
onValueChange={(v) => { setQuiet(v); dispatch('kai-change', { value: v }); }}
|
|
200
|
+
/>
|
|
201
|
+
</>
|
|
202
|
+
);
|
|
203
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { defineWebComponent } from './define';
|
|
2
|
+
import { Kbd, type KbdPlatform } from '../ui/kbd';
|
|
3
|
+
|
|
4
|
+
interface Props extends Record<string, unknown> {
|
|
5
|
+
/** Shortcut spec — tokens joined by `+` (e.g. `Mod+Shift+K`). Omit it to show
|
|
6
|
+
* default-slot content instead. Display only; the element does not bind keys. */
|
|
7
|
+
keys?: string;
|
|
8
|
+
/** `mac` uses ⌘/⌥, `other` uses Ctrl. `auto` (default) sniffs the OS. */
|
|
9
|
+
platform?: KbdPlatform;
|
|
10
|
+
/** Cap size: `sm` or `md`. Defaults to `md`. */
|
|
11
|
+
size?: 'sm' | 'md';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* `<kai-kbd>` — a keyboard-shortcut display. Feed it `keys` (tokens joined by
|
|
16
|
+
* `+`) and it renders one inset cap per token, mapping each to a platform glyph
|
|
17
|
+
* (`Mod` → ⌘ on mac else Ctrl, `Shift` → ⇧, `ArrowUp` → ↑, `Enter` → ⏎, …).
|
|
18
|
+
* Display only — it does not bind keys.
|
|
19
|
+
*
|
|
20
|
+
* ```html
|
|
21
|
+
* <kai-kbd keys="Mod+K"></kai-kbd>
|
|
22
|
+
* <kai-kbd keys="Mod+Shift+ArrowUp" platform="mac"></kai-kbd>
|
|
23
|
+
* <kai-kbd>Esc</kai-kbd> <!-- omit keys to show your own content -->
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* `platform="auto"` (default) sniffs the OS for ⌘ vs Ctrl. Restyle the caps via
|
|
27
|
+
* `::part(key)` and the gaps via `::part(separator)`.
|
|
28
|
+
*/
|
|
29
|
+
defineWebComponent<Props>('kai-kbd', {
|
|
30
|
+
keys: undefined,
|
|
31
|
+
platform: 'auto',
|
|
32
|
+
size: 'md',
|
|
33
|
+
}, (props) => (
|
|
34
|
+
<>
|
|
35
|
+
{/* Base sets `:host{display:block}`; a shortcut hint flows inline like a chip. */}
|
|
36
|
+
<style>{':host{display:inline-flex}'}</style>
|
|
37
|
+
<Kbd
|
|
38
|
+
keys={props.keys as string | undefined}
|
|
39
|
+
platform={(props.platform as KbdPlatform) ?? 'auto'}
|
|
40
|
+
size={(props.size as 'sm' | 'md') ?? 'md'}
|
|
41
|
+
>
|
|
42
|
+
<slot />
|
|
43
|
+
</Kbd>
|
|
44
|
+
</>
|
|
45
|
+
));
|