@kitn.ai/ui 0.26.0 → 0.28.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 +25 -6
- package/bin/mcp.js +16 -3
- package/bin/route.js +23 -0
- package/bin/route.test.js +58 -0
- package/dist/{elements/chunks/Icon--Y8vsFal.js → Icon-DObhsRtm.js} +1 -1
- package/dist/action-icons-CcgNN2oT.js +1 -0
- package/dist/arrow-down-CjRU3JgV.js +1 -0
- package/dist/arrow-left-Bnpb1UEW.js +1 -0
- package/dist/artifact-Bwt7OgcR.js +1 -0
- package/dist/assets/dev-5XzXYR21.js +91 -0
- package/dist/attachments-Qr4kg-2b.js +1 -0
- package/dist/{elements/chunks/audio-visualizer-D7lB6mvR.js → audio-visualizer-DToYdfSc.js} +1 -1
- package/dist/badge-CdEu_jn2.js +1 -0
- package/dist/bash-InADTalH.js +1 -6
- package/dist/bell-DQAAOpDz.js +1 -0
- package/dist/{elements/chunks/button-flUbeufF.js → button-DkuOnGLy.js} +1 -1
- package/dist/card-renderer-Jx70m6_l.js +1 -0
- package/dist/card-routing-0YidER_3.js +1 -0
- package/dist/check-njkVdZu2.js +1 -0
- package/dist/checkbox-D7iRB3nL.js +1 -0
- package/dist/checkbox-group-B2_rpoPM.js +1 -0
- package/dist/chevron-down-B72s6PXR.js +1 -0
- package/dist/chevron-right-BatuHzUm.js +1 -0
- package/dist/choice-card-m0BYqqOK.js +1 -0
- package/dist/circle-check-B62pODB3.js +1 -0
- package/dist/circle-x-BPG0iPst.js +1 -0
- package/dist/circle-zx0ByzY9.js +1 -0
- package/dist/{elements/chunks/cn-CU7UAWzk.js → cn-DN5AWfiS.js} +1 -1
- package/dist/code-block-ClMLKb7C.js +1 -0
- package/dist/{elements/chunks/collapsible-BzbXpPzr.js → collapsible-B4DlWicL.js} +1 -1
- package/dist/components/attachment-types.d.ts +7 -0
- package/dist/components/audio-visualizer/fit-scale.d.ts +1 -1
- package/dist/components/card-renderer.d.ts +13 -0
- package/dist/components/card.d.ts +4 -0
- package/dist/components/chat-thread.d.ts +135 -2
- package/dist/components/conversation-item.d.ts +35 -7
- package/dist/components/conversation-list.d.ts +17 -5
- package/dist/components/conversation-panel.d.ts +29 -0
- package/dist/components/form-widgets.d.ts +67 -2
- package/dist/components/form.d.ts +48 -1
- package/dist/components/home-panel.d.ts +34 -0
- package/dist/components/message.d.ts +25 -3
- package/dist/components/reasoning.d.ts +6 -0
- package/dist/components/scroll-button.d.ts +11 -0
- package/dist/components/thread.d.ts +5 -0
- package/dist/components/tool-types.d.ts +9 -0
- package/dist/components/widget-tab-bar.d.ts +16 -0
- package/dist/composer-sQ0HcvyG.js +106 -0
- package/dist/confirm-card-rQWDQsnC.js +1 -0
- package/dist/construct-cli.es.js +1337 -0
- package/dist/{elements/chunks/context-VLIL3sJ-.js → context-0kg4ZX1J.js} +1 -1
- package/dist/controllable-CnGpMF6r.js +1 -0
- package/dist/conversation-item-BxwQLaFJ.js +1 -0
- package/dist/conversation-list-BCfGN1JU.js +1 -0
- package/dist/copy-n9u9rqpi.js +1 -0
- package/dist/core-AYMC6_lb.js +12 -5874
- package/dist/{create-tween-BFT6c-Y8.js → create-tween-C-q-JCM-.js} +1 -1
- package/dist/{create-tween-CJNlzoaO.js → create-tween-CRrJXxBd.js} +1 -1
- package/dist/{create-tween-CQED4T0g.js → create-tween-DZ3RRDHD.js} +1 -1
- package/dist/{elements/chunks/create-tween-c4Z8TDYz.js → create-tween-uPkArjIG.js} +2 -2
- package/dist/css-M7EaDHN_.js +1 -6
- package/dist/custom-elements.json +1433 -202
- package/dist/default-input-CaMrJkgH.js +1 -0
- package/dist/define-By-uL588.js +1 -0
- package/dist/define.d.ts +4 -0
- package/dist/define.js +510 -0
- package/dist/define.server.d.ts +5 -0
- package/dist/define.server.js +506 -0
- package/dist/{elements/chunks/disclosure-CcNbyLy0.js → disclosure-WUImBbDv.js} +1 -1
- package/dist/{elements/chunks/dropdown-BgWTthUx.js → dropdown-wZVeJOMd.js} +1 -1
- package/dist/elements/agent-card.js +1 -1
- package/dist/elements/artifact.js +1 -1
- package/dist/elements/attachments.js +1 -1
- package/dist/elements/audio-visualizer.js +1 -1
- package/dist/elements/autoloader.js +1 -1
- package/dist/elements/avatar.js +1 -1
- package/dist/elements/badge.js +1 -1
- package/dist/elements/button.js +1 -1
- 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-workspace.js +1 -1
- package/dist/elements/chat.js +1 -1
- package/dist/elements/checkbox-group.d.ts +1 -0
- package/dist/elements/checkbox-group.js +1 -0
- package/dist/elements/checkbox.d.ts +1 -0
- package/dist/elements/checkbox.js +1 -0
- package/dist/elements/checkpoint.js +1 -1
- package/dist/elements/choice.js +1 -1
- package/dist/elements/coachmark.js +1 -1
- package/dist/elements/code-block.js +1 -1
- package/dist/elements/command.js +1 -1
- package/dist/elements/compare.js +1 -1
- package/dist/elements/composer.js +1 -1
- package/dist/elements/confirm-card.js +1 -1
- package/dist/elements/context-meter.js +1 -1
- package/dist/elements/conversation-item.js +1 -1
- package/dist/elements/conversation-list.js +1 -1
- package/dist/elements/define-entry.d.ts +12 -0
- package/dist/elements/dialog.js +1 -1
- package/dist/elements/dock.js +102 -8
- package/dist/elements/dropdown.js +1 -1
- package/dist/elements/editable-label.js +1 -1
- package/dist/elements/element-data-types.d.ts +37 -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.js +1 -1
- package/dist/elements/icon.js +1 -1
- package/dist/elements/image.js +1 -1
- package/dist/elements/input.js +1 -1
- package/dist/elements/kbd.js +1 -1
- 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.js +1 -1
- 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.js +1 -1
- package/dist/elements/notice.js +1 -1
- package/dist/elements/pane-grid.d.ts +1 -0
- package/dist/elements/pane-grid.js +1 -0
- package/dist/elements/pane-group.js +1 -1
- package/dist/elements/pane.js +1 -1
- package/dist/elements/popover.js +1 -1
- package/dist/elements/progress-bar.js +1 -1
- package/dist/elements/prompt-dock.js +1 -1
- package/dist/elements/prompt-input.js +1 -1
- package/dist/elements/prompt-suggestions.js +1 -1
- package/dist/elements/radio-group.d.ts +1 -0
- package/dist/elements/radio-group.js +1 -0
- package/dist/elements/reasoning.js +1 -1
- package/dist/elements/remote.js +1 -1
- package/dist/elements/resizable.js +1 -1
- package/dist/elements/response-stream.js +2 -2
- package/dist/elements/screen.js +1 -1
- package/dist/elements/scroll-area.js +1 -1
- package/dist/elements/scroll-button.js +1 -1
- package/dist/elements/search.js +1 -1
- package/dist/elements/segmented.js +1 -1
- package/dist/elements/select.d.ts +1 -0
- package/dist/elements/select.js +1 -0
- package/dist/elements/separator.js +1 -1
- package/dist/elements/setting-item.js +1 -1
- package/dist/elements/settings-group.js +1 -1
- package/dist/elements/skeleton.js +1 -1
- package/dist/elements/slider.d.ts +1 -0
- package/dist/elements/slider.js +1 -0
- package/dist/elements/slots.d.ts +1 -1
- package/dist/elements/source.js +1 -1
- package/dist/elements/status.js +1 -1
- package/dist/elements/switch.js +1 -1
- package/dist/elements/tabs.js +1 -1
- 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/thread.js +1 -1
- package/dist/elements/toast.js +1 -1
- package/dist/elements/tool.js +1 -1
- package/dist/elements/tooltip.js +1 -1
- package/dist/elements/voice-input.js +1 -1
- package/dist/elements/voice-output.js +1 -1
- package/dist/elements.d.ts +380 -26
- package/dist/{elements/chunks/ellipsis-7gU33mL2.js → ellipsis-CbOpJnU3.js} +1 -1
- package/dist/embed-CrfjkbUG.js +1 -0
- package/dist/engine-javascript-vq0WuIJl.js +14 -2516
- package/dist/{elements/chunks/external-link-CSOEsNlx.js → external-link-ByXAwBBQ.js} +1 -1
- package/dist/file-text-DMib2qwt.js +1 -0
- package/dist/{elements/chunks/file-tree-zvB2i7P9.js → file-tree-CJqM2aP7.js} +1 -1
- package/dist/folder-_BAb929C.js +1 -0
- package/dist/form-DSZgZQZk.js +1 -0
- package/dist/github-dark-dimmed-DUshB20C.js +1 -4
- package/dist/github-light-JYsPkUQd.js +1 -4
- package/dist/hover-card-BQbul9eq.js +1 -0
- package/dist/html-CPZ3oZQ7.js +1 -10
- package/dist/icon-CdcfRhYI.js +1 -0
- package/dist/{elements/chunks/index-BCRhi84a.js → index-xu_pdcPi.js} +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +7474 -5857
- package/dist/index.server.js +5965 -4762
- package/dist/info-DsFjGuI_.js +1 -0
- package/dist/input-DKbmkMos.js +1 -0
- package/dist/javascript-C25yR2R2.js +1 -6
- package/dist/json-DxJze_jm.js +1 -6
- package/dist/kai.es.js +1 -1
- package/dist/kbd-PvdGhX4s.js +1 -0
- package/dist/{elements/chunks/link-preview-OQ9IEq0f.js → link-preview-DbM1866N.js} +1 -1
- package/dist/link-zF8PzWfF.js +1 -0
- package/dist/loader-BM4CEz4G.js +1 -0
- package/dist/{elements/chunks/markdown-DgBFaGAz.js → markdown-LMvmAyBk.js} +7 -7
- package/dist/mcp.es.js +1361 -81
- package/dist/message-BSsgvHvf.js +1 -0
- package/dist/message-BYZECyek.js +1 -0
- package/dist/message-circle-DruwObfX.js +1 -0
- package/dist/message-square-BG6q6mlm.js +1 -0
- package/dist/{elements/chunks/minimize-2-DPIUKTrT.js → minimize-2-BQRoBV1V.js} +1 -1
- package/dist/{elements/chunks/model-switcher-DsT8tFB0.js → model-switcher-CMpCOYcB.js} +1 -1
- package/dist/{elements/chunks/overlay-DuiwdXjm.js → overlay-Cb-MkyDa.js} +1 -1
- package/dist/panel-right-i8warFxT.js +1 -0
- package/dist/paperclip-ByY3UVO6.js +1 -0
- package/dist/play-BvKKq3fX.js +1 -0
- package/dist/primitives/card-data-types.d.ts +49 -0
- package/dist/primitives/card-routing.d.ts +1 -33
- package/dist/primitives/card-validate.d.ts +2 -2
- package/dist/primitives/chat-config.d.ts +29 -2
- package/dist/primitives/conversation-store.d.ts +54 -0
- package/dist/primitives/field-mask.d.ts +96 -0
- package/dist/primitives/field-semantics.d.ts +36 -0
- package/dist/primitives/input-mask.d.ts +46 -0
- package/dist/primitives/url-scheme-policy.d.ts +34 -0
- package/dist/primitives/use-resize-observer.d.ts +2 -2
- package/dist/progress-bar-jVAHvMUf.js +1 -0
- package/dist/prompt-suggestion-CD-qtNgC.js +1 -0
- package/dist/radio-BsoBMhkF.js +1 -0
- package/dist/react/index.d.ts +586 -19
- package/dist/react.js +223 -187
- package/dist/reasoning-4kBPtlTx.js +1 -0
- package/dist/register-impl-B1hLkrI8.js +424 -0
- package/dist/{elements/chunks/resizable-D181b4fM.js → resizable-uPmY9VY-.js} +1 -1
- package/dist/rotate-ccw-B2xn93py.js +1 -0
- package/dist/rotate-cw-CMVLoCyH.js +1 -0
- package/dist/schemas/form.schema.json +21 -1
- package/dist/schemas/tool-defs.d.ts +11 -1
- package/dist/schemas.js +81 -81
- package/dist/scroll-area-BqLUo8ZZ.js +1 -0
- package/dist/scroll-button-DslXiJyL.js +1 -0
- package/dist/select-2cLRtPGT.js +1 -0
- package/dist/{elements/chunks/separator-CeJHQqLW.js → separator-BWQtNJcM.js} +1 -1
- package/dist/{elements/chunks/settings-CqaHgJF9.js → settings-BBR63jLg.js} +1 -1
- package/dist/{elements/chunks/settings-group-CjqjLCOn.js → settings-group-B2ciy-Iw.js} +1 -1
- package/dist/{elements/chunks/skeleton-D8akBnKS.js → skeleton-CkHI-HgC.js} +1 -1
- package/dist/slider-DDR9U-i0.js +1 -0
- package/dist/{solid-BtdqNZI7.js → solid-BzCFdL25.js} +9771 -7594
- package/dist/{solid-CnavwBye.js → solid-DruVOXnf.js} +7893 -6183
- package/dist/solid.d.ts +16 -2
- package/dist/solid.js +256 -243
- package/dist/solid.server.js +256 -243
- package/dist/source-GEnFF528.js +1 -0
- package/dist/star-CilHq8GP.js +1 -0
- package/dist/state/index.d.ts +1 -1
- package/dist/state/mock.d.ts +32 -2
- package/dist/state.js +133 -108
- package/dist/store-Ciyk6eZG.js +1 -0
- package/dist/svelte--5p79yCD.js +1 -15
- package/dist/switch-KkeQIbuH.js +1 -0
- package/dist/tasks-card-BrN4bggJ.js +1 -0
- package/dist/text-shimmer-Dcj1MHuq.js +1 -0
- package/dist/textarea-Dpvbngbg.js +1 -0
- package/dist/theme.tokens.css +110 -13
- package/dist/{elements/chunks/thumbs-up-DX2Ijk3H.js → thumbs-up-CsT9Wzb9.js} +1 -1
- package/dist/toast-store-tgK6MuMv.js +1 -0
- package/dist/{elements/chunks/tool-DKQ2D1DP.js → tool-DzUjIBT8.js} +1 -1
- package/dist/{elements/chunks/tooltip-B0G99y8w.js → tooltip-Bkkg_4t0.js} +1 -1
- package/dist/trash-2-jBKxjGGQ.js +1 -0
- package/dist/{elements/chunks/triangle-alert-F9cyUEyy.js → triangle-alert-DlQ68ppf.js} +1 -1
- package/dist/tsx-B8rCNbgL.js +1 -6
- package/dist/types.d.ts +48 -3
- package/dist/typescript-RycA9KXf.js +1 -6
- package/dist/ui/checkbox-group.d.ts +83 -0
- package/dist/ui/checkbox.d.ts +40 -0
- package/dist/ui/dock.d.ts +51 -0
- package/dist/ui/icon.d.ts +3 -0
- package/dist/ui/input.d.ts +48 -2
- package/dist/ui/radio.d.ts +85 -0
- package/dist/ui/select.d.ts +71 -0
- package/dist/ui/slider.d.ts +65 -0
- package/dist/ui/switch.d.ts +9 -2
- package/dist/upload-TcAHXv9W.js +1 -0
- package/dist/url-scheme-policy-DR5DgvkM.js +1 -0
- package/dist/use-card-resolution-DaZqAdWf.js +1 -0
- package/dist/{elements/chunks/variant-aurora-qt6Zct8M.js → variant-aurora-BhLuYxJR.js} +1 -1
- package/dist/{variant-aurora-B8II3-I1.js → variant-aurora-CNmfHhcx.js} +2 -2
- package/dist/{variant-aurora-CMNWOSJR.js → variant-aurora-D6GsdTPA.js} +2 -2
- package/dist/{variant-aurora-CcuDMWwQ.js → variant-aurora-DbW_OWL2.js} +1 -1
- package/dist/{elements/chunks/variant-custom-tJp22_BQ.js → variant-custom-BRvaNHSi.js} +1 -1
- package/dist/{variant-custom-L16JLLZy.js → variant-custom-BvYHR62b.js} +1 -1
- package/dist/{variant-custom-BdvYC7af.js → variant-custom-DMTrEO5w.js} +2 -2
- package/dist/{variant-custom-C714mqKl.js → variant-custom-DV2x254s.js} +2 -2
- package/dist/{variant-wave-ecwykeyL.js → variant-wave-BNMGrDfj.js} +2 -2
- package/dist/{variant-wave-2S4La2Ka.js → variant-wave-BpDd8t3Z.js} +1 -1
- package/dist/{variant-wave-D7ruiA1W.js → variant-wave-CyBueXj9.js} +2 -2
- package/dist/{elements/chunks/variant-wave-CaQ5ti39.js → variant-wave-sp-qwsdI.js} +1 -1
- package/dist/vue-BmIZj4XD.js +1 -33
- package/dist/x-Z5UntkIJ.js +1 -0
- package/frameworks/react/index.tsx +210 -22
- package/llms-full.txt +1184 -22
- package/llms.txt +6 -3
- package/package.json +17 -4
- package/src/agent-tooling/README.md +192 -0
- package/src/agent-tooling/catalog/invariants.ts +3 -3
- package/src/agent-tooling/catalog/surfaces.ts +72 -0
- package/src/agent-tooling/construct/cli-entry.ts +8 -0
- package/src/agent-tooling/construct/cli.ts +147 -0
- package/src/agent-tooling/construct/codegen.ts +1635 -0
- package/src/agent-tooling/construct/construct.v1.schema.json +319 -0
- package/src/agent-tooling/construct/dev.ts +148 -0
- package/src/agent-tooling/construct/fixtures/demo-widget.construct.json +7 -0
- package/src/agent-tooling/construct/fixtures/ops-console.construct.json +44 -0
- package/src/agent-tooling/construct/fixtures/owner-widget.construct.json +32 -0
- package/src/agent-tooling/construct/schema.ts +452 -0
- package/src/agent-tooling/mcp/server.ts +2 -1
- package/src/agent-tooling/mcp/tools/construct.ts +130 -0
- package/src/agent-tooling/mcp/tools/debug.ts +126 -4
- package/src/agent-tooling/mcp/tools/reference.ts +104 -3
- package/src/agent-tooling/recipes/composed-thread.ts +714 -0
- package/src/agent-tooling/recipes/index.ts +22 -0
- package/src/agent-tooling/recipes/types.ts +32 -0
- package/src/agent-tooling/registry.ts +5 -0
- package/src/components/attachment-types.ts +7 -0
- package/src/components/audio-visualizer/fit-scale.ts +1 -1
- package/src/components/card-renderer.tsx +39 -8
- package/src/components/card.tsx +10 -2
- package/src/components/chat-scope-picker.tsx +2 -2
- package/src/components/chat-thread.tsx +602 -43
- package/src/components/choice-card.tsx +102 -37
- package/src/components/coachmark.tsx +1 -1
- package/src/components/code-block.tsx +2 -2
- package/src/components/composer.tsx +89 -15
- package/src/components/confirm-card.tsx +20 -4
- package/src/components/conversation-item.tsx +56 -9
- package/src/components/conversation-list.tsx +25 -10
- package/src/components/conversation-panel.tsx +118 -0
- package/src/components/empty.tsx +14 -3
- package/src/components/file-tree.tsx +5 -1
- package/src/components/form-widgets.tsx +257 -195
- package/src/components/form.tsx +297 -9
- package/src/components/home-panel.tsx +159 -0
- package/src/components/loader.tsx +12 -5
- package/src/components/message-skills.tsx +1 -1
- package/src/components/message.tsx +71 -11
- package/src/components/prompt-input.tsx +7 -1
- package/src/components/prompt-suggestion.tsx +4 -1
- package/src/components/reasoning.tsx +30 -3
- package/src/components/response-compare.tsx +2 -2
- package/src/components/scroll-button.tsx +56 -4
- package/src/components/source.tsx +6 -1
- package/src/components/tasks-card.tsx +58 -16
- package/src/components/thread.tsx +10 -1
- package/src/components/toast.tsx +1 -1
- package/src/components/tool-types.ts +9 -0
- package/src/components/widget-tab-bar.tsx +73 -0
- package/src/elements/attachments.tsx +3 -1
- package/src/elements/chat-workspace.tsx +1 -1
- package/src/elements/chat.tsx +115 -5
- package/src/elements/checkbox-group.tsx +164 -0
- package/src/elements/checkbox.tsx +134 -0
- package/src/elements/compiled.css +1 -1
- package/src/elements/composer.tsx +12 -1
- package/src/elements/conversation-item.tsx +62 -22
- package/src/elements/conversation-list.tsx +2 -2
- package/src/elements/define-entry.ts +12 -0
- package/src/elements/dock.tsx +11 -0
- package/src/elements/element-data-types.ts +40 -0
- package/src/elements/element-manifest.json +24 -0
- package/src/elements/element-meta.json +767 -34
- package/src/elements/element-nonscalar.json +17 -0
- package/src/elements/element-types.d.ts +380 -26
- package/src/elements/feedback-bar.tsx +5 -0
- package/src/elements/icon-names.json +29 -0
- package/src/elements/input.tsx +312 -23
- package/src/elements/message.tsx +2 -0
- package/src/elements/pane-grid.tsx +111 -0
- package/src/elements/prompt-input.tsx +8 -2
- package/src/elements/radio-group.tsx +129 -0
- package/src/elements/register-impl.ts +6 -0
- package/src/elements/scroll-button.tsx +54 -6
- package/src/elements/select.tsx +165 -0
- package/src/elements/slider.tsx +171 -0
- package/src/elements/slots.ts +1 -1
- package/src/elements/styles.css +89 -3
- package/src/elements/thread.tsx +2 -0
- package/src/elements/toast.tsx +14 -1
- package/src/index.ts +5 -2
- package/src/primitives/card-data-types.ts +49 -0
- package/src/primitives/card-host.tsx +4 -2
- package/src/primitives/card-routing.ts +7 -56
- package/src/primitives/card-schemas/form.schema.json +21 -1
- package/src/primitives/card-validate.ts +10 -2
- package/src/primitives/chat-config.tsx +33 -6
- package/src/primitives/conversation-store.ts +248 -0
- package/src/primitives/field-mask.ts +256 -0
- package/src/primitives/field-semantics.ts +115 -0
- package/src/primitives/input-mask.ts +853 -0
- package/src/primitives/toast-store.ts +66 -4
- package/src/primitives/url-scheme-policy.ts +70 -0
- package/src/primitives/use-resize-observer.ts +2 -2
- package/src/schemas/tool-defs.ts +12 -2
- package/src/solid.ts +20 -2
- package/src/state/index.ts +1 -1
- package/src/state/mock.ts +92 -6
- package/src/types.ts +45 -3
- package/src/ui/agent-card.tsx +2 -2
- package/src/ui/avatar.tsx +1 -1
- package/src/ui/checkbox-group.tsx +153 -0
- package/src/ui/checkbox.tsx +63 -0
- package/src/ui/dock.tsx +192 -7
- package/src/ui/icon.tsx +53 -0
- package/src/ui/input.tsx +249 -9
- package/src/ui/kbd.tsx +1 -1
- package/src/ui/nav.tsx +1 -1
- package/src/ui/pane-group.tsx +2 -2
- package/src/ui/radio.tsx +150 -0
- package/src/ui/select.tsx +168 -0
- package/src/ui/slider.tsx +178 -0
- package/src/ui/switch.tsx +49 -18
- package/src/utils/cn.ts +11 -5
- package/theme.css +112 -13
- package/dist/elements/chunks/action-icons-D9u3OzYW.js +0 -1
- package/dist/elements/chunks/arrow-left-CVh1TeN7.js +0 -1
- package/dist/elements/chunks/artifact-BkYcfIlZ.js +0 -1
- package/dist/elements/chunks/attachments-DwfNlubq.js +0 -1
- package/dist/elements/chunks/badge-Q0-Cmwzz.js +0 -1
- package/dist/elements/chunks/bash-InADTalH.js +0 -1
- package/dist/elements/chunks/card-renderer-3Dyl-FpN.js +0 -1
- package/dist/elements/chunks/card-routing-BK09BdmL.js +0 -1
- package/dist/elements/chunks/check-B5kBPKeo.js +0 -1
- package/dist/elements/chunks/chevron-down-DZ1GS39h.js +0 -1
- package/dist/elements/chunks/chevron-right-CvP7OUd2.js +0 -1
- package/dist/elements/chunks/choice-card-D4QUIOWZ.js +0 -1
- package/dist/elements/chunks/circle-CDf9g6MQ.js +0 -1
- package/dist/elements/chunks/circle-check-CA47Nqbz.js +0 -1
- package/dist/elements/chunks/circle-x-CJ_HVbC8.js +0 -1
- package/dist/elements/chunks/code-block-BdLiTitd.js +0 -1
- package/dist/elements/chunks/composer-Byve-n8K.js +0 -69
- package/dist/elements/chunks/confirm-card-B0flE3MN.js +0 -1
- package/dist/elements/chunks/controllable-DTwTIlwp.js +0 -1
- package/dist/elements/chunks/conversation-item-BDztezOG.js +0 -1
- package/dist/elements/chunks/copy-Nf-kqxXH.js +0 -1
- package/dist/elements/chunks/core-AYMC6_lb.js +0 -12
- package/dist/elements/chunks/css-M7EaDHN_.js +0 -1
- package/dist/elements/chunks/default-input-C2iLFq0b.js +0 -1
- package/dist/elements/chunks/define-wjHR1MkU.js +0 -1
- package/dist/elements/chunks/download-C4V7tBdb.js +0 -1
- package/dist/elements/chunks/embed-D3KewsIJ.js +0 -1
- package/dist/elements/chunks/engine-javascript-vq0WuIJl.js +0 -141
- package/dist/elements/chunks/file-text-D1G8khle.js +0 -1
- package/dist/elements/chunks/folder-WW2LGLid.js +0 -1
- package/dist/elements/chunks/form-CQirdC4W.js +0 -1
- package/dist/elements/chunks/github-dark-dimmed-DUshB20C.js +0 -1
- package/dist/elements/chunks/github-light-JYsPkUQd.js +0 -1
- package/dist/elements/chunks/hover-card-CJJkfHTK.js +0 -1
- package/dist/elements/chunks/html-CPZ3oZQ7.js +0 -1
- package/dist/elements/chunks/icon-Cfgmf4fa.js +0 -1
- package/dist/elements/chunks/info-DX3YMOt6.js +0 -1
- package/dist/elements/chunks/input-BtW9U6Sq.js +0 -1
- package/dist/elements/chunks/javascript-C25yR2R2.js +0 -1
- package/dist/elements/chunks/json-DxJze_jm.js +0 -1
- package/dist/elements/chunks/kbd-LGXwuT_V.js +0 -1
- package/dist/elements/chunks/link-2My69BqT.js +0 -1
- package/dist/elements/chunks/loader-iOxc_Tu-.js +0 -1
- package/dist/elements/chunks/message-VMZohrXx.js +0 -1
- package/dist/elements/chunks/message-circle-CpXMM-_n.js +0 -1
- package/dist/elements/chunks/message-square-DxcWtETQ.js +0 -1
- package/dist/elements/chunks/message-tZmV2A3p.js +0 -1
- package/dist/elements/chunks/paperclip-CRZVp4z_.js +0 -1
- package/dist/elements/chunks/progress-bar-DNy66e_E.js +0 -1
- package/dist/elements/chunks/prompt-suggestion-Bn64Nl7L.js +0 -1
- package/dist/elements/chunks/reasoning-Emn9N4-T.js +0 -1
- package/dist/elements/chunks/rotate-cw-CPWe37D9.js +0 -1
- package/dist/elements/chunks/scroll-area-ClZkZxIk.js +0 -1
- package/dist/elements/chunks/scroll-button-DPE-t3x_.js +0 -1
- package/dist/elements/chunks/share-CyfnNEqp.js +0 -1
- package/dist/elements/chunks/source-UWCvmVak.js +0 -1
- package/dist/elements/chunks/star-DoHFAikQ.js +0 -1
- package/dist/elements/chunks/store-Cjq0qwYN.js +0 -1
- package/dist/elements/chunks/svelte--5p79yCD.js +0 -1
- package/dist/elements/chunks/tasks-card-CmZ5xh6v.js +0 -1
- package/dist/elements/chunks/text-shimmer-DYn09zrz.js +0 -1
- package/dist/elements/chunks/textarea-skiGHURM.js +0 -1
- package/dist/elements/chunks/toast-store-CFnQpThX.js +0 -1
- package/dist/elements/chunks/tsx-B8rCNbgL.js +0 -1
- package/dist/elements/chunks/typescript-RycA9KXf.js +0 -1
- package/dist/elements/chunks/use-card-resolution-DoA2f_EU.js +0 -1
- package/dist/elements/chunks/vue-BmIZj4XD.js +0 -1
- package/dist/elements/chunks/x-B6UnOiLw.js +0 -1
- package/dist/llms/llms-full.txt +0 -2949
- package/dist/llms/llms.txt +0 -156
- package/dist/register-impl-DpE7icIb.js +0 -293
- package/dist/ui/stat.d.ts +0 -16
- package/src/ui/stat.tsx +0 -41
- /package/dist/{elements/chunks/card-tags-D8lZ-C_U.js → card-tags-D8lZ-C_U.js} +0 -0
- /package/dist/{elements/chunks/link-preview-DNILK391.js → link-preview-DNILK391.js} +0 -0
- /package/dist/{elements/chunks/slots-DaNjX0rc.js → slots-DaNjX0rc.js} +0 -0
|
@@ -19,7 +19,9 @@ import {
|
|
|
19
19
|
interface Props extends Record<string, unknown> {
|
|
20
20
|
/** The attachments to render. Omit (or pass an empty array) for the empty
|
|
21
21
|
* state, which shows `emptyText` if set and nothing otherwise. Set as a JS
|
|
22
|
-
* property (array).
|
|
22
|
+
* property (array). Each item's `url` must be a `data:` URI or an https
|
|
23
|
+
* URL, never `URL.createObjectURL`: a `blob:` URL previews here but the
|
|
24
|
+
* wire encoders (`toOpenAIMessages`/`toAnthropicMessages`) refuse it. */
|
|
23
25
|
items?: AttachmentData[];
|
|
24
26
|
/** Layout: `grid` = visual tiles, `inline` = icon + label chips, `list` = rows. */
|
|
25
27
|
variant?: AttachmentVariant;
|
|
@@ -75,7 +75,7 @@ interface Events {
|
|
|
75
75
|
* (480px). Read once at upgrade. Parts: `header` · `start` · `main` · `end` ·
|
|
76
76
|
* `footer` (the asides also match `::part(aside)`).
|
|
77
77
|
*
|
|
78
|
-
* **BREAKING (
|
|
78
|
+
* **BREAKING (0.24):** this element was a chat
|
|
79
79
|
* preset; it is now a layout shell, and everything chat-shaped is gone from its
|
|
80
80
|
* surface. Where each removed prop went:
|
|
81
81
|
*
|
package/src/elements/chat.tsx
CHANGED
|
@@ -10,12 +10,63 @@ import type { ChatMessage } from './chat-types';
|
|
|
10
10
|
import type { TriggerDef } from '../components/composer';
|
|
11
11
|
import type { ComposerDoc } from '../primitives/composer-model';
|
|
12
12
|
import type { ProseSize } from '../primitives/chat-config';
|
|
13
|
-
import type { ModelOption } from '../types';
|
|
13
|
+
import type { ModelOption, HomeConfig, HomeLinkEntry } from '../types';
|
|
14
|
+
import type { ConversationStore } from '../primitives/conversation-store';
|
|
14
15
|
|
|
15
16
|
type Props = Omit<ChatThreadProps,
|
|
16
17
|
'class' | 'onValueChange' | 'onSubmit' | 'onAttachmentsChange' | 'onSuggestionClick' | 'onModelChange'
|
|
17
|
-
| 'onMessageAction' | 'onWebSearch' | 'onVoice' | 'controllerRef' | 'cardTypes' | 'cardSchemas' | 'messages'
|
|
18
|
-
| 'accept' | 'onAttachmentsRejected'
|
|
18
|
+
| 'onMessageAction' | 'onWebSearch' | 'onVoice' | 'controllerRef' | 'cardTypes' | 'cardSchemas' | 'cardHostElement' | 'messages'
|
|
19
|
+
| 'accept' | 'onAttachmentsRejected'
|
|
20
|
+
// `conversations`/`store` are re-declared below (own doc comments, matching
|
|
21
|
+
// this element's own attribute/property conventions) rather than left to
|
|
22
|
+
// flow through `Omit`'s pass-through — same reason `messages` is excluded
|
|
23
|
+
// above. Left unexcluded, the intersection carries TWO declarations of the
|
|
24
|
+
// same property (the inherited `ChatThreadProps` one plus the re-declared
|
|
25
|
+
// one below) and `gen-element-api.mjs` concatenates both JSDoc comments into
|
|
26
|
+
// one duplicated, em-dash-laden description.
|
|
27
|
+
| 'conversations' | 'store'
|
|
28
|
+
// `home` is re-declared below for the same reason as `conversations`/`store`
|
|
29
|
+
// above (own element-facing doc comment rather than the ChatThread-level one
|
|
30
|
+
// flowing through `Omit`'s pass-through). `onHomeLink` is wired internally
|
|
31
|
+
// (JSX prop on `<ChatThread>` below) as a dispatched `kai-home-link` event,
|
|
32
|
+
// matching every other ChatThread callback on this element — same reasoning
|
|
33
|
+
// as `onConversationLoad` just below.
|
|
34
|
+
| 'home' | 'onHomeLink'
|
|
35
|
+
// `onConversationLoad` is wired internally (below, JSX prop on
|
|
36
|
+
// `<ChatThread>`) as a dispatched `kai-conversation-load` event — matching
|
|
37
|
+
// every other ChatThread callback on this element — rather than left as a
|
|
38
|
+
// settable JS property: a `JSX.Element`-shaped callback prop has no HTML-
|
|
39
|
+
// consumer analogue the way `store`/`messages` do, and the kai- contract's
|
|
40
|
+
// idiom for "this thread wants to tell you something" is already an event.
|
|
41
|
+
// Excluded from `Props` for the same reason `onValueChange`/`onSubmit`/etc
|
|
42
|
+
// are excluded above: it is not a property a consumer of `<kai-chat>` sets.
|
|
43
|
+
| 'onConversationLoad'
|
|
44
|
+
// `hostOpen`/`onUnreadChange` (unread indicators, 2026-08-26) are the SAME
|
|
45
|
+
// "types without forwarding" trap as `onConversationLoad` above, for the
|
|
46
|
+
// same reason: this facade does not read either off the host element and
|
|
47
|
+
// forward it onto `<ChatThread>` below. Both exist for a caller composing
|
|
48
|
+
// `ChatThread` directly as a Solid component with its OWN show/hide chrome
|
|
49
|
+
// to report through `hostOpen` and its own sibling control (a `Dock`'s
|
|
50
|
+
// `unread` badge) to mirror `onUnreadChange` onto — the construct engine's
|
|
51
|
+
// emitted App is the motivating case (codegen.ts's `emitChatThreadUnreadProps`),
|
|
52
|
+
// exactly like `headerEndContent`/`emptyContent` below. `<kai-chat>` has no
|
|
53
|
+
// such sibling chrome of its own to report to or read from, so there is
|
|
54
|
+
// nothing here for either prop to DO — left unexcluded, `gen-element-api.mjs`
|
|
55
|
+
// would still type them into the public API and docs as settable properties
|
|
56
|
+
// that silently do nothing when set.
|
|
57
|
+
| 'hostOpen' | 'onUnreadChange'
|
|
58
|
+
// `headerEndContent`/`emptyContent` are JSX.Element escape hatches for a caller
|
|
59
|
+
// composing `ChatThread` directly as a Solid component (see their doc comments in
|
|
60
|
+
// chat-thread.tsx — the construct-engine's emitted App is the motivating case).
|
|
61
|
+
// `<kai-chat>` is the OPPOSITE shape: a custom element crossing the shadow-DOM
|
|
62
|
+
// boundary, where a `JSX.Element` value cannot exist for a consumer to construct
|
|
63
|
+
// (React/Vue/plain HTML have no such type) and the facade already has its own
|
|
64
|
+
// working mechanism for both regions — `slot="header-end"` and `slot="empty"`.
|
|
65
|
+
// Omitted here rather than left to flow through `Omit`'s default pass-through:
|
|
66
|
+
// without this, `gen-element-api.mjs` picked them up and put a JSX.Element type
|
|
67
|
+
// (which it stringifies as Solid's internal array-like union — meaningless to a
|
|
68
|
+
// web-component consumer) into `<kai-chat>`'s public prop surface and docs.
|
|
69
|
+
| 'headerEndContent' | 'emptyContent'> & Record<string, unknown> & {
|
|
19
70
|
/** Which attachment media types the user may stage, in HTML `accept` syntax:
|
|
20
71
|
* `<kai-chat accept="image/*,application/pdf">`. A plain string, so unlike
|
|
21
72
|
* `messages` it DOES work as an attribute. Omitted means no filter.
|
|
@@ -63,6 +114,40 @@ type Props = Omit<ChatThreadProps,
|
|
|
63
114
|
* authored one carries `$schema`/`title`/`description`/`additionalProperties`,
|
|
64
115
|
* so the tighter type would reject both of the normal ways to supply one. */
|
|
65
116
|
cardSchemas?: Record<string, object>;
|
|
117
|
+
/** Turns on the prior-conversations list (a list-toggle button in the
|
|
118
|
+
* header, plus a second list view sharing the panel, C-1). Attribute-
|
|
119
|
+
* settable like every other boolean flag on this element:
|
|
120
|
+
* `<kai-chat conversations>`. Requires `store`. A row select, "new
|
|
121
|
+
* conversation," or the visitor's mount-time auto-restore all deliver
|
|
122
|
+
* their messages the same way: listen for `kai-conversation-load` and
|
|
123
|
+
* set `el.messages` from `event.detail.messages` (a fresh array): this
|
|
124
|
+
* element does not update `messages` for you. Set with no `store`, the
|
|
125
|
+
* underlying `ChatThread` decides loudly (one console.error) and stays
|
|
126
|
+
* visually off; this facade always supplies its own internal load
|
|
127
|
+
* handler (the `kai-conversation-load` dispatch below), so the second
|
|
128
|
+
* ChatThread guard, missing `onConversationLoad`, never trips here,
|
|
129
|
+
* even for a consumer who never listens for the event. Default false. */
|
|
130
|
+
conversations?: boolean;
|
|
131
|
+
/** The adapter this thread persists conversations through: an object of
|
|
132
|
+
* three functions (`list`/`load`/`save`; `ConversationStore`, exported
|
|
133
|
+
* from `@kitn.ai/ui`'s `primitives/conversation-store`). A JS PROPERTY
|
|
134
|
+
* ONLY: `el.store = myAdapter`. It can never be an attribute, since a
|
|
135
|
+
* function-bearing object has no HTML string form, the same reasoning
|
|
136
|
+
* that keeps `messages`/`cardSchemas` property-only (the kai- contract:
|
|
137
|
+
* array/object props are JS properties, never attributes). Two built-ins
|
|
138
|
+
* ship: `localStorageStore(name, userId?)` and `fetchStore(url, userId?)`. */
|
|
139
|
+
store?: ConversationStore;
|
|
140
|
+
/** Turns on the widget home screen (Intercom-pattern): the panel boots into
|
|
141
|
+
* a `home` view, with a greeting, most-recent-conversation card, a "new
|
|
142
|
+
* conversation" CTA, and host-defined links, plus a Home/Messages tab bar
|
|
143
|
+
* for switching back to the thread. An OBJECT, so it is a JS property only:
|
|
144
|
+
* `el.home = { greeting: { title: 'Hey' }, links: [...] }`, never an
|
|
145
|
+
* attribute (the kai- contract: array/object props are JS properties).
|
|
146
|
+
* A `links` entry with no `href` fires `kai-home-link` with that entry when
|
|
147
|
+
* tapped, rather than navigating; one WITH `href` opens it directly
|
|
148
|
+
* (only when the URL passes the kit's own scheme allowlist). Omit for the
|
|
149
|
+
* no-home widget (chat view only, unchanged). */
|
|
150
|
+
home?: HomeConfig;
|
|
66
151
|
};
|
|
67
152
|
|
|
68
153
|
interface Events {
|
|
@@ -90,6 +175,19 @@ interface Events {
|
|
|
90
175
|
'kai-web-search': Record<string, never>;
|
|
91
176
|
/** The Mic / voice button was clicked. */
|
|
92
177
|
'kai-voice': Record<string, never>;
|
|
178
|
+
/** A conversation's history loaded: a row tap in the list, "new
|
|
179
|
+
* conversation," or the visitor's own mount-time auto-restore of their
|
|
180
|
+
* most recent thread (only fires when `conversations` is on and a `store`
|
|
181
|
+
* is set). `detail.id` is that conversation's id, `undefined` for the
|
|
182
|
+
* "new conversation" case (no id exists until the first message mints
|
|
183
|
+
* one, C-6). Set `el.messages = event.detail.messages` (already a fresh
|
|
184
|
+
* array) to actually render it, since this element does not do that for
|
|
185
|
+
* you; `messages` stays your own state like everywhere else on this
|
|
186
|
+
* element. */
|
|
187
|
+
'kai-conversation-load': { id: string | undefined; messages: ChatMessage[] };
|
|
188
|
+
/** A `home.links` entry with no `href` was activated (tapped/clicked/Enter).
|
|
189
|
+
* Meaningful only when `home` is set. */
|
|
190
|
+
'kai-home-link': { entry: HomeLinkEntry };
|
|
93
191
|
}
|
|
94
192
|
|
|
95
193
|
defineWebComponent<Props, Events>('kai-chat', {
|
|
@@ -97,8 +195,10 @@ defineWebComponent<Props, Events>('kai-chat', {
|
|
|
97
195
|
suggestions: undefined, suggestionMode: 'submit', persistSuggestions: false, proseSize: 'sm',
|
|
98
196
|
codeTheme: 'github-dark-dimmed', codeHighlight: true, chatTitle: undefined,
|
|
99
197
|
models: undefined, currentModel: undefined, context: undefined, scrollButton: true,
|
|
100
|
-
webSearch: false, voice: false, triggers: undefined, kindIcons: undefined,
|
|
198
|
+
attach: true, webSearch: false, voice: false, triggers: undefined, kindIcons: undefined,
|
|
101
199
|
actionsReveal: 'always', cardTypes: undefined, cardSchemas: undefined, accept: undefined,
|
|
200
|
+
reasoning: undefined, reasoningOpen: undefined, conversations: false, store: undefined,
|
|
201
|
+
home: undefined,
|
|
102
202
|
}, (props, { dispatch, flag, reflectFlag, element, expose }) => {
|
|
103
203
|
// `messages` is an untyped boundary: a consumer can hand it anything at
|
|
104
204
|
// runtime (a pre-0.20.0 `{ id, role, content }` array, in particular). Skip
|
|
@@ -164,12 +264,22 @@ defineWebComponent<Props, Events>('kai-chat', {
|
|
|
164
264
|
codeTheme={props.codeTheme as string} codeHighlight={flag('codeHighlight')}
|
|
165
265
|
chatTitle={props.chatTitle as string | undefined} models={props.models as ModelOption[] | undefined}
|
|
166
266
|
currentModel={props.currentModel as string | undefined} context={props.context as ChatThreadContextUsage | undefined}
|
|
167
|
-
scrollButton={props.scrollButton !== false} webSearch={flag('webSearch')} voice={flag('voice')}
|
|
267
|
+
scrollButton={props.scrollButton !== false} attach={flag('attach')} webSearch={flag('webSearch')} voice={flag('voice')}
|
|
268
|
+
reasoning={props.reasoning as 'full' | 'compact' | 'off' | undefined}
|
|
269
|
+
reasoningOpen={flag('reasoningOpen')}
|
|
168
270
|
triggers={props.triggers as TriggerDef[] | undefined}
|
|
169
271
|
kindIcons={props.kindIcons as Record<string, string> | undefined}
|
|
170
272
|
actionsReveal={props.actionsReveal as 'always' | 'hover'}
|
|
171
273
|
cardTypes={cardComponentsFromTags(props.cardTypes as Record<string, string> | undefined, (props as { theme?: string }).theme)}
|
|
172
274
|
cardSchemas={props.cardSchemas as Record<string, object> | undefined}
|
|
275
|
+
conversations={flag('conversations')}
|
|
276
|
+
store={props.store as ConversationStore | undefined}
|
|
277
|
+
onConversationLoad={(messages, id) => dispatch('kai-conversation-load', { id, messages })}
|
|
278
|
+
home={props.home as HomeConfig | undefined}
|
|
279
|
+
onHomeLink={(entry) => dispatch('kai-home-link', { entry })}
|
|
280
|
+
/* F-26: card parts emit off THIS element as the bubbling `kai-card` event,
|
|
281
|
+
so `listenForCardEvents(el)` / addEventListener('kai-card') work. */
|
|
282
|
+
cardHostElement={element}
|
|
173
283
|
onValueChange={(value) => dispatch('kai-value-change', { value })}
|
|
174
284
|
onSubmit={(detail) => dispatch('kai-submit', detail)}
|
|
175
285
|
accept={props.accept as string | undefined}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { createEffect, createSignal, untrack } from 'solid-js';
|
|
2
|
+
import { defineWebComponent } from './define';
|
|
3
|
+
import { CheckboxGroup } from '../ui/checkbox-group';
|
|
4
|
+
// Public shape of the `options` prop; lives in ./element-data-types so the ROOT
|
|
5
|
+
// entry can re-export it (see that file's header).
|
|
6
|
+
import type { KaiCheckboxOption } from './element-data-types';
|
|
7
|
+
|
|
8
|
+
interface Props extends Record<string, unknown> {
|
|
9
|
+
/** The choices, top to bottom. Set as a JS PROPERTY (array), never an attribute.
|
|
10
|
+
* Rendered in full: the kit never truncates, re-orders or de-duplicates them. */
|
|
11
|
+
options: KaiCheckboxOption[];
|
|
12
|
+
/** The FIRST selected value. Settable and reflected to the `value` attribute, so
|
|
13
|
+
* `:host([value])` and `el.value` see live state, and a seed can be written in
|
|
14
|
+
* markup. Writing it makes that the whole selection; to read or drive the rest,
|
|
15
|
+
* use `el.values`. */
|
|
16
|
+
value?: string;
|
|
17
|
+
/**
|
|
18
|
+
* The shared form-control name every box carries, so `FormData.getAll(name)` reads
|
|
19
|
+
* the whole selection back under one key.
|
|
20
|
+
*
|
|
21
|
+
* NO DEFAULT, unlike `<kai-radio-group>`. A radio set needs a shared `name` for the
|
|
22
|
+
* browser to make it exclusive and arrow-navigable, so one is generated when none is
|
|
23
|
+
* given; checkboxes are independent controls and behave correctly with no name at
|
|
24
|
+
* all. Generating one here would submit the selection under a random key, which is
|
|
25
|
+
* worse than submitting nothing.
|
|
26
|
+
*
|
|
27
|
+
* The element is NOT form-associated (no `ElementInternals`, no `setFormValue()`),
|
|
28
|
+
* the same known gap `<kai-input>` records: the boxes live in a shadow root, so a
|
|
29
|
+
* surrounding `<form>` collects nothing from them whether or not `name` is set. Read
|
|
30
|
+
* `el.values`. The name still lands on every inner input, so it is right the day form
|
|
31
|
+
* association arrives.
|
|
32
|
+
*/
|
|
33
|
+
name?: string;
|
|
34
|
+
/** Disable every row. Individual rows carry their own `disabled`. */
|
|
35
|
+
disabled?: boolean;
|
|
36
|
+
/** Accessible name for the group. */
|
|
37
|
+
label?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Events fired by `<kai-checkbox-group>`. */
|
|
41
|
+
interface Events {
|
|
42
|
+
/** A row was ticked or unticked. `values` is the whole selection after the change,
|
|
43
|
+
* which is what a multi-select control needs; `value` is the first of them (empty
|
|
44
|
+
* when nothing is selected). Both are always present, so neither shape silently
|
|
45
|
+
* loses the other. This is `<kai-select>`'s detail, deliberately. */
|
|
46
|
+
'kai-change': { value: string; values: string[] };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* `<kai-checkbox-group>` — the kit's "pick any number" control, and
|
|
51
|
+
* `<kai-radio-group>`'s sibling: the same options shape and the same divided row
|
|
52
|
+
* chrome over real `<input type="checkbox">`es, multi-value instead of exclusive. A
|
|
53
|
+
* box per tab stop, Space to toggle and correct announcement are the browser's, not a
|
|
54
|
+
* reimplementation.
|
|
55
|
+
*
|
|
56
|
+
* Feed it `options` (a JS-property array of `{ value, label, description?, disabled? }`),
|
|
57
|
+
* drive and read the selection with the `values` property, and listen for `kai-change`.
|
|
58
|
+
* `value` is the first selected option and is reflected to the `value` attribute.
|
|
59
|
+
*
|
|
60
|
+
* Re-rendering follows the kit's reactivity contract: hand it a NEW array reference,
|
|
61
|
+
* and a new object for any option whose content changed — the rows are a
|
|
62
|
+
* reference-keyed list, so mutating an option in place changes nothing on screen.
|
|
63
|
+
*
|
|
64
|
+
* No validation and no limits: "at least one", "at most three" and anything else that
|
|
65
|
+
* lands in a policy document is the application's rule, not the kit's.
|
|
66
|
+
*
|
|
67
|
+
* ```html
|
|
68
|
+
* <kai-checkbox-group label="Environments" name="env"></kai-checkbox-group>
|
|
69
|
+
* <script type="module">
|
|
70
|
+
* import '@kitn.ai/ui/elements';
|
|
71
|
+
* const group = document.querySelector('kai-checkbox-group');
|
|
72
|
+
* // ARRAY prop — a JS property, never an attribute.
|
|
73
|
+
* group.options = [
|
|
74
|
+
* { value: 'prod', label: 'Production', description: 'Pages the on-call' },
|
|
75
|
+
* { value: 'staging', label: 'Staging' },
|
|
76
|
+
* { value: 'dev', label: 'Development' },
|
|
77
|
+
* ];
|
|
78
|
+
* group.addEventListener('kai-change', (e) => console.log(e.detail.values));
|
|
79
|
+
* group.values = ['prod', 'dev']; // drive it (no kai-change — the host already knows)
|
|
80
|
+
* </script>
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
defineWebComponent<Props, Events>('kai-checkbox-group', {
|
|
84
|
+
options: [],
|
|
85
|
+
value: undefined,
|
|
86
|
+
name: undefined,
|
|
87
|
+
disabled: undefined,
|
|
88
|
+
label: undefined,
|
|
89
|
+
}, (props, ctx) => {
|
|
90
|
+
const { element, dispatch, flag, expose } = ctx;
|
|
91
|
+
|
|
92
|
+
// Lift the selection into the facade and drive CheckboxGroup CONTROLLED so the host
|
|
93
|
+
// can read it (`el.values` / `:host([value])`) and set it after mount. Seed from the
|
|
94
|
+
// `value` property/attribute present on mount; nothing is auto-selected, because
|
|
95
|
+
// `options` normally arrives as a property AFTER upgrade (kai-select's structure).
|
|
96
|
+
const seed = (props.value as string | undefined) ?? element.getAttribute('value') ?? '';
|
|
97
|
+
const [values, setValues] = createSignal<string[]>(seed ? [seed] : []);
|
|
98
|
+
const first = () => values()[0] ?? '';
|
|
99
|
+
|
|
100
|
+
// Coerce anything arriving through the `value` setter (a JS assignment, or the
|
|
101
|
+
// attributeChangedCallback write-back the reflect effect below triggers) to a string,
|
|
102
|
+
// falling back to the live attribute when nullish so the write-back equals the signal
|
|
103
|
+
// and the guard absorbs it — no attr⇄prop feedback loop.
|
|
104
|
+
const coerce = (v: unknown): string =>
|
|
105
|
+
v == null ? (element.getAttribute('value') ?? '') : String(v);
|
|
106
|
+
|
|
107
|
+
// Apply a new selection and fire kai-change once (the user-toggle path).
|
|
108
|
+
const apply = (next: string[]) => {
|
|
109
|
+
const prev = untrack(values);
|
|
110
|
+
if (prev.length === next.length && prev.every((v, i) => v === next[i])) return;
|
|
111
|
+
setValues(next);
|
|
112
|
+
dispatch('kai-change', { value: next[0] ?? '', values: next });
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
Object.defineProperty(element, 'value', {
|
|
116
|
+
get: () => first(),
|
|
117
|
+
set: (v: unknown) => {
|
|
118
|
+
const next = coerce(v);
|
|
119
|
+
if (untrack(first) !== next) setValues(next ? [next] : []);
|
|
120
|
+
},
|
|
121
|
+
configurable: true,
|
|
122
|
+
enumerable: true,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// The multi-selection read/write side, spelled exactly as `<kai-select multiple>`
|
|
126
|
+
// spells it. `value` alone cannot represent a checkbox group's selection, and
|
|
127
|
+
// returning only the first ticked box would be a silent drop.
|
|
128
|
+
Object.defineProperty(element, 'values', {
|
|
129
|
+
get: () => values(),
|
|
130
|
+
set: (v: unknown) => setValues(Array.isArray(v) ? v.map(String) : []),
|
|
131
|
+
configurable: true,
|
|
132
|
+
enumerable: true,
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// Reflect the first value → the `[value]` host attribute (for `:host([value])`).
|
|
136
|
+
createEffect(() => {
|
|
137
|
+
const v = first();
|
|
138
|
+
if (v) {
|
|
139
|
+
if (element.getAttribute('value') !== v) element.setAttribute('value', v);
|
|
140
|
+
} else if (element.hasAttribute('value')) {
|
|
141
|
+
element.removeAttribute('value');
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
expose({
|
|
146
|
+
/** Focus the group's first box. Not "the first ticked one", which is
|
|
147
|
+
* `<kai-radio-group>`'s rule: a radio group is ONE tab stop that lands on the
|
|
148
|
+
* selection, while every checkbox here is its own tab stop, so the entry point is
|
|
149
|
+
* simply the top of the list. */
|
|
150
|
+
focus: (options?: FocusOptions) =>
|
|
151
|
+
element.shadowRoot?.querySelector<HTMLInputElement>('input[type="checkbox"]')?.focus(options),
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
return (
|
|
155
|
+
<CheckboxGroup
|
|
156
|
+
options={(props.options ?? []) as KaiCheckboxOption[]}
|
|
157
|
+
value={values()}
|
|
158
|
+
name={props.name as string | undefined}
|
|
159
|
+
disabled={flag('disabled')}
|
|
160
|
+
label={props.label as string | undefined}
|
|
161
|
+
onChange={(next) => apply(next)}
|
|
162
|
+
/>
|
|
163
|
+
);
|
|
164
|
+
});
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { createEffect, createSignal, untrack } from 'solid-js';
|
|
2
|
+
import { defineWebComponent } from './define';
|
|
3
|
+
import { Checkbox } from '../ui/checkbox';
|
|
4
|
+
|
|
5
|
+
interface Props extends Record<string, unknown> {
|
|
6
|
+
/** Controlled checked state. Settable and reflected to the `checked` attribute.
|
|
7
|
+
* `el.checked = true` (or `<kai-checkbox checked>`) drives it; ticking the box
|
|
8
|
+
* updates it and fires `kai-change`. Read `el.checked` for live state. */
|
|
9
|
+
checked?: boolean;
|
|
10
|
+
/** Initial checked state on mount (uncontrolled seed). Bare attribute
|
|
11
|
+
* (`<kai-checkbox default-checked>`) turns it on. */
|
|
12
|
+
defaultChecked?: boolean;
|
|
13
|
+
/** The mixed state, for a parent box whose children are partly ticked. Visual
|
|
14
|
+
* plus an accessibility hint: the box still reports `checked === false`. */
|
|
15
|
+
indeterminate?: boolean;
|
|
16
|
+
/** Disable interaction. */
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
/** Set the native `required` attribute, and nothing more. Whether an unticked box
|
|
19
|
+
* is an error is the application's rule, not the kit's. */
|
|
20
|
+
required?: boolean;
|
|
21
|
+
/** Accessible label. The visible text beside the box is the consumer's to render. */
|
|
22
|
+
label?: string;
|
|
23
|
+
/** Form-control name (paired with `value`). */
|
|
24
|
+
name?: string;
|
|
25
|
+
/** Submitted value when checked (paired with `name`). Defaults to `'on'`. */
|
|
26
|
+
value?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Events fired by `<kai-checkbox>`. */
|
|
30
|
+
interface Events {
|
|
31
|
+
/** The box was ticked or unticked. */
|
|
32
|
+
'kai-change': { checked: boolean };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* `<kai-checkbox>` — a checkbox over a real `<input type="checkbox">`. Drive/read
|
|
37
|
+
* its state with the `checked` property (settable + reflected to the `checked`
|
|
38
|
+
* attribute, so `:host([checked])` and `el.checked` see live state); seed the
|
|
39
|
+
* initial state with `default-checked` and read changes from `kai-change`.
|
|
40
|
+
*
|
|
41
|
+
* ```html
|
|
42
|
+
* <label>
|
|
43
|
+
* <kai-checkbox default-checked label="Stream responses"></kai-checkbox>
|
|
44
|
+
* Stream responses
|
|
45
|
+
* </label>
|
|
46
|
+
* <script type="module">
|
|
47
|
+
* import '@kitn.ai/ui/elements';
|
|
48
|
+
* const box = document.querySelector('kai-checkbox');
|
|
49
|
+
* box.addEventListener('kai-change', (e) => console.log(e.detail.checked));
|
|
50
|
+
* box.checked = false; // drive it (no kai-change — the host already knows)
|
|
51
|
+
* box.indeterminate = true;
|
|
52
|
+
* box.toggle(); // flip it (fires kai-change)
|
|
53
|
+
* </script>
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
defineWebComponent<Props, Events>('kai-checkbox', {
|
|
57
|
+
checked: undefined,
|
|
58
|
+
defaultChecked: undefined,
|
|
59
|
+
indeterminate: undefined,
|
|
60
|
+
disabled: undefined,
|
|
61
|
+
required: undefined,
|
|
62
|
+
label: undefined,
|
|
63
|
+
name: undefined,
|
|
64
|
+
value: undefined,
|
|
65
|
+
}, (props, ctx) => {
|
|
66
|
+
const { element, dispatch, flag, expose } = ctx;
|
|
67
|
+
|
|
68
|
+
// Lift the on/off state into the facade and drive Checkbox CONTROLLED so the host
|
|
69
|
+
// can read it (`el.checked` / `:host([checked])`) and set it after mount. Seed from
|
|
70
|
+
// `defaultChecked` (or a bare `checked` attribute present on mount). This is
|
|
71
|
+
// kai-switch's structure, deliberately — same contract, same failure modes.
|
|
72
|
+
const [checked, setChecked] = createSignal(flag('defaultChecked') || flag('checked'));
|
|
73
|
+
|
|
74
|
+
// Coerce anything arriving through the `checked` setter (a JS assignment, or the
|
|
75
|
+
// write-back `attributeChangedCallback` fires when the attribute changes) to a
|
|
76
|
+
// boolean, falling back to attribute presence to match `flag`'s semantics. The
|
|
77
|
+
// `undefined` write-back `toggleAttribute` triggers thus resolves to the attribute
|
|
78
|
+
// just written, equals the signal, and is absorbed by the guard below — no attr⇄prop
|
|
79
|
+
// feedback loop.
|
|
80
|
+
const coerce = (v: unknown): boolean =>
|
|
81
|
+
v === true ? true
|
|
82
|
+
: v === false ? false
|
|
83
|
+
: element.hasAttribute('checked') && element.getAttribute('checked') !== 'false';
|
|
84
|
+
|
|
85
|
+
// Apply a new checked state and fire kai-change once (the user path). No-op while
|
|
86
|
+
// disabled.
|
|
87
|
+
const apply = (next: boolean) => {
|
|
88
|
+
if (flag('disabled')) return;
|
|
89
|
+
if (untrack(checked) === next) return;
|
|
90
|
+
setChecked(next);
|
|
91
|
+
dispatch('kai-change', { checked: next });
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// Reads return LIVE state; host writes drive it WITHOUT firing kai-change — the
|
|
95
|
+
// host already knows what it set. The equality guard kills the reflect write-back.
|
|
96
|
+
Object.defineProperty(element, 'checked', {
|
|
97
|
+
get: () => checked(),
|
|
98
|
+
set: (v: unknown) => { const next = coerce(v); if (untrack(checked) !== next) setChecked(next); },
|
|
99
|
+
configurable: true,
|
|
100
|
+
enumerable: true,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// Reflect internal checked → the `[checked]` host attribute (for `:host([checked])`).
|
|
104
|
+
createEffect(() => {
|
|
105
|
+
const c = checked();
|
|
106
|
+
if (c !== element.hasAttribute('checked')) element.toggleAttribute('checked', c);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
expose({
|
|
110
|
+
/** Flip the box and fire `kai-change` (no-op while disabled). */
|
|
111
|
+
toggle: () => apply(!untrack(checked)),
|
|
112
|
+
/** Focus the inner input (the host element can't reach it). */
|
|
113
|
+
focus: (options?: FocusOptions) =>
|
|
114
|
+
element.shadowRoot?.querySelector<HTMLInputElement>('input[type="checkbox"]')?.focus(options),
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
<>
|
|
119
|
+
{/* Base sets `:host{display:block}`; a checkbox flows inline beside its text. */}
|
|
120
|
+
<style>{':host{display:inline-flex}'}</style>
|
|
121
|
+
<Checkbox
|
|
122
|
+
checked={checked()}
|
|
123
|
+
indeterminate={flag('indeterminate')}
|
|
124
|
+
disabled={flag('disabled')}
|
|
125
|
+
required={flag('required')}
|
|
126
|
+
aria-label={props.label as string | undefined}
|
|
127
|
+
aria-checked={flag('indeterminate') ? 'mixed' : undefined}
|
|
128
|
+
name={props.name as string | undefined}
|
|
129
|
+
value={(props.value as string | undefined) ?? 'on'}
|
|
130
|
+
onChange={(e) => apply(e.currentTarget.checked)}
|
|
131
|
+
/>
|
|
132
|
+
</>
|
|
133
|
+
);
|
|
134
|
+
});
|