@kitn.ai/ui 0.26.0 → 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 +16 -5
- package/bin/mcp.js +16 -3
- package/bin/route.js +23 -0
- package/bin/route.test.js +58 -0
- package/dist/{elements/chunks/Icon--Y8vsFal.js → Icon-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/{elements/chunks/audio-visualizer-D7lB6mvR.js → audio-visualizer-B-79y1Tj.js} +1 -1
- 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-flUbeufF.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/{elements/chunks/code-block-BdLiTitd.js → code-block-CUQ5mtv0.js} +1 -1
- package/dist/{elements/chunks/collapsible-BzbXpPzr.js → collapsible-CPJbf6FM.js} +1 -1
- package/dist/components/attachment-types.d.ts +7 -0
- package/dist/components/audio-visualizer/fit-scale.d.ts +1 -1
- package/dist/components/card-renderer.d.ts +13 -0
- package/dist/components/card.d.ts +4 -0
- package/dist/components/chat-thread.d.ts +46 -1
- package/dist/components/conversation-item.d.ts +19 -7
- package/dist/components/conversation-list.d.ts +17 -5
- package/dist/components/form-widgets.d.ts +67 -2
- package/dist/components/form.d.ts +48 -1
- package/dist/components/message.d.ts +25 -3
- package/dist/components/reasoning.d.ts +6 -0
- package/dist/components/scroll-button.d.ts +11 -0
- package/dist/components/thread.d.ts +5 -0
- package/dist/components/tool-types.d.ts +9 -0
- package/dist/composer-CjngLzal.js +106 -0
- package/dist/confirm-card-DCx_A4bU.js +1 -0
- package/dist/construct-cli.es.js +1169 -0
- package/dist/{elements/chunks/context-VLIL3sJ-.js → context-BY8V-Nlp.js} +1 -1
- 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-CQED4T0g.js → create-tween-BPzaefTp.js} +1 -1
- package/dist/{create-tween-BFT6c-Y8.js → create-tween-CnMHviKB.js} +1 -1
- package/dist/{create-tween-CJNlzoaO.js → create-tween-D1aiGZZh.js} +1 -1
- package/dist/{elements/chunks/create-tween-c4Z8TDYz.js → create-tween-DUSQUKpr.js} +2 -2
- package/dist/css-M7EaDHN_.js +1 -6
- package/dist/custom-elements.json +1400 -218
- 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/{elements/chunks/disclosure-CcNbyLy0.js → disclosure-CbLtajUQ.js} +1 -1
- package/dist/{elements/chunks/dropdown-BgWTthUx.js → dropdown-BwhViJFd.js} +1 -1
- package/dist/elements/agent-card.js +1 -1
- package/dist/elements/artifact.js +1 -1
- package/dist/elements/attachments.js +1 -1
- package/dist/elements/audio-visualizer.js +1 -1
- package/dist/elements/autoloader.js +1 -1
- package/dist/elements/avatar.js +1 -1
- package/dist/elements/badge.js +1 -1
- package/dist/elements/button.js +1 -1
- package/dist/elements/card.js +1 -1
- package/dist/elements/cards.js +1 -1
- package/dist/elements/chain-of-thought.js +1 -1
- package/dist/elements/chat-scope-picker.js +1 -1
- package/dist/elements/chat-workspace.js +1 -1
- package/dist/elements/chat.js +1 -1
- package/dist/elements/checkbox-group.d.ts +1 -0
- package/dist/elements/checkbox-group.js +1 -0
- package/dist/elements/checkbox.d.ts +1 -0
- package/dist/elements/checkbox.js +1 -0
- package/dist/elements/checkpoint.js +1 -1
- package/dist/elements/choice.js +1 -1
- package/dist/elements/coachmark.js +1 -1
- package/dist/elements/code-block.js +1 -1
- package/dist/elements/command.js +1 -1
- package/dist/elements/compare.js +1 -1
- package/dist/elements/composer.js +1 -1
- package/dist/elements/confirm-card.js +1 -1
- package/dist/elements/context-meter.js +1 -1
- package/dist/elements/conversation-item.js +1 -1
- package/dist/elements/conversation-list.js +1 -1
- package/dist/elements/define-entry.d.ts +12 -0
- package/dist/elements/dialog.js +1 -1
- package/dist/elements/dock.js +101 -7
- package/dist/elements/dropdown.js +1 -1
- package/dist/elements/editable-label.js +1 -1
- package/dist/elements/element-data-types.d.ts +37 -0
- package/dist/elements/embed.js +1 -1
- package/dist/elements/empty.js +1 -1
- package/dist/elements/feedback-bar.js +1 -1
- package/dist/elements/file-tree.js +1 -1
- package/dist/elements/file-upload.js +1 -1
- package/dist/elements/form.js +1 -1
- package/dist/elements/hover-card.js +1 -1
- package/dist/elements/icon.js +1 -1
- package/dist/elements/image.js +1 -1
- package/dist/elements/input.js +1 -1
- package/dist/elements/kbd.js +1 -1
- package/dist/elements/link-preview.js +1 -1
- package/dist/elements/loader.js +1 -1
- package/dist/elements/markdown.js +1 -1
- package/dist/elements/menu.js +1 -1
- package/dist/elements/message-skills.js +1 -1
- package/dist/elements/message.js +1 -1
- package/dist/elements/model-switcher.js +1 -1
- package/dist/elements/nav.js +1 -1
- package/dist/elements/notice.js +1 -1
- package/dist/elements/pane-grid.d.ts +1 -0
- package/dist/elements/pane-grid.js +1 -0
- package/dist/elements/pane-group.js +1 -1
- package/dist/elements/pane.js +1 -1
- package/dist/elements/popover.js +1 -1
- package/dist/elements/progress-bar.js +1 -1
- package/dist/elements/prompt-dock.js +1 -1
- package/dist/elements/prompt-input.js +1 -1
- package/dist/elements/prompt-suggestions.js +1 -1
- package/dist/elements/radio-group.d.ts +1 -0
- package/dist/elements/radio-group.js +1 -0
- package/dist/elements/reasoning.js +1 -1
- package/dist/elements/remote.js +1 -1
- package/dist/elements/resizable.js +1 -1
- package/dist/elements/response-stream.js +2 -2
- package/dist/elements/screen.js +1 -1
- package/dist/elements/scroll-area.js +1 -1
- package/dist/elements/scroll-button.js +1 -1
- package/dist/elements/search.js +1 -1
- package/dist/elements/segmented.js +1 -1
- package/dist/elements/select.d.ts +1 -0
- package/dist/elements/select.js +1 -0
- package/dist/elements/separator.js +1 -1
- package/dist/elements/setting-item.js +1 -1
- package/dist/elements/settings-group.js +1 -1
- package/dist/elements/skeleton.js +1 -1
- package/dist/elements/slider.d.ts +1 -0
- package/dist/elements/slider.js +1 -0
- package/dist/elements/slots.d.ts +1 -1
- package/dist/elements/source.js +1 -1
- package/dist/elements/status.js +1 -1
- package/dist/elements/switch.js +1 -1
- package/dist/elements/tabs.js +1 -1
- package/dist/elements/tasks.js +1 -1
- package/dist/elements/text-shimmer.js +1 -1
- package/dist/elements/thinking-bar.js +1 -1
- package/dist/elements/thread.js +1 -1
- package/dist/elements/toast.js +1 -1
- package/dist/elements/tool.js +1 -1
- package/dist/elements/tooltip.js +1 -1
- package/dist/elements/voice-input.js +1 -1
- package/dist/elements/voice-output.js +1 -1
- package/dist/elements.d.ts +362 -24
- package/dist/{elements/chunks/ellipsis-7gU33mL2.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-CSOEsNlx.js → external-link-u9d85ORQ.js} +1 -1
- package/dist/file-text-CX7_x42o.js +1 -0
- package/dist/{elements/chunks/file-tree-zvB2i7P9.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 +1 -1
- package/dist/index.js +7330 -5852
- package/dist/index.server.js +5823 -4759
- 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.es.js +1 -1
- package/dist/kbd-961zMPFB.js +1 -0
- package/dist/link-DlZZBGaR.js +1 -0
- package/dist/{elements/chunks/link-preview-OQ9IEq0f.js → link-preview-DIIbV2Sd.js} +1 -1
- package/dist/loader-YQszHFaW.js +1 -0
- package/dist/{elements/chunks/markdown-DgBFaGAz.js → markdown-CVk1MPsj.js} +1 -1
- package/dist/mcp.es.js +1285 -79
- 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-DPIUKTrT.js → minimize-2-UEZmP2QT.js} +1 -1
- package/dist/{elements/chunks/model-switcher-DsT8tFB0.js → model-switcher-Kk1jEQ5t.js} +1 -1
- package/dist/{elements/chunks/overlay-DuiwdXjm.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 +2 -2
- 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 +193 -19
- package/dist/react.js +216 -180
- package/dist/reasoning-Cackq4Rh.js +1 -0
- package/dist/register-impl-C7rENvPK.js +424 -0
- package/dist/{elements/chunks/resizable-D181b4fM.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/tool-defs.d.ts +11 -1
- package/dist/schemas.js +81 -81
- 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-CeJHQqLW.js → separator-CE6vly6z.js} +1 -1
- package/dist/{elements/chunks/settings-CqaHgJF9.js → settings-CE-78SvZ.js} +1 -1
- package/dist/{elements/chunks/settings-group-CjqjLCOn.js → settings-group-ZFWNxFQR.js} +1 -1
- package/dist/{elements/chunks/skeleton-D8akBnKS.js → skeleton-BebdP4mf.js} +1 -1
- package/dist/slider-BAKRYUlz.js +1 -0
- package/dist/{solid-BtdqNZI7.js → solid-BE5ui6sy.js} +8727 -7212
- package/dist/{solid-CnavwBye.js → solid-DFhsce3O.js} +7015 -5886
- package/dist/solid.d.ts +10 -0
- package/dist/solid.js +240 -234
- package/dist/solid.server.js +240 -234
- package/dist/source-B0FlguSx.js +1 -0
- package/dist/star-CBMZvLuN.js +1 -0
- package/dist/state/index.d.ts +1 -1
- package/dist/state/mock.d.ts +32 -2
- package/dist/state.js +133 -108
- package/dist/{elements/chunks/store-Cjq0qwYN.js → store-7eoadydQ.js} +1 -1
- 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-DX2Ijk3H.js → thumbs-up-DQcu2HMO.js} +1 -1
- package/dist/toast-store-C6yKOhbk.js +1 -0
- package/dist/{elements/chunks/tool-DKQ2D1DP.js → tool-BCYNlfKy.js} +1 -1
- package/dist/{elements/chunks/tooltip-B0G99y8w.js → tooltip-05zI4hjs.js} +1 -1
- package/dist/trash-2-BR1RxGky.js +1 -0
- package/dist/{elements/chunks/triangle-alert-F9cyUEyy.js → triangle-alert-DHohDOCy.js} +1 -1
- package/dist/tsx-B8rCNbgL.js +1 -6
- 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 +22 -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-B8II3-I1.js → variant-aurora-BUOVgPOB.js} +2 -2
- package/dist/{variant-aurora-CMNWOSJR.js → variant-aurora-CUsUJvFI.js} +2 -2
- package/dist/{variant-aurora-CcuDMWwQ.js → variant-aurora-CW2i4bfr.js} +1 -1
- package/dist/{elements/chunks/variant-aurora-qt6Zct8M.js → variant-aurora-xiMPty8f.js} +1 -1
- package/dist/{variant-custom-L16JLLZy.js → variant-custom-BQtOnmeO.js} +1 -1
- package/dist/{variant-custom-C714mqKl.js → variant-custom-CAm9L-E5.js} +2 -2
- package/dist/{variant-custom-BdvYC7af.js → variant-custom-CAnzzppW.js} +2 -2
- package/dist/{elements/chunks/variant-custom-tJp22_BQ.js → variant-custom-D91HjAKz.js} +1 -1
- package/dist/{variant-wave-ecwykeyL.js → variant-wave-Ca1Ls4_y.js} +2 -2
- package/dist/{variant-wave-D7ruiA1W.js → variant-wave-CxX39DKd.js} +2 -2
- package/dist/{elements/chunks/variant-wave-CaQ5ti39.js → variant-wave-DYyzIIZv.js} +1 -1
- package/dist/{variant-wave-2S4La2Ka.js → variant-wave-uY5crU_K.js} +1 -1
- package/dist/vue-BmIZj4XD.js +1 -33
- package/dist/x-C5m1JFgi.js +1 -0
- package/frameworks/react/index.tsx +198 -20
- package/llms-full.txt +1178 -21
- package/llms.txt +6 -3
- package/package.json +17 -4
- package/src/agent-tooling/catalog/invariants.ts +1 -1
- package/src/agent-tooling/catalog/surfaces.ts +72 -0
- package/src/agent-tooling/construct/cli-entry.ts +8 -0
- package/src/agent-tooling/construct/cli.ts +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/mcp/server.ts +2 -1
- package/src/agent-tooling/mcp/tools/construct.ts +130 -0
- package/src/agent-tooling/mcp/tools/debug.ts +126 -4
- package/src/agent-tooling/mcp/tools/reference.ts +104 -3
- package/src/agent-tooling/recipes/composed-thread.ts +714 -0
- package/src/agent-tooling/recipes/index.ts +22 -0
- package/src/agent-tooling/recipes/types.ts +32 -0
- package/src/agent-tooling/registry.ts +5 -0
- package/src/components/attachment-types.ts +7 -0
- package/src/components/audio-visualizer/fit-scale.ts +1 -1
- package/src/components/card-renderer.tsx +39 -8
- package/src/components/card.tsx +10 -2
- package/src/components/chat-scope-picker.tsx +2 -2
- package/src/components/chat-thread.tsx +72 -9
- package/src/components/choice-card.tsx +102 -37
- package/src/components/coachmark.tsx +1 -1
- package/src/components/code-block.tsx +2 -2
- package/src/components/composer.tsx +89 -15
- package/src/components/confirm-card.tsx +20 -4
- package/src/components/conversation-item.tsx +33 -9
- package/src/components/conversation-list.tsx +25 -10
- package/src/components/empty.tsx +14 -3
- package/src/components/file-tree.tsx +5 -1
- package/src/components/form-widgets.tsx +257 -195
- package/src/components/form.tsx +297 -9
- package/src/components/loader.tsx +12 -5
- package/src/components/message-skills.tsx +1 -1
- package/src/components/message.tsx +71 -11
- package/src/components/prompt-input.tsx +7 -1
- package/src/components/prompt-suggestion.tsx +4 -1
- package/src/components/reasoning.tsx +30 -3
- package/src/components/response-compare.tsx +2 -2
- package/src/components/scroll-button.tsx +56 -4
- package/src/components/source.tsx +6 -1
- package/src/components/tasks-card.tsx +58 -16
- package/src/components/thread.tsx +10 -1
- package/src/components/toast.tsx +1 -1
- package/src/components/tool-types.ts +9 -0
- package/src/elements/attachments.tsx +3 -1
- package/src/elements/chat-workspace.tsx +1 -1
- package/src/elements/chat.tsx +22 -4
- package/src/elements/checkbox-group.tsx +164 -0
- package/src/elements/checkbox.tsx +134 -0
- package/src/elements/compiled.css +1 -1
- package/src/elements/composer.tsx +12 -1
- package/src/elements/conversation-item.tsx +62 -22
- package/src/elements/conversation-list.tsx +2 -2
- package/src/elements/define-entry.ts +12 -0
- package/src/elements/dock.tsx +11 -0
- package/src/elements/element-data-types.ts +40 -0
- package/src/elements/element-manifest.json +24 -0
- package/src/elements/element-meta.json +736 -46
- package/src/elements/element-nonscalar.json +15 -0
- package/src/elements/element-types.d.ts +362 -24
- package/src/elements/feedback-bar.tsx +5 -0
- package/src/elements/icon-names.json +29 -0
- package/src/elements/input.tsx +312 -23
- package/src/elements/message.tsx +2 -0
- package/src/elements/pane-grid.tsx +111 -0
- package/src/elements/prompt-input.tsx +8 -2
- package/src/elements/radio-group.tsx +129 -0
- package/src/elements/register-impl.ts +6 -0
- package/src/elements/scroll-button.tsx +54 -6
- package/src/elements/select.tsx +165 -0
- package/src/elements/slider.tsx +171 -0
- package/src/elements/slots.ts +1 -1
- package/src/elements/styles.css +89 -3
- package/src/elements/thread.tsx +2 -0
- package/src/elements/toast.tsx +14 -1
- package/src/index.ts +2 -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 +2 -2
- package/src/schemas/tool-defs.ts +12 -2
- package/src/solid.ts +10 -0
- package/src/state/index.ts +1 -1
- package/src/state/mock.ts +92 -6
- package/src/ui/agent-card.tsx +2 -2
- package/src/ui/avatar.tsx +1 -1
- package/src/ui/checkbox-group.tsx +153 -0
- package/src/ui/checkbox.tsx +63 -0
- package/src/ui/dock.tsx +145 -6
- package/src/ui/icon.tsx +53 -0
- package/src/ui/input.tsx +249 -9
- package/src/ui/kbd.tsx +1 -1
- package/src/ui/nav.tsx +1 -1
- package/src/ui/pane-group.tsx +2 -2
- package/src/ui/radio.tsx +150 -0
- package/src/ui/select.tsx +168 -0
- package/src/ui/slider.tsx +178 -0
- package/src/ui/switch.tsx +49 -18
- package/src/utils/cn.ts +11 -5
- package/theme.css +84 -13
- package/dist/elements/chunks/action-icons-D9u3OzYW.js +0 -1
- package/dist/elements/chunks/arrow-left-CVh1TeN7.js +0 -1
- package/dist/elements/chunks/artifact-BkYcfIlZ.js +0 -1
- package/dist/elements/chunks/attachments-DwfNlubq.js +0 -1
- package/dist/elements/chunks/badge-Q0-Cmwzz.js +0 -1
- package/dist/elements/chunks/bash-InADTalH.js +0 -1
- package/dist/elements/chunks/card-renderer-3Dyl-FpN.js +0 -1
- package/dist/elements/chunks/card-routing-BK09BdmL.js +0 -1
- package/dist/elements/chunks/check-B5kBPKeo.js +0 -1
- package/dist/elements/chunks/chevron-down-DZ1GS39h.js +0 -1
- package/dist/elements/chunks/chevron-right-CvP7OUd2.js +0 -1
- package/dist/elements/chunks/choice-card-D4QUIOWZ.js +0 -1
- package/dist/elements/chunks/circle-CDf9g6MQ.js +0 -1
- package/dist/elements/chunks/circle-check-CA47Nqbz.js +0 -1
- package/dist/elements/chunks/circle-x-CJ_HVbC8.js +0 -1
- package/dist/elements/chunks/composer-Byve-n8K.js +0 -69
- package/dist/elements/chunks/confirm-card-B0flE3MN.js +0 -1
- package/dist/elements/chunks/controllable-DTwTIlwp.js +0 -1
- package/dist/elements/chunks/conversation-item-BDztezOG.js +0 -1
- package/dist/elements/chunks/copy-Nf-kqxXH.js +0 -1
- package/dist/elements/chunks/core-AYMC6_lb.js +0 -12
- package/dist/elements/chunks/css-M7EaDHN_.js +0 -1
- package/dist/elements/chunks/default-input-C2iLFq0b.js +0 -1
- package/dist/elements/chunks/define-wjHR1MkU.js +0 -1
- package/dist/elements/chunks/download-C4V7tBdb.js +0 -1
- package/dist/elements/chunks/embed-D3KewsIJ.js +0 -1
- package/dist/elements/chunks/engine-javascript-vq0WuIJl.js +0 -141
- package/dist/elements/chunks/file-text-D1G8khle.js +0 -1
- package/dist/elements/chunks/folder-WW2LGLid.js +0 -1
- package/dist/elements/chunks/form-CQirdC4W.js +0 -1
- package/dist/elements/chunks/github-dark-dimmed-DUshB20C.js +0 -1
- package/dist/elements/chunks/github-light-JYsPkUQd.js +0 -1
- package/dist/elements/chunks/hover-card-CJJkfHTK.js +0 -1
- package/dist/elements/chunks/html-CPZ3oZQ7.js +0 -1
- package/dist/elements/chunks/icon-Cfgmf4fa.js +0 -1
- package/dist/elements/chunks/info-DX3YMOt6.js +0 -1
- package/dist/elements/chunks/input-BtW9U6Sq.js +0 -1
- package/dist/elements/chunks/javascript-C25yR2R2.js +0 -1
- package/dist/elements/chunks/json-DxJze_jm.js +0 -1
- package/dist/elements/chunks/kbd-LGXwuT_V.js +0 -1
- package/dist/elements/chunks/link-2My69BqT.js +0 -1
- package/dist/elements/chunks/loader-iOxc_Tu-.js +0 -1
- package/dist/elements/chunks/message-VMZohrXx.js +0 -1
- package/dist/elements/chunks/message-circle-CpXMM-_n.js +0 -1
- package/dist/elements/chunks/message-square-DxcWtETQ.js +0 -1
- package/dist/elements/chunks/message-tZmV2A3p.js +0 -1
- package/dist/elements/chunks/paperclip-CRZVp4z_.js +0 -1
- package/dist/elements/chunks/progress-bar-DNy66e_E.js +0 -1
- package/dist/elements/chunks/prompt-suggestion-Bn64Nl7L.js +0 -1
- package/dist/elements/chunks/reasoning-Emn9N4-T.js +0 -1
- package/dist/elements/chunks/rotate-cw-CPWe37D9.js +0 -1
- package/dist/elements/chunks/scroll-area-ClZkZxIk.js +0 -1
- package/dist/elements/chunks/scroll-button-DPE-t3x_.js +0 -1
- package/dist/elements/chunks/share-CyfnNEqp.js +0 -1
- package/dist/elements/chunks/source-UWCvmVak.js +0 -1
- package/dist/elements/chunks/star-DoHFAikQ.js +0 -1
- package/dist/elements/chunks/svelte--5p79yCD.js +0 -1
- package/dist/elements/chunks/tasks-card-CmZ5xh6v.js +0 -1
- package/dist/elements/chunks/text-shimmer-DYn09zrz.js +0 -1
- package/dist/elements/chunks/textarea-skiGHURM.js +0 -1
- package/dist/elements/chunks/toast-store-CFnQpThX.js +0 -1
- package/dist/elements/chunks/tsx-B8rCNbgL.js +0 -1
- package/dist/elements/chunks/typescript-RycA9KXf.js +0 -1
- package/dist/elements/chunks/use-card-resolution-DoA2f_EU.js +0 -1
- package/dist/elements/chunks/vue-BmIZj4XD.js +0 -1
- package/dist/elements/chunks/x-B6UnOiLw.js +0 -1
- package/dist/llms/llms-full.txt +0 -2949
- package/dist/llms/llms.txt +0 -156
- package/dist/register-impl-DpE7icIb.js +0 -293
- package/dist/ui/stat.d.ts +0 -16
- package/src/ui/stat.tsx +0 -41
- /package/dist/{elements/chunks/card-tags-D8lZ-C_U.js → card-tags-D8lZ-C_U.js} +0 -0
- /package/dist/{elements/chunks/link-preview-DNILK391.js → link-preview-DNILK391.js} +0 -0
- /package/dist/{elements/chunks/slots-DaNjX0rc.js → slots-DaNjX0rc.js} +0 -0
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
|
|
@@ -83,6 +105,40 @@
|
|
|
83
105
|
*::-webkit-scrollbar-thumb:hover { background-color: var(--color-scrollbar-thumb-hover); }
|
|
84
106
|
*::-webkit-scrollbar-corner { background: transparent; }
|
|
85
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
|
+
|
|
86
142
|
/* Respect a user's reduced-motion preference: disable the tw-animate-css
|
|
87
143
|
enter/exit keyframe animations (toasts, overlays, cards) so they appear and
|
|
88
144
|
disappear instantly instead of sliding/fading. Targets the utility classes
|
|
@@ -169,6 +225,36 @@
|
|
|
169
225
|
.kai-checkbox:checked {
|
|
170
226
|
box-shadow: 0 1px 4px color-mix(in srgb, var(--color-primary) 26%, transparent);
|
|
171
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
|
+
}
|
|
172
258
|
.kai-radio:disabled,
|
|
173
259
|
.kai-checkbox:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
174
260
|
|
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,6 +45,15 @@ 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
|
*
|
package/src/index.ts
CHANGED
|
@@ -419,7 +419,8 @@ export type { KaiTabItem } from './ui/tabs';
|
|
|
419
419
|
export type { PaneStatus } from './ui/pane';
|
|
420
420
|
export type { PaneTab } from './ui/pane-group';
|
|
421
421
|
export type {
|
|
422
|
-
KaiCommandItem, KaiContextUsage, KaiMenuItem, KaiSegmentedOption,
|
|
422
|
+
KaiCheckboxOption, KaiCommandItem, KaiContextUsage, KaiMenuItem, KaiRadioOption, KaiSegmentedOption, KaiSelectOption,
|
|
423
|
+
KaiSourceItem,
|
|
423
424
|
} from './elements/element-data-types';
|
|
424
425
|
// `kai-audio-visualizer.shader` takes a ShaderSpec. The element arrived from main
|
|
425
426
|
// after this block was written, and prop-types-exported.test.ts caught it, which
|
|
@@ -207,6 +207,55 @@ export type FormField = {
|
|
|
207
207
|
| 'switch';
|
|
208
208
|
'x-kai-placeholder'?: string;
|
|
209
209
|
'x-kai-step'?: number;
|
|
210
|
+
/**
|
|
211
|
+
* Display format for a string field. `tel` / `ssn` / `credit-card`
|
|
212
|
+
* apply that type's standard mask and submit digits only; `custom` masks with
|
|
213
|
+
* `x-kai-mask` and submits the formatted value.
|
|
214
|
+
*
|
|
215
|
+
* NOT the JSON Schema `format` keyword, and deliberately not an extension of it:
|
|
216
|
+
* `format` has a registered vocabulary with assertion semantics, `widgetFor()`
|
|
217
|
+
* already switches on it to pick a widget, and `toJsonSchema()` turns it into a
|
|
218
|
+
* validation pattern. This is a UI hint, so it lives in the `x-kai-*` namespace
|
|
219
|
+
* with the other UI hints — and it selects FORMATTING, never a widget.
|
|
220
|
+
*
|
|
221
|
+
* Typed as the semantic-type union for a consumer authoring a form definition by
|
|
222
|
+
* hand. A value arriving from a MODEL is untrusted and may be anything at all;
|
|
223
|
+
* `resolveFieldMask()` degrades an unrecognised one to an unmasked text field with
|
|
224
|
+
* a console warning rather than trusting this declaration.
|
|
225
|
+
*
|
|
226
|
+
* SPELLED OUT HERE RATHER THAN IMPORTED, and that is not laziness. `FieldSemanticType`
|
|
227
|
+
* is declared in `./field-semantics`, which carries the semantics TABLE and its
|
|
228
|
+
* `console.warn` — and this file's whole reason for existing is that a Node/no-DOM
|
|
229
|
+
* backend can name a card payload with `lib: ["ESNext"]` and `types: []`, where
|
|
230
|
+
* `console` does not exist (measured: TS2584, by
|
|
231
|
+
* `tests/schemas/card-data-types-node-safe.test.ts`, which is what caught the import).
|
|
232
|
+
* A type import still has to RESOLVE, so importing the union would drag the engine into
|
|
233
|
+
* the server-safe entry's graph.
|
|
234
|
+
*
|
|
235
|
+
* AN APP CANNOT PIN THIS ON THE MODEL TODAY.
|
|
236
|
+
* `cardTools({ require })` narrows a projected tool schema by dot-path, but there is
|
|
237
|
+
* no path that reaches a form FIELD: a form card's payload is itself a JSON Schema, so
|
|
238
|
+
* `form.schema.json` describes `properties` as a map of field definitions rather than
|
|
239
|
+
* as a node per field, and `require: { form: [{ path: 'properties.ticketId' }] }` is a
|
|
240
|
+
* TypeError naming a path that does not resolve. "Force the model to mask the ticket
|
|
241
|
+
* field" is therefore not expressible; the enum above is what makes it LIKELY, and an
|
|
242
|
+
* app that needs a guarantee validates the arriving envelope itself.
|
|
243
|
+
*
|
|
244
|
+
* It is therefore a REGISTERED COPY of `FIELD_SEMANTIC_TYPES`: the two are pinned
|
|
245
|
+
* mutually assignable at compile time in
|
|
246
|
+
* `tests/components/form-field-formats.test.tsx`, so adding a fifth token to the enum
|
|
247
|
+
* without adding it here fails `nx typecheck ui` rather than shipping a form card that
|
|
248
|
+
* cannot name it.
|
|
249
|
+
*/
|
|
250
|
+
'x-kai-format'?: 'tel' | 'ssn' | 'credit-card' | 'custom';
|
|
251
|
+
/** The mask pattern, read only when `x-kai-format` is `custom`: `#` a digit, `@` an
|
|
252
|
+
* alphanumeric, `*` an obscurable alphanumeric, everything else a literal
|
|
253
|
+
* (`CHG-####`). Capped at the mask engine's own limit; a longer one is refused. */
|
|
254
|
+
'x-kai-mask'?: string;
|
|
255
|
+
/** Placeholder text for the mask's unfilled positions, aligned character for
|
|
256
|
+
* character with the pattern (`mm/dd/yyyy`). Derived from the pattern when absent;
|
|
257
|
+
* a misaligned one is dropped, loudly, and the mask survives. */
|
|
258
|
+
'x-kai-mask-guide'?: string;
|
|
210
259
|
};
|
|
211
260
|
|
|
212
261
|
/** The form definition = CardEnvelope.data for type:'form'. */
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
// src/primitives/card-host.tsx
|
|
2
2
|
// The native transport: a Solid context exposing a CardHost (context() + emit()).
|
|
3
3
|
// emit() routes through the contract policy via the shared routeCardEvent. Cards
|
|
4
|
-
// inside <
|
|
5
|
-
// kai-
|
|
4
|
+
// inside a <CardProvider> use this; cards inside <kai-chat>/<kai-message>/
|
|
5
|
+
// <kai-thread> (and bare cards given a hostElement) fall back to the bubbling
|
|
6
|
+
// kai-card event off the host element (see card-routing.listenForCardEvents and
|
|
7
|
+
// CardRenderer's hostElement prop).
|
|
6
8
|
import { createContext, useContext, type JSX } from 'solid-js';
|
|
7
9
|
import type { CardContext, CardEvent, CardHost, CardPolicy } from './card-contract';
|
|
8
10
|
import { routeCardEvent } from './card-routing';
|
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
// policy router (used by BOTH the native listener and the remote transport), and a
|
|
4
4
|
// host-side listener helper for the bare-element path.
|
|
5
5
|
import type { CardEvent, CardPolicy } from './card-contract';
|
|
6
|
+
// isSafeUrl/isScriptUrl live in their own DOM-free file so schema.ts
|
|
7
|
+
// (agent-tooling/construct, checked under tsconfig.mcp.json's Node-only pass)
|
|
8
|
+
// can import isSafeUrl without dragging this file's HTMLElement/window/
|
|
9
|
+
// CustomEvent references into a no-DOM-lib compile. Re-exported here so this
|
|
10
|
+
// module's own public surface is unchanged.
|
|
11
|
+
import { isSafeUrl, isScriptUrl } from './url-scheme-policy';
|
|
12
|
+
export { isSafeUrl, isScriptUrl } from './url-scheme-policy';
|
|
6
13
|
|
|
7
14
|
/** The single contract event name. */
|
|
8
15
|
export const CARD_EVENT_NAME = 'kai-card';
|
|
@@ -16,62 +23,6 @@ export function emitCardEvent(element: HTMLElement, event: CardEvent): void {
|
|
|
16
23
|
);
|
|
17
24
|
}
|
|
18
25
|
|
|
19
|
-
const SAFE_SCHEMES = ['http:', 'https:', 'mailto:'];
|
|
20
|
-
const SCRIPT_SCHEMES = ['javascript:', 'vbscript:'];
|
|
21
|
-
|
|
22
|
-
/** The scheme the WHATWG parser reads out of `url`, resolved against a base so a
|
|
23
|
-
* relative input inherits `http:`. `undefined` when it will not parse at all.
|
|
24
|
-
*
|
|
25
|
-
* ONE parser for the two questions below, deliberately: the parsing is where
|
|
26
|
-
* the subtlety lives (it strips embedded tabs/newlines and trims surrounding
|
|
27
|
-
* whitespace before reading the scheme, so `java\nscript:` and
|
|
28
|
-
* ` javascript:... ` are both read as `javascript:` -- which a regex over the
|
|
29
|
-
* raw string would miss). Two predicates over one parse cannot drift on that;
|
|
30
|
-
* two hand-rolled parsers would. */
|
|
31
|
-
function schemeOf(url: string): string | undefined {
|
|
32
|
-
try { return new URL(url, 'http://_invalid_base').protocol; } catch { return undefined; }
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/** True when `url` is safe to put in an href / hand to `window.open`.
|
|
36
|
-
*
|
|
37
|
-
* Exported so the MARKDOWN renderer and the ARTIFACT viewer reuse this exact
|
|
38
|
-
* guard rather than growing a second scheme list that can drift from this one.
|
|
39
|
-
*
|
|
40
|
-
* Resolving against a base is deliberate and is what makes it correct for
|
|
41
|
-
* markdown: a relative or fragment link (`/docs`, `#section`, `./rel`) is
|
|
42
|
-
* ordinary markdown, and resolving it inherits the base's `http:` so it
|
|
43
|
-
* passes, while `javascript:`/`data:`/`vbscript:` keep their own protocol and
|
|
44
|
-
* fail. It is correct for the artifact viewer for the same reason: a file with
|
|
45
|
-
* no `src` to resolve against yields a bare relative path (`docs/report.pdf`),
|
|
46
|
-
* which is a legitimate artifact address. Contrast `isRenderableLink` in
|
|
47
|
-
* `primitives/link-preview.ts`, which takes NO base and so demands an absolute
|
|
48
|
-
* http(s) URL: that is the right guard for a model-supplied citation -- a
|
|
49
|
-
* reference to a page on the public web -- this one for markdown body links and
|
|
50
|
-
* artifact file addresses. */
|
|
51
|
-
export function isSafeUrl(url: string): boolean {
|
|
52
|
-
const scheme = schemeOf(url);
|
|
53
|
-
return scheme !== undefined && SAFE_SCHEMES.includes(scheme);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/** True when navigating to `url` would EXECUTE it as script in the initiating
|
|
57
|
-
* document's origin.
|
|
58
|
-
*
|
|
59
|
-
* Strictly narrower than `!isSafeUrl(url)`, and not a competing policy: it
|
|
60
|
-
* answers a different question, for the one sink where the allowlist is the
|
|
61
|
-
* wrong tool. An `<iframe src>` legitimately takes `data:` and `blob:` (a
|
|
62
|
-
* `data:` blob artifact is a documented `<kai-artifact>` use -- it is what
|
|
63
|
-
* `displayUrl` exists for) and both get an OPAQUE origin in every modern
|
|
64
|
-
* browser, so neither can reach the host page. `javascript:`/`vbscript:` are
|
|
65
|
-
* the schemes that run in the EMBEDDER's origin, and they are the whole risk:
|
|
66
|
-
* the default sandbox (no `allow-same-origin`) already makes the browser refuse
|
|
67
|
-
* them, but a consumer who sets `allow-same-origin` turns a model-supplied
|
|
68
|
-
* `src` into host-origin script execution. The artifact viewer used to suggest
|
|
69
|
-
* that setting for "an artifact you trust"; it no longer does, and this guard
|
|
70
|
-
* is what protects the consumers who took the old advice. */
|
|
71
|
-
export function isScriptUrl(url: string): boolean {
|
|
72
|
-
const scheme = schemeOf(url);
|
|
73
|
-
return scheme !== undefined && SCRIPT_SCHEMES.includes(scheme);
|
|
74
|
-
}
|
|
75
26
|
function warnNoHandler(kind: string): void {
|
|
76
27
|
// eslint-disable-next-line no-console
|
|
77
28
|
console.warn(`[kai-card] no policy handler for "${kind}"`);
|
|
@@ -11,7 +11,27 @@
|
|
|
11
11
|
"description": { "type": "string" },
|
|
12
12
|
"required": { "type": "array", "items": { "type": "string" } },
|
|
13
13
|
"properties": {
|
|
14
|
-
"type": "object"
|
|
14
|
+
"type": "object",
|
|
15
|
+
"description": "The fields to collect, keyed by property name. Each value is a JSON Schema field definition (type, title, description, enum, minimum/maximum, minLength/maxLength, pattern, items) plus optional x-kai-* UI hints. Only the display-format hints are spelled out below; the rest of a field definition is ordinary JSON Schema.",
|
|
16
|
+
"additionalProperties": {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"properties": {
|
|
19
|
+
"x-kai-format": {
|
|
20
|
+
"description": "Display format for a string field. `tel`, `ssn` and `credit-card` apply that type's standard mask and submit digits only; `custom` masks with `x-kai-mask` and submits the formatted value. Omit it for a plain text field.",
|
|
21
|
+
"enum": ["tel", "ssn", "credit-card", "custom"]
|
|
22
|
+
},
|
|
23
|
+
"x-kai-mask": {
|
|
24
|
+
"description": "The mask pattern, used only with `x-kai-format: \"custom\"`: `#` one digit, `@` one letter or digit, `*` one letter or digit that may be obscured; every other character is a literal shown as typed, e.g. `CHG-####`.",
|
|
25
|
+
"type": "string",
|
|
26
|
+
"maxLength": 64
|
|
27
|
+
},
|
|
28
|
+
"x-kai-mask-guide": {
|
|
29
|
+
"description": "Placeholder text shown at the unfilled positions of the mask, aligned character for character with the pattern (`mm/dd/yyyy` for `##/##/####`). Derived from the pattern when omitted.",
|
|
30
|
+
"type": "string",
|
|
31
|
+
"maxLength": 64
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
15
35
|
},
|
|
16
36
|
"x-kai-order": { "type": "array", "items": { "type": "string" } },
|
|
17
37
|
"x-kai-inlineMax": { "type": "integer", "minimum": 1 },
|
|
@@ -6,8 +6,16 @@
|
|
|
6
6
|
export interface JsonSchema {
|
|
7
7
|
type?: 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object' | 'null';
|
|
8
8
|
const?: unknown;
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
// `readonly`: a construct's card schema is emitted `as const` (codegen.ts,
|
|
10
|
+
// emitCardsRegistry) so its literal types survive into CardTools' input —
|
|
11
|
+
// that turns array-valued fields into readonly tuples, which a mutable
|
|
12
|
+
// `T[]` does not structurally accept even under a `Readonly<Record<...>>`
|
|
13
|
+
// wrapper. JsonSchema is read-only data everywhere it is consumed (no
|
|
14
|
+
// caller mutates `.required`/`.enum` in place — see the callers in
|
|
15
|
+
// tool-defs.ts and form.tsx, which all build a fresh array via spread/
|
|
16
|
+
// filter/Set before assigning), so widening these two costs nothing.
|
|
17
|
+
enum?: readonly unknown[];
|
|
18
|
+
required?: readonly string[];
|
|
11
19
|
properties?: Record<string, JsonSchema>;
|
|
12
20
|
items?: JsonSchema;
|
|
13
21
|
minimum?: number; maximum?: number;
|
|
@@ -55,22 +55,49 @@ export function useChatConfig(): ChatConfigValue {
|
|
|
55
55
|
return useContext(ChatConfigContext)!;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Maps prose size to the Tailwind Typography *size modifier* for consumers who
|
|
60
|
+
* render their own `prose` block.
|
|
61
|
+
*
|
|
62
|
+
* The `prose-*` names are deliberately NOT re-pointed at the --kai-text-* scale.
|
|
63
|
+
* They are not font sizes: each is a plugin-generated bundle of proportional
|
|
64
|
+
* margins, list indents, heading ratios and line-heights for every nested
|
|
65
|
+
* element, keyed to hardcoded rems, and they only do anything alongside `prose`
|
|
66
|
+
* itself. There is no `prose-body` to alias them to, and collapsing them to a
|
|
67
|
+
* bare font-size would throw away the vertical rhythm that is their whole job.
|
|
68
|
+
* The kit's own markdown does not go through them at all — it renders through
|
|
69
|
+
* `.chat-markdown` (theme.css), which is em-relative and therefore already
|
|
70
|
+
* scales off whatever `textClass` sets.
|
|
71
|
+
*
|
|
72
|
+
* The one raw font-size here (`xs`) DOES join the semantic scale, so it stays in
|
|
73
|
+
* step with `textClass('xs')`.
|
|
74
|
+
*/
|
|
59
75
|
export function proseClass(size: ProseSize): string {
|
|
60
76
|
switch (size) {
|
|
61
|
-
case 'xs': return 'prose-sm text-
|
|
77
|
+
case 'xs': return 'prose-sm text-meta';
|
|
62
78
|
case 'sm': return 'prose-sm';
|
|
63
79
|
case 'base': return '';
|
|
64
80
|
case 'lg': return 'prose-lg';
|
|
65
81
|
}
|
|
66
82
|
}
|
|
67
83
|
|
|
68
|
-
/**
|
|
84
|
+
/**
|
|
85
|
+
* Maps prose size to a text class for message content, markdown, and non-prose
|
|
86
|
+
* chrome (sidebar, input).
|
|
87
|
+
*
|
|
88
|
+
* These are the kit's SEMANTIC type-scale utilities, not Tailwind's raw scale:
|
|
89
|
+
* each resolves through a namespaced --kai-text-* token in theme.css, so a
|
|
90
|
+
* consumer setting `--kai-text-body` moves the reading text. The public
|
|
91
|
+
* `proseSize` strings ('xs' | 'sm' | 'base' | 'lg') are unchanged — this is an
|
|
92
|
+
* internal re-point only. Sizes are byte-identical to the Tailwind classes they
|
|
93
|
+
* replace (text-meta ≡ text-xs, text-body ≡ text-sm, text-title ≡ text-base),
|
|
94
|
+
* so nothing moves until a token is actually overridden.
|
|
95
|
+
*/
|
|
69
96
|
export function textClass(size: ProseSize): string {
|
|
70
97
|
switch (size) {
|
|
71
|
-
case 'xs': return 'text-
|
|
72
|
-
case 'sm': return 'text-
|
|
73
|
-
case 'base': return 'text-
|
|
98
|
+
case 'xs': return 'text-meta';
|
|
99
|
+
case 'sm': return 'text-body';
|
|
100
|
+
case 'base': return 'text-title';
|
|
74
101
|
case 'lg': return 'text-lg';
|
|
75
102
|
}
|
|
76
103
|
}
|