@kitn.ai/ui 0.25.2 → 0.27.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 +17 -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-b5A8hlHs.js → Icon-BnFKqqtY.js} +1 -1
- package/dist/action-icons-CBskfBMz.js +1 -0
- package/dist/arrow-down-Br0qtpsz.js +1 -0
- package/dist/arrow-left-Dj7xgE12.js +1 -0
- package/dist/artifact-CvXEm1lS.js +1 -0
- package/dist/assets/dev-5XzXYR21.js +91 -0
- package/dist/attachments-C43ZegEq.js +1 -0
- package/dist/audio-visualizer-B-79y1Tj.js +1 -0
- package/dist/badge-BpUbq8c0.js +1 -0
- package/dist/bash-InADTalH.js +1 -6
- package/dist/bell-sn17Ip9v.js +1 -0
- package/dist/{elements/chunks/button-B9okqG73.js → button-BH6rN0U-.js} +1 -1
- package/dist/card-renderer-Cb1gQmth.js +1 -0
- package/dist/card-routing-DifQgS7n.js +1 -0
- package/dist/check-DPeeMUYx.js +1 -0
- package/dist/checkbox-Dc9Yov_B.js +1 -0
- package/dist/checkbox-group-B1kDLLYk.js +1 -0
- package/dist/chevron-down-CHSWk7ZT.js +1 -0
- package/dist/chevron-right-B7l_fMgx.js +1 -0
- package/dist/choice-card-BT3c1S8g.js +1 -0
- package/dist/circle-Bb0yOpqM.js +1 -0
- package/dist/circle-check-BGZpCiz7.js +1 -0
- package/dist/circle-x-wobWkoSx.js +1 -0
- package/dist/{elements/chunks/cn-CU7UAWzk.js → cn-DN5AWfiS.js} +1 -1
- package/dist/code-block-CUQ5mtv0.js +1 -0
- package/dist/collapsible-CPJbf6FM.js +1 -0
- package/dist/components/attachment-types.d.ts +53 -1
- package/dist/components/attachments.d.ts +31 -0
- package/dist/components/audio-visualizer/fit-scale.d.ts +50 -0
- package/dist/components/audio-visualizer/index.d.ts +15 -1
- package/dist/components/audio-visualizer/variant-bar.d.ts +24 -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 +49 -42
- package/dist/components/code-block.d.ts +22 -0
- package/dist/components/conversation-item.d.ts +66 -1
- package/dist/components/conversation-list.d.ts +77 -0
- package/dist/components/form-widgets.d.ts +67 -2
- package/dist/components/form.d.ts +89 -0
- package/dist/components/message.d.ts +29 -0
- 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/toast.d.ts +2 -1
- package/dist/components/tool-types.d.ts +9 -0
- package/dist/components/voice-input.d.ts +8 -0
- package/dist/components/voice-output.d.ts +12 -1
- package/dist/components/workspace-shell.d.ts +87 -0
- package/dist/composer-CjngLzal.js +106 -0
- package/dist/confirm-card-DCx_A4bU.js +1 -0
- package/dist/construct-cli.es.js +1169 -0
- package/dist/context-BY8V-Nlp.js +1 -0
- package/dist/controllable-D43BKmtX.js +1 -0
- package/dist/conversation-list-D4lLU_yS.js +1 -0
- package/dist/copy-B6DO4PqB.js +1 -0
- package/dist/core-AYMC6_lb.js +12 -5874
- package/dist/{create-tween-CUzOlaMS.js → create-tween-BPzaefTp.js} +1 -1
- package/dist/{create-tween-B5Y4Im8G.js → create-tween-CnMHviKB.js} +1 -1
- package/dist/{create-tween-4z1XYLkR.js → create-tween-D1aiGZZh.js} +1 -1
- package/dist/{elements/chunks/create-tween-CUrM6D_o.js → create-tween-DUSQUKpr.js} +2 -2
- package/dist/css-M7EaDHN_.js +1 -6
- package/dist/custom-elements.json +3468 -1927
- package/dist/default-input-CucQEOqH.js +1 -0
- package/dist/define-CGGX-7Vg.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/diagnostics/hook.d.ts +81 -0
- package/dist/diagnostics/index.d.ts +7 -0
- package/dist/diagnostics/report-request.d.ts +61 -0
- package/dist/diagnostics.d.ts +5 -0
- package/dist/diagnostics.js +209 -0
- package/dist/disclosure-CbLtajUQ.js +1 -0
- package/dist/dropdown-BwhViJFd.js +1 -0
- 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.d.ts +1 -0
- package/dist/elements/conversation-item.js +1 -0
- package/dist/elements/conversation-list.js +1 -1
- package/dist/elements/default-input.d.ts +3 -3
- package/dist/elements/define-entry.d.ts +12 -0
- package/dist/elements/define.d.ts +27 -0
- package/dist/elements/diagnostic-events.d.ts +74 -0
- package/dist/elements/dialog.js +1 -1
- package/dist/elements/dock.d.ts +1 -0
- package/dist/elements/dock.js +243 -0
- package/dist/elements/dropdown.d.ts +1 -0
- package/dist/elements/dropdown.js +1 -0
- package/dist/elements/editable-label.js +1 -1
- package/dist/elements/element-data-types.d.ts +37 -0
- package/dist/elements/element-diagnostics.d.ts +81 -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/register.d.ts +2 -0
- package/dist/elements/remote.js +1 -1
- package/dist/elements/resizable.js +1 -1
- package/dist/elements/response-stream.js +3 -3
- 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 +36 -4
- 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 +589 -167
- package/dist/{elements/chunks/ellipsis-CVxqfsDZ.js → ellipsis-DFr4Vqr3.js} +1 -1
- package/dist/embed-5s_vU4J0.js +1 -0
- package/dist/engine-javascript-vq0WuIJl.js +14 -2516
- package/dist/{elements/chunks/external-link-DG2sRdQL.js → external-link-u9d85ORQ.js} +1 -1
- package/dist/file-text-CX7_x42o.js +1 -0
- package/dist/{elements/chunks/file-tree-yGWNK0Js.js → file-tree-D3kBjXI5.js} +1 -1
- package/dist/folder-V-YdIL8f.js +1 -0
- package/dist/form-BRNUMCN2.js +1 -0
- package/dist/github-dark-dimmed-DUshB20C.js +1 -4
- package/dist/github-light-JYsPkUQd.js +1 -4
- package/dist/hover-card-DaeiYrTA.js +1 -0
- package/dist/html-CPZ3oZQ7.js +1 -10
- package/dist/icon-BpixdZNq.js +1 -0
- package/dist/{elements/chunks/index-BCRhi84a.js → index-xu_pdcPi.js} +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +8473 -6470
- package/dist/index.server.js +6495 -4958
- package/dist/info-8mFsIjS3.js +1 -0
- package/dist/input-d1Yuu-hz.js +1 -0
- package/dist/javascript-C25yR2R2.js +1 -6
- package/dist/json-DxJze_jm.js +1 -6
- package/dist/kai-provider.es.js +40 -40
- package/dist/kai.es.js +1 -1
- package/dist/kbd-961zMPFB.js +1 -0
- package/dist/link-DlZZBGaR.js +1 -0
- package/dist/{elements/chunks/link-preview-Cf5KOP-i.js → link-preview-DIIbV2Sd.js} +1 -1
- package/dist/loader-YQszHFaW.js +1 -0
- package/dist/{elements/chunks/markdown-DbozyYqa.js → markdown-CVk1MPsj.js} +1 -1
- package/dist/mcp.es.js +3873 -544
- package/dist/message-CwKVEdZg.js +1 -0
- package/dist/message-DS8lzHc1.js +1 -0
- package/dist/message-circle-Xf8Q-vZp.js +1 -0
- package/dist/message-square-Cxnwgkns.js +1 -0
- package/dist/{elements/chunks/minimize-2-SegJ_oku.js → minimize-2-UEZmP2QT.js} +1 -1
- package/dist/{elements/chunks/model-switcher-D7JrFFHp.js → model-switcher-Kk1jEQ5t.js} +1 -1
- package/dist/{elements/chunks/overlay-CV7z2YuX.js → overlay-C1od6LOz.js} +1 -1
- package/dist/panel-right-ryET0yyn.js +1 -0
- package/dist/paperclip-BDNoZFJP.js +1 -0
- package/dist/play-OFIvYXUQ.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/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 +23 -0
- package/dist/primitives/use-speech-recognition.d.ts +8 -0
- package/dist/primitives/use-text-stream.d.ts +5 -0
- package/dist/progress-bar-BvYX0aoy.js +1 -0
- package/dist/prompt-suggestion-BRFu2lcu.js +1 -0
- package/dist/radio-DcL23cNJ.js +1 -0
- package/dist/react/index.d.ts +306 -283
- package/dist/react.js +309 -247
- package/dist/reasoning-Cackq4Rh.js +1 -0
- package/dist/register-impl-C7rENvPK.js +424 -0
- package/dist/{elements/chunks/resizable-Dpzjlvp4.js → resizable-Cp9HUYih.js} +1 -1
- package/dist/rotate-ccw-0DLRDHH5.js +1 -0
- package/dist/rotate-cw-DOB9IGcU.js +1 -0
- package/dist/schemas/form.schema.json +21 -1
- package/dist/schemas/index.d.ts +1 -1
- package/dist/schemas/tool-defs.d.ts +45 -0
- package/dist/schemas.js +398 -305
- package/dist/scroll-area-emVmWP4K.js +1 -0
- package/dist/scroll-button-CeP_gv1x.js +1 -0
- package/dist/select-CWmu00tS.js +1 -0
- package/dist/{elements/chunks/separator-DH2r_ZSZ.js → separator-CE6vly6z.js} +1 -1
- package/dist/{elements/chunks/settings-BFMOd6yB.js → settings-CE-78SvZ.js} +1 -1
- package/dist/{elements/chunks/settings-group-B3VZKIcz.js → settings-group-ZFWNxFQR.js} +1 -1
- package/dist/{elements/chunks/skeleton-N8BuWYmf.js → skeleton-BebdP4mf.js} +1 -1
- package/dist/slider-BAKRYUlz.js +1 -0
- package/dist/slots-DaNjX0rc.js +1 -0
- package/dist/{solid-BMuDmFo_.js → solid-BE5ui6sy.js} +10672 -8116
- package/dist/{solid-CGYNdLRR.js → solid-DFhsce3O.js} +8137 -6056
- package/dist/solid.d.ts +15 -0
- package/dist/solid.js +248 -235
- package/dist/solid.server.js +248 -235
- package/dist/source-B0FlguSx.js +1 -0
- package/dist/star-CBMZvLuN.js +1 -0
- package/dist/state/index.d.ts +5 -1
- package/dist/state/mock.d.ts +32 -2
- package/dist/state/persistence.d.ts +51 -0
- package/dist/state/stream.d.ts +50 -0
- package/dist/state/threads.d.ts +71 -0
- package/dist/state.js +297 -172
- package/dist/store-7eoadydQ.js +1 -0
- package/dist/svelte--5p79yCD.js +1 -15
- package/dist/switch-CViARZCy.js +1 -0
- package/dist/tasks-card-MjCcOhR_.js +1 -0
- package/dist/text-shimmer-DKlwRF2G.js +1 -0
- package/dist/textarea-3ay2Me2-.js +1 -0
- package/dist/theme.tokens.css +82 -13
- package/dist/{elements/chunks/thumbs-up-DQe0hvkZ.js → thumbs-up-DQcu2HMO.js} +1 -1
- package/dist/toast-store-C6yKOhbk.js +1 -0
- package/dist/{elements/chunks/tool-C1YtxwPu.js → tool-BCYNlfKy.js} +1 -1
- package/dist/{elements/chunks/tooltip-BqwnFWhn.js → tooltip-05zI4hjs.js} +1 -1
- package/dist/trash-2-BR1RxGky.js +1 -0
- package/dist/{elements/chunks/triangle-alert-B6or7F5u.js → triangle-alert-DHohDOCy.js} +1 -1
- package/dist/tsx-B8rCNbgL.js +1 -6
- package/dist/types.d.ts +4 -2
- 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 +131 -0
- package/dist/ui/hover-card.d.ts +44 -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-BbGW6A_u.js +1 -0
- package/dist/url-scheme-policy-DHpoTJwB.js +1 -0
- package/dist/use-card-resolution-CJW4grFa.js +1 -0
- package/dist/{variant-aurora-DwSOfraQ.js → variant-aurora-BUOVgPOB.js} +27 -27
- package/dist/{variant-aurora-wKvAQ5wp.js → variant-aurora-CUsUJvFI.js} +28 -28
- package/dist/{variant-aurora-XEkPT0_z.js → variant-aurora-CW2i4bfr.js} +2 -2
- package/dist/{elements/chunks/variant-aurora-QXTZPyST.js → variant-aurora-xiMPty8f.js} +2 -2
- package/dist/variant-custom-BQtOnmeO.js +1 -0
- package/dist/{variant-custom-BhS9wIpU.js → variant-custom-CAm9L-E5.js} +65 -65
- package/dist/{variant-custom-eFIg2XWQ.js → variant-custom-CAnzzppW.js} +40 -40
- package/dist/variant-custom-D91HjAKz.js +1 -0
- package/dist/{variant-wave-CUWGx9Bn.js → variant-wave-Ca1Ls4_y.js} +21 -21
- package/dist/{variant-wave-CbVsmgwT.js → variant-wave-CxX39DKd.js} +25 -25
- package/dist/{variant-wave-BwzrHD1s.js → variant-wave-DYyzIIZv.js} +2 -2
- package/dist/{elements/chunks/variant-wave-DDCwhLas.js → variant-wave-uY5crU_K.js} +2 -2
- package/dist/vue-BmIZj4XD.js +1 -33
- package/dist/wire/chunk.d.ts +47 -0
- package/dist/wire/diagnostics.d.ts +575 -0
- package/dist/wire/encode-probe.d.ts +70 -0
- package/dist/wire/encode.d.ts +24 -0
- package/dist/wire/index.d.ts +2 -0
- package/dist/wire/sse.d.ts +10 -2
- package/dist/wire.js +917 -480
- package/dist/x-C5m1JFgi.js +1 -0
- package/frameworks/react/index.tsx +325 -108
- package/llms-full.txt +1354 -82
- package/llms.txt +6 -3
- package/package.json +39 -6
- package/src/agent-tooling/archetypes.ts +41 -9
- package/src/agent-tooling/catalog/README.md +676 -0
- package/src/agent-tooling/catalog/catalog-types.ts +231 -0
- package/src/agent-tooling/catalog/fabrications.ts +96 -0
- package/src/agent-tooling/catalog/invariants.ts +284 -0
- package/src/agent-tooling/catalog/labs-titles.ts +114 -0
- package/src/agent-tooling/catalog/scenarios.ts +87 -0
- package/src/agent-tooling/catalog/surfaces.ts +347 -0
- package/src/agent-tooling/construct/cli-entry.ts +8 -0
- package/src/agent-tooling/construct/cli.ts +131 -0
- package/src/agent-tooling/construct/codegen.ts +1353 -0
- package/src/agent-tooling/construct/construct.v1.schema.json +250 -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 +23 -0
- package/src/agent-tooling/construct/schema.ts +371 -0
- package/src/agent-tooling/integrations/anthropic.ts +7 -1
- package/src/agent-tooling/integrations/cloudflare.ts +43 -2
- package/src/agent-tooling/integrations/langgraph.ts +7 -1
- package/src/agent-tooling/integrations/mastra.ts +7 -1
- package/src/agent-tooling/integrations/mock.ts +92 -17
- package/src/agent-tooling/integrations/ollama.ts +7 -1
- package/src/agent-tooling/integrations/openai.ts +7 -1
- package/src/agent-tooling/integrations/openrouter.ts +7 -1
- package/src/agent-tooling/integrations/pi.ts +56 -1
- package/src/agent-tooling/integrations/vercel-ai-sdk.ts +7 -1
- package/src/agent-tooling/mcp/css-raw.d.ts +12 -0
- package/src/agent-tooling/mcp/manifest.ts +100 -1
- package/src/agent-tooling/mcp/server.ts +63 -6
- 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 +542 -5
- package/src/agent-tooling/mcp/tools/scaffold.ts +1834 -307
- package/src/agent-tooling/mcp/tools/theme.ts +146 -30
- package/src/agent-tooling/mcp/validate-args.ts +141 -0
- 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 +24 -7
- package/src/agent-tooling/route-emit.ts +26 -2
- package/src/components/attachment-types.ts +54 -1
- package/src/components/attachments.tsx +169 -22
- package/src/components/audio-visualizer/fit-scale.ts +112 -0
- package/src/components/audio-visualizer/index.tsx +80 -3
- package/src/components/audio-visualizer/variant-aurora.tsx +10 -4
- package/src/components/audio-visualizer/variant-bar.tsx +38 -6
- package/src/components/audio-visualizer/variant-custom.tsx +8 -2
- package/src/components/audio-visualizer/variant-grid.tsx +16 -11
- package/src/components/audio-visualizer/variant-radial.tsx +15 -10
- package/src/components/audio-visualizer/variant-wave.tsx +7 -2
- package/src/components/card-renderer.tsx +39 -8
- package/src/components/card.tsx +10 -2
- package/src/components/chat-container.tsx +4 -1
- package/src/components/chat-scope-picker.tsx +2 -2
- package/src/components/chat-thread.tsx +105 -13
- package/src/components/choice-card.tsx +102 -37
- package/src/components/coachmark.tsx +1 -1
- package/src/components/code-block.tsx +81 -5
- package/src/components/composer.tsx +89 -8
- package/src/components/confirm-card.tsx +20 -4
- package/src/components/conversation-item.tsx +138 -4
- package/src/components/conversation-list.tsx +230 -15
- package/src/components/embed.tsx +4 -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 +336 -21
- package/src/components/loader.tsx +12 -5
- package/src/components/message-skills.tsx +1 -1
- package/src/components/message.tsx +142 -12
- 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/response-stream.tsx +13 -7
- package/src/components/screen.tsx +5 -0
- package/src/components/scroll-button.tsx +63 -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 +11 -5
- package/src/components/tool-types.ts +9 -0
- package/src/components/voice-input.tsx +35 -3
- package/src/components/voice-output.tsx +46 -6
- package/src/components/workspace-shell.tsx +285 -0
- package/src/diagnostics/hook.ts +352 -0
- package/src/diagnostics/index.ts +82 -0
- package/src/diagnostics/report-request.ts +296 -0
- package/src/elements/attachments.tsx +9 -8
- package/src/elements/audio-visualizer.tsx +48 -4
- package/src/elements/chat-workspace.tsx +159 -287
- package/src/elements/chat.tsx +31 -10
- package/src/elements/checkbox-group.tsx +164 -0
- package/src/elements/checkbox.tsx +134 -0
- package/src/elements/code-block.tsx +19 -1
- package/src/elements/command.tsx +4 -1
- package/src/elements/compiled.css +1 -1
- package/src/elements/composer.tsx +12 -1
- package/src/elements/conversation-item.tsx +120 -0
- package/src/elements/conversation-list.tsx +60 -11
- package/src/elements/default-input.tsx +5 -5
- package/src/elements/define-entry.ts +12 -0
- package/src/elements/define.tsx +168 -8
- package/src/elements/diagnostic-events.ts +114 -0
- package/src/elements/dialog.tsx +47 -0
- package/src/elements/disclosure.ts +34 -12
- package/src/elements/dock.tsx +215 -0
- package/src/elements/dropdown.tsx +123 -0
- package/src/elements/element-data-types.ts +40 -0
- package/src/elements/element-diagnostics.ts +392 -0
- package/src/elements/element-manifest.json +36 -0
- package/src/elements/element-meta.json +1483 -560
- package/src/elements/element-nonscalar.json +185 -0
- package/src/elements/element-types.d.ts +589 -167
- 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/menu.tsx +13 -0
- package/src/elements/message.tsx +2 -0
- package/src/elements/pane-grid.tsx +111 -0
- package/src/elements/prompt-dock.tsx +2 -1
- package/src/elements/prompt-input.tsx +16 -10
- package/src/elements/radio-group.tsx +129 -0
- package/src/elements/register-impl.ts +52 -0
- package/src/elements/register.ts +28 -0
- package/src/elements/resizable.tsx +52 -25
- package/src/elements/scroll-button.tsx +59 -6
- package/src/elements/select.tsx +165 -0
- package/src/elements/slider.tsx +171 -0
- package/src/elements/slots.ts +108 -13
- package/src/elements/styles.css +119 -9
- package/src/elements/thinking-bar.tsx +16 -7
- package/src/elements/thread.tsx +2 -0
- package/src/elements/toast.tsx +17 -1
- package/src/elements/tool.tsx +26 -5
- package/src/elements/voice-input.tsx +11 -2
- package/src/elements/voice-output.tsx +16 -3
- package/src/index.ts +4 -1
- 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/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 +33 -0
- package/src/primitives/use-speech-recognition.ts +12 -1
- package/src/primitives/use-stick-to-bottom.ts +34 -2
- package/src/primitives/use-text-stream.ts +33 -2
- package/src/remote/provider-runtime.ts +6 -3
- package/src/schemas/index.ts +1 -0
- package/src/schemas/tool-defs.ts +307 -6
- package/src/solid.ts +15 -0
- package/src/state/index.ts +13 -1
- package/src/state/mock.ts +92 -6
- package/src/state/persistence.ts +180 -0
- package/src/state/stream.ts +71 -4
- package/src/state/threads.ts +142 -0
- package/src/types.ts +4 -2
- 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/dialog.tsx +6 -0
- package/src/ui/dock.tsx +584 -0
- package/src/ui/dropdown.tsx +67 -23
- package/src/ui/hover-card.tsx +156 -6
- package/src/ui/icon.tsx +53 -0
- package/src/ui/input.tsx +275 -16
- 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/resizable.tsx +11 -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/src/wire/chunk.ts +47 -0
- package/src/wire/consume.ts +185 -26
- package/src/wire/diagnostics.ts +727 -0
- package/src/wire/encode-probe.ts +214 -0
- package/src/wire/encode.ts +267 -14
- package/src/wire/formats/anthropic.ts +8 -1
- package/src/wire/formats/openai.ts +5 -0
- package/src/wire/index.ts +22 -0
- package/src/wire/read.ts +250 -6
- package/src/wire/sse.ts +16 -3
- package/theme.css +84 -13
- package/dist/elements/chunks/action-icons-DW9muWrY.js +0 -1
- package/dist/elements/chunks/arrow-left-iJVnQmxA.js +0 -1
- package/dist/elements/chunks/artifact-BSuPYFHY.js +0 -1
- package/dist/elements/chunks/attachments-CL6TaqIb.js +0 -1
- package/dist/elements/chunks/audio-visualizer-BuUqQmaO.js +0 -1
- package/dist/elements/chunks/badge-TIMiJFKc.js +0 -1
- package/dist/elements/chunks/bash-InADTalH.js +0 -1
- package/dist/elements/chunks/card-renderer-CSoTL_e1.js +0 -1
- package/dist/elements/chunks/card-routing-BK09BdmL.js +0 -1
- package/dist/elements/chunks/chat-thread-DxoKaStk.js +0 -1
- package/dist/elements/chunks/check-MdLzbxrm.js +0 -1
- package/dist/elements/chunks/chevron-down-MK7IzDqe.js +0 -1
- package/dist/elements/chunks/chevron-right-C5jXhmtV.js +0 -1
- package/dist/elements/chunks/choice-card-CGMc3kek.js +0 -1
- package/dist/elements/chunks/circle-BG7VkPep.js +0 -1
- package/dist/elements/chunks/circle-check-GqvO2UBs.js +0 -1
- package/dist/elements/chunks/circle-x-mhH7pOK2.js +0 -1
- package/dist/elements/chunks/code-block-ClhQO9RW.js +0 -1
- package/dist/elements/chunks/collapsible-DBcBkFPh.js +0 -1
- package/dist/elements/chunks/composer-CZZmtYOT.js +0 -69
- package/dist/elements/chunks/confirm-card-BWjf2-xo.js +0 -1
- package/dist/elements/chunks/context-hKjNqiyQ.js +0 -1
- package/dist/elements/chunks/conversation-list-CsGJjSKG.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-B1Mem5wu.js +0 -1
- package/dist/elements/chunks/define-B_tXMYRm.js +0 -1
- package/dist/elements/chunks/disclosure-DAoYOKew.js +0 -1
- package/dist/elements/chunks/download-DnCyWFJE.js +0 -1
- package/dist/elements/chunks/dropdown-CmNna5lT.js +0 -1
- package/dist/elements/chunks/embed-CjAD2jSi.js +0 -1
- package/dist/elements/chunks/engine-javascript-vq0WuIJl.js +0 -141
- package/dist/elements/chunks/file-text-D0J9F6M7.js +0 -1
- package/dist/elements/chunks/folder-NV1pi_ud.js +0 -1
- package/dist/elements/chunks/form-Cp8Y00Wn.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-6KtXpLwT.js +0 -1
- package/dist/elements/chunks/html-CPZ3oZQ7.js +0 -1
- package/dist/elements/chunks/icon-97R8SR2p.js +0 -1
- package/dist/elements/chunks/info-C8r5Q6cc.js +0 -1
- package/dist/elements/chunks/input-DrseEjhp.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-OGJDUT-O.js +0 -1
- package/dist/elements/chunks/link-BdsfLB7b.js +0 -1
- package/dist/elements/chunks/loader-B5QzK_8_.js +0 -1
- package/dist/elements/chunks/message-CE4k-qaj.js +0 -1
- package/dist/elements/chunks/message-DtXKPqiR.js +0 -1
- package/dist/elements/chunks/message-square-C9ovmtOo.js +0 -1
- package/dist/elements/chunks/paperclip-Bg0ITU3b.js +0 -1
- package/dist/elements/chunks/progress-bar-D1_rzt6N.js +0 -1
- package/dist/elements/chunks/prompt-suggestion-D5Sm8xF1.js +0 -1
- package/dist/elements/chunks/reasoning-BrxQfpfI.js +0 -1
- package/dist/elements/chunks/rotate-cw-DzVDJOA1.js +0 -1
- package/dist/elements/chunks/scroll-area-93A1bbeG.js +0 -1
- package/dist/elements/chunks/scroll-button-CrTo7wm4.js +0 -1
- package/dist/elements/chunks/share-DgNbkJKY.js +0 -1
- package/dist/elements/chunks/slots-CIw9RlAe.js +0 -1
- package/dist/elements/chunks/source-w9V0NnBn.js +0 -1
- package/dist/elements/chunks/star-DHvACxtm.js +0 -1
- package/dist/elements/chunks/store-HIPGhNz9.js +0 -1
- package/dist/elements/chunks/svelte--5p79yCD.js +0 -1
- package/dist/elements/chunks/tasks-card-lPxoodlA.js +0 -1
- package/dist/elements/chunks/text-shimmer-BY_rI3s5.js +0 -1
- package/dist/elements/chunks/textarea-DPfuhswM.js +0 -1
- package/dist/elements/chunks/toast-store-VUZZBhzH.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-DJg32jGH.js +0 -1
- package/dist/elements/chunks/variant-custom-D5ZlmziF.js +0 -1
- package/dist/elements/chunks/video-Bb86fVYI.js +0 -1
- package/dist/elements/chunks/vue-BmIZj4XD.js +0 -1
- package/dist/elements/chunks/x-BOhjBeOd.js +0 -1
- package/dist/llms/llms-full.txt +0 -2834
- package/dist/llms/llms.txt +0 -156
- package/dist/primitives/card-validate-generator.testlib.d.ts +0 -20
- package/dist/register-impl-DGmGzrEM.js +0 -145
- package/dist/ui/stat.d.ts +0 -16
- package/dist/variant-custom-MkTNTycd.js +0 -1
- package/src/primitives/card-validate-generator.testlib.ts +0 -38
- 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/src/elements/slots.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Composition slots for `kai-*` elements. A slot is a named region a consumer
|
|
3
3
|
* fills with their own markup. This registry is the SINGLE SOURCE OF TRUTH:
|
|
4
4
|
* the facade derives its detection from it (and, later, docs are generated
|
|
5
|
-
* from it).
|
|
5
|
+
* from it).
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
/** `inject` = additive (the built-in region still renders, your markup is added
|
|
@@ -62,6 +62,39 @@ export const CONVERSATIONS_PARTS: PartDef[] = [
|
|
|
62
62
|
doc: 'The right-aligned trailing text on each conversation row (a count, status, or relative time). Set it per item via the `trailing` field; otherwise a short auto relative time is derived from `updatedAt`. Recolor or resize it from outside.',
|
|
63
63
|
recipe: 'kai-conversations::part(trailing) { color: var(--color-primary); font-variant-numeric: tabular-nums }',
|
|
64
64
|
},
|
|
65
|
+
{
|
|
66
|
+
name: 'items',
|
|
67
|
+
doc: 'The item-mode listbox region wrapping your slotted `<kai-conversation-item>` children.',
|
|
68
|
+
recipe: 'kai-conversations::part(items) { gap: 2px }',
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
/** Slots of `<kai-conversation-item>` — one composed row of a consumer-owned
|
|
73
|
+
* conversation loop (the default slot is the title). */
|
|
74
|
+
export const CONVERSATION_ITEM_SLOTS: SlotDef[] = [
|
|
75
|
+
{ name: 'leading', mode: 'inject', part: true, doc: 'Leading region before the title (an icon or avatar).' },
|
|
76
|
+
{ name: 'meta', mode: 'inject', part: true, doc: 'Meta region under the title (a timestamp or status line).' },
|
|
77
|
+
{ name: 'menu', mode: 'inject', part: true, doc: 'Your own row menu (a popover trigger). Never selects the row.' },
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
/** Styleable `::part`s of `<kai-conversation-item>`. (`leading`/`meta`/`menu`
|
|
81
|
+
* are covered by their slot defs' `part: true` flags.) */
|
|
82
|
+
export const CONVERSATION_ITEM_PARTS: PartDef[] = [
|
|
83
|
+
{
|
|
84
|
+
name: 'body',
|
|
85
|
+
doc: 'The activation surface inside the row (button role; carries aria-current and the roving tabindex). The focus ring paints here.',
|
|
86
|
+
recipe: 'kai-conversation-item::part(body) { outline-offset: 2px }',
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: 'row',
|
|
90
|
+
doc: 'The whole row surface. Carries `data-active` while selected.',
|
|
91
|
+
recipe: 'kai-conversation-item::part(row) { border-radius: 0.5rem }',
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: 'title',
|
|
95
|
+
doc: 'The title line (the default slot renders inside it).',
|
|
96
|
+
recipe: 'kai-conversation-item::part(title) { font-weight: 600 }',
|
|
97
|
+
},
|
|
65
98
|
];
|
|
66
99
|
|
|
67
100
|
/** Slots of `<kai-message>` — per-message composition seams. `before-body` and
|
|
@@ -183,6 +216,33 @@ export const SKELETON_PARTS: PartDef[] = [
|
|
|
183
216
|
},
|
|
184
217
|
];
|
|
185
218
|
|
|
219
|
+
/**
|
|
220
|
+
* The parts of ONE attachment item, declared by `components/attachments.tsx`
|
|
221
|
+
* and therefore surfaced by every element that renders an attachment — the
|
|
222
|
+
* standalone `<kai-attachments>` AND the thread inside `<kai-message>` /
|
|
223
|
+
* `<kai-chat>`. Shared rather than duplicated so the two can never document
|
|
224
|
+
* different names for the same node.
|
|
225
|
+
*
|
|
226
|
+
* These are a styling seam and a TESTING seam, and the second is why they exist
|
|
227
|
+
* at all. `examples/internal/openrouter-spike` proves "a user can see which file
|
|
228
|
+
* was attached" by locating these; before they existed it pinned the chip by
|
|
229
|
+
* `span.truncate` and broke the day the thread moved to the grid tile, while the
|
|
230
|
+
* filename was still plainly on screen. A published part is what lets an
|
|
231
|
+
* assertion name the thing rather than its current markup.
|
|
232
|
+
*/
|
|
233
|
+
export const ATTACHMENT_ITEM_PARTS: PartDef[] = [
|
|
234
|
+
{
|
|
235
|
+
name: 'attachment',
|
|
236
|
+
doc: 'One attachment item: the chip, row or tile, whichever variant is rendering. Restyle its background, radius or border from outside without caring which layout it is.',
|
|
237
|
+
recipe: 'kai-chat::part(attachment) { border-radius: 0.25rem }',
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
name: 'attachment-name',
|
|
241
|
+
doc: 'The attachment’s filename label. Present in every variant that shows one (a grid tile omits it for an image, which is its own label). Retune its type or hide it entirely.',
|
|
242
|
+
recipe: 'kai-chat::part(attachment-name) { font-size: 0.75rem }',
|
|
243
|
+
},
|
|
244
|
+
];
|
|
245
|
+
|
|
186
246
|
/** Styleable `::part`s of `<kai-message>`. (The `avatar` part is contributed by
|
|
187
247
|
* the `avatar` slot's `part: true` flag, so it is not repeated here.) */
|
|
188
248
|
export const MESSAGE_PARTS: PartDef[] = [
|
|
@@ -211,6 +271,10 @@ export const MESSAGE_PARTS: PartDef[] = [
|
|
|
211
271
|
doc: 'The citation row rendered from the message’s `source` parts: a wrapped row of chips below the bubble, never inside it. Restyle its spacing or hide it entirely from outside.',
|
|
212
272
|
recipe: 'kai-message::part(citations) { gap: 0.5rem }',
|
|
213
273
|
},
|
|
274
|
+
// A message renders its `file` parts through the same Attachment chrome
|
|
275
|
+
// `<kai-attachments>` uses, so it exposes the same handles. Shared, not
|
|
276
|
+
// restated — see ATTACHMENT_ITEM_PARTS.
|
|
277
|
+
...ATTACHMENT_ITEM_PARTS,
|
|
214
278
|
];
|
|
215
279
|
|
|
216
280
|
/** Styleable `::part`s of `<kai-attachments>`. */
|
|
@@ -220,6 +284,7 @@ export const ATTACHMENTS_PARTS: PartDef[] = [
|
|
|
220
284
|
doc: 'The image shown in an attachment’s hover-card preview. Bounded by default (max ~320×256, aspect preserved) so a large image never blows up the card. Raise or lower the cap from outside.',
|
|
221
285
|
recipe: 'kai-attachments::part(preview) { max-width: 32rem; max-height: 24rem }',
|
|
222
286
|
},
|
|
287
|
+
...ATTACHMENT_ITEM_PARTS,
|
|
223
288
|
];
|
|
224
289
|
|
|
225
290
|
/** Styleable `::part`s of `<kai-status>`. */
|
|
@@ -323,21 +388,21 @@ export const CARD_PARTS: PartDef[] = [
|
|
|
323
388
|
},
|
|
324
389
|
];
|
|
325
390
|
|
|
326
|
-
/**
|
|
327
|
-
* content into: brand/tabs, the upgrade/Design/user-menu cluster, a top banner). */
|
|
391
|
+
/** Slots of `<kai-workspace>` (the five shell regions; main also takes the default slot). */
|
|
328
392
|
export const WORKSPACE_SLOTS: SlotDef[] = [
|
|
329
|
-
{ name: '
|
|
330
|
-
{ name: '
|
|
331
|
-
{ name: 'main
|
|
332
|
-
{ name: '
|
|
393
|
+
{ name: 'header', mode: 'inject', part: true, doc: 'The top band across the full shell width (app bar, tabs, breadcrumbs).' },
|
|
394
|
+
{ name: 'start', mode: 'inject', part: true, doc: 'The inline-start aside column (a conversation rail, a nav, a file tree). Resizable and collapsible.' },
|
|
395
|
+
{ name: 'main', mode: 'inject', part: true, doc: 'The main region. Unnamed children project here too, via the default slot.' },
|
|
396
|
+
{ name: 'end', mode: 'inject', part: true, doc: 'The inline-end aside column (inspector, notes, preview). Resizable and collapsible.' },
|
|
397
|
+
{ name: 'footer', mode: 'inject', part: true, doc: 'The bottom band across the full shell width (status bar, disclaimers).' },
|
|
333
398
|
];
|
|
334
399
|
|
|
335
|
-
/** Styleable `::part`s of `<kai-workspace
|
|
400
|
+
/** Styleable `::part`s of `<kai-workspace>` (beyond the slot-backed header/start/main/end/footer parts). */
|
|
336
401
|
export const WORKSPACE_PARTS: PartDef[] = [
|
|
337
402
|
{
|
|
338
|
-
name: '
|
|
339
|
-
doc: '
|
|
340
|
-
recipe: 'kai-workspace::part(
|
|
403
|
+
name: 'aside',
|
|
404
|
+
doc: 'Both aside columns match this part (each also matches its own start/end part). Restyle the shared aside surface or border from outside; the --kai-workspace-start-* and --kai-workspace-end-* custom properties set the widths.',
|
|
405
|
+
recipe: 'kai-workspace::part(aside) { background: var(--color-card) }',
|
|
341
406
|
},
|
|
342
407
|
];
|
|
343
408
|
|
|
@@ -474,6 +539,18 @@ export const PROMPT_DOCK_PARTS: PartDef[] = [
|
|
|
474
539
|
},
|
|
475
540
|
];
|
|
476
541
|
|
|
542
|
+
/** Slots + styleable `::part`s of `<kai-dock>` (the floating corner launcher — not
|
|
543
|
+
* `<kai-prompt-dock>`, which is an in-flow tray around a prompt input). */
|
|
544
|
+
export const DOCK_SLOTS: SlotDef[] = [
|
|
545
|
+
{ name: 'panel', mode: 'replace', part: true, doc: 'The panel body. ANY element: a `<kai-chat>`, a form, your own component. The dock never reads or types it, and the default slot is the same region.' },
|
|
546
|
+
{ name: 'launcher', mode: 'inject', doc: 'Content inside the built-in button while CLOSED; defaults to a chat glyph. Text works as well as an icon: the button keeps its height and grows sideways into a pill, so a label like "Support" is not clipped. The BUTTON is never slotted away, because it owns aria-expanded, aria-controls, the toggle wiring and the focus return.' },
|
|
547
|
+
{ name: 'launcher-open', mode: 'inject', doc: 'Content inside the button while OPEN; defaults to a ✕. Fill only `launcher` and that glyph stays while open rather than morphing into a built-in that clashes with it.' },
|
|
548
|
+
];
|
|
549
|
+
export const DOCK_PARTS: PartDef[] = [
|
|
550
|
+
{ name: 'launcher', doc: 'The launcher button pinned to the corner: a disc by default, a pill once you slot a text label. Restyle its surface or shadow; --kai-dock-launcher-size sets its height and its minimum width.', recipe: 'kai-dock::part(launcher) { background: var(--color-info) }' },
|
|
551
|
+
{ name: 'badge', doc: 'The unread dot on the launcher, rendered only while closed and only when `unread` is set. Restyle its color or size.', recipe: 'kai-dock::part(badge) { background: var(--color-success) }' },
|
|
552
|
+
];
|
|
553
|
+
|
|
477
554
|
/** Styleable `::part`s of `<kai-segmented>`. */
|
|
478
555
|
export const SEGMENTED_PARTS: PartDef[] = [
|
|
479
556
|
{ name: 'track', doc: 'The segmented track (the pill container holding the segments). Restyle its background, radius, or padding.', recipe: 'kai-segmented::part(track) { border-radius: 9999px }' },
|
|
@@ -512,6 +589,13 @@ export const AGENT_CARD_PARTS: PartDef[] = [
|
|
|
512
589
|
{ name: 'menu', doc: 'The trailing overflow ("...") menu button.', recipe: 'kai-agent-card::part(menu) { opacity: 1 }' },
|
|
513
590
|
];
|
|
514
591
|
|
|
592
|
+
/** Styleable `::part`s of `<kai-code-block>` (one syntax-highlighted code block).
|
|
593
|
+
* The code region itself is not a part — it is rebuilt when the highlight lands,
|
|
594
|
+
* and its look is owned by the Shiki theme (`code-theme`). */
|
|
595
|
+
export const CODE_BLOCK_PARTS: PartDef[] = [
|
|
596
|
+
{ name: 'copy', doc: 'The copy-to-clipboard button in the header row. Hide it with `copy="false"` rather than CSS.', recipe: 'kai-code-block::part(copy) { color: var(--color-primary) }' },
|
|
597
|
+
];
|
|
598
|
+
|
|
515
599
|
/** Slots + styleable `::part`s of `<kai-dialog>` (the centered modal). */
|
|
516
600
|
export const DIALOG_SLOTS: SlotDef[] = [
|
|
517
601
|
{ name: 'header', mode: 'inject', part: true, doc: 'Optional title region at the top of the panel.' },
|
|
@@ -594,6 +678,13 @@ export const POPOVER_SLOTS: SlotDef[] = [
|
|
|
594
678
|
{ name: 'trigger', mode: 'replace', doc: 'The control that opens the popover (a button, an avatar, …). The panel anchors to it.' },
|
|
595
679
|
];
|
|
596
680
|
|
|
681
|
+
/** Slots of `<kai-dropdown>`. The menu body is the default slot; `trigger` is the
|
|
682
|
+
* VISUAL content of the built-in trigger button (never your own `<button>`/`<a>`,
|
|
683
|
+
* which would nest interactive elements — the `kai-menu` rule). */
|
|
684
|
+
export const DROPDOWN_SLOTS: SlotDef[] = [
|
|
685
|
+
{ name: 'trigger', mode: 'replace', doc: 'Visual content of the trigger button (an icon, text, an `<svg>`). Replaces the built-in trigger* content; name it with `label`.' },
|
|
686
|
+
];
|
|
687
|
+
|
|
597
688
|
/** Styleable `::part`s of `<kai-audio-visualizer>`. Every DOM variant (`bar`,
|
|
598
689
|
* `grid`, `radial`) shares the `bar`/`cell` markup pattern; the shader variants
|
|
599
690
|
* (`wave`, `aurora`) share the `canvas` part. Lit items ALSO carry the
|
|
@@ -631,7 +722,8 @@ export const AUDIO_VISUALIZER_PARTS: PartDef[] = [
|
|
|
631
722
|
export const ELEMENT_COMPOSITION: Record<string, ElementComposition> = {
|
|
632
723
|
'kai-chat': { slots: CHAT_SLOTS, parts: CHAT_PARTS },
|
|
633
724
|
'kai-command': { parts: COMMAND_PARTS },
|
|
634
|
-
'kai-conversations': { slots: CONVERSATIONS_SLOTS, parts: CONVERSATIONS_PARTS },
|
|
725
|
+
'kai-conversations': { slots: CONVERSATIONS_SLOTS, parts: CONVERSATIONS_PARTS, children: 'Your own `<kai-conversation-item>` rows (item mode: the consumer-owned loop). Data rows do not render while any are present.' },
|
|
726
|
+
'kai-conversation-item': { slots: CONVERSATION_ITEM_SLOTS, parts: CONVERSATION_ITEM_PARTS, children: 'The row title. `leading`, `meta` and `menu` are the named regions around it.' },
|
|
635
727
|
'kai-message': { slots: MESSAGE_SLOTS, parts: MESSAGE_PARTS },
|
|
636
728
|
'kai-thread': { slots: THREAD_SLOTS },
|
|
637
729
|
'kai-prompt-input': { slots: PROMPT_INPUT_SLOTS, parts: PROMPT_INPUT_PARTS },
|
|
@@ -650,7 +742,7 @@ export const ELEMENT_COMPOSITION: Record<string, ElementComposition> = {
|
|
|
650
742
|
'kai-voice-output': { parts: VOICE_OUTPUT_PARTS },
|
|
651
743
|
'kai-screen': { slots: SCREEN_SLOTS, parts: SCREEN_PARTS, children: 'The screen body, below the title bar.' },
|
|
652
744
|
'kai-card': { slots: CARD_SLOTS, parts: CARD_PARTS, children: 'The card body, below the header/media regions.' },
|
|
653
|
-
'kai-workspace': { slots: WORKSPACE_SLOTS, parts: WORKSPACE_PARTS },
|
|
745
|
+
'kai-workspace': { slots: WORKSPACE_SLOTS, parts: WORKSPACE_PARTS, children: 'The main region content (same region as the `main` slot): your `<kai-chat>`, or any app view.' },
|
|
654
746
|
'kai-nav': { parts: NAV_PARTS },
|
|
655
747
|
'kai-coachmark': { slots: COACHMARK_SLOTS, parts: COACHMARK_PARTS, children: 'The ANCHOR the coachmark points at: the element it attaches to and positions against. The bubble body is the `content` slot.' },
|
|
656
748
|
'kai-progress-bar': { parts: PROGRESS_BAR_PARTS },
|
|
@@ -664,6 +756,7 @@ export const ELEMENT_COMPOSITION: Record<string, ElementComposition> = {
|
|
|
664
756
|
'kai-pane-group': { parts: PANE_GROUP_PARTS, children: 'Content shown for every tab. Use it INSTEAD of the per-tab `slot="<tab id>"` seams when you swap the content yourself.' },
|
|
665
757
|
'kai-agent-card': { parts: AGENT_CARD_PARTS },
|
|
666
758
|
'kai-dialog': { slots: DIALOG_SLOTS, parts: DIALOG_PARTS, children: 'The dialog body, between the `header` and `footer` slots.' },
|
|
759
|
+
'kai-dock': { slots: DOCK_SLOTS, parts: DOCK_PARTS, children: 'The panel body, the same region as `slot="panel"`.' },
|
|
667
760
|
'kai-input': { slots: INPUT_SLOTS, parts: INPUT_PARTS },
|
|
668
761
|
'kai-search': { parts: SEARCH_PARTS },
|
|
669
762
|
'kai-kbd': { parts: KBD_PARTS, children: 'Literal key text, when you are not using the `keys` prop to render key caps.' },
|
|
@@ -671,9 +764,11 @@ export const ELEMENT_COMPOSITION: Record<string, ElementComposition> = {
|
|
|
671
764
|
'kai-empty': { slots: EMPTY_SLOTS, children: 'The empty-state body below the title/description, usually the call to action.' },
|
|
672
765
|
'kai-file-upload': { children: 'Custom dropzone content, replacing the default label (the `label` prop is the fallback).' },
|
|
673
766
|
'kai-popover': { slots: POPOVER_SLOTS, children: 'The popover panel body. The control that opens it is the `trigger` slot.' },
|
|
767
|
+
'kai-dropdown': { slots: DROPDOWN_SLOTS, children: 'The menu body: your own rows. Give each `role="menuitem"`. The control that opens it is the `trigger` slot.' },
|
|
674
768
|
'kai-resizable': { children: 'The `<kai-resizable-item>` panels, in order. Dividers are inserted between them.' },
|
|
675
769
|
'kai-resizable-item': { children: 'This panel\'s content.' },
|
|
676
770
|
'kai-tooltip': { children: 'The TRIGGER the tooltip describes. The tip text is the `text` prop.' },
|
|
771
|
+
'kai-code-block': { parts: CODE_BLOCK_PARTS },
|
|
677
772
|
'kai-audio-visualizer': { parts: AUDIO_VISUALIZER_PARTS },
|
|
678
773
|
};
|
|
679
774
|
|
package/src/elements/styles.css
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
|
-
/* Element-bundle stylesheet
|
|
2
|
-
custom element's shadow root
|
|
1
|
+
/* Element-bundle stylesheet, and the SOURCE OF TRUTH for element CSS. Compiled to
|
|
2
|
+
compiled.css and injected into each custom element's shadow root;
|
|
3
|
+
.storybook/styles.css @imports this file rather than restating it, so a rule
|
|
4
|
+
added here reaches the shadow roots AND the light-DOM Solid stories at once.
|
|
5
|
+
|
|
6
|
+
It used to be the other way round — Storybook hand-copied a few of these rules
|
|
7
|
+
under "Mirror the shipped ..." comments. Nothing enforced the copy, so
|
|
8
|
+
.kai-radio, .kai-checkbox, .kai-range and .kai-focus-inset were simply missing
|
|
9
|
+
there: three form controls rendered as raw OS chrome in every story while the
|
|
10
|
+
shipped element rendered them fully designed, and an agent and the owner each
|
|
11
|
+
concluded the kit had unstyled controls. Never copy a rule from here into the
|
|
12
|
+
Storybook sheet; add it here.
|
|
13
|
+
|
|
14
|
+
The one thing that cannot cross is :host, which selects nothing in the light
|
|
15
|
+
DOM. Its defaults are re-stated on `body` in the Storybook sheet's shim. */
|
|
3
16
|
@import "tailwindcss";
|
|
4
17
|
/* tw-animate-css supplies the animate-in/animate-out + slide/fade/zoom utilities
|
|
5
18
|
the kit uses for every overlay enter/exit (toast, popover, tooltip, dropdown,
|
|
@@ -16,10 +29,19 @@
|
|
|
16
29
|
/* Base typography is token-driven so a theme can restyle it. --kai-font-base is
|
|
17
30
|
the family for ALL text/UI (named "base", not "sans", so a serif body works);
|
|
18
31
|
--kai-tracking is global letter-spacing. Both pierce the Shadow DOM via the
|
|
19
|
-
var() fallback, exactly like the --kai-color-* tokens.
|
|
32
|
+
var() fallback, exactly like the --kai-color-* tokens.
|
|
33
|
+
|
|
34
|
+
font-size is the third: without it every shadow root inherited the DOCUMENT's
|
|
35
|
+
size (16px in a stock page), so any surface that never set an explicit text-*
|
|
36
|
+
class rendered a step larger than the rest of the kit and looked like a bug in
|
|
37
|
+
that one component. --text-body is the scale's primary reading size and itself
|
|
38
|
+
resolves through --kai-text-body, so overriding that one token still moves the
|
|
39
|
+
default. The literal fallback matches theme.css's --text-body so the rule is
|
|
40
|
+
still correct if this sheet is ever used without the @theme block. */
|
|
20
41
|
:host {
|
|
21
42
|
display: block;
|
|
22
43
|
font-family: var(--kai-font-base, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);
|
|
44
|
+
font-size: var(--text-body, var(--kai-text-body, 0.875rem));
|
|
23
45
|
letter-spacing: var(--kai-tracking, normal);
|
|
24
46
|
}
|
|
25
47
|
/* Code/monospace surfaces use --kai-font-code (named for its ROLE — code — not
|
|
@@ -40,12 +62,23 @@
|
|
|
40
62
|
/* One token-driven focus ring for EVERY focusable element in the shadow root.
|
|
41
63
|
Blue by default (via --color-ring), consistent in light + dark, and
|
|
42
64
|
overridable through --kai-color-ring. Uses `outline` (not a box-shadow
|
|
43
|
-
ring)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
the
|
|
65
|
+
ring) because it follows the element's radius and — unlike a `ring-*`
|
|
66
|
+
utility — is written in literal values, so it does not depend on any
|
|
67
|
+
`--tw-*` custom property. That matters more than it looks: `@property`
|
|
68
|
+
registration is document-global and is ignored inside a shadow root, so
|
|
69
|
+
every `--tw-*` here is unset and every `ring-*` utility computes to
|
|
70
|
+
nothing. This literal rule is the only reason most of the kit had a focus
|
|
71
|
+
indicator at all. `:focus-visible` so it only appears for keyboard
|
|
72
|
+
navigation, never on a mouse click. Components that render their own ring
|
|
73
|
+
set `focus-visible:outline-none` (a utility in a later cascade layer) and
|
|
74
|
+
win over this — so there's no double ring, just a guaranteed blue fallback
|
|
75
|
+
for the many controls that have no explicit focus style.
|
|
76
|
+
|
|
77
|
+
CAVEAT, learned the hard way: an outline is NOT immune to clipping. It is
|
|
78
|
+
unaffected by the element's OWN overflow, but `outline-offset: 2px` draws
|
|
79
|
+
it entirely outside the border box, where an ANCESTOR with
|
|
80
|
+
`overflow: clip`/`hidden` erases it completely. Controls that sit flush
|
|
81
|
+
inside such a container need `.kai-focus-inset` below. */
|
|
49
82
|
:focus-visible {
|
|
50
83
|
outline: 2px solid var(--color-ring);
|
|
51
84
|
outline-offset: 2px;
|
|
@@ -72,6 +105,40 @@
|
|
|
72
105
|
*::-webkit-scrollbar-thumb:hover { background-color: var(--color-scrollbar-thumb-hover); }
|
|
73
106
|
*::-webkit-scrollbar-corner { background: transparent; }
|
|
74
107
|
|
|
108
|
+
/* SELECTED text, kit-owned. Scoped to the shadow root — deliberately, and this
|
|
109
|
+
is the whole design decision, so read it before "simplifying" it into
|
|
110
|
+
theme.css.
|
|
111
|
+
|
|
112
|
+
WHY THE KIT OWNS IT AT ALL: left to the UA, the browser's blue selection was
|
|
113
|
+
visually stronger than the kit's OWN deliberate emphasis (the composer's
|
|
114
|
+
--color-highlight mark), so an incidental drag-select outranked a keyword the
|
|
115
|
+
app had flagged on purpose. How selected text reads is a fact about the
|
|
116
|
+
medium, which is the kit's call.
|
|
117
|
+
|
|
118
|
+
WHY ONLY HERE, AND NOT IN theme.css: theme.css is imported into a CONSUMER's
|
|
119
|
+
Tailwind build, so a bare ::selection there would restyle every paragraph on
|
|
120
|
+
their page — the kit deciding for the app's own content, which is not ours to
|
|
121
|
+
decide. The shadow root IS the kit's DOM, so the same rule is unambiguous
|
|
122
|
+
here. Identical reasoning to the scrollbar and :focus-visible rules above,
|
|
123
|
+
which are scoped the same way and for the same reason. theme.css therefore
|
|
124
|
+
carries the TOKENS only, and a Solid-layer consumer rendering our components
|
|
125
|
+
into their own light DOM opts in with one rule of their own:
|
|
126
|
+
`.my-chat ::selection { background-color: var(--color-selection); … }`.
|
|
127
|
+
|
|
128
|
+
WHY THE RULE MUST BE IN THIS SHEET AND NOT INHERITED: ::selection does NOT
|
|
129
|
+
cross the shadow boundary the way ordinary inherited properties do — a
|
|
130
|
+
document-level ::selection leaves shadow content on the UA default. The
|
|
131
|
+
--kai-color-selection TOKEN does pierce (custom properties inherit normally),
|
|
132
|
+
which is what keeps a consumer override working.
|
|
133
|
+
|
|
134
|
+
Both background AND color are set; see the theme.css note for why the
|
|
135
|
+
foreground is load-bearing rather than cosmetic (coloured text falls under
|
|
136
|
+
WCAG AA on this fill if it keeps its own colour). */
|
|
137
|
+
::selection {
|
|
138
|
+
background-color: var(--color-selection);
|
|
139
|
+
color: var(--color-selection-foreground);
|
|
140
|
+
}
|
|
141
|
+
|
|
75
142
|
/* Respect a user's reduced-motion preference: disable the tw-animate-css
|
|
76
143
|
enter/exit keyframe animations (toasts, overlays, cards) so they appear and
|
|
77
144
|
disappear instantly instead of sliding/fading. Targets the utility classes
|
|
@@ -87,6 +154,19 @@
|
|
|
87
154
|
}
|
|
88
155
|
|
|
89
156
|
@layer components {
|
|
157
|
+
/* Focus ring drawn INSIDE the element's border box, for focusable regions
|
|
158
|
+
that sit flush against a clipping ancestor. The scrollable code-block body
|
|
159
|
+
and the message log are both `overflow-*` regions filling a rounded
|
|
160
|
+
`overflow: clip` container, so the default `outline-offset: 2px` put the
|
|
161
|
+
whole ring outside the clip and it never painted — the outline computed
|
|
162
|
+
correctly, matched `:focus-visible`, and was erased before it reached the
|
|
163
|
+
screen. A negative offset keeps it clear of the boundary. Same token and
|
|
164
|
+
width as the base ring, so it reads identically. */
|
|
165
|
+
.kai-focus-inset:focus-visible {
|
|
166
|
+
outline: 2px solid var(--color-ring);
|
|
167
|
+
outline-offset: -2px;
|
|
168
|
+
}
|
|
169
|
+
|
|
90
170
|
/* Designed radio + checkbox (appearance-none) so the form controls read as
|
|
91
171
|
intentional, theme correctly in light/dark, and have comfortable targets —
|
|
92
172
|
replacing the weak native defaults. Used via `.kai-radio` / `.kai-checkbox`. */
|
|
@@ -145,6 +225,36 @@
|
|
|
145
225
|
.kai-checkbox:checked {
|
|
146
226
|
box-shadow: 0 1px 4px color-mix(in srgb, var(--color-primary) 26%, transparent);
|
|
147
227
|
}
|
|
228
|
+
/* The mixed state ("some of the children below are ticked"). `indeterminate` is a
|
|
229
|
+
DOM property with no HTML attribute, so a rule is the ONLY way it can be seen —
|
|
230
|
+
without one a mixed box paints pixel-identically to an unchecked one and lies
|
|
231
|
+
about its state. That was live: `<kai-tasks>` in `select` mode puts an
|
|
232
|
+
indeterminate select-all above a partial selection, and it read as "none
|
|
233
|
+
selected".
|
|
234
|
+
|
|
235
|
+
Same fill and the same masked `::after` as `:checked`, with the tick mask
|
|
236
|
+
swapped for a bar, so the two states are siblings of one technique rather than
|
|
237
|
+
two: the bar is `--color-primary-foreground` on `--color-primary`, exactly the
|
|
238
|
+
pair the tick already uses, so it themes and contrasts identically in both
|
|
239
|
+
themes and stays consumer-themable through the same tokens.
|
|
240
|
+
|
|
241
|
+
Ordered AFTER the `:checked` rules on purpose. `indeterminate` is independent of
|
|
242
|
+
`checked`, so a box can be both; specificity is equal, so source order decides,
|
|
243
|
+
and mixed-wins is what the browser's own native rendering does.
|
|
244
|
+
|
|
245
|
+
Scoped to `.kai-checkbox` on purpose: `:indeterminate` also matches every radio
|
|
246
|
+
in a group with nothing selected, and an empty radio group must go on reading as
|
|
247
|
+
empty rather than sprouting a third state. */
|
|
248
|
+
.kai-checkbox:indeterminate {
|
|
249
|
+
background-color: var(--color-primary);
|
|
250
|
+
border-color: var(--color-primary);
|
|
251
|
+
box-shadow: 0 1px 4px color-mix(in srgb, var(--color-primary) 26%, transparent);
|
|
252
|
+
}
|
|
253
|
+
.kai-checkbox:indeterminate::after {
|
|
254
|
+
transform: scale(1);
|
|
255
|
+
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
256
|
+
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
257
|
+
}
|
|
148
258
|
.kai-radio:disabled,
|
|
149
259
|
.kai-checkbox:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
150
260
|
|
|
@@ -25,10 +25,19 @@ defineWebComponent<Props, Events>('kai-thinking-bar', {
|
|
|
25
25
|
text: 'Thinking',
|
|
26
26
|
stoppable: false,
|
|
27
27
|
stopLabel: 'Answer now',
|
|
28
|
-
}, (props, { dispatch, flag }) =>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
)
|
|
28
|
+
}, (props, { dispatch, flag, reflectFlag }) => {
|
|
29
|
+
// `stoppable` reflects, following kai-tool's `disabled` (its FIX1). Without it the
|
|
30
|
+
// remove direction is dead: `el.removeAttribute('stoppable')` parses to `undefined`,
|
|
31
|
+
// the prop was already `undefined` after a bare-attribute add, so no prop change
|
|
32
|
+
// fires and `flag()`'s non-reactive hasAttribute fallback is never re-read — the
|
|
33
|
+
// stop affordance stays rendered forever. reflectFlag's coercing read-back resolves
|
|
34
|
+
// every write through the same `flag()` policy, making both directions reactive.
|
|
35
|
+
reflectFlag('stoppable');
|
|
36
|
+
return (
|
|
37
|
+
<ThinkingBar
|
|
38
|
+
text={props.text}
|
|
39
|
+
stopLabel={props.stopLabel}
|
|
40
|
+
onStop={flag('stoppable') ? () => dispatch('kai-stop') : undefined}
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
});
|
package/src/elements/thread.tsx
CHANGED
|
@@ -128,6 +128,8 @@ defineWebComponent<Props, Events>('kai-thread', {
|
|
|
128
128
|
scrollButton={props.scrollButton !== false}
|
|
129
129
|
cardTypes={cardComponentsFromTags(props.cardTypes as Record<string, string> | undefined, (props as { theme?: string }).theme)}
|
|
130
130
|
cardSchemas={props.cardSchemas as Record<string, object> | undefined}
|
|
131
|
+
/* F-26: card parts emit off THIS element as the bubbling `kai-card` event. */
|
|
132
|
+
cardHostElement={element}
|
|
131
133
|
empty={slots()['empty'] ? <slot name="empty" /> : undefined}
|
|
132
134
|
onMessageAction={(detail) => dispatch('kai-message-action', detail)}
|
|
133
135
|
controllerRef={(c) => (controller = c)}
|
package/src/elements/toast.tsx
CHANGED
|
@@ -5,7 +5,11 @@ import { toast as toastStore, type ToastItem } from '../primitives/toast-store';
|
|
|
5
5
|
interface Props extends Record<string, unknown> {
|
|
6
6
|
/** The toasts to render. Newest is shown on top. Set as a JS property (array);
|
|
7
7
|
* pass a new array reference to update. Omit for an empty region, which is
|
|
8
|
-
* the normal resting state and how the imperative `toast()` API starts.
|
|
8
|
+
* the normal resting state and how the imperative `toast()` API starts.
|
|
9
|
+
* Note the handover: the first `toast()` call ADOPTS a region you placed in
|
|
10
|
+
* markup (no second region mounts) and binds the imperative store to this
|
|
11
|
+
* property, replacing any array you set. Drive a region as data OR via
|
|
12
|
+
* `toast()`, not both at once. */
|
|
9
13
|
toasts?: ToastItem[];
|
|
10
14
|
/** Stack anchor: `'top-center'` (default), `'top-right'`, `'bottom-center'`, … */
|
|
11
15
|
position?: ToastPosition;
|
|
@@ -41,12 +45,24 @@ interface Events {
|
|
|
41
45
|
* also usable declaratively — set `el.toasts = [...]` (a JS property, never an
|
|
42
46
|
* attribute) and listen for `kai-dismiss` / `kai-action`.
|
|
43
47
|
*
|
|
48
|
+
* The two modes meet gracefully: `toast()` ADOPTS the first connected
|
|
49
|
+
* `<kai-toast-region>` already in the document instead of mounting a second
|
|
50
|
+
* one, and creates its own on `document.body` only when none exists. Adoption
|
|
51
|
+
* keeps your authored attributes (position/stack/appearance) but binds the
|
|
52
|
+
* imperative store to `toasts`, replacing an array you were driving as data —
|
|
53
|
+
* so within one app, either own the array or call `toast()`, not both. With
|
|
54
|
+
* two or more regions placed, the first in document order is adopted and a
|
|
55
|
+
* one-time console.warn flags the ambiguity.
|
|
56
|
+
*
|
|
44
57
|
* Because it is a real `kai-*` element it carries its own shadow root + the
|
|
45
58
|
* shared kit stylesheet, so it is viewport-positioned AND kit-styled.
|
|
46
59
|
*
|
|
47
60
|
* Stack-level defaults are also declarative: `<kai-toast-region appearance="card"
|
|
48
61
|
* inverse>` makes every toast that doesn't set its own `appearance`/`inverse`
|
|
49
62
|
* render as an inverted card. A per-toast value always wins.
|
|
63
|
+
*
|
|
64
|
+
* Your app chrome must stay below the toast layer; set `--kai-toast-z`
|
|
65
|
+
* (default 100) on the host to move the layer.
|
|
50
66
|
*/
|
|
51
67
|
defineWebComponent<Props, Events>('kai-toast-region', {
|
|
52
68
|
toasts: [],
|
package/src/elements/tool.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Show } from 'solid-js';
|
|
1
|
+
import { createSignal, Show } from 'solid-js';
|
|
2
2
|
import { defineWebComponent } from './define';
|
|
3
3
|
import { Tool, type ToolPart } from '../components/tool';
|
|
4
4
|
import { wireDisclosure } from './disclosure';
|
|
@@ -36,13 +36,34 @@ defineWebComponent<Props, Events>('kai-tool', {
|
|
|
36
36
|
defaultOpen: undefined,
|
|
37
37
|
disabled: undefined,
|
|
38
38
|
}, (props, ctx) => {
|
|
39
|
-
const { flag } = ctx;
|
|
40
|
-
|
|
39
|
+
const { flag, reflectFlag } = ctx;
|
|
40
|
+
|
|
41
|
+
// A SIGNAL, not a `let`. This facade gates its whole subtree on `<Show when={props.tool}>`,
|
|
42
|
+
// and `tool` is an object prop, so the only sequence a consumer of the HTML spelling
|
|
43
|
+
// has is markup-then-assign: the element connects with no tool, renders nothing, and
|
|
44
|
+
// the Collapsible — and therefore the controller — arrives a tick later.
|
|
45
|
+
//
|
|
46
|
+
// With a plain `let`, wireDisclosure's effects ran once against `undefined` and never
|
|
47
|
+
// again, because the getter they were handed was not reactive and a bare `open`
|
|
48
|
+
// attribute never changes `props.open` to re-trigger them. Net result: `<kai-tool open>`
|
|
49
|
+
// silently stayed shut while `el.open` read back `true` — the property and the
|
|
50
|
+
// rendering disagreed. Making the controller reactive is the whole fix: the effects
|
|
51
|
+
// re-run the moment it lands. `Tool` already tracks its own copy this way internally.
|
|
52
|
+
// Pinned by the ordering rows in tests/elements/tool.test.tsx.
|
|
53
|
+
const [api, setApi] = createSignal<CollapsibleController>();
|
|
41
54
|
|
|
42
55
|
// The standard disclosure surface: settable+reflecting `open`, kai-open-change,
|
|
43
56
|
// show/hide/toggle, disabled-gating. See ./disclosure. This is the SOLE emitter
|
|
44
57
|
// of kai-open-change — the Tool/Collapsible no longer wires its own.
|
|
45
|
-
wireDisclosure(ctx,
|
|
58
|
+
wireDisclosure(ctx, api, () => props.open);
|
|
59
|
+
|
|
60
|
+
// `disabled` reflects too, following kai-dock. Without it the prop is write-only in
|
|
61
|
+
// the read direction AND deaf in the write one: `el.setAttribute('disabled', '')`
|
|
62
|
+
// after mount is parsed by component-register to `undefined`, so the prop never
|
|
63
|
+
// changes and nothing re-renders. reflectFlag's coercing setter resolves that
|
|
64
|
+
// `undefined` back through the same `flag()` policy, which is what makes the plain
|
|
65
|
+
// HTML gesture work at runtime and not only at parse time (findings G-05).
|
|
66
|
+
reflectFlag('disabled');
|
|
46
67
|
|
|
47
68
|
return (
|
|
48
69
|
<Show when={props.tool}>
|
|
@@ -50,7 +71,7 @@ defineWebComponent<Props, Events>('kai-tool', {
|
|
|
50
71
|
toolPart={props.tool!}
|
|
51
72
|
defaultOpen={flag('defaultOpen')}
|
|
52
73
|
disabled={flag('disabled')}
|
|
53
|
-
controllerRef={(a) => (
|
|
74
|
+
controllerRef={(a) => setApi(a)}
|
|
54
75
|
/>
|
|
55
76
|
</Show>
|
|
56
77
|
);
|
|
@@ -39,6 +39,13 @@ interface Events {
|
|
|
39
39
|
* push-to-talk indicator) in sync with the mic. Fires on real transitions
|
|
40
40
|
* only (manual click and programmatic start()/stop()), never on mount. */
|
|
41
41
|
'kai-recording-change': { recording: boolean };
|
|
42
|
+
/** A voice session failed, so no failure is ever silent. `detail.source` names
|
|
43
|
+
* the failing side (`recognition` on `<kai-voice-input>`, `synthesis` on
|
|
44
|
+
* `<kai-voice-output>`), `detail.error` carries the platform error code, the
|
|
45
|
+
* thrown exception's name, or `no-result` when recognition ended with no error
|
|
46
|
+
* and no text (the user said nothing), and `detail.message` is human-readable.
|
|
47
|
+
* Deliberate cancellation does not fire. */
|
|
48
|
+
'kai-voice-error': { source: 'recognition'; error: string; message: string };
|
|
42
49
|
}
|
|
43
50
|
|
|
44
51
|
/**
|
|
@@ -47,8 +54,9 @@ interface Events {
|
|
|
47
54
|
* `SpeechRecognition` (Chrome/Safari; no Firefox — and cloud-based in Chrome).
|
|
48
55
|
* Set `el.transcribe` to route audio through your own async transcriber instead.
|
|
49
56
|
* Where neither is available it records the blob and emits `kai-audio-captured`
|
|
50
|
-
* with no text. Also emits `kai-transcription` (final text)
|
|
51
|
-
* `kai-transcript-interim`
|
|
57
|
+
* with no text. Also emits `kai-transcription` (final text), `kai-voice-error`
|
|
58
|
+
* (a failed or empty session) and, with `interim`, `kai-transcript-interim`
|
|
59
|
+
* (live partials).
|
|
52
60
|
*/
|
|
53
61
|
defineWebComponent<Props, Events>('kai-voice-input', {
|
|
54
62
|
transcribe: undefined,
|
|
@@ -85,6 +93,7 @@ defineWebComponent<Props, Events>('kai-voice-input', {
|
|
|
85
93
|
onTranscription={(text) => dispatch('kai-transcription', { text })}
|
|
86
94
|
onInterim={(text) => dispatch('kai-transcript-interim', { text })}
|
|
87
95
|
onRecordingChange={(recording) => dispatch('kai-recording-change', { recording })}
|
|
96
|
+
onError={(detail) => dispatch('kai-voice-error', detail)}
|
|
88
97
|
controllerRef={(c) => (controller = c)}
|
|
89
98
|
/>
|
|
90
99
|
);
|
|
@@ -20,18 +20,30 @@ interface Props extends Record<string, unknown> {
|
|
|
20
20
|
|
|
21
21
|
/** Events fired by `<kai-voice-output>`. */
|
|
22
22
|
interface Events {
|
|
23
|
-
/** Playback started or stopped. Drive your own UI in sync.
|
|
24
|
-
*
|
|
23
|
+
/** Playback started or stopped. Drive your own UI in sync. `speaking: true`
|
|
24
|
+
* fires when audio actually starts (utterance.onstart natively; audio playback
|
|
25
|
+
* beginning on the `synthesize` path), not when speak() is called; earlier
|
|
26
|
+
* releases fired it optimistically inside speak() itself. Fires on real
|
|
27
|
+
* transitions only (manual click and programmatic speak()/stop()), never on
|
|
28
|
+
* mount. */
|
|
25
29
|
'kai-speaking-change': { speaking: boolean };
|
|
26
30
|
/** The model path (`synthesize`) resolved audio: the raw `Blob` before playback. */
|
|
27
31
|
'kai-synthesized': { blob: Blob };
|
|
32
|
+
/** A voice session failed, so no failure is ever silent. `detail.source` names
|
|
33
|
+
* the failing side (`recognition` on `<kai-voice-input>`, `synthesis` on
|
|
34
|
+
* `<kai-voice-output>`), `detail.error` carries the platform error code, the
|
|
35
|
+
* thrown exception's name, or `no-result` when recognition ended with no error
|
|
36
|
+
* and no text (the user said nothing), and `detail.message` is human-readable.
|
|
37
|
+
* Deliberate cancellation does not fire. */
|
|
38
|
+
'kai-voice-error': { source: 'synthesis'; error: string; message: string };
|
|
28
39
|
}
|
|
29
40
|
|
|
30
41
|
/**
|
|
31
42
|
* `<kai-voice-output>` — a speaker button that reads `text` aloud. Native by
|
|
32
43
|
* default (`speechSynthesis`); set `el.synthesize` to route through your TTS
|
|
33
44
|
* model instead. The output sibling of `<kai-voice-input>`. Emits
|
|
34
|
-
* `kai-speaking-change` and (model
|
|
45
|
+
* `kai-speaking-change`, `kai-voice-error` (a failed synthesis) and (model
|
|
46
|
+
* path) `kai-synthesized`.
|
|
35
47
|
*/
|
|
36
48
|
defineWebComponent<Props, Events>('kai-voice-output', {
|
|
37
49
|
text: '',
|
|
@@ -63,6 +75,7 @@ defineWebComponent<Props, Events>('kai-voice-output', {
|
|
|
63
75
|
onSynthesize={props.synthesize ? (text) => props.synthesize!(text) : undefined}
|
|
64
76
|
onSpeakingChange={(speaking) => dispatch('kai-speaking-change', { speaking })}
|
|
65
77
|
onSynthesized={(blob) => dispatch('kai-synthesized', { blob })}
|
|
78
|
+
onError={(detail) => dispatch('kai-voice-error', detail)}
|
|
66
79
|
controllerRef={(c) => (controller = c)}
|
|
67
80
|
/>
|
|
68
81
|
);
|
package/src/index.ts
CHANGED
|
@@ -339,6 +339,8 @@ export type { VoiceInputProps, VoiceInputController } from './components/voice-i
|
|
|
339
339
|
export { ConversationList } from './components/conversation-list';
|
|
340
340
|
export type { ConversationListProps, ConversationListController } from './components/conversation-list';
|
|
341
341
|
export { ConversationItem } from './components/conversation-item';
|
|
342
|
+
export { SlottedConversationItem } from './components/conversation-item';
|
|
343
|
+
export type { SlottedConversationItemProps } from './components/conversation-item';
|
|
342
344
|
export type { ConversationItemProps } from './components/conversation-item';
|
|
343
345
|
export { ModelSwitcher } from './components/model-switcher';
|
|
344
346
|
export type { ModelSwitcherProps } from './components/model-switcher';
|
|
@@ -417,7 +419,8 @@ export type { KaiTabItem } from './ui/tabs';
|
|
|
417
419
|
export type { PaneStatus } from './ui/pane';
|
|
418
420
|
export type { PaneTab } from './ui/pane-group';
|
|
419
421
|
export type {
|
|
420
|
-
KaiCommandItem, KaiContextUsage, KaiMenuItem, KaiSegmentedOption,
|
|
422
|
+
KaiCheckboxOption, KaiCommandItem, KaiContextUsage, KaiMenuItem, KaiRadioOption, KaiSegmentedOption, KaiSelectOption,
|
|
423
|
+
KaiSourceItem,
|
|
421
424
|
} from './elements/element-data-types';
|
|
422
425
|
// `kai-audio-visualizer.shader` takes a ShaderSpec. The element arrived from main
|
|
423
426
|
// after this block was written, and prop-types-exported.test.ts caught it, which
|