@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
|
@@ -8,18 +8,20 @@ import {
|
|
|
8
8
|
createMemo,
|
|
9
9
|
createEffect,
|
|
10
10
|
on,
|
|
11
|
+
onMount,
|
|
11
12
|
ErrorBoundary,
|
|
12
13
|
createUniqueId,
|
|
13
14
|
} from 'solid-js';
|
|
14
15
|
import { cn } from '../utils/cn';
|
|
15
16
|
import { Button } from '../ui/button';
|
|
17
|
+
import { ProgressBar } from '../ui/progress-bar';
|
|
16
18
|
import { Card } from './card';
|
|
17
19
|
import { DismissedStub } from './dismissed-stub';
|
|
18
20
|
import type { CardEnvelope, CardEvent, CardHost, CardResolution } from '../primitives/card-contract';
|
|
19
21
|
import { useCardResolution } from './use-card-resolution';
|
|
20
22
|
import { emitCardEvent } from '../primitives/card-routing';
|
|
21
23
|
import { useCardHost } from '../primitives/card-host';
|
|
22
|
-
import { Check, X } from 'lucide-solid';
|
|
24
|
+
import { Check, Circle, CircleCheck, X } from 'lucide-solid';
|
|
23
25
|
|
|
24
26
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
25
27
|
// Types (tasks.schema.json) — see src/primitives/card-schemas/tasks.schema.json
|
|
@@ -34,7 +36,15 @@ export interface TasksTask {
|
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
export interface TasksCardData {
|
|
37
|
-
|
|
39
|
+
/**
|
|
40
|
+
* `select` (default) = checkbox rows + a confirm button that emits the contract
|
|
41
|
+
* `submit`. `progress` = an onboarding/checklist look: a header `done / total`
|
|
42
|
+
* count, circular indicators, per-item title + muted description, and NO confirm
|
|
43
|
+
* button (checking a row is itself the terminal action). Both share the same
|
|
44
|
+
* selection model (toggle by id, the `max` gate, `kai-value-change`); `progress`
|
|
45
|
+
* is purely a presentational variant.
|
|
46
|
+
*/
|
|
47
|
+
mode?: 'select' | 'progress';
|
|
38
48
|
heading?: string;
|
|
39
49
|
tasks: TasksTask[]; // >=1
|
|
40
50
|
selectAll?: boolean;
|
|
@@ -123,6 +133,16 @@ export function showSelectAll(data: TasksCardData, tasks: TasksTask[]): boolean
|
|
|
123
133
|
return true;
|
|
124
134
|
}
|
|
125
135
|
|
|
136
|
+
/** Whether the card is in the onboarding-checklist `progress` look (no confirm). */
|
|
137
|
+
export function isProgressMode(data: TasksCardData): boolean {
|
|
138
|
+
return data.mode === 'progress';
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** The header progress count (`done` checked / `total` rows) for `progress` mode. */
|
|
142
|
+
export function progressCount(tasks: TasksTask[], selected: Set<string>): { done: number; total: number } {
|
|
143
|
+
return { done: tasks.filter((t) => selected.has(t.id)).length, total: tasks.length };
|
|
144
|
+
}
|
|
145
|
+
|
|
126
146
|
/** Whether confirm is enabled for the current selection count. */
|
|
127
147
|
export function canConfirm(data: TasksCardData, count: number): boolean {
|
|
128
148
|
const min = data.min ?? (data.allowEmpty ? 0 : 1);
|
|
@@ -149,6 +169,24 @@ export function confirmReason(data: TasksCardData, count: number): string | unde
|
|
|
149
169
|
// The <TasksCard> component.
|
|
150
170
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
151
171
|
|
|
172
|
+
/** Imperative handle exposed via `controllerRef` — surfaces the tasks card's latent
|
|
173
|
+
* selection model (set the checked ids, toggle one, confirm, focus the group,
|
|
174
|
+
* dismiss/reopen) so the `<kai-tasks>` facade can forward them as instance methods. */
|
|
175
|
+
export interface TasksCardController {
|
|
176
|
+
/** Set the checked ids (local-only, no emit), respecting disabled/max. No arg = select all toggleable rows. */
|
|
177
|
+
select(taskIds?: string[]): void;
|
|
178
|
+
/** Toggle one task by id, honoring the max gate. */
|
|
179
|
+
toggle(taskId: string, checked?: boolean): void;
|
|
180
|
+
/** Confirm the current selection (only when allowed) — emits `submit` + resolves. */
|
|
181
|
+
send(): void;
|
|
182
|
+
/** Focus the task group (select-all checkbox if shown, else the first row). */
|
|
183
|
+
focus(options?: FocusOptions): void;
|
|
184
|
+
/** Trigger the dismiss path (emit `dismiss` + collapse to the re-openable stub). */
|
|
185
|
+
dismiss(): void;
|
|
186
|
+
/** Re-open a dismissed card from its stub (emit `reopen`). */
|
|
187
|
+
reopen(): void;
|
|
188
|
+
}
|
|
189
|
+
|
|
152
190
|
export interface TasksCardProps {
|
|
153
191
|
/** The tasks definition (CardEnvelope.data). */
|
|
154
192
|
data?: TasksCardData;
|
|
@@ -164,6 +202,20 @@ export interface TasksCardProps {
|
|
|
164
202
|
class?: string;
|
|
165
203
|
/** When set, render the chromed read-only summary instead of the interactive controls. */
|
|
166
204
|
resolution?: CardResolution;
|
|
205
|
+
/** Controlled selection (task ids) — when set, this wins over internal state. */
|
|
206
|
+
value?: string[];
|
|
207
|
+
/** Uncontrolled initial selection (task ids), overlaying per-task `checked`. */
|
|
208
|
+
defaultValue?: string[];
|
|
209
|
+
/** Freeze the whole list + Confirm. */
|
|
210
|
+
disabled?: boolean;
|
|
211
|
+
/** Display-only: rows can't be toggled and show the default cursor (no pointer,
|
|
212
|
+
* no hover background, no focus ring). Keeps the visual content as-is — this only
|
|
213
|
+
* drops the interactive affordances + a11y exposure. */
|
|
214
|
+
readonly?: boolean;
|
|
215
|
+
/** Fires on every selection change with the selected ids (distinct from submit). */
|
|
216
|
+
onValueChange?: (payload: { value: string[] }) => void;
|
|
217
|
+
/** Receive the imperative controller once mounted. */
|
|
218
|
+
controllerRef?: (controller: TasksCardController) => void;
|
|
167
219
|
}
|
|
168
220
|
|
|
169
221
|
const DEFAULT_DATA: TasksCardData = { tasks: [] };
|
|
@@ -177,7 +229,10 @@ const DEFAULT_DATA: TasksCardData = { tasks: [] };
|
|
|
177
229
|
*/
|
|
178
230
|
export function TasksCard(props: TasksCardProps): JSX.Element {
|
|
179
231
|
const merged = mergeProps({ cardId: 'kai-tasks' }, props);
|
|
180
|
-
const [local] = splitProps(merged, [
|
|
232
|
+
const [local] = splitProps(merged, [
|
|
233
|
+
'data', 'cardId', 'heading', 'host', 'hostElement', 'class', 'resolution',
|
|
234
|
+
'value', 'defaultValue', 'disabled', 'readonly', 'onValueChange', 'controllerRef',
|
|
235
|
+
]);
|
|
181
236
|
|
|
182
237
|
const ctxHost = useCardHost();
|
|
183
238
|
const uid = createUniqueId();
|
|
@@ -198,16 +253,37 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
|
|
|
198
253
|
|
|
199
254
|
const res = useCardResolution({ prop: () => local.resolution, data: () => local.data });
|
|
200
255
|
|
|
201
|
-
//
|
|
256
|
+
// Only ids that exist in the current task list (drop unknown ids defensively).
|
|
257
|
+
const validIds = (ids: string[]): string[] => {
|
|
258
|
+
const known = new Set(tasks().map((t) => t.id));
|
|
259
|
+
return ids.filter((id) => known.has(id));
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
// Seed selection from `value` (controlled) > `defaultValue` > per-task `checked`,
|
|
263
|
+
// when a NEW definition arrives.
|
|
202
264
|
createEffect(
|
|
203
265
|
on(
|
|
204
266
|
() => local.data,
|
|
205
267
|
() => {
|
|
206
|
-
|
|
268
|
+
const seedIds = local.value ?? local.defaultValue ?? initialSelected(tasks());
|
|
269
|
+
setSelected(new Set(validIds(seedIds)));
|
|
207
270
|
},
|
|
208
271
|
),
|
|
209
272
|
);
|
|
210
273
|
|
|
274
|
+
// Controlled selection: when the consumer drives `value`, mirror it into the set
|
|
275
|
+
// (the controlled prop wins). Deferred so mount's seed runs first.
|
|
276
|
+
createEffect(on(() => local.value, (v) => {
|
|
277
|
+
if (!v) return;
|
|
278
|
+
setSelected(new Set(validIds(v)));
|
|
279
|
+
}, { defer: true }));
|
|
280
|
+
|
|
281
|
+
// Fire the live change signal whenever the selection set changes (distinct from
|
|
282
|
+
// the terminal submit). Deferred so the initial seed doesn't emit.
|
|
283
|
+
createEffect(on(selected, (s) => {
|
|
284
|
+
local.onValueChange?.({ value: selectedInOrder(tasks(), s) });
|
|
285
|
+
}, { defer: true }));
|
|
286
|
+
|
|
211
287
|
// ready / error lifecycle emits.
|
|
212
288
|
createEffect(
|
|
213
289
|
on(valid, (ok) => {
|
|
@@ -216,28 +292,41 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
|
|
|
216
292
|
}),
|
|
217
293
|
);
|
|
218
294
|
|
|
295
|
+
const groupDisabled = (): boolean => local.disabled === true;
|
|
296
|
+
// Display-only: block all toggling/confirm and drop the interactive affordances,
|
|
297
|
+
// without the dimmed/`disabled` look.
|
|
298
|
+
const readOnly = (): boolean => local.readonly === true;
|
|
299
|
+
|
|
219
300
|
const count = createMemo(() => selected().size);
|
|
301
|
+
// `progress` mode = the onboarding-checklist look: a header `done / total`
|
|
302
|
+
// count, circular indicators, no confirm button. Same selection model.
|
|
303
|
+
const progress = createMemo(() => isProgressMode(data()));
|
|
304
|
+
const progressN = createMemo(() => progressCount(tasks(), selected()));
|
|
220
305
|
const confirmLabel = () => data().confirmLabel ?? 'Confirm';
|
|
221
306
|
const masterState = createMemo(() => selectAllState(tasks(), selected()));
|
|
222
307
|
const showMaster = createMemo(() => showSelectAll(data(), tasks()));
|
|
223
308
|
const reason = createMemo(() => confirmReason(data(), count()));
|
|
224
|
-
const confirmEnabled = createMemo(() => canConfirm(data(), count()) && !res.isResolved());
|
|
309
|
+
const confirmEnabled = createMemo(() => canConfirm(data(), count()) && !res.isResolved() && !groupDisabled() && !readOnly());
|
|
225
310
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const next = new Set(selected());
|
|
311
|
+
// Apply one id to a selection set, honoring the max gate (mutates+returns `next`).
|
|
312
|
+
const applyToggle = (next: Set<string>, id: string, on: boolean): Set<string> => {
|
|
229
313
|
if (on) {
|
|
230
314
|
// Respect max: block adding past max.
|
|
231
|
-
if (isMaxReached(data(), next.size) && !next.has(id)) return;
|
|
315
|
+
if (isMaxReached(data(), next.size) && !next.has(id)) return next;
|
|
232
316
|
next.add(id);
|
|
233
317
|
} else {
|
|
234
318
|
next.delete(id);
|
|
235
319
|
}
|
|
236
|
-
|
|
320
|
+
return next;
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
const toggle = (id: string, on: boolean): void => {
|
|
324
|
+
if (res.isResolved() || groupDisabled() || readOnly()) return;
|
|
325
|
+
setSelected(applyToggle(new Set(selected()), id, on));
|
|
237
326
|
};
|
|
238
327
|
|
|
239
328
|
const toggleAll = (on: boolean): void => {
|
|
240
|
-
if (res.isResolved()) return;
|
|
329
|
+
if (res.isResolved() || groupDisabled() || readOnly()) return;
|
|
241
330
|
const next = new Set(selected());
|
|
242
331
|
for (const id of toggleableIds(tasks())) {
|
|
243
332
|
if (on) next.add(id);
|
|
@@ -262,6 +351,43 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
|
|
|
262
351
|
};
|
|
263
352
|
const onReopen = (): void => emit({ kind: 'reopen', cardId: local.cardId });
|
|
264
353
|
|
|
354
|
+
// Imperative controller (Pattern C): hand the facade a handle over the tasks
|
|
355
|
+
// card's latent selection model. select sets the checked ids local-only (no
|
|
356
|
+
// submit); toggle drives one row; send confirms (same path as Confirm); focus
|
|
357
|
+
// targets the group; dismiss/reopen drive the stub.
|
|
358
|
+
onMount(() => {
|
|
359
|
+
local.controllerRef?.({
|
|
360
|
+
select: (taskIds) => {
|
|
361
|
+
if (res.isResolved() || groupDisabled() || readOnly()) return;
|
|
362
|
+
if (taskIds === undefined) { toggleAll(true); return; }
|
|
363
|
+
// Build the set fresh, honoring max + disabled per id (skip disabled rows).
|
|
364
|
+
const next = new Set<string>();
|
|
365
|
+
const toggleable = new Set(toggleableIds(tasks()));
|
|
366
|
+
for (const id of validIds(taskIds)) {
|
|
367
|
+
if (!toggleable.has(id)) continue; // skip per-task-disabled rows
|
|
368
|
+
applyToggle(next, id, true);
|
|
369
|
+
}
|
|
370
|
+
setSelected(next);
|
|
371
|
+
},
|
|
372
|
+
toggle: (taskId, checked) => {
|
|
373
|
+
// No explicit `checked` → flip the current state.
|
|
374
|
+
const on = checked ?? !selected().has(taskId);
|
|
375
|
+
toggle(taskId, on);
|
|
376
|
+
},
|
|
377
|
+
send: () => onConfirm(),
|
|
378
|
+
focus: (options) => {
|
|
379
|
+
const root = local.hostElement?.shadowRoot ?? document;
|
|
380
|
+
const group = root.querySelector<HTMLElement>('[role="group"]');
|
|
381
|
+
// Prefer the select-all checkbox (it's the first labelled input), else the
|
|
382
|
+
// first row's checkbox; fall back to the group container itself.
|
|
383
|
+
const firstInput = group?.querySelector<HTMLElement>('input[type="checkbox"]');
|
|
384
|
+
(firstInput ?? group)?.focus(options);
|
|
385
|
+
},
|
|
386
|
+
dismiss: () => onDismiss(),
|
|
387
|
+
reopen: () => onReopen(),
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
|
|
265
391
|
// Surface the resolved state for host styling. Only a `submit` resolution is the
|
|
266
392
|
// "submitted" state; a deferred `dismissed` (or `expired`) is not.
|
|
267
393
|
createEffect(() => {
|
|
@@ -283,6 +409,9 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
|
|
|
283
409
|
|
|
284
410
|
const reasonId = `kai-tl-reason-${uid}`;
|
|
285
411
|
const countId = `kai-tl-count-${uid}`;
|
|
412
|
+
const progressCountId = `kai-tl-progress-${uid}`;
|
|
413
|
+
const progressHeadingId = `kai-tl-heading-${uid}`;
|
|
414
|
+
const headingText = () => local.heading ?? local.data?.heading;
|
|
286
415
|
|
|
287
416
|
return (
|
|
288
417
|
<Show when={valid()} fallback={<Card heading={local.heading} errorMessage={errorMessage()} />}>
|
|
@@ -299,9 +428,14 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
|
|
|
299
428
|
}
|
|
300
429
|
>
|
|
301
430
|
<Card
|
|
302
|
-
heading
|
|
431
|
+
// In `progress` mode the heading + count render as a custom in-body row
|
|
432
|
+
// (so the count can sit right-aligned beside the heading), so the Card
|
|
433
|
+
// chrome's own heading is suppressed.
|
|
434
|
+
heading={progress() ? undefined : headingText()}
|
|
303
435
|
actions={
|
|
304
|
-
|
|
436
|
+
// `progress` mode is confirm-less: checking a row IS the action.
|
|
437
|
+
// `readonly` is display-only, so there's no confirm/dismiss row either.
|
|
438
|
+
progress() || res.isResolved() || readOnly() ? undefined : (
|
|
305
439
|
<div class="flex w-full flex-wrap items-center justify-between gap-2">
|
|
306
440
|
<Show when={local.data?.dismissible === true}>
|
|
307
441
|
<Button
|
|
@@ -340,9 +474,31 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
|
|
|
340
474
|
when={!res.isResolved()}
|
|
341
475
|
fallback={<TasksResolved summary={resolvedSummary()!} optimistic={res.isOptimistic()} />}
|
|
342
476
|
>
|
|
477
|
+
<Show when={progress()}>
|
|
478
|
+
<ProgressChecklist
|
|
479
|
+
heading={headingText()}
|
|
480
|
+
headingId={progressHeadingId}
|
|
481
|
+
countId={progressCountId}
|
|
482
|
+
done={progressN().done}
|
|
483
|
+
total={progressN().total}
|
|
484
|
+
tasks={tasks()}
|
|
485
|
+
uid={uid}
|
|
486
|
+
isChecked={(id) => selected().has(id)}
|
|
487
|
+
isBlocked={(task) =>
|
|
488
|
+
groupDisabled() || task.disabled === true ||
|
|
489
|
+
(!selected().has(task.id) && isMaxReached(data(), count()))
|
|
490
|
+
}
|
|
491
|
+
onToggle={(id, on) => toggle(id, on)}
|
|
492
|
+
groupClass={local.class}
|
|
493
|
+
maxNote={data().max !== undefined ? data().max : undefined}
|
|
494
|
+
readonly={readOnly()}
|
|
495
|
+
/>
|
|
496
|
+
</Show>
|
|
497
|
+
<Show when={!progress()}>
|
|
343
498
|
<div
|
|
344
499
|
role="group"
|
|
345
500
|
aria-label={local.heading ?? local.data?.heading ?? 'Tasks'}
|
|
501
|
+
aria-readonly={readOnly() ? 'true' : undefined}
|
|
346
502
|
class={cn('flex flex-col', local.class)}
|
|
347
503
|
onKeyDown={(e) => {
|
|
348
504
|
// Enter anywhere in the card (off a checkbox) confirms when enabled.
|
|
@@ -359,16 +515,20 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
|
|
|
359
515
|
return (
|
|
360
516
|
<label
|
|
361
517
|
class={cn(
|
|
362
|
-
'flex
|
|
518
|
+
'flex items-center gap-3 px-3 py-2.5 text-sm font-medium transition-colors',
|
|
519
|
+
readOnly() ? 'cursor-default' : 'cursor-pointer',
|
|
363
520
|
masterState() === 'checked'
|
|
364
521
|
? 'bg-accent text-accent-foreground'
|
|
365
|
-
:
|
|
522
|
+
: readOnly()
|
|
523
|
+
? 'text-foreground'
|
|
524
|
+
: 'text-foreground hover:bg-muted/50',
|
|
366
525
|
)}
|
|
367
526
|
>
|
|
368
527
|
<input
|
|
369
528
|
type="checkbox"
|
|
370
529
|
class="kai-checkbox"
|
|
371
530
|
checked={masterState() === 'checked'}
|
|
531
|
+
disabled={groupDisabled() || readOnly()}
|
|
372
532
|
aria-checked={indeterminate() ? 'mixed' : masterState() === 'checked'}
|
|
373
533
|
ref={(el) => {
|
|
374
534
|
createEffect(() => {
|
|
@@ -387,15 +547,17 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
|
|
|
387
547
|
{(task) => {
|
|
388
548
|
const checked = () => selected().has(task.id);
|
|
389
549
|
const blocked = () =>
|
|
390
|
-
task.disabled || (!checked() && isMaxReached(data(), count()));
|
|
550
|
+
groupDisabled() || task.disabled || (!checked() && isMaxReached(data(), count()));
|
|
391
551
|
const descId = `kai-tl-desc-${uid}-${task.id}`;
|
|
392
552
|
return (
|
|
393
553
|
<label
|
|
394
554
|
class={cn(
|
|
395
555
|
'flex items-start gap-3 px-3 py-2.5 text-sm transition-colors',
|
|
396
|
-
|
|
397
|
-
? 'cursor-
|
|
398
|
-
:
|
|
556
|
+
readOnly()
|
|
557
|
+
? 'cursor-default'
|
|
558
|
+
: blocked()
|
|
559
|
+
? 'cursor-not-allowed opacity-60'
|
|
560
|
+
: 'cursor-pointer hover:bg-muted/50',
|
|
399
561
|
checked() && !blocked()
|
|
400
562
|
? 'bg-accent font-medium text-accent-foreground'
|
|
401
563
|
: 'text-foreground',
|
|
@@ -406,7 +568,7 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
|
|
|
406
568
|
type="checkbox"
|
|
407
569
|
class="kai-checkbox mt-0.5"
|
|
408
570
|
checked={checked()}
|
|
409
|
-
disabled={blocked()}
|
|
571
|
+
disabled={blocked() || readOnly()}
|
|
410
572
|
aria-disabled={blocked() ? 'true' : undefined}
|
|
411
573
|
aria-describedby={task.description ? descId : undefined}
|
|
412
574
|
onChange={(e) => toggle(task.id, e.currentTarget.checked)}
|
|
@@ -429,6 +591,7 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
|
|
|
429
591
|
<p class="pt-1 text-xs text-muted-foreground">Up to {data().max} selected.</p>
|
|
430
592
|
</Show>
|
|
431
593
|
</div>
|
|
594
|
+
</Show>
|
|
432
595
|
</Show>
|
|
433
596
|
</Card>
|
|
434
597
|
</Show>
|
|
@@ -437,6 +600,163 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
|
|
|
437
600
|
);
|
|
438
601
|
}
|
|
439
602
|
|
|
603
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
604
|
+
// Onboarding-checklist (`mode: 'progress'`) presenter: a header `done / total`
|
|
605
|
+
// count + circular indicators + per-item title/description, no confirm button.
|
|
606
|
+
// Drives the same selection model, where toggling a row IS the action.
|
|
607
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
608
|
+
|
|
609
|
+
function ProgressChecklist(props: {
|
|
610
|
+
heading?: string;
|
|
611
|
+
headingId: string;
|
|
612
|
+
countId: string;
|
|
613
|
+
done: number;
|
|
614
|
+
total: number;
|
|
615
|
+
tasks: TasksTask[];
|
|
616
|
+
uid: string;
|
|
617
|
+
isChecked: (id: string) => boolean;
|
|
618
|
+
isBlocked: (task: TasksTask) => boolean;
|
|
619
|
+
onToggle: (id: string, on: boolean) => void;
|
|
620
|
+
groupClass?: string;
|
|
621
|
+
maxNote?: number;
|
|
622
|
+
/** Display-only: rows aren't focusable/toggleable and show the default cursor. */
|
|
623
|
+
readonly?: boolean;
|
|
624
|
+
}): JSX.Element {
|
|
625
|
+
return (
|
|
626
|
+
<div class={cn('flex flex-col gap-3', props.groupClass)}>
|
|
627
|
+
<Show when={props.heading}>
|
|
628
|
+
<div class="flex items-center justify-between gap-3">
|
|
629
|
+
<span id={props.headingId} class="text-sm font-medium text-foreground">
|
|
630
|
+
{props.heading}
|
|
631
|
+
</span>
|
|
632
|
+
<span
|
|
633
|
+
id={props.countId}
|
|
634
|
+
aria-live="polite"
|
|
635
|
+
class="shrink-0 text-sm font-medium tabular-nums text-muted-foreground"
|
|
636
|
+
>
|
|
637
|
+
{props.done} / {props.total}
|
|
638
|
+
</span>
|
|
639
|
+
</div>
|
|
640
|
+
</Show>
|
|
641
|
+
|
|
642
|
+
{/* Thin progress bar under the heading: filled to done / total. Named off the
|
|
643
|
+
checklist heading (no duplicate caption), or a generic label when headless. */}
|
|
644
|
+
<ProgressBar
|
|
645
|
+
value={props.done}
|
|
646
|
+
max={props.total}
|
|
647
|
+
tone="success"
|
|
648
|
+
aria-labelledby={props.heading ? props.headingId : undefined}
|
|
649
|
+
aria-label={props.heading ? undefined : 'Task progress'}
|
|
650
|
+
/>
|
|
651
|
+
|
|
652
|
+
<ul
|
|
653
|
+
aria-labelledby={props.heading ? props.headingId : undefined}
|
|
654
|
+
aria-label={props.heading ? undefined : 'Checklist'}
|
|
655
|
+
class="flex flex-col gap-1"
|
|
656
|
+
>
|
|
657
|
+
<For each={props.tasks}>
|
|
658
|
+
{(task) => {
|
|
659
|
+
const checked = () => props.isChecked(task.id);
|
|
660
|
+
const blocked = () => props.isBlocked(task);
|
|
661
|
+
const descId = `kai-tl-pdesc-${props.uid}-${task.id}`;
|
|
662
|
+
return (
|
|
663
|
+
<li>
|
|
664
|
+
<label
|
|
665
|
+
class={cn(
|
|
666
|
+
'group flex items-start gap-3 rounded-lg px-2.5 py-2 text-sm transition-colors',
|
|
667
|
+
// Keyboard focus ring (kit standard, inset so it stays within the
|
|
668
|
+
// row). focus-visible only, so a mouse click that parks focus on the
|
|
669
|
+
// row doesn't leave a noisy persistent outline — and it makes a
|
|
670
|
+
// Tab-focused completed row's open description perceivable. Dropped
|
|
671
|
+
// entirely when readonly (the row isn't focusable then).
|
|
672
|
+
!props.readonly &&
|
|
673
|
+
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring',
|
|
674
|
+
props.readonly
|
|
675
|
+
? 'cursor-default'
|
|
676
|
+
: blocked()
|
|
677
|
+
? 'cursor-not-allowed opacity-60'
|
|
678
|
+
: 'cursor-pointer hover:bg-muted/50',
|
|
679
|
+
)}
|
|
680
|
+
data-task-id={task.id}
|
|
681
|
+
// Completed rows hide their description until hover/focus, so make the
|
|
682
|
+
// row itself focusable to drive the focus-reveal (group-focus-within).
|
|
683
|
+
// Incomplete rows — and every row when readonly — stay unfocusable.
|
|
684
|
+
// Expose the label + description to AT.
|
|
685
|
+
tabindex={!props.readonly && checked() ? 0 : undefined}
|
|
686
|
+
aria-label={checked() ? task.label : undefined}
|
|
687
|
+
aria-describedby={checked() && task.description ? descId : undefined}
|
|
688
|
+
>
|
|
689
|
+
<input
|
|
690
|
+
type="checkbox"
|
|
691
|
+
class="sr-only"
|
|
692
|
+
checked={checked()}
|
|
693
|
+
disabled={blocked() || props.readonly}
|
|
694
|
+
aria-disabled={blocked() ? 'true' : undefined}
|
|
695
|
+
aria-describedby={task.description ? descId : undefined}
|
|
696
|
+
onChange={(e) => props.onToggle(task.id, e.currentTarget.checked)}
|
|
697
|
+
/>
|
|
698
|
+
<span
|
|
699
|
+
class={cn(
|
|
700
|
+
'mt-0.5 shrink-0 text-muted-foreground',
|
|
701
|
+
// Completed rows: the check gently scales on hover.
|
|
702
|
+
checked() && 'motion-safe:transition-transform motion-safe:group-hover:scale-110',
|
|
703
|
+
)}
|
|
704
|
+
aria-hidden="true"
|
|
705
|
+
>
|
|
706
|
+
<Show
|
|
707
|
+
when={checked()}
|
|
708
|
+
fallback={<Circle size={18} />}
|
|
709
|
+
>
|
|
710
|
+
<CircleCheck size={18} class="text-foreground" />
|
|
711
|
+
</Show>
|
|
712
|
+
</span>
|
|
713
|
+
<span class="flex min-w-0 flex-col gap-0.5">
|
|
714
|
+
<span
|
|
715
|
+
class={cn(
|
|
716
|
+
'font-medium text-foreground',
|
|
717
|
+
// Completed: strike through + muted, brightening on hover.
|
|
718
|
+
checked() && 'line-through opacity-70 motion-safe:transition-opacity motion-safe:group-hover:opacity-100',
|
|
719
|
+
)}
|
|
720
|
+
>
|
|
721
|
+
{task.label}
|
|
722
|
+
</span>
|
|
723
|
+
<Show when={task.description}>
|
|
724
|
+
<Show
|
|
725
|
+
when={checked()}
|
|
726
|
+
fallback={
|
|
727
|
+
<span id={descId} class="text-xs font-normal text-muted-foreground">
|
|
728
|
+
{task.description}
|
|
729
|
+
</span>
|
|
730
|
+
}
|
|
731
|
+
>
|
|
732
|
+
{/* Completed: collapse the description and reveal it on hover or
|
|
733
|
+
keyboard focus via the grid-rows height trick. Height-collapse
|
|
734
|
+
keeps the text in the DOM + a11y tree (unlike display:none). */}
|
|
735
|
+
<div class="grid grid-rows-[0fr] group-hover:grid-rows-[1fr] group-focus-within:grid-rows-[1fr] motion-safe:transition-[grid-template-rows] motion-safe:duration-200">
|
|
736
|
+
<span
|
|
737
|
+
id={descId}
|
|
738
|
+
class="overflow-hidden text-xs font-normal text-muted-foreground opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 motion-safe:transition-opacity"
|
|
739
|
+
>
|
|
740
|
+
{task.description}
|
|
741
|
+
</span>
|
|
742
|
+
</div>
|
|
743
|
+
</Show>
|
|
744
|
+
</Show>
|
|
745
|
+
</span>
|
|
746
|
+
</label>
|
|
747
|
+
</li>
|
|
748
|
+
);
|
|
749
|
+
}}
|
|
750
|
+
</For>
|
|
751
|
+
</ul>
|
|
752
|
+
|
|
753
|
+
<Show when={props.maxNote !== undefined}>
|
|
754
|
+
<p class="text-xs text-muted-foreground">Up to {props.maxNote} selected.</p>
|
|
755
|
+
</Show>
|
|
756
|
+
</div>
|
|
757
|
+
);
|
|
758
|
+
}
|
|
759
|
+
|
|
440
760
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
441
761
|
// Read-only resolved summary presenter.
|
|
442
762
|
// ─────────────────────────────────────────────────────────────────────────────
|