@kitn.ai/ui 0.28.0 → 0.30.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 +11 -7
- package/dist/{Icon-DObhsRtm.js → Icon-BzBET3E-.js} +1 -1
- package/dist/{action-icons-CcgNN2oT.js → action-icons-DaW2pU6m.js} +1 -1
- package/dist/agent-tooling/construct/public.d.ts +15 -0
- package/dist/agent-tooling/construct/schema.d.ts +111 -0
- package/dist/arrow-down-D783iMJj.js +1 -0
- package/dist/arrow-left-0VLM5kyg.js +1 -0
- package/dist/artifact-DGjzHYUT.js +1 -0
- package/dist/{attachments-Qr4kg-2b.js → attachments-YvXHlg88.js} +1 -1
- package/dist/{audio-visualizer-DToYdfSc.js → audio-visualizer-9lz5IHsL.js} +1 -1
- package/dist/{badge-CdEu_jn2.js → badge-Dh_vp8A5.js} +1 -1
- package/dist/{bell-DQAAOpDz.js → bell-CT7_WUwS.js} +1 -1
- package/dist/{button-DkuOnGLy.js → button-C_3te6fm.js} +1 -1
- package/dist/{card-renderer-Jx70m6_l.js → card-renderer-DZVaGH2e.js} +1 -1
- package/dist/check-CiEOVnEN.js +1 -0
- package/dist/{checkbox-D7iRB3nL.js → checkbox-Bu2T2e0U.js} +1 -1
- package/dist/{checkbox-group-B2_rpoPM.js → checkbox-group-BiryEXPQ.js} +1 -1
- package/dist/chevron-down-CSobuZRG.js +1 -0
- package/dist/chevron-right-DR9ZAP-2.js +1 -0
- package/dist/{choice-card-m0BYqqOK.js → choice-card-CM6IjkmL.js} +1 -1
- package/dist/circle-BC66EYF7.js +1 -0
- package/dist/circle-check-BqmahW0O.js +1 -0
- package/dist/{circle-x-BPG0iPst.js → circle-x-Bk-dA5Wf.js} +1 -1
- package/dist/{code-block-ClMLKb7C.js → code-block-B26t-Q7q.js} +1 -1
- package/dist/{collapsible-B4DlWicL.js → collapsible-Bhc636Cf.js} +1 -1
- package/dist/components/builder-composer-triggers.d.ts +62 -0
- package/dist/components/builder-layout.d.ts +54 -0
- package/dist/components/builder-message-actions.d.ts +72 -0
- package/dist/components/builder-panel.d.ts +189 -0
- package/dist/components/builder-preview.d.ts +11 -0
- package/dist/components/builder-shell-controls.d.ts +69 -0
- package/dist/components/builder-skeleton.d.ts +58 -0
- package/dist/components/builder-start.d.ts +75 -0
- package/dist/components/builder-workspace-variants.d.ts +23 -0
- package/dist/components/captions.d.ts +66 -0
- package/dist/{composer-sQ0HcvyG.js → composer-DMI85B6j.js} +1 -1
- package/dist/{confirm-card-rQWDQsnC.js → confirm-card-B0YIAwXp.js} +1 -1
- package/dist/construct-cli.es.js +3 -3
- package/dist/construct.d.ts +5 -0
- package/dist/construct.js +327 -0
- package/dist/{context-0kg4ZX1J.js → context-DWgfhqWp.js} +1 -1
- package/dist/controllable-BagRpyHv.js +1 -0
- package/dist/{conversation-item-BxwQLaFJ.js → conversation-item-BsOsVGmT.js} +1 -1
- package/dist/{conversation-list-BCfGN1JU.js → conversation-list-aX3Vtc7L.js} +1 -1
- package/dist/{copy-n9u9rqpi.js → copy-BmEwsNhJ.js} +1 -1
- package/dist/core-C8fzo39E.js +1 -12
- package/dist/{create-tween-uPkArjIG.js → create-tween-CNOAU3Fx.js} +1 -1
- package/dist/{create-tween-C-q-JCM-.js → create-tween-WfqiENls.js} +1 -1
- package/dist/{create-tween-CRrJXxBd.js → create-tween-wlFtW9Kh.js} +1 -1
- package/dist/{create-tween-DZ3RRDHD.js → create-tween-zt79ba32.js} +1 -1
- package/dist/{default-input-CaMrJkgH.js → default-input-DMV5Eaze.js} +1 -1
- package/dist/define-CI0y3eE4.js +1 -0
- package/dist/define.js +40 -40
- package/dist/define.server.js +45 -45
- package/dist/{disclosure-WUImBbDv.js → disclosure-NnACBxsC.js} +1 -1
- package/dist/{dropdown-wZVeJOMd.js → dropdown-DT7G0RGR.js} +1 -1
- package/dist/elements/agent-card.js +1 -1
- package/dist/elements/artifact.js +1 -1
- package/dist/elements/attachments.js +1 -1
- package/dist/elements/audio-visualizer.js +1 -1
- package/dist/elements/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.js +1 -1
- package/dist/elements/checkbox.js +1 -1
- package/dist/elements/checkpoint.js +1 -1
- package/dist/elements/choice.js +1 -1
- package/dist/elements/coachmark.js +1 -1
- package/dist/elements/code-block.js +1 -1
- package/dist/elements/command.js +1 -1
- package/dist/elements/compare.js +1 -1
- package/dist/elements/composer.js +1 -1
- package/dist/elements/confirm-card.js +1 -1
- package/dist/elements/context-meter.js +1 -1
- package/dist/elements/conversation-item.js +1 -1
- package/dist/elements/conversation-list.js +1 -1
- package/dist/elements/dialog.js +1 -1
- package/dist/elements/dock.js +1 -1
- package/dist/elements/dropdown.js +1 -1
- package/dist/elements/editable-label.js +1 -1
- 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.js +1 -1
- 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.js +1 -1
- package/dist/elements/reasoning.js +1 -1
- package/dist/elements/remote.js +1 -1
- package/dist/elements/resizable.js +1 -1
- package/dist/elements/response-stream.js +1 -1
- 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.js +1 -1
- 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.js +1 -1
- package/dist/elements/source.js +1 -1
- package/dist/elements/status.js +1 -1
- package/dist/elements/switch.js +1 -1
- package/dist/elements/tabs.js +1 -1
- package/dist/elements/tasks.js +1 -1
- package/dist/elements/text-shimmer.js +1 -1
- package/dist/elements/thinking-bar.js +1 -1
- package/dist/elements/thread.js +1 -1
- package/dist/elements/toast.js +1 -1
- package/dist/elements/tool.js +1 -1
- package/dist/elements/tooltip.js +1 -1
- package/dist/elements/voice-input.js +1 -1
- package/dist/elements/voice-output.js +1 -1
- package/dist/{ellipsis-CbOpJnU3.js → ellipsis-6pJ7SxYT.js} +1 -1
- package/dist/{embed-CrfjkbUG.js → embed-BMje-nxj.js} +1 -1
- package/dist/engine-javascript-C1x7zo1_.js +1 -141
- package/dist/{external-link-ByXAwBBQ.js → external-link-Beh9DKeR.js} +1 -1
- package/dist/{file-text-DMib2qwt.js → file-text-D1GPfZ8Q.js} +1 -1
- package/dist/{file-tree-CJqM2aP7.js → file-tree-Dwj2lqg-.js} +1 -1
- package/dist/{folder-_BAb929C.js → folder-b6D8x1DY.js} +1 -1
- package/dist/{form-DSZgZQZk.js → form-DWgdxDXu.js} +1 -1
- package/dist/{hover-card-BQbul9eq.js → hover-card-CWRkqm40.js} +1 -1
- package/dist/{icon-CdcfRhYI.js → icon-CL0jdhsf.js} +1 -1
- package/dist/index.js +1741 -1725
- package/dist/index.server.js +1582 -1566
- package/dist/{info-DsFjGuI_.js → info-0cOUherQ.js} +1 -1
- package/dist/{input-DKbmkMos.js → input-BH6Ru91Q.js} +1 -1
- package/dist/kai.es.js +1 -1
- package/dist/{kbd-PvdGhX4s.js → kbd-DRAnVtNX.js} +1 -1
- package/dist/{link-zF8PzWfF.js → link-Dlr0vssB.js} +1 -1
- package/dist/{link-preview-DbM1866N.js → link-preview-DODgRyV9.js} +1 -1
- package/dist/loader-KvJB6NrT.js +1 -0
- package/dist/{markdown-LMvmAyBk.js → markdown-DX9tuJVj.js} +1 -1
- package/dist/mcp.es.js +9 -5
- package/dist/{message-BYZECyek.js → message-BqQ7Ot5q.js} +1 -1
- package/dist/{message-BSsgvHvf.js → message-DkaGfBd8.js} +1 -1
- package/dist/message-circle-BPpp5QKv.js +1 -0
- package/dist/message-square-BLbsd9BJ.js +1 -0
- package/dist/{minimize-2-BQRoBV1V.js → minimize-2-CyOHJwcN.js} +1 -1
- package/dist/{model-switcher-CMpCOYcB.js → model-switcher-0hrKDiK2.js} +1 -1
- package/dist/{overlay-Cb-MkyDa.js → overlay-DBMFXie6.js} +1 -1
- package/dist/{panel-right-i8warFxT.js → panel-right-t8SWJL6e.js} +1 -1
- package/dist/{paperclip-ByY3UVO6.js → paperclip-CdzuOjbU.js} +1 -1
- package/dist/play-BXy1u7rW.js +1 -0
- package/dist/primitives/use-auto-resize.d.ts +11 -0
- package/dist/{progress-bar-jVAHvMUf.js → progress-bar-CiBtxMWT.js} +1 -1
- package/dist/{prompt-suggestion-CD-qtNgC.js → prompt-suggestion-I_DHP21i.js} +1 -1
- package/dist/{radio-BsoBMhkF.js → radio-C_p3n39l.js} +1 -1
- package/dist/{reasoning-4kBPtlTx.js → reasoning-BDwy_tIe.js} +1 -1
- package/dist/register-impl-DvEnhIxx.js +424 -0
- package/dist/{resizable-uPmY9VY-.js → resizable-SYC-fStM.js} +1 -1
- package/dist/{rotate-ccw-B2xn93py.js → rotate-ccw-B1nwmwuY.js} +1 -1
- package/dist/{rotate-cw-CMVLoCyH.js → rotate-cw-CLAnBcm1.js} +1 -1
- package/dist/{scroll-area-BqLUo8ZZ.js → scroll-area-zRyXoLhI.js} +1 -1
- package/dist/{scroll-button-DslXiJyL.js → scroll-button-jzrbYCG9.js} +1 -1
- package/dist/{select-2cLRtPGT.js → select-DM-0nEe0.js} +1 -1
- package/dist/{separator-BWQtNJcM.js → separator-BToOOoOt.js} +1 -1
- package/dist/{settings-BBR63jLg.js → settings-PaGo_S4U.js} +1 -1
- package/dist/{settings-group-B2ciy-Iw.js → settings-group-BFXGIfXq.js} +1 -1
- package/dist/{skeleton-CkHI-HgC.js → skeleton-DYpmFnnm.js} +1 -1
- package/dist/{slider-DDR9U-i0.js → slider-ebutAmkQ.js} +1 -1
- package/dist/{solid-DruVOXnf.js → solid-15v_3WVL.js} +3563 -3412
- package/dist/{solid-BzCFdL25.js → solid-5P-otgdi.js} +4502 -4296
- package/dist/solid.d.ts +6 -0
- package/dist/solid.js +259 -254
- package/dist/solid.server.js +259 -254
- package/dist/{source-GEnFF528.js → source-c1gpRl9h.js} +1 -1
- package/dist/{star-CilHq8GP.js → star-pcV_3LqF.js} +1 -1
- package/dist/{store-Ciyk6eZG.js → store-CSgbFFCg.js} +1 -1
- package/dist/{switch-KkeQIbuH.js → switch-Bh2OdLV2.js} +1 -1
- package/dist/{tasks-card-BrN4bggJ.js → tasks-card-CbqQAn2S.js} +1 -1
- package/dist/text-shimmer-BSzgEnDH.js +1 -0
- package/dist/textarea-DrYNt_0z.js +1 -0
- package/dist/theme.tokens.css +22 -21
- package/dist/{thumbs-up-CsT9Wzb9.js → thumbs-up-BL3-NenK.js} +1 -1
- package/dist/{toast-store-tgK6MuMv.js → toast-store-DkOlYczt.js} +1 -1
- package/dist/{tool-DzUjIBT8.js → tool-CeIWUVUe.js} +1 -1
- package/dist/{tooltip-Bkkg_4t0.js → tooltip-GA-nmg06.js} +1 -1
- package/dist/{trash-2-jBKxjGGQ.js → trash-2-CT66QWlm.js} +1 -1
- package/dist/{triangle-alert-DlQ68ppf.js → triangle-alert-CeHLWxhD.js} +1 -1
- package/dist/ui/color-field.d.ts +48 -0
- package/dist/ui/textarea.d.ts +4 -0
- package/dist/ui/toggle-chip.d.ts +40 -0
- package/dist/{upload-TcAHXv9W.js → upload-9Csb0F0J.js} +1 -1
- package/dist/{use-card-resolution-DaZqAdWf.js → use-card-resolution-Zg0a08Z-.js} +1 -1
- package/dist/{variant-aurora-DbW_OWL2.js → variant-aurora-4VBQHIKV.js} +1 -1
- package/dist/{variant-aurora-CNmfHhcx.js → variant-aurora-DBeCAQNk.js} +2 -2
- package/dist/{variant-aurora-D6GsdTPA.js → variant-aurora-FzHVXHby.js} +2 -2
- package/dist/{variant-aurora-BhLuYxJR.js → variant-aurora-LE3fqxgw.js} +1 -1
- package/dist/{variant-custom-BvYHR62b.js → variant-custom-AFRGcOBS.js} +1 -1
- package/dist/{variant-custom-DV2x254s.js → variant-custom-BQkNuPpE.js} +2 -2
- package/dist/{variant-custom-BRvaNHSi.js → variant-custom-DI5R0rln.js} +1 -1
- package/dist/{variant-custom-DMTrEO5w.js → variant-custom-WWnrrRHS.js} +2 -2
- package/dist/{variant-wave-CyBueXj9.js → variant-wave-DUCbH5oI.js} +2 -2
- package/dist/{variant-wave-BNMGrDfj.js → variant-wave-DuQV7DhQ.js} +2 -2
- package/dist/{variant-wave-BpDd8t3Z.js → variant-wave-nSI2sfII.js} +1 -1
- package/dist/{variant-wave-sp-qwsdI.js → variant-wave-wTP5v_jU.js} +1 -1
- package/dist/x-eiO9V6J6.js +1 -0
- package/{src/elements/styles.css → kit-base.css} +27 -44
- package/package.json +32 -17
- package/solid.css +33 -0
- package/theme.css +39 -23
- package/bin/route.test.js +0 -58
- package/dist/arrow-down-CjRU3JgV.js +0 -1
- package/dist/arrow-left-Bnpb1UEW.js +0 -1
- package/dist/artifact-Bwt7OgcR.js +0 -1
- package/dist/check-njkVdZu2.js +0 -1
- package/dist/chevron-down-B72s6PXR.js +0 -1
- package/dist/chevron-right-BatuHzUm.js +0 -1
- package/dist/circle-check-B62pODB3.js +0 -1
- package/dist/circle-zx0ByzY9.js +0 -1
- package/dist/controllable-CnGpMF6r.js +0 -1
- package/dist/define-By-uL588.js +0 -1
- package/dist/loader-BM4CEz4G.js +0 -1
- package/dist/message-circle-DruwObfX.js +0 -1
- package/dist/message-square-BG6q6mlm.js +0 -1
- package/dist/play-BvKKq3fX.js +0 -1
- package/dist/register-impl-B1hLkrI8.js +0 -424
- package/dist/text-shimmer-Dcj1MHuq.js +0 -1
- package/dist/textarea-Dpvbngbg.js +0 -1
- package/dist/x-Z5UntkIJ.js +0 -1
- package/src/agent-tooling/README.md +0 -192
- package/src/agent-tooling/archetypes.ts +0 -205
- package/src/agent-tooling/catalog/README.md +0 -676
- package/src/agent-tooling/catalog/catalog-types.ts +0 -231
- package/src/agent-tooling/catalog/fabrications.ts +0 -96
- package/src/agent-tooling/catalog/invariants.ts +0 -284
- package/src/agent-tooling/catalog/labs-titles.ts +0 -114
- package/src/agent-tooling/catalog/scenarios.ts +0 -87
- package/src/agent-tooling/catalog/surfaces.ts +0 -347
- package/src/agent-tooling/construct/cli-entry.ts +0 -8
- package/src/agent-tooling/construct/cli.ts +0 -147
- package/src/agent-tooling/construct/codegen.ts +0 -1635
- package/src/agent-tooling/construct/construct.v1.schema.json +0 -319
- package/src/agent-tooling/construct/dev.ts +0 -148
- package/src/agent-tooling/construct/fixtures/demo-widget.construct.json +0 -7
- package/src/agent-tooling/construct/fixtures/ops-console.construct.json +0 -44
- package/src/agent-tooling/construct/fixtures/owner-widget.construct.json +0 -32
- package/src/agent-tooling/construct/schema.ts +0 -452
- package/src/agent-tooling/integrations/anthropic.ts +0 -442
- package/src/agent-tooling/integrations/cloudflare.ts +0 -218
- package/src/agent-tooling/integrations/langgraph.ts +0 -133
- package/src/agent-tooling/integrations/mastra.ts +0 -182
- package/src/agent-tooling/integrations/mock.ts +0 -148
- package/src/agent-tooling/integrations/ollama.ts +0 -97
- package/src/agent-tooling/integrations/openai.ts +0 -95
- package/src/agent-tooling/integrations/openrouter.ts +0 -82
- package/src/agent-tooling/integrations/pi.ts +0 -176
- package/src/agent-tooling/integrations/pydantic-ai.ts +0 -108
- package/src/agent-tooling/integrations/vercel-ai-sdk.ts +0 -398
- package/src/agent-tooling/mcp/css-raw.d.ts +0 -12
- package/src/agent-tooling/mcp/manifest.ts +0 -422
- package/src/agent-tooling/mcp/server.ts +0 -116
- package/src/agent-tooling/mcp/stdio.ts +0 -18
- package/src/agent-tooling/mcp/tools/construct.ts +0 -130
- package/src/agent-tooling/mcp/tools/debug.ts +0 -621
- package/src/agent-tooling/mcp/tools/reference.ts +0 -980
- package/src/agent-tooling/mcp/tools/scaffold.ts +0 -6708
- package/src/agent-tooling/mcp/tools/theme.ts +0 -456
- package/src/agent-tooling/mcp/tools/types.ts +0 -14
- package/src/agent-tooling/mcp/validate-args.ts +0 -141
- package/src/agent-tooling/recipes/composed-thread.ts +0 -714
- package/src/agent-tooling/recipes/index.ts +0 -22
- package/src/agent-tooling/recipes/types.ts +0 -32
- package/src/agent-tooling/registry.ts +0 -132
- package/src/agent-tooling/route-emit.ts +0 -305
- package/src/agent-tooling/types.ts +0 -390
- package/src/components/artifact-card.tsx +0 -120
- package/src/components/artifact.tsx +0 -914
- package/src/components/attachment-types.ts +0 -66
- package/src/components/attachments.tsx +0 -536
- package/src/components/audio-visualizer/audio-visualizer.voice-fixture.ts +0 -257
- package/src/components/audio-visualizer/aurora.glsl.ts +0 -330
- package/src/components/audio-visualizer/fit-scale.ts +0 -112
- package/src/components/audio-visualizer/index.tsx +0 -528
- package/src/components/audio-visualizer/labs/lab-choreography.ts +0 -187
- package/src/components/audio-visualizer/labs/lab-shaders.ts +0 -363
- package/src/components/audio-visualizer/labs/lab-visualizer.tsx +0 -102
- package/src/components/audio-visualizer/shader-canvas.tsx +0 -876
- package/src/components/audio-visualizer/sizes.ts +0 -54
- package/src/components/audio-visualizer/variant-aurora.tsx +0 -305
- package/src/components/audio-visualizer/variant-bar.tsx +0 -175
- package/src/components/audio-visualizer/variant-custom.tsx +0 -344
- package/src/components/audio-visualizer/variant-grid.tsx +0 -175
- package/src/components/audio-visualizer/variant-radial.tsx +0 -163
- package/src/components/audio-visualizer/variant-wave.tsx +0 -130
- package/src/components/audio-visualizer/wave.glsl.ts +0 -130
- package/src/components/card-fallback.tsx +0 -60
- package/src/components/card-renderer.tsx +0 -220
- package/src/components/card.tsx +0 -212
- package/src/components/chain-of-thought.tsx +0 -348
- package/src/components/chat-container.tsx +0 -89
- package/src/components/chat-scope-picker.tsx +0 -57
- package/src/components/chat-thread.tsx +0 -1014
- package/src/components/checkpoint.tsx +0 -88
- package/src/components/choice-card.tsx +0 -743
- package/src/components/coachmark.tsx +0 -249
- package/src/components/code-block.tsx +0 -181
- package/src/components/composer-dom.ts +0 -159
- package/src/components/composer-highlight.ts +0 -242
- package/src/components/composer-history.ts +0 -82
- package/src/components/composer.tsx +0 -1075
- package/src/components/confirm-card.tsx +0 -402
- package/src/components/context.tsx +0 -377
- package/src/components/conversation-item.tsx +0 -241
- package/src/components/conversation-list.tsx +0 -429
- package/src/components/conversation-panel.tsx +0 -118
- package/src/components/dismissed-stub.tsx +0 -80
- package/src/components/embed.tsx +0 -200
- package/src/components/empty.tsx +0 -177
- package/src/components/feedback-bar.tsx +0 -166
- package/src/components/file-tree.tsx +0 -530
- package/src/components/file-upload.tsx +0 -167
- package/src/components/form-widgets.tsx +0 -525
- package/src/components/form.tsx +0 -1296
- package/src/components/home-panel.tsx +0 -159
- package/src/components/image.tsx +0 -65
- package/src/components/link-preview.tsx +0 -195
- package/src/components/loader.tsx +0 -367
- package/src/components/markdown.tsx +0 -162
- package/src/components/message-skills.tsx +0 -40
- package/src/components/message.tsx +0 -765
- package/src/components/model-switcher.tsx +0 -132
- package/src/components/prompt-input.tsx +0 -188
- package/src/components/prompt-suggestion.tsx +0 -150
- package/src/components/reasoning.tsx +0 -293
- package/src/components/response-compare-types.ts +0 -152
- package/src/components/response-compare.tsx +0 -455
- package/src/components/response-stream.tsx +0 -109
- package/src/components/screen.tsx +0 -181
- package/src/components/scroll-button.tsx +0 -93
- package/src/components/source.tsx +0 -192
- package/src/components/tasks-card.tsx +0 -801
- package/src/components/text-shimmer.tsx +0 -37
- package/src/components/thinking-bar.tsx +0 -50
- package/src/components/thread.tsx +0 -228
- package/src/components/toast.tsx +0 -503
- package/src/components/tool-classify.ts +0 -26
- package/src/components/tool-types.ts +0 -49
- package/src/components/tool.tsx +0 -190
- package/src/components/use-card-resolution.ts +0 -44
- package/src/components/voice-input.tsx +0 -222
- package/src/components/voice-output.tsx +0 -242
- package/src/components/widget-tab-bar.tsx +0 -73
- package/src/components/workspace-shell.tsx +0 -285
- package/src/diagnostics/hook.ts +0 -352
- package/src/diagnostics/index.ts +0 -82
- package/src/diagnostics/report-request.ts +0 -296
- package/src/elements/agent-card.tsx +0 -67
- package/src/elements/artifact.tsx +0 -194
- package/src/elements/attachments.tsx +0 -140
- package/src/elements/audio-visualizer.tsx +0 -227
- package/src/elements/autoloader.ts +0 -89
- package/src/elements/avatar.tsx +0 -33
- package/src/elements/badge.tsx +0 -32
- package/src/elements/button.tsx +0 -149
- package/src/elements/card.tsx +0 -133
- package/src/elements/cards.tsx +0 -266
- package/src/elements/chain-of-thought.tsx +0 -141
- package/src/elements/chat-scope-picker.tsx +0 -65
- package/src/elements/chat-types.ts +0 -102
- package/src/elements/chat-workspace.tsx +0 -188
- package/src/elements/chat.tsx +0 -304
- package/src/elements/checkbox-group.tsx +0 -164
- package/src/elements/checkbox.tsx +0 -134
- package/src/elements/checkpoint.tsx +0 -47
- package/src/elements/choice.tsx +0 -100
- package/src/elements/coachmark.tsx +0 -90
- package/src/elements/code-block.tsx +0 -60
- package/src/elements/command.tsx +0 -197
- package/src/elements/compare.tsx +0 -111
- package/src/elements/compiled.css +0 -2
- package/src/elements/composer.tsx +0 -162
- package/src/elements/confirm-card.tsx +0 -76
- package/src/elements/context-meter.tsx +0 -107
- package/src/elements/conversation-item.tsx +0 -120
- package/src/elements/conversation-list.tsx +0 -203
- package/src/elements/css.ts +0 -5
- package/src/elements/default-input.tsx +0 -392
- package/src/elements/define-entry.ts +0 -12
- package/src/elements/define.tsx +0 -563
- package/src/elements/diagnostic-events.ts +0 -114
- package/src/elements/dialog.tsx +0 -145
- package/src/elements/disclosure.ts +0 -95
- package/src/elements/dock.tsx +0 -215
- package/src/elements/dropdown.tsx +0 -123
- package/src/elements/editable-label.tsx +0 -140
- package/src/elements/element-data-types.ts +0 -152
- package/src/elements/element-diagnostics.ts +0 -392
- package/src/elements/element-manifest.json +0 -354
- package/src/elements/element-nonscalar.json +0 -187
- package/src/elements/element-types.d.ts +0 -4353
- package/src/elements/embed.tsx +0 -35
- package/src/elements/empty.tsx +0 -29
- package/src/elements/feedback-bar.tsx +0 -66
- package/src/elements/file-tree.tsx +0 -62
- package/src/elements/file-upload.tsx +0 -44
- package/src/elements/form.tsx +0 -94
- package/src/elements/hover-card.tsx +0 -80
- package/src/elements/icon.tsx +0 -41
- package/src/elements/image.tsx +0 -32
- package/src/elements/input.tsx +0 -492
- package/src/elements/kbd.tsx +0 -45
- package/src/elements/link-preview.tsx +0 -34
- package/src/elements/loader.tsx +0 -25
- package/src/elements/markdown.tsx +0 -38
- package/src/elements/menu.tsx +0 -241
- package/src/elements/message-skills.tsx +0 -83
- package/src/elements/message.tsx +0 -361
- package/src/elements/model-switcher.tsx +0 -121
- package/src/elements/nav.tsx +0 -87
- package/src/elements/notice.tsx +0 -53
- package/src/elements/pane-grid.tsx +0 -111
- package/src/elements/pane-group.tsx +0 -119
- package/src/elements/pane.tsx +0 -129
- package/src/elements/popover.tsx +0 -81
- package/src/elements/progress-bar.tsx +0 -39
- package/src/elements/prompt-dock.tsx +0 -82
- package/src/elements/prompt-input.tsx +0 -240
- package/src/elements/prompt-suggestions.tsx +0 -113
- package/src/elements/radio-group.tsx +0 -129
- package/src/elements/reasoning.tsx +0 -71
- package/src/elements/register-impl.ts +0 -148
- package/src/elements/register.ts +0 -76
- package/src/elements/remote.tsx +0 -225
- package/src/elements/resizable.globals.d.ts +0 -36
- package/src/elements/resizable.tsx +0 -704
- package/src/elements/response-stream.tsx +0 -40
- package/src/elements/screen.tsx +0 -90
- package/src/elements/scroll-area.tsx +0 -33
- package/src/elements/scroll-button.tsx +0 -179
- package/src/elements/search.tsx +0 -185
- package/src/elements/segmented.tsx +0 -129
- package/src/elements/select.tsx +0 -165
- package/src/elements/separator.tsx +0 -36
- package/src/elements/setting-item.tsx +0 -50
- package/src/elements/settings-group.tsx +0 -37
- package/src/elements/skeleton.tsx +0 -45
- package/src/elements/slider.tsx +0 -171
- package/src/elements/slot-text.ts +0 -73
- package/src/elements/slots.ts +0 -787
- package/src/elements/source.tsx +0 -126
- package/src/elements/status.tsx +0 -42
- package/src/elements/switch.tsx +0 -118
- package/src/elements/tabs.tsx +0 -95
- package/src/elements/tasks.tsx +0 -103
- package/src/elements/text-shimmer.tsx +0 -28
- package/src/elements/thinking-bar.tsx +0 -43
- package/src/elements/thread.tsx +0 -139
- package/src/elements/toast.tsx +0 -106
- package/src/elements/tool.tsx +0 -78
- package/src/elements/tooltip.tsx +0 -85
- package/src/elements/validate-messages.ts +0 -76
- package/src/elements/voice-input.tsx +0 -100
- package/src/elements/voice-output.tsx +0 -82
- package/src/index.ts +0 -430
- package/src/primitives/audio-bands.ts +0 -174
- package/src/primitives/card-component-types.ts +0 -63
- package/src/primitives/card-contract.ts +0 -80
- package/src/primitives/card-data-types.ts +0 -361
- package/src/primitives/card-host.tsx +0 -37
- package/src/primitives/card-recovery.ts +0 -160
- package/src/primitives/card-registry.tsx +0 -78
- package/src/primitives/card-resolution.ts +0 -36
- package/src/primitives/card-routing.ts +0 -85
- package/src/primitives/card-schemas/artifact.schema.json +0 -92
- package/src/primitives/card-schemas/card-envelope.schema.json +0 -14
- package/src/primitives/card-schemas/card-event.schema.json +0 -12
- package/src/primitives/card-schemas/choice.schema.json +0 -75
- package/src/primitives/card-schemas/confirm.schema.json +0 -65
- package/src/primitives/card-schemas/embed.schema.json +0 -63
- package/src/primitives/card-schemas/form.result.schema.json +0 -7
- package/src/primitives/card-schemas/form.schema.json +0 -53
- package/src/primitives/card-schemas/link.schema.json +0 -54
- package/src/primitives/card-schemas/tasks.result.schema.json +0 -16
- package/src/primitives/card-schemas/tasks.schema.json +0 -83
- package/src/primitives/card-tags.ts +0 -61
- package/src/primitives/card-validate-cards.ts +0 -255
- package/src/primitives/card-validate-schemas.ts +0 -58
- package/src/primitives/card-validate.ts +0 -131
- package/src/primitives/chat-config.tsx +0 -103
- package/src/primitives/composer-model.ts +0 -49
- package/src/primitives/composer-triggers.ts +0 -35
- package/src/primitives/controllable.ts +0 -21
- package/src/primitives/conversation-store.ts +0 -248
- package/src/primitives/create-kai-chat.ts +0 -66
- package/src/primitives/create-tween.ts +0 -266
- package/src/primitives/embed-providers.ts +0 -254
- package/src/primitives/field-mask.ts +0 -256
- package/src/primitives/field-semantics.ts +0 -115
- package/src/primitives/highlighter.ts +0 -157
- package/src/primitives/input-mask.ts +0 -853
- package/src/primitives/link-preview.ts +0 -87
- package/src/primitives/message-feedback.ts +0 -124
- package/src/primitives/pdf-preview.ts +0 -121
- package/src/primitives/toast-store.ts +0 -338
- package/src/primitives/url-scheme-policy.ts +0 -70
- package/src/primitives/use-audio-analysis.ts +0 -340
- package/src/primitives/use-auto-resize.ts +0 -31
- package/src/primitives/use-resize-observer.ts +0 -45
- package/src/primitives/use-sequencer.ts +0 -72
- package/src/primitives/use-speech-recognition.ts +0 -146
- package/src/primitives/use-stick-to-bottom.ts +0 -75
- package/src/primitives/use-text-stream.ts +0 -143
- package/src/primitives/use-voice-recorder.ts +0 -62
- package/src/primitives/visualizer-sequences.ts +0 -350
- package/src/remote/host-embed.ts +0 -345
- package/src/remote/index.ts +0 -2
- package/src/remote/origin.ts +0 -30
- package/src/remote/provider-runtime.ts +0 -262
- package/src/remote/provider.ts +0 -2
- package/src/remote/validate.ts +0 -22
- package/src/remote/version.ts +0 -12
- package/src/remote/wire.ts +0 -48
- package/src/schemas/from-tool-call.ts +0 -151
- package/src/schemas/index.ts +0 -341
- package/src/schemas/provider-subsets.ts +0 -538
- package/src/schemas/registry.ts +0 -355
- package/src/schemas/tool-defs.ts +0 -793
- package/src/solid.ts +0 -173
- package/src/state/index.ts +0 -44
- package/src/state/messages.ts +0 -53
- package/src/state/mock.ts +0 -297
- package/src/state/parts.ts +0 -295
- package/src/state/persistence.ts +0 -180
- package/src/state/stream.ts +0 -246
- package/src/state/suggestions.ts +0 -9
- package/src/state/threads.ts +0 -142
- package/src/test-utils/fake-clock.ts +0 -88
- package/src/types.ts +0 -95
- package/src/ui/action-icons.ts +0 -53
- package/src/ui/agent-card.tsx +0 -218
- package/src/ui/avatar.tsx +0 -23
- package/src/ui/badge.tsx +0 -21
- package/src/ui/button.tsx +0 -49
- package/src/ui/card.tsx +0 -245
- package/src/ui/checkbox-group.tsx +0 -153
- package/src/ui/checkbox.tsx +0 -63
- package/src/ui/collapsible.tsx +0 -163
- package/src/ui/command.tsx +0 -103
- package/src/ui/dialog.tsx +0 -223
- package/src/ui/dock.tsx +0 -630
- package/src/ui/dropdown.tsx +0 -636
- package/src/ui/editable-label.tsx +0 -112
- package/src/ui/hover-card.tsx +0 -345
- package/src/ui/icon.tsx +0 -167
- package/src/ui/input.tsx +0 -391
- package/src/ui/kbd.tsx +0 -118
- package/src/ui/nav.tsx +0 -282
- package/src/ui/notice.tsx +0 -84
- package/src/ui/overlay.tsx +0 -277
- package/src/ui/pane-grid.tsx +0 -117
- package/src/ui/pane-group.tsx +0 -291
- package/src/ui/pane.tsx +0 -193
- package/src/ui/popover.tsx +0 -106
- package/src/ui/progress-bar.tsx +0 -83
- package/src/ui/prompt-dock.tsx +0 -145
- package/src/ui/radio.tsx +0 -150
- package/src/ui/resizable.tsx +0 -693
- package/src/ui/scroll-area.tsx +0 -26
- package/src/ui/segmented.tsx +0 -109
- package/src/ui/select.tsx +0 -168
- package/src/ui/separator.tsx +0 -10
- package/src/ui/settings-group.tsx +0 -67
- package/src/ui/skeleton.tsx +0 -73
- package/src/ui/slider.tsx +0 -178
- package/src/ui/status.tsx +0 -48
- package/src/ui/switch.tsx +0 -119
- package/src/ui/tabs.tsx +0 -168
- package/src/ui/textarea.tsx +0 -21
- package/src/ui/tooltip.tsx +0 -118
- package/src/utils/cn.ts +0 -30
- package/src/wire/chunk.ts +0 -248
- package/src/wire/consume.ts +0 -599
- package/src/wire/diagnostics.ts +0 -727
- package/src/wire/encode-probe.ts +0 -214
- package/src/wire/encode.ts +0 -947
- package/src/wire/files.ts +0 -342
- package/src/wire/formats/anthropic.ts +0 -274
- package/src/wire/formats/openai.ts +0 -228
- package/src/wire/index.ts +0 -95
- package/src/wire/media-types.ts +0 -344
- package/src/wire/read.ts +0 -396
- package/src/wire/sink-helpers.ts +0 -50
- package/src/wire/sse.ts +0 -153
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { For, Show } from 'solid-js';
|
|
2
|
-
import { defineWebComponent } from './define';
|
|
3
|
-
import {
|
|
4
|
-
Attachments,
|
|
5
|
-
Attachment,
|
|
6
|
-
AttachmentPreview,
|
|
7
|
-
AttachmentInfo,
|
|
8
|
-
AttachmentRemove,
|
|
9
|
-
AttachmentHoverCard,
|
|
10
|
-
AttachmentHoverCardTrigger,
|
|
11
|
-
AttachmentHoverCardContent,
|
|
12
|
-
AttachmentEmpty,
|
|
13
|
-
getAttachmentLabel,
|
|
14
|
-
getMediaCategory,
|
|
15
|
-
type AttachmentData,
|
|
16
|
-
type AttachmentVariant,
|
|
17
|
-
} from '../components/attachments';
|
|
18
|
-
|
|
19
|
-
interface Props extends Record<string, unknown> {
|
|
20
|
-
/** The attachments to render. Omit (or pass an empty array) for the empty
|
|
21
|
-
* state, which shows `emptyText` if set and nothing otherwise. Set as a JS
|
|
22
|
-
* property (array). Each item's `url` must be a `data:` URI or an https
|
|
23
|
-
* URL, never `URL.createObjectURL`: a `blob:` URL previews here but the
|
|
24
|
-
* wire encoders (`toOpenAIMessages`/`toAnthropicMessages`) refuse it. */
|
|
25
|
-
items?: AttachmentData[];
|
|
26
|
-
/** Layout: `grid` = visual tiles, `inline` = icon + label chips, `list` = rows. */
|
|
27
|
-
variant?: AttachmentVariant;
|
|
28
|
-
/** Wrap each item in a hover card that previews its details. */
|
|
29
|
-
hoverCard?: boolean;
|
|
30
|
-
/** Show a remove button per item; clicking it fires a `kai-remove` event. */
|
|
31
|
-
removable?: boolean;
|
|
32
|
-
/** Also show the media type beneath the filename (non-grid variants). */
|
|
33
|
-
showMediaType?: boolean;
|
|
34
|
-
/** Text shown when `items` is empty. */
|
|
35
|
-
emptyText?: string;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/** Events fired by `<kai-attachments>`. */
|
|
39
|
-
interface Events {
|
|
40
|
-
/** A remove button was clicked. */
|
|
41
|
-
'kai-remove': { id: string };
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* `<kai-attachments>` — the exemplar for the "collapse a compound primitive to
|
|
46
|
-
* ONE configurable element" pattern (Route 1). The presentation knobs that the
|
|
47
|
-
* SolidJS layer expresses by composing sub-parts (`<AttachmentPreview>`,
|
|
48
|
-
* `<AttachmentInfo>`, `<AttachmentHoverCard>`, `<AttachmentRemove>`) become
|
|
49
|
-
* attributes/flags here:
|
|
50
|
-
*
|
|
51
|
-
* - icon + label .......... `variant="inline"`
|
|
52
|
-
* - visual + hover card .... `variant="grid" hover-card`
|
|
53
|
-
* - removable chips ........ add `removable` (emits `kai-remove` → { id })
|
|
54
|
-
*
|
|
55
|
-
* Data in via the `items` property; the only interaction (`remove`) comes back
|
|
56
|
-
* as an event. For fully-custom hover content, the SolidJS primitives remain the
|
|
57
|
-
* escape hatch (a templated slot — "Route 2" — is a deliberate future add).
|
|
58
|
-
*/
|
|
59
|
-
defineWebComponent<Props, Events>('kai-attachments', {
|
|
60
|
-
items: [],
|
|
61
|
-
variant: 'grid',
|
|
62
|
-
hoverCard: false,
|
|
63
|
-
removable: false,
|
|
64
|
-
showMediaType: false,
|
|
65
|
-
emptyText: undefined,
|
|
66
|
-
}, (props, { dispatch, flag }) => {
|
|
67
|
-
const variant = () => props.variant ?? 'grid';
|
|
68
|
-
const hoverCard = () => flag('hoverCard');
|
|
69
|
-
const removable = () => flag('removable');
|
|
70
|
-
const showMediaType = () => flag('showMediaType');
|
|
71
|
-
|
|
72
|
-
return (
|
|
73
|
-
<Show
|
|
74
|
-
when={props.items?.length}
|
|
75
|
-
fallback={<Show when={props.emptyText}><AttachmentEmpty>{props.emptyText}</AttachmentEmpty></Show>}
|
|
76
|
-
>
|
|
77
|
-
<Attachments variant={variant()}>
|
|
78
|
-
<For each={props.items ?? []}>
|
|
79
|
-
{(item) => (
|
|
80
|
-
<Attachment
|
|
81
|
-
data={item}
|
|
82
|
-
onRemove={removable() ? () => dispatch('kai-remove', { id: item.id }) : undefined}
|
|
83
|
-
>
|
|
84
|
-
<Show
|
|
85
|
-
when={hoverCard()}
|
|
86
|
-
fallback={
|
|
87
|
-
<>
|
|
88
|
-
<AttachmentPreview />
|
|
89
|
-
{/* Rendered for EVERY variant now. `AttachmentInfo` decides
|
|
90
|
-
what a grid tile gets — a visible caption for a non-image
|
|
91
|
-
tile, nothing for an image, which is the only tile that
|
|
92
|
-
really is a self-contained visual. */}
|
|
93
|
-
<AttachmentInfo showMediaType={showMediaType()} />
|
|
94
|
-
</>
|
|
95
|
-
}
|
|
96
|
-
>
|
|
97
|
-
{/* The trigger carries the layout itself — a bare inline <span>
|
|
98
|
-
collapses inline/list rows. Grid wraps just the tile (the
|
|
99
|
-
label/details surface in the hover card instead). */}
|
|
100
|
-
<AttachmentHoverCard>
|
|
101
|
-
<AttachmentHoverCardTrigger
|
|
102
|
-
class={variant() === 'grid'
|
|
103
|
-
? 'block size-full'
|
|
104
|
-
: `flex items-center gap-1.5${variant() === 'list' ? ' w-full' : ''}`}
|
|
105
|
-
>
|
|
106
|
-
<AttachmentPreview />
|
|
107
|
-
<AttachmentInfo showMediaType={showMediaType()} />
|
|
108
|
-
</AttachmentHoverCardTrigger>
|
|
109
|
-
<AttachmentHoverCardContent>
|
|
110
|
-
{/* For image attachments, preview the actual thumbnail;
|
|
111
|
-
otherwise fall back to the label + media-type details. */}
|
|
112
|
-
<Show
|
|
113
|
-
when={getMediaCategory(item) === 'image' && item.type === 'file' && item.url}
|
|
114
|
-
fallback={
|
|
115
|
-
<>
|
|
116
|
-
<div class="text-body font-medium">{getAttachmentLabel(item)}</div>
|
|
117
|
-
<Show when={item.mediaType}>
|
|
118
|
-
<div class="text-muted-foreground text-caption">{item.mediaType}</div>
|
|
119
|
-
</Show>
|
|
120
|
-
</>
|
|
121
|
-
}
|
|
122
|
-
>
|
|
123
|
-
<img
|
|
124
|
-
part="preview"
|
|
125
|
-
src={item.url}
|
|
126
|
-
alt={getAttachmentLabel(item)}
|
|
127
|
-
class="block max-h-64 max-w-xs rounded object-contain"
|
|
128
|
-
/>
|
|
129
|
-
</Show>
|
|
130
|
-
</AttachmentHoverCardContent>
|
|
131
|
-
</AttachmentHoverCard>
|
|
132
|
-
</Show>
|
|
133
|
-
<AttachmentRemove />
|
|
134
|
-
</Attachment>
|
|
135
|
-
)}
|
|
136
|
-
</For>
|
|
137
|
-
</Attachments>
|
|
138
|
-
</Show>
|
|
139
|
-
);
|
|
140
|
-
});
|
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
import type { JSX } from 'solid-js';
|
|
2
|
-
import { AudioVisualizer, type ShaderSpec, type VisualizerVariant } from '../components/audio-visualizer';
|
|
3
|
-
import type { VisualizerSize } from '../components/audio-visualizer/sizes';
|
|
4
|
-
import { defineWebComponent, type WebComponentContext } from './define';
|
|
5
|
-
|
|
6
|
-
interface Props extends Record<string, unknown> {
|
|
7
|
-
/** Look to render: `bar` (default), `grid`, `radial`, `wave`, `aurora`, `custom`.
|
|
8
|
-
* `aura` is accepted as a LiveKit-markup alias for `aurora`. Attribute: `variant`. */
|
|
9
|
-
variant?: string;
|
|
10
|
-
/** `idle` (default), `connecting`, `listening`, `thinking`, `speaking`,
|
|
11
|
-
* `disconnected` (connection down: the dead, flat look). LiveKit's
|
|
12
|
-
* room-lifecycle state names are accepted as aliases. Attribute: `state`. */
|
|
13
|
-
state?: string;
|
|
14
|
-
/** `icon` | `sm` | `md` (default) | `lg` | `xl`. Attribute: `size`. */
|
|
15
|
-
size?: string;
|
|
16
|
-
/** Bars to draw. Bar and radial only. Attribute: `bar-count`. */
|
|
17
|
-
barCount?: number;
|
|
18
|
-
/** Grid only: rows and columns of the (always square) grid. Attribute: `count`. */
|
|
19
|
-
count?: number;
|
|
20
|
-
/** Radial only: ring distance from center, in px. Attribute: `radius`. */
|
|
21
|
-
radius?: number;
|
|
22
|
-
/** Grid only: ring distance for the connecting animation, in cells. Attribute: `spread`. */
|
|
23
|
-
spread?: number;
|
|
24
|
-
/** Grid only: ms between scripted frames. Attribute: `interval`. */
|
|
25
|
-
interval?: number;
|
|
26
|
-
/** CSS color for the geometry, overriding the inherited `currentColor`. Attribute: `color`. */
|
|
27
|
-
color?: string;
|
|
28
|
-
/** Shader variants only: pattern density, 0..1. Attribute: `complexity`. */
|
|
29
|
-
complexity?: number;
|
|
30
|
-
/** Setting this makes the element an announced image (`role="img"`) instead of
|
|
31
|
-
* decorative (`aria-hidden`). Attribute: `label`. */
|
|
32
|
-
label?: string;
|
|
33
|
-
/** Live microphone or WebRTC audio to analyze. JS property only. NOTE: amplitude
|
|
34
|
-
* renders only while state is "speaking" unless listening-amplitude is set; every
|
|
35
|
-
* other state plays its scripted animation and ignores the audio. */
|
|
36
|
-
stream?: MediaStream;
|
|
37
|
-
/** An `<audio>` or `<video>` element to tap for its audio. JS property only. NOTE:
|
|
38
|
-
* amplitude renders only while state is "speaking" unless listening-amplitude is
|
|
39
|
-
* set; every other state plays its scripted animation and ignores the audio. */
|
|
40
|
-
audioElement?: HTMLMediaElement;
|
|
41
|
-
/** Pre-computed levels, 0..1. Set this and no AudioContext is ever built, which is
|
|
42
|
-
* what keeps headless/SSR rendering and browser-speech-synthesis playback (which
|
|
43
|
-
* exposes no audio node) free of Web Audio entirely. JS property only. A new
|
|
44
|
-
* array reference is required for each update; mutating the existing array in
|
|
45
|
-
* place will not re-render. NOTE: amplitude renders only while state is "speaking"
|
|
46
|
-
* unless listening-amplitude is set; every other state plays its scripted
|
|
47
|
-
* animation and ignores the audio. */
|
|
48
|
-
bands?: number[];
|
|
49
|
-
/** Render live amplitude during the listening state as well, using the same
|
|
50
|
-
* presentation as speaking. Off by default, which keeps LiveKit parity: amplitude
|
|
51
|
-
* from stream, audio-element or bands renders only while state is "speaking". Set
|
|
52
|
-
* it to show a real mic-level picture while the user is the one talking. Boolean.
|
|
53
|
-
* Attribute: `listening-amplitude` (a bare attribute means true; reflected, so the
|
|
54
|
-
* property reads back what the attribute set). */
|
|
55
|
-
listeningAmplitude?: boolean;
|
|
56
|
-
/** Custom fragment shader for `variant="custom"`. JS property only. */
|
|
57
|
-
shader?: ShaderSpec;
|
|
58
|
-
/** Shader variants only: keep animating while scrolled off screen. Off by default,
|
|
59
|
-
* which stops drawing and releases the WebGL context until the element comes back
|
|
60
|
-
* (browsers ration contexts to roughly 16 a page). Does not override
|
|
61
|
-
* `prefers-reduced-motion`. Attribute: `animate-when-not-visible`. */
|
|
62
|
-
animateWhenNotVisible?: boolean;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Parse a numeric attribute or JS property value. Attribute values arrive as
|
|
67
|
-
* strings, so a missing or non-numeric one must resolve to `undefined` (which
|
|
68
|
-
* the composed component then defaults itself), never `NaN`, which would
|
|
69
|
-
* poison the downstream geometry (bar counts, radii, grid dimensions).
|
|
70
|
-
*/
|
|
71
|
-
export function num(value: unknown): number | undefined {
|
|
72
|
-
if (value == null || value === '') return undefined;
|
|
73
|
-
const n = Number(value);
|
|
74
|
-
return Number.isFinite(n) ? n : undefined;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* The facade's render logic, extracted to a named function so it can be
|
|
79
|
-
* exercised directly in tests (a plain Solid component call, no shadow DOM
|
|
80
|
-
* involved) without needing `defineWebComponent`'s browser-only custom-element
|
|
81
|
-
* upgrade path. Identical to what was previously an inline arrow passed to
|
|
82
|
-
* `defineWebComponent` below, plus forwarding the resolved theme (see `dark`
|
|
83
|
-
* below) once that context field existed to forward.
|
|
84
|
-
*
|
|
85
|
-
* `ctx` is optional so the existing declarative test (which calls this
|
|
86
|
-
* directly with just `props`, the way it did before `dark` existed) keeps
|
|
87
|
-
* working unchanged. `defineWebComponent` always supplies a real one; the
|
|
88
|
-
* `false` fallback only matters for that reduced, no-shadow-DOM call path.
|
|
89
|
-
*/
|
|
90
|
-
export function AudioVisualizerFacade(
|
|
91
|
-
props: Props,
|
|
92
|
-
ctx?: Partial<Pick<WebComponentContext, 'dark' | 'flag' | 'reflectFlag'>>,
|
|
93
|
-
): JSX.Element {
|
|
94
|
-
// Every element already resolves `theme='light'|'dark'|'auto'` against a
|
|
95
|
-
// live `prefers-color-scheme` listener in `defineWebComponent` (see
|
|
96
|
-
// `createDarkMode`), to drive the `.dark` class every element's content
|
|
97
|
-
// sits inside. A WebGL shader cannot read that class or a CSS custom
|
|
98
|
-
// property, so `<kai-audio-visualizer variant="aurora">` needs the ALREADY
|
|
99
|
-
// -RESOLVED boolean forwarded explicitly instead. Passing it through as a
|
|
100
|
-
// definite 'light'/'dark' (never 'auto') means the resolution RULE itself
|
|
101
|
-
// -- explicit wins, 'auto' follows the media query -- lives in exactly one
|
|
102
|
-
// place (`createDarkMode`); this is a plain relay, not a second
|
|
103
|
-
// implementation of that rule.
|
|
104
|
-
const dark = ctx?.dark?.() ?? false;
|
|
105
|
-
|
|
106
|
-
// `flag` is what makes a BARE attribute
|
|
107
|
-
// (`<kai-audio-visualizer animate-when-not-visible>`) mean true:
|
|
108
|
-
// component-register parses a valueless boolean attribute to `undefined`, so
|
|
109
|
-
// the prop alone cannot tell it apart from an absent one. Same helper every
|
|
110
|
-
// other boolean-attribute element uses, so the coercion rule lives in one
|
|
111
|
-
// place. The `props` fallback only covers the ctx-less direct-call path the
|
|
112
|
-
// declarative test uses, where there is no host element carrying an
|
|
113
|
-
// attribute at all.
|
|
114
|
-
const animateWhenNotVisible = ctx?.flag
|
|
115
|
-
? ctx.flag('animateWhenNotVisible')
|
|
116
|
-
: props.animateWhenNotVisible === true;
|
|
117
|
-
|
|
118
|
-
// Same bare-attribute coercion for the second boolean on this element.
|
|
119
|
-
const listeningAmplitude = ctx?.flag
|
|
120
|
-
? ctx.flag('listeningAmplitude')
|
|
121
|
-
: props.listeningAmplitude === true;
|
|
122
|
-
|
|
123
|
-
// Reflected (kai-dock precedent, findings G-05): without this,
|
|
124
|
-
// `<kai-audio-visualizer listening-amplitude>` would leave
|
|
125
|
-
// `el.listeningAmplitude === undefined` even while the element honours the
|
|
126
|
-
// attribute, because toggleAttribute's empty-string write-back parses to
|
|
127
|
-
// undefined. See WebComponentContext.reflectFlag. `animateWhenNotVisible`
|
|
128
|
-
// predates the reflectFlag seam and is deliberately left as-is here; if it
|
|
129
|
-
// ever earns reflection that is its own change, not a rider on this one.
|
|
130
|
-
ctx?.reflectFlag?.('listeningAmplitude');
|
|
131
|
-
|
|
132
|
-
return (
|
|
133
|
-
<AudioVisualizer
|
|
134
|
-
variant={props.variant as VisualizerVariant | undefined}
|
|
135
|
-
state={props.state as string | undefined}
|
|
136
|
-
size={props.size as VisualizerSize | undefined}
|
|
137
|
-
barCount={num(props.barCount)}
|
|
138
|
-
count={num(props.count)}
|
|
139
|
-
radius={num(props.radius)}
|
|
140
|
-
spread={num(props.spread)}
|
|
141
|
-
interval={num(props.interval)}
|
|
142
|
-
color={props.color as string | undefined}
|
|
143
|
-
complexity={num(props.complexity)}
|
|
144
|
-
label={props.label as string | undefined}
|
|
145
|
-
stream={props.stream as MediaStream | undefined}
|
|
146
|
-
audioElement={props.audioElement as HTMLMediaElement | undefined}
|
|
147
|
-
bands={props.bands as number[] | undefined}
|
|
148
|
-
listeningAmplitude={listeningAmplitude}
|
|
149
|
-
shader={props.shader as ShaderSpec | undefined}
|
|
150
|
-
animateWhenNotVisible={animateWhenNotVisible}
|
|
151
|
-
theme={dark ? 'dark' : 'light'}
|
|
152
|
-
/>
|
|
153
|
-
);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* `<kai-audio-visualizer>` renders live audio as bars, a grid, a ring, a wave,
|
|
158
|
-
* or a glowing aurora. It also animates from `state` alone with no audio at
|
|
159
|
-
* all, which is what you want when the source cannot be tapped (browser
|
|
160
|
-
* speech synthesis exposes no audio node).
|
|
161
|
-
*
|
|
162
|
-
* ```html
|
|
163
|
-
* <kai-audio-visualizer variant="bar" state="speaking" size="md"></kai-audio-visualizer>
|
|
164
|
-
* <kai-audio-visualizer variant="radial" size="lg" bar-count="24"></kai-audio-visualizer>
|
|
165
|
-
* ```
|
|
166
|
-
*
|
|
167
|
-
* Audio sources and rich data are JS properties, never attributes:
|
|
168
|
-
* ```js
|
|
169
|
-
* el.stream = micStream // MediaStream
|
|
170
|
-
* el.audioElement = audioRef // HTMLMediaElement
|
|
171
|
-
* el.bands = [0.2, 0.8, 0.4] // pre-computed, skips Web Audio; new array each update
|
|
172
|
-
* el.shader = { fragment: glsl } // variant="custom" only
|
|
173
|
-
* ```
|
|
174
|
-
*
|
|
175
|
-
* Audio drives the geometry only while `state="speaking"`. Every other state
|
|
176
|
-
* plays its scripted animation, so a mic stream attached during `listening`
|
|
177
|
-
* changes nothing by default (LiveKit parity). Set `listening-amplitude` to
|
|
178
|
-
* render real amplitude while the USER is the one talking:
|
|
179
|
-
* ```html
|
|
180
|
-
* <kai-audio-visualizer state="listening" listening-amplitude></kai-audio-visualizer>
|
|
181
|
-
* ```
|
|
182
|
-
*
|
|
183
|
-
* Size tiers are fixed pixel designs, but the element never clips: in a
|
|
184
|
-
* container narrower than the tier's natural footprint the whole picture
|
|
185
|
-
* scales down proportionally to fit, and returns to the exact designed
|
|
186
|
-
* metrics as soon as the space is back. Nothing to configure.
|
|
187
|
-
*
|
|
188
|
-
* The `wave`, `aurora`, and `custom` variants render through WebGL, and a
|
|
189
|
-
* browser only allows about 16 live WebGL contexts per page. So a shader
|
|
190
|
-
* variant scrolled off screen stops drawing and hands its context back,
|
|
191
|
-
* picking up where it left off when it returns. Opt out per element when a
|
|
192
|
-
* visualizer must keep running unseen:
|
|
193
|
-
*
|
|
194
|
-
* ```html
|
|
195
|
-
* <kai-audio-visualizer variant="wave" animate-when-not-visible></kai-audio-visualizer>
|
|
196
|
-
* ```
|
|
197
|
-
*
|
|
198
|
-
* This is a display element: no methods, no events.
|
|
199
|
-
*
|
|
200
|
-
* Restyle from outside via `::part(bar)` / `::part(cell)` / `::part(canvas)`,
|
|
201
|
-
* the bar and cell parts each carrying `data-kai-index` and `data-kai-highlighted`.
|
|
202
|
-
*/
|
|
203
|
-
defineWebComponent<Props>('kai-audio-visualizer', {
|
|
204
|
-
variant: 'bar',
|
|
205
|
-
state: 'idle',
|
|
206
|
-
size: 'md',
|
|
207
|
-
barCount: undefined,
|
|
208
|
-
count: undefined,
|
|
209
|
-
radius: undefined,
|
|
210
|
-
spread: undefined,
|
|
211
|
-
interval: undefined,
|
|
212
|
-
color: undefined,
|
|
213
|
-
complexity: undefined,
|
|
214
|
-
label: undefined,
|
|
215
|
-
stream: undefined,
|
|
216
|
-
audioElement: undefined,
|
|
217
|
-
bands: undefined,
|
|
218
|
-
// `undefined`, not `false`, for the same resolveFlag reason as
|
|
219
|
-
// `animateWhenNotVisible` below.
|
|
220
|
-
listeningAmplitude: undefined,
|
|
221
|
-
shader: undefined,
|
|
222
|
-
// `undefined`, not `false`: `resolveFlag` short-circuits on an explicit
|
|
223
|
-
// `false` prop value, so a `false` default would beat a bare
|
|
224
|
-
// `animate-when-not-visible` attribute if component-register ever left the
|
|
225
|
-
// default in place instead of writing `undefined` for a valueless attribute.
|
|
226
|
-
animateWhenNotVisible: undefined,
|
|
227
|
-
}, AudioVisualizerFacade);
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
// The kai-* autoloader (opt-in, additive — the Web Awesome model).
|
|
2
|
-
//
|
|
3
|
-
// Include this ONE module (via a CDN/static `<script type="module">` tag) and it
|
|
4
|
-
// watches the DOM for undefined kai-* elements and dynamically imports each
|
|
5
|
-
// element's module on demand — so a page that only uses <kai-chat> never downloads
|
|
6
|
-
// the others. The register-all bundle (@kitn.ai/ui/elements) stays the default;
|
|
7
|
-
// this is the delivery for NO-BUILD / CDN / static-served pages.
|
|
8
|
-
//
|
|
9
|
-
// IMPORTANT — this is a CDN / static-file pattern (it resolves sibling element
|
|
10
|
-
// modules relative to its own URL). It is NOT importable through a bundler: Vite /
|
|
11
|
-
// webpack relocate `import.meta.url` away from the element files and cannot analyze
|
|
12
|
-
// the dynamic import, so it 404s. In a BUNDLED app use per-element imports
|
|
13
|
-
// (`import '@kitn.ai/ui/elements/<el>'`) or the register-all bundle. (Advanced: host
|
|
14
|
-
// dist/elements/ yourself and call setAutoloaderBasePath('<url>/') before use.)
|
|
15
|
-
//
|
|
16
|
-
// Tag → module is resolved through the generated manifest (filenames don't always
|
|
17
|
-
// equal the tag, and some modules register more than one tag), and modules are
|
|
18
|
-
// fetched relative to THIS module's URL.
|
|
19
|
-
import manifest from './element-manifest.json';
|
|
20
|
-
|
|
21
|
-
const tagToModule: Record<string, string> = manifest.tags;
|
|
22
|
-
const inFlight = new Set<string>();
|
|
23
|
-
|
|
24
|
-
// Base = the directory of this module. Computed via string ops on import.meta.url
|
|
25
|
-
// (NOT `new URL('./x', import.meta.url)`, which Vite rewrites into a static-asset
|
|
26
|
-
// glob that resolves to undefined at runtime).
|
|
27
|
-
const BASE = import.meta.url.slice(0, import.meta.url.lastIndexOf('/') + 1);
|
|
28
|
-
|
|
29
|
-
/** Override where element modules are fetched from (e.g. a CDN). Call before use. */
|
|
30
|
-
let baseOverride: string | null = null;
|
|
31
|
-
export function setAutoloaderBasePath(path: string): void {
|
|
32
|
-
baseOverride = path.endsWith('/') ? path : path + '/';
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async function register(tag: string): Promise<void> {
|
|
36
|
-
if (customElements.get(tag) || inFlight.has(tag)) return;
|
|
37
|
-
const file = tagToModule[tag];
|
|
38
|
-
if (!file) return; // not one of ours
|
|
39
|
-
inFlight.add(tag);
|
|
40
|
-
try {
|
|
41
|
-
await import(/* @vite-ignore */ `${baseOverride ?? BASE}${file}.js`);
|
|
42
|
-
} catch (err) {
|
|
43
|
-
inFlight.delete(tag);
|
|
44
|
-
warnOnce(tag, err);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// One actionable warning per session (the failure is almost always "imported
|
|
49
|
-
// through a bundler" — see the header note), instead of a silent per-tag error.
|
|
50
|
-
let warned = false;
|
|
51
|
-
function warnOnce(tag: string, err: unknown): void {
|
|
52
|
-
if (warned) return;
|
|
53
|
-
warned = true;
|
|
54
|
-
const msg = (err as { message?: string })?.message ?? String(err);
|
|
55
|
-
// eslint-disable-next-line no-console
|
|
56
|
-
console.warn(
|
|
57
|
-
`[kai-autoloader] could not load "${tag}" (${msg}). The autoloader is a CDN / ` +
|
|
58
|
-
`static-file tool — load it from a <script type="module" src=".../@kitn.ai/ui/dist/elements/autoloader.js">. ` +
|
|
59
|
-
`It is NOT importable through a bundler. In a bundled app, register elements with per-element imports ` +
|
|
60
|
-
`(import '@kitn.ai/ui/elements/<el>') or the register-all bundle (import '@kitn.ai/ui/elements'). To drive ` +
|
|
61
|
-
`the autoloader from a bundler, host dist/elements/ and call setAutoloaderBasePath('<url>/') before use.`,
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function discover(root: ParentNode | Element): void {
|
|
66
|
-
const tags = new Set<string>();
|
|
67
|
-
const self = (root as Element).tagName?.toLowerCase?.();
|
|
68
|
-
if (self && self in tagToModule && !customElements.get(self)) tags.add(self);
|
|
69
|
-
root.querySelectorAll?.(':not(:defined)').forEach((el) => {
|
|
70
|
-
const t = el.tagName.toLowerCase();
|
|
71
|
-
if (t in tagToModule) tags.add(t);
|
|
72
|
-
});
|
|
73
|
-
tags.forEach(register);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/** Start watching `root` (default: the whole document) for undefined kai-* elements. */
|
|
77
|
-
export function startAutoloader(root: ParentNode = document): void {
|
|
78
|
-
discover(root as Element);
|
|
79
|
-
new MutationObserver((mutations) => {
|
|
80
|
-
for (const m of mutations)
|
|
81
|
-
for (const node of m.addedNodes)
|
|
82
|
-
if (node.nodeType === 1) discover(node as Element);
|
|
83
|
-
}).observe(document.documentElement, { childList: true, subtree: true });
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Self-start on import (the <script type="module"> use case). Deferred to a
|
|
87
|
-
// microtask so a consumer that calls setAutoloaderBasePath() right after importing
|
|
88
|
-
// (the advanced bundler-from-CDN path) takes effect before the first discovery pass.
|
|
89
|
-
if (typeof document !== 'undefined') queueMicrotask(() => startAutoloader());
|
package/src/elements/avatar.tsx
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { Avatar } from '../ui/avatar';
|
|
2
|
-
import { defineWebComponent } from './define';
|
|
3
|
-
|
|
4
|
-
interface Props extends Record<string, unknown> {
|
|
5
|
-
/** Image URL/data-URI. When absent, the `fallback` initials show instead. */
|
|
6
|
-
src?: string;
|
|
7
|
-
/** Alt text for the image. Defaults to `fallback`. */
|
|
8
|
-
alt?: string;
|
|
9
|
-
/** Short text shown when there's no image, usually initials (e.g. "JD", "AI"). */
|
|
10
|
-
fallback?: string;
|
|
11
|
-
/** Size token: `sm` | `md` (default) | `lg`. */
|
|
12
|
-
size?: 'sm' | 'md' | 'lg';
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* `<kai-avatar>` — a person/entity avatar: a rounded image that falls back to
|
|
17
|
-
* initials when there's no `src`. This is an *identity* badge (the thing next to
|
|
18
|
-
* a message or in a conversation list), not a generic icon — for a glyph, use an
|
|
19
|
-
* `icon` prop on another element.
|
|
20
|
-
*
|
|
21
|
-
* ```html
|
|
22
|
-
* <kai-avatar src="/me.jpg" fallback="JD"></kai-avatar>
|
|
23
|
-
* <kai-avatar fallback="AI" size="sm"></kai-avatar>
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
|
-
defineWebComponent<Props>('kai-avatar', {
|
|
27
|
-
src: undefined,
|
|
28
|
-
alt: undefined,
|
|
29
|
-
fallback: '',
|
|
30
|
-
size: 'md',
|
|
31
|
-
}, (props) => (
|
|
32
|
-
<Avatar src={props.src} alt={props.alt} fallback={props.fallback ?? ''} size={props.size ?? 'md'} />
|
|
33
|
-
));
|
package/src/elements/badge.tsx
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { Badge } from '../ui/badge';
|
|
2
|
-
import { defineWebComponent } from './define';
|
|
3
|
-
|
|
4
|
-
interface Props extends Record<string, unknown> {
|
|
5
|
-
/** `default` (muted pill) · `count` (compact number badge) · `citation`
|
|
6
|
-
* (filled primary, for inline citation markers). Defaults to `default`. */
|
|
7
|
-
variant?: 'default' | 'count' | 'citation';
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* `<kai-badge>` — a small pill for labels, status, counts, or citation markers.
|
|
12
|
-
* Put the content as light-DOM text.
|
|
13
|
-
*
|
|
14
|
-
* ```html
|
|
15
|
-
* <kai-badge>Beta</kai-badge>
|
|
16
|
-
* <kai-badge variant="count">3</kai-badge>
|
|
17
|
-
* <kai-badge variant="citation">1</kai-badge>
|
|
18
|
-
* ```
|
|
19
|
-
* Restyle via `::part(badge)`.
|
|
20
|
-
*/
|
|
21
|
-
defineWebComponent<Props>('kai-badge', {
|
|
22
|
-
variant: 'default',
|
|
23
|
-
}, (props) => (
|
|
24
|
-
<>
|
|
25
|
-
{/* Base sets `:host{display:block}`; a badge/pill flows inline with text and
|
|
26
|
-
beside sibling badges, so inline-flex like kai-button. */}
|
|
27
|
-
<style>{':host{display:inline-flex}'}</style>
|
|
28
|
-
<Badge variant={props.variant ?? 'default'} part="badge">
|
|
29
|
-
<slot />
|
|
30
|
-
</Badge>
|
|
31
|
-
</>
|
|
32
|
-
));
|
package/src/elements/button.tsx
DELETED
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import { Show } from 'solid-js';
|
|
2
|
-
import { Button } from '../ui/button';
|
|
3
|
-
import { renderIcon } from '../ui/icon';
|
|
4
|
-
import { defineWebComponent } from './define';
|
|
5
|
-
import { createSlotText } from './slot-text';
|
|
6
|
-
|
|
7
|
-
interface Props extends Record<string, unknown> {
|
|
8
|
-
/** Visual style. `default` (filled), `subtle` (muted text, hover tint, the
|
|
9
|
-
* toolbar icon look), `ghost` (transparent, hover fill), `outline`, or
|
|
10
|
-
* `destructive`. Defaults to `default`. */
|
|
11
|
-
variant?: 'default' | 'subtle' | 'ghost' | 'outline' | 'destructive';
|
|
12
|
-
/** Size token. `icon` / `icon-sm` are square (for icon-only buttons); `sm` /
|
|
13
|
-
* `md` / `lg` size text buttons. Defaults to `md`. */
|
|
14
|
-
size?: 'sm' | 'md' | 'lg' | 'icon' | 'icon-sm';
|
|
15
|
-
/** Leading icon: a named icon (e.g. `"mic"`, `"plus"`), an image URL/data-URI,
|
|
16
|
-
* or plain text. Renders before any slotted label. */
|
|
17
|
-
icon?: string;
|
|
18
|
-
/** Trailing icon, after the label (e.g. `"chevron-down"` for a menu affordance). */
|
|
19
|
-
iconTrailing?: string;
|
|
20
|
-
/** Accessible name. REQUIRED for icon-only buttons (no visible text); ignored
|
|
21
|
-
* when you slot visible text, which already names the button. An `aria-label`
|
|
22
|
-
* on top of visible text REPLACES that name rather than adding to it, so a
|
|
23
|
-
* button reading "Save" that answers to "Submit" is unusable by speech input
|
|
24
|
-
* (WCAG 2.5.3, Label in Name). The visible text wins. An `icon` / `icon-sm`
|
|
25
|
-
* size hides the slot, which makes the button icon-only whatever you slotted,
|
|
26
|
-
* so `label` is what names it there. */
|
|
27
|
-
label?: string;
|
|
28
|
-
/** Disable the button (non-interactive, dimmed). */
|
|
29
|
-
disabled?: boolean;
|
|
30
|
-
/** Stretch the button to the full width of its container (a block button),
|
|
31
|
-
* e.g. a card CTA or a stacked action. Attribute: `full`. */
|
|
32
|
-
full?: boolean;
|
|
33
|
-
/** Justify the button's content: `start`, `center` (default), or `end`.
|
|
34
|
-
* Combine with `full` for a full-width, left-aligned button. */
|
|
35
|
-
align?: 'start' | 'center' | 'end';
|
|
36
|
-
/** Native button `type`. Defaults to `button` (so it never submits a form). */
|
|
37
|
-
type?: 'button' | 'submit' | 'reset';
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/** Events fired by `<kai-button>`. */
|
|
41
|
-
interface Events {
|
|
42
|
-
/** The button was activated (pointer or keyboard). Carries no detail. The
|
|
43
|
-
* native `click` also bubbles (composed) for consumers who prefer it. */
|
|
44
|
-
'kai-click': void;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* `<kai-button>` — the kit's button as a drop-in element, so consumers compose
|
|
49
|
-
* polished, theme-aware controls instead of hand-rolling `<button>` + inline
|
|
50
|
-
* hover styles. Put the label as light-DOM text; use `icon` for a leading glyph
|
|
51
|
-
* and `label` to name an icon-only button.
|
|
52
|
-
*
|
|
53
|
-
* ```html
|
|
54
|
-
* <kai-button variant="subtle" size="icon" icon="mic" label="Voice input"></kai-button>
|
|
55
|
-
* <kai-button variant="ghost" icon-trailing="chevron-down">High</kai-button>
|
|
56
|
-
* <kai-button>Send</kai-button>
|
|
57
|
-
* <kai-button label="Ship"><svg slot="icon" viewBox="0 0 24 24">…</svg></kai-button>
|
|
58
|
-
* ```
|
|
59
|
-
*
|
|
60
|
-
* The `icon` prop renders a curated/URL icon; for anything else, slot your own
|
|
61
|
-
* inline SVG via `slot="icon"` (it wins over `icon`). Restyle via `::part(button)`.
|
|
62
|
-
* Emits `kai-click`.
|
|
63
|
-
*/
|
|
64
|
-
defineWebComponent<Props, Events>('kai-button', {
|
|
65
|
-
variant: 'default',
|
|
66
|
-
size: 'md',
|
|
67
|
-
icon: undefined,
|
|
68
|
-
iconTrailing: undefined,
|
|
69
|
-
label: undefined,
|
|
70
|
-
disabled: false,
|
|
71
|
-
full: false,
|
|
72
|
-
align: 'center',
|
|
73
|
-
type: 'button',
|
|
74
|
-
}, (props, { dispatch, flag, element, expose }) => {
|
|
75
|
-
// `icon` / `icon-sm` are square, icon-ONLY sizes: suppress the text label and
|
|
76
|
-
// trailing icon so a stray label doesn't get cramped into the square (the
|
|
77
|
-
// `label` prop still names it for assistive tech).
|
|
78
|
-
const iconOnly = () => props.size === 'icon' || props.size === 'icon-sm';
|
|
79
|
-
|
|
80
|
-
// Slotted text names the button by itself (name-from-contents reaches through
|
|
81
|
-
// the slot), so `label` must NOT be emitted on top of it: aria-label REPLACES
|
|
82
|
-
// the computed name, and a name that disagrees with the visible text locks
|
|
83
|
-
// speech-input users out of the control (WCAG 2.5.3). This is what the `label`
|
|
84
|
-
// doc has always promised, and what `kai-checkpoint` already does.
|
|
85
|
-
//
|
|
86
|
-
// `flatten` so a consumer who wraps <kai-button> in their own component and
|
|
87
|
-
// forwards a <slot> still counts as having visible text. Safe here because the
|
|
88
|
-
// default slot has no fallback content — see createSlotText.
|
|
89
|
-
const slotted = createSlotText({ flatten: true });
|
|
90
|
-
|
|
91
|
-
// The name to emit, or nothing. An `icon`/`icon-sm` size does not render the
|
|
92
|
-
// default slot at all, so whatever was slotted is INVISIBLE and `label` is the
|
|
93
|
-
// only name available — dropping it there would leave icon buttons nameless,
|
|
94
|
-
// which is the worse bug.
|
|
95
|
-
const ariaLabel = () => (!iconOnly() && slotted.hasText() ? undefined : props.label);
|
|
96
|
-
|
|
97
|
-
// ── Imperative API (instance methods on the host) ──────────────────────────
|
|
98
|
-
// The real <button> lives in the shadow root, so native focus()/blur()/click()
|
|
99
|
-
// on the host hit the wrapper, not the control. Forward to the inner button.
|
|
100
|
-
// These shadow the inherited HTMLElement methods — intended; expose() uses
|
|
101
|
-
// defineProperty so the override sticks. No collision with the props above.
|
|
102
|
-
expose({
|
|
103
|
-
/** Focus the inner `<button>` (host.focus() would focus the wrapper). */
|
|
104
|
-
focus: (options?: FocusOptions) =>
|
|
105
|
-
element.shadowRoot?.querySelector('button')?.focus(options),
|
|
106
|
-
/** Blur the inner `<button>`. */
|
|
107
|
-
blur: () => element.shadowRoot?.querySelector('button')?.blur(),
|
|
108
|
-
/** Programmatically activate the button. Runs the same path as a user
|
|
109
|
-
* click and fires kai-click. Forwarding to the inner button means
|
|
110
|
-
* `disabled` is respected automatically. */
|
|
111
|
-
click: () => element.shadowRoot?.querySelector('button')?.click(),
|
|
112
|
-
});
|
|
113
|
-
return (
|
|
114
|
-
<>
|
|
115
|
-
{/* The host shrinks to the label by default (inline-flex), so a text button
|
|
116
|
-
is only as wide as its content — until a parent stretches it. A text
|
|
117
|
-
button's inner control is w-full, so when the host IS stretched (a flex
|
|
118
|
-
column with items-stretch, e.g. a card's collapsed footer, or an explicit
|
|
119
|
-
`full`) the button fills it. `full` forces that standalone (a block CTA).
|
|
120
|
-
Icon buttons stay square (no w-full). */}
|
|
121
|
-
<style>{':host{display:inline-flex}:host([full]){display:block}'}</style>
|
|
122
|
-
<Button
|
|
123
|
-
part="button"
|
|
124
|
-
variant={props.variant ?? 'default'}
|
|
125
|
-
size={props.size ?? 'md'}
|
|
126
|
-
align={props.align ?? 'center'}
|
|
127
|
-
full={flag('full') || !iconOnly()}
|
|
128
|
-
type={props.type ?? 'button'}
|
|
129
|
-
disabled={flag('disabled')}
|
|
130
|
-
aria-label={ariaLabel()}
|
|
131
|
-
onClick={() => dispatch('kai-click')}
|
|
132
|
-
>
|
|
133
|
-
{/* Leading icon: a slotted SVG (slot="icon") wins — drop in any icon
|
|
134
|
-
library or your own; otherwise the `icon` prop renders a curated/URL one. */}
|
|
135
|
-
<slot name="icon">
|
|
136
|
-
<Show when={props.icon}>
|
|
137
|
-
{renderIcon(props.icon, { class: 'size-4 shrink-0', imgClass: 'size-4 shrink-0', spanClass: 'inline-flex size-4 shrink-0 items-center justify-center', ariaHidden: true })}
|
|
138
|
-
</Show>
|
|
139
|
-
</slot>
|
|
140
|
-
<Show when={!iconOnly()}>
|
|
141
|
-
<slot ref={slotted.ref} />
|
|
142
|
-
</Show>
|
|
143
|
-
<Show when={props.iconTrailing && !iconOnly()}>
|
|
144
|
-
{renderIcon(props.iconTrailing, { class: 'size-4 shrink-0 opacity-60', imgClass: 'size-4 shrink-0', spanClass: 'inline-flex size-4 shrink-0 items-center justify-center', ariaHidden: true })}
|
|
145
|
-
</Show>
|
|
146
|
-
</Button>
|
|
147
|
-
</>
|
|
148
|
-
);
|
|
149
|
-
});
|