@kitn.ai/ui 0.15.1 → 0.17.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 +37 -13
- package/bin/mcp.js +22 -0
- package/dist/bash-InADTalH.js +6 -1
- package/dist/components/artifact.d.ts +58 -0
- package/dist/components/attachments.d.ts +67 -0
- package/dist/components/card-fallback.d.ts +10 -0
- package/dist/components/card-renderer.d.ts +13 -0
- package/dist/components/card.d.ts +28 -0
- package/dist/components/chain-of-thought.d.ts +29 -0
- package/dist/components/chat-container.d.ts +19 -0
- package/dist/components/chat-scope-picker.d.ts +9 -0
- package/dist/components/chat-thread.d.ts +91 -0
- package/dist/components/checkpoint.d.ts +20 -0
- package/dist/components/choice-card.d.ts +78 -0
- package/dist/components/code-block.d.ts +16 -0
- package/dist/components/confirm-card.d.ts +57 -0
- package/dist/components/context.d.ts +65 -0
- package/dist/components/conversation-item.d.ts +8 -0
- package/dist/components/conversation-list.d.ts +11 -0
- package/dist/components/dismissed-stub.d.ts +22 -0
- package/dist/components/embed.d.ts +21 -0
- package/dist/components/empty.d.ts +43 -0
- package/dist/components/feedback-bar.d.ts +45 -0
- package/dist/components/file-tree.d.ts +57 -0
- package/dist/components/file-upload.d.ts +16 -0
- package/dist/components/form-widgets.d.ts +31 -0
- package/dist/components/form.d.ts +103 -0
- package/dist/components/image.d.ts +12 -0
- package/dist/components/link-preview.d.ts +23 -0
- package/dist/components/loader.d.ts +60 -0
- package/dist/components/markdown.d.ts +8 -0
- package/dist/components/message-skills.d.ts +15 -0
- package/dist/components/message.d.ts +111 -0
- package/dist/components/model-switcher.d.ts +8 -0
- package/dist/components/prompt-input.d.ts +38 -0
- package/dist/components/prompt-suggestion.d.ts +13 -0
- package/dist/components/reasoning.d.ts +20 -0
- package/dist/components/response-compare-types.d.ts +66 -0
- package/dist/components/response-compare.d.ts +51 -0
- package/dist/components/response-stream.d.ts +14 -0
- package/dist/components/scroll-button.d.ts +7 -0
- package/dist/components/slash-command.d.ts +15 -0
- package/dist/components/source.d.ts +23 -0
- package/dist/components/tasks-card.d.ts +72 -0
- package/dist/components/text-shimmer.d.ts +9 -0
- package/dist/components/thinking-bar.d.ts +10 -0
- package/dist/components/toast.d.ts +48 -0
- package/dist/components/tool.d.ts +16 -0
- package/dist/components/use-card-resolution.d.ts +16 -0
- package/dist/components/voice-input.d.ts +7 -0
- package/dist/core-AYMC6_lb.js +5874 -12
- package/dist/css-M7EaDHN_.js +6 -1
- package/dist/custom-elements.json +260 -11
- package/dist/elements/artifact.d.ts +1 -0
- package/dist/elements/artifact.js +1 -0
- package/dist/elements/attachments.d.ts +1 -0
- package/dist/elements/attachments.js +1 -0
- package/dist/elements/autoloader.d.ts +2 -0
- package/dist/elements/autoloader.js +1 -0
- package/dist/elements/card.d.ts +1 -0
- package/dist/elements/card.js +1 -0
- package/dist/elements/cards.d.ts +1 -0
- package/dist/elements/cards.js +1 -0
- package/dist/elements/chain-of-thought.d.ts +1 -0
- package/dist/elements/chain-of-thought.js +1 -0
- package/dist/elements/chat-scope-picker.d.ts +1 -0
- package/dist/elements/chat-scope-picker.js +1 -0
- package/dist/elements/chat-workspace.d.ts +1 -0
- package/dist/elements/chat-workspace.js +1 -0
- package/dist/elements/chat.d.ts +1 -0
- package/dist/elements/chat.js +1 -0
- package/dist/elements/checkpoint.d.ts +1 -0
- package/dist/elements/checkpoint.js +1 -0
- package/dist/elements/choice.d.ts +1 -0
- package/dist/elements/choice.js +1 -0
- package/dist/elements/chunks/Icon-D_Zmwmwh.js +1 -0
- package/dist/elements/chunks/action-icons-PVfIvcuG.js +1 -0
- package/dist/elements/chunks/attachments-Dp6vqtrc.js +1 -0
- package/dist/elements/chunks/bash-InADTalH.js +1 -0
- package/dist/elements/chunks/button-CKyYD9G4.js +1 -0
- package/dist/elements/chunks/card-Cjho-PYk.js +1 -0
- package/dist/elements/chunks/card-routing-C986KuUA.js +1 -0
- package/dist/elements/chunks/chat-thread-RT808iPf.js +1 -0
- package/dist/elements/chunks/check-CDYaMYrM.js +1 -0
- package/dist/elements/chunks/chevron-down-3SBiq8HF.js +1 -0
- package/dist/elements/chunks/chevron-right-k2UFlIVK.js +1 -0
- package/dist/elements/chunks/cn-Dogu6PbV.js +1 -0
- package/dist/elements/chunks/code-block-BYUmfFSd.js +1 -0
- package/dist/elements/chunks/collapsible-BiNwdOn6.js +1 -0
- package/dist/elements/chunks/context-18g6oi4J.js +1 -0
- package/dist/elements/chunks/conversation-list-D9Y0NVdo.js +1 -0
- package/dist/elements/chunks/core-AYMC6_lb.js +12 -0
- package/dist/elements/chunks/css-M7EaDHN_.js +1 -0
- package/dist/elements/chunks/default-input-CSAoYYMd.js +1 -0
- package/dist/elements/chunks/download-D8K0Je8r.js +1 -0
- package/dist/elements/chunks/dropdown-bUs2iTia.js +1 -0
- package/dist/elements/chunks/engine-javascript-vq0WuIJl.js +141 -0
- package/dist/elements/chunks/external-link-6mA0wxab.js +1 -0
- package/dist/elements/chunks/file-text-DnaYk3Dm.js +1 -0
- package/dist/elements/chunks/file-tree-CgtRLlxK.js +1 -0
- package/dist/elements/chunks/github-dark-dimmed-DUshB20C.js +1 -0
- package/dist/elements/chunks/github-light-JYsPkUQd.js +1 -0
- package/dist/elements/chunks/hover-card-CIGw62gP.js +1 -0
- package/dist/elements/chunks/html-CPZ3oZQ7.js +1 -0
- package/dist/elements/chunks/index-CTBEJeo6.js +1 -0
- package/dist/elements/chunks/javascript-C25yR2R2.js +1 -0
- package/dist/elements/chunks/json-DxJze_jm.js +1 -0
- package/dist/elements/chunks/link-BlGSeoPy.js +1 -0
- package/dist/elements/chunks/loader-DvhR4qa0.js +1 -0
- package/dist/elements/chunks/markdown-CMTGx9r8.js +64 -0
- package/dist/elements/chunks/message-CDZwXjhL.js +1 -0
- package/dist/elements/chunks/message-feedback-CYx81QiA.js +1 -0
- package/dist/elements/chunks/model-switcher-O_tUhoOT.js +1 -0
- package/dist/elements/chunks/overlay-DydXYMQW.js +1 -0
- package/dist/elements/chunks/prompt-suggestion-ldlWV5kd.js +1 -0
- package/dist/elements/chunks/reasoning-2PUnHlmr.js +1 -0
- package/dist/elements/chunks/resizable-B5WNbSeb.js +1 -0
- package/dist/elements/chunks/star-t9tI-P0q.js +1 -0
- package/dist/elements/chunks/store-C6rIooZz.js +1 -0
- package/dist/elements/chunks/svelte--5p79yCD.js +1 -0
- package/dist/elements/chunks/text-shimmer-uh9V_KUh.js +1 -0
- package/dist/elements/chunks/textarea-3nm6Ia9U.js +1 -0
- package/dist/elements/chunks/thumbs-up-BBtguGld.js +1 -0
- package/dist/elements/chunks/toast-store-D8cL3fWl.js +1 -0
- package/dist/elements/chunks/tool-GJ3vwp1U.js +1 -0
- package/dist/elements/chunks/tooltip-DwKAz4XR.js +1 -0
- package/dist/elements/chunks/triangle-alert-Ct1zt2JL.js +1 -0
- package/dist/elements/chunks/tsx-B8rCNbgL.js +1 -0
- package/dist/elements/chunks/typescript-RycA9KXf.js +1 -0
- package/dist/elements/chunks/use-card-resolution-D-_0Alzy.js +1 -0
- package/dist/elements/chunks/video-mVYiM99-.js +1 -0
- package/dist/elements/chunks/vue-BmIZj4XD.js +1 -0
- package/dist/elements/chunks/x-CzxL27Ch.js +1 -0
- package/dist/elements/code-block.d.ts +1 -0
- package/dist/elements/code-block.js +1 -0
- package/dist/elements/compare.d.ts +1 -0
- package/dist/elements/compare.js +1 -0
- package/dist/elements/confirm-card.d.ts +1 -0
- package/dist/elements/confirm-card.js +1 -0
- package/dist/elements/context-meter.d.ts +1 -0
- package/dist/elements/context-meter.js +1 -0
- package/dist/elements/conversation-list.d.ts +1 -0
- package/dist/elements/conversation-list.js +1 -0
- package/dist/elements/embed.d.ts +1 -0
- package/dist/elements/embed.js +1 -0
- package/dist/elements/empty.d.ts +1 -0
- package/dist/elements/empty.js +1 -0
- package/dist/elements/feedback-bar.d.ts +1 -0
- package/dist/elements/feedback-bar.js +1 -0
- package/dist/elements/file-tree.d.ts +1 -0
- package/dist/elements/file-tree.js +1 -0
- package/dist/elements/file-upload.d.ts +1 -0
- package/dist/elements/file-upload.js +1 -0
- package/dist/elements/form.d.ts +1 -0
- package/dist/elements/form.js +1 -0
- package/dist/elements/image.d.ts +1 -0
- package/dist/elements/image.js +1 -0
- package/dist/elements/link-preview.d.ts +1 -0
- package/dist/elements/link-preview.js +1 -0
- package/dist/elements/loader.d.ts +1 -0
- package/dist/elements/loader.js +1 -0
- package/dist/elements/markdown.d.ts +1 -0
- package/dist/elements/markdown.js +1 -0
- package/dist/elements/message-skills.d.ts +1 -0
- package/dist/elements/message-skills.js +1 -0
- package/dist/elements/message.d.ts +1 -0
- package/dist/elements/message.js +1 -0
- package/dist/elements/model-switcher.d.ts +1 -0
- package/dist/elements/model-switcher.js +1 -0
- package/dist/elements/popover.d.ts +1 -0
- package/dist/elements/popover.js +1 -0
- package/dist/elements/prompt-input.d.ts +1 -0
- package/dist/elements/prompt-input.js +1 -0
- package/dist/elements/prompt-suggestions.d.ts +1 -0
- package/dist/elements/prompt-suggestions.js +1 -0
- package/dist/elements/reasoning.d.ts +1 -0
- package/dist/elements/reasoning.js +1 -0
- package/dist/elements/resizable.d.ts +1 -0
- package/dist/elements/resizable.js +1 -0
- package/dist/elements/response-stream.d.ts +1 -0
- package/dist/elements/response-stream.js +14 -0
- package/dist/elements/scroll-button.d.ts +1 -0
- package/dist/elements/scroll-button.js +1 -0
- package/dist/elements/source.d.ts +1 -0
- package/dist/elements/source.js +1 -0
- package/dist/elements/switch.d.ts +1 -0
- package/dist/elements/switch.js +1 -0
- package/dist/elements/tasks.d.ts +1 -0
- package/dist/elements/tasks.js +1 -0
- package/dist/elements/text-shimmer.d.ts +1 -0
- package/dist/elements/text-shimmer.js +1 -0
- package/dist/elements/thinking-bar.d.ts +1 -0
- package/dist/elements/thinking-bar.js +1 -0
- package/dist/elements/toast.d.ts +1 -0
- package/dist/elements/toast.js +1 -0
- package/dist/elements/tool.d.ts +1 -0
- package/dist/elements/tool.js +1 -0
- package/dist/elements/voice-input.d.ts +1 -0
- package/dist/elements/voice-input.js +1 -0
- package/dist/elements.d.ts +768 -0
- package/dist/engine-javascript-vq0WuIJl.js +2516 -14
- package/dist/github-dark-dimmed-DUshB20C.js +4 -1
- package/dist/github-light-JYsPkUQd.js +4 -1
- package/dist/html-CPZ3oZQ7.js +10 -1
- package/dist/index.d.ts +124 -2
- package/dist/index.js +15593 -0
- package/dist/javascript-C25yR2R2.js +6 -1
- package/dist/json-DxJze_jm.js +6 -1
- package/dist/kitn-chat.es.js +1 -77
- package/dist/llms/llms-full.txt +57 -12
- package/dist/llms/llms.txt +3 -3
- package/dist/mcp.es.js +2296 -0
- package/dist/primitives/card-contract.d.ts +119 -0
- package/dist/primitives/card-host.d.ts +12 -0
- package/dist/primitives/card-recovery.d.ts +55 -0
- package/dist/primitives/card-registry.d.ts +17 -0
- package/dist/primitives/card-resolution.d.ts +8 -0
- package/dist/primitives/card-routing.d.ts +12 -0
- package/dist/primitives/card-validate.d.ts +25 -0
- package/dist/primitives/chat-config.d.ts +31 -0
- package/dist/primitives/controllable.d.ts +13 -0
- package/dist/primitives/embed-providers.d.ts +65 -0
- package/dist/primitives/highlighter.d.ts +23 -0
- package/dist/primitives/link-preview.d.ts +47 -0
- package/dist/primitives/message-feedback.d.ts +35 -0
- package/dist/primitives/pdf-preview.d.ts +50 -0
- package/dist/primitives/toast-store.d.ts +88 -0
- package/dist/primitives/use-auto-resize.d.ts +8 -0
- package/dist/primitives/use-resize-observer.d.ts +1 -0
- package/dist/primitives/use-stick-to-bottom.d.ts +5 -0
- package/dist/primitives/use-text-stream.d.ts +19 -0
- package/dist/primitives/use-voice-recorder.d.ts +9 -0
- package/dist/react/index.d.ts +1198 -0
- package/dist/react/runtime.d.ts +15 -0
- package/dist/react.js +275 -0
- package/dist/register-JyTglR6m.js +1 -0
- package/dist/register-impl-C6wlSsts.js +77 -0
- package/dist/remote/host-embed.d.ts +33 -0
- package/dist/remote/index.d.ts +2 -0
- package/dist/remote/origin.d.ts +5 -0
- package/dist/remote/provider-runtime.d.ts +27 -0
- package/dist/remote/provider.d.ts +2 -0
- package/dist/remote/validate.d.ts +4 -0
- package/dist/remote/version.d.ts +4 -0
- package/dist/remote/wire.d.ts +53 -0
- package/dist/schemas/choice.schema.json +5 -0
- package/dist/schemas/tasks.schema.json +5 -0
- package/dist/svelte--5p79yCD.js +15 -1
- package/dist/tsx-B8rCNbgL.js +6 -1
- package/dist/types.d.ts +42 -0
- package/dist/typescript-RycA9KXf.js +6 -1
- package/dist/ui/action-icons.d.ts +11 -0
- package/dist/ui/avatar.d.ts +8 -0
- package/dist/ui/badge.d.ts +9 -0
- package/dist/ui/button.d.ts +10 -0
- package/dist/ui/collapsible.d.ts +27 -0
- package/dist/ui/dropdown.d.ts +20 -0
- package/dist/ui/hover-card.d.ts +28 -0
- package/dist/ui/overlay.d.ts +67 -0
- package/dist/ui/popover.d.ts +32 -0
- package/dist/ui/resizable.d.ts +76 -0
- package/dist/ui/scroll-area.d.ts +5 -0
- package/dist/ui/separator.d.ts +5 -0
- package/dist/ui/skeleton.d.ts +5 -0
- package/dist/ui/switch.d.ts +19 -0
- package/dist/ui/textarea.d.ts +6 -0
- package/dist/ui/tooltip.d.ts +9 -0
- package/dist/utils/cn.d.ts +2 -0
- package/dist/vue-BmIZj4XD.js +33 -1
- package/frameworks/react/index.tsx +67 -11
- package/frameworks/react/runtime.tsx +16 -2
- package/llms-full.txt +57 -12
- package/llms.txt +3 -3
- package/package.json +36 -14
- package/src/agent-tooling/archetypes.ts +46 -0
- package/src/agent-tooling/integrations/cloudflare.ts +88 -0
- package/src/agent-tooling/integrations/langgraph.ts +60 -0
- package/src/agent-tooling/integrations/mastra.ts +27 -0
- package/src/agent-tooling/integrations/mock.ts +34 -0
- package/src/agent-tooling/integrations/ollama.ts +47 -0
- package/src/agent-tooling/integrations/openrouter.ts +26 -0
- package/src/agent-tooling/integrations/pi.ts +40 -0
- package/src/agent-tooling/integrations/pydantic-ai.ts +52 -0
- package/src/agent-tooling/integrations/vercel-ai-sdk.ts +44 -0
- package/src/agent-tooling/mcp/manifest.ts +128 -0
- package/src/agent-tooling/mcp/server.ts +59 -0
- package/src/agent-tooling/mcp/stdio.ts +18 -0
- package/src/agent-tooling/mcp/tools/debug.ts +489 -0
- package/src/agent-tooling/mcp/tools/reference.ts +132 -0
- package/src/agent-tooling/mcp/tools/scaffold.ts +1759 -0
- package/src/agent-tooling/mcp/tools/theme.ts +340 -0
- package/src/agent-tooling/mcp/tools/types.ts +14 -0
- package/src/agent-tooling/registry.ts +41 -0
- package/src/agent-tooling/types.ts +30 -0
- package/src/components/chat-thread.tsx +27 -35
- package/src/components/choice-card.tsx +33 -4
- package/src/components/component-meta.json +250 -26
- package/src/components/confirm-card.tsx +15 -1
- package/src/components/dismissed-stub.tsx +80 -0
- package/src/components/form.tsx +21 -3
- package/src/components/message.tsx +151 -10
- package/src/components/response-compare-types.ts +127 -0
- package/src/components/response-compare.tsx +431 -0
- package/src/components/tasks-card.tsx +33 -3
- package/src/components/toast.tsx +398 -0
- package/src/components/use-card-resolution.ts +24 -8
- package/src/elements/autoloader.ts +89 -0
- package/src/elements/chat-types.ts +7 -0
- package/src/elements/chat-workspace.tsx +4 -2
- package/src/elements/chat.tsx +4 -2
- package/src/elements/compare.tsx +88 -0
- package/src/elements/compiled.css +1 -1
- package/src/elements/define.tsx +7 -1
- package/src/elements/element-manifest.json +182 -0
- package/src/elements/element-meta.json +191 -68
- package/src/elements/element-types.d.ts +43 -6
- package/src/elements/framework-usage.json +25 -0
- package/src/elements/message.tsx +27 -45
- package/src/elements/register-impl.ts +58 -0
- package/src/elements/register.ts +26 -51
- package/src/elements/remote.tsx +4 -0
- package/src/elements/styles.css +19 -0
- package/src/elements/toast.tsx +74 -0
- package/src/index.ts +30 -0
- package/src/primitives/card-contract.ts +14 -5
- package/src/primitives/card-recovery.ts +149 -0
- package/src/primitives/card-routing.ts +3 -0
- package/src/primitives/card-schemas/choice.schema.json +5 -0
- package/src/primitives/card-schemas/tasks.schema.json +5 -0
- package/src/primitives/message-feedback.ts +123 -0
- package/src/primitives/toast-store.ts +235 -0
- package/src/ui/tooltip.tsx +8 -2
- package/theme.css +4 -2
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
// Re-exports for `import { … } from '@kitn.ai/ui/elements'`.
|
|
7
7
|
export type { ChatMessage, ChatMessageAction } from './chat-types';
|
|
8
|
-
export { configureCodeHighlighting, isCodeHighlightingEnabled } from '../primitives/highlighter';
|
|
9
8
|
export type { CodeHighlightingOptions } from '../primitives/highlighter';
|
|
9
|
+
export declare function configureCodeHighlighting(options: CodeHighlightingOptions): void;
|
|
10
|
+
export declare function isCodeHighlightingEnabled(): boolean;
|
|
10
11
|
|
|
11
12
|
export interface KaiArtifactElement extends HTMLElement {
|
|
12
13
|
/** Color mode (`auto` follows prefers-color-scheme). */
|
|
@@ -79,11 +80,11 @@ export interface KaiCardsElement extends HTMLElement {
|
|
|
79
80
|
/** Color mode (`auto` follows prefers-color-scheme). */
|
|
80
81
|
theme?: 'light' | 'dark' | 'auto';
|
|
81
82
|
/** The stream of card envelopes to render. Set as a JS PROPERTY: `el.cards = [...]`. */
|
|
82
|
-
cards?: { type: string; id: string; data: unknown; title?: string; resolution?: { kind: "action"; action: string; payload?: unknown; at?: string } | { kind: "submit"; data: unknown; at?: string } }[];
|
|
83
|
+
cards?: { type: string; id: string; data: unknown; title?: string; resolution?: { kind: "action"; action: string; payload?: unknown; at?: string } | { kind: "submit"; data: unknown; at?: string } | { kind: "dismissed"; at?: string } | { kind: "expired"; reason?: string; at?: string } }[];
|
|
83
84
|
/** Optional type→tag overrides/additions (merged over the built-ins). Property: `el.types`. Typed as a plain string map (not the `CardTagMap` alias) so the generated React wrapper inlines it instead of emitting an unresolved named type. */
|
|
84
85
|
types?: Record<string, string>;
|
|
85
86
|
/** Optional CardPolicy handling child events. Property: `el.policy`. */
|
|
86
|
-
policy?: { onSubmit?: (cardId: string, data: unknown) => void; onAction?: (cardId: string, action: string, payload?: unknown) => void; onSendPrompt?: (text: string, opts: { mode: "compose" | "send"; context?: unknown; }) => void; onOpen?: (url: string, target: "tab" | "artifact") => void; onState?: (cardId: string, patch: unknown) => void; onDismiss?: (cardId: string) => void; onError?: (cardId: string, message: string) => void; maxSendPromptMode?: "compose" | "send" };
|
|
87
|
+
policy?: { onSubmit?: (cardId: string, data: unknown) => void; onAction?: (cardId: string, action: string, payload?: unknown) => void; onSendPrompt?: (text: string, opts: { mode: "compose" | "send"; context?: unknown; }) => void; onOpen?: (url: string, target: "tab" | "artifact") => void; onState?: (cardId: string, patch: unknown) => void; onDismiss?: (cardId: string) => void; onReopen?: (cardId: string) => void; onError?: (cardId: string, message: string) => void; maxSendPromptMode?: "compose" | "send" };
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
export interface KaiChainOfThoughtElement extends HTMLElement {
|
|
@@ -97,7 +98,7 @@ export interface KaiChatElement extends HTMLElement {
|
|
|
97
98
|
/** Color mode (`auto` follows prefers-color-scheme). */
|
|
98
99
|
theme?: 'light' | 'dark' | 'auto';
|
|
99
100
|
/** The full message thread to render, newest last. Each entry carries its role, content, and optional reasoning/tools/attachments/actions. Set as a JS property (`el.messages = [...]`). */
|
|
100
|
-
messages: { id: string; role: "user" | "assistant"; content: string; reasoning?: undefined | { text: string; label?: undefined | string }; tools?: undefined | { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: undefined | Record<string, unknown>; output?: undefined | Record<string, unknown>; toolCallId?: undefined | string; errorText?: undefined | string }[]; attachments?: undefined | { id: string; type: "file" | "source-document"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[]; actions?: undefined | ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: undefined | string; tooltip?: undefined | string })[]; avatar?: undefined | { src?: undefined | string; fallback?: undefined | string; alt?: undefined | string } }[];
|
|
101
|
+
messages: { id: string; role: "user" | "assistant"; content: string; reasoning?: undefined | { text: string; label?: undefined | string }; tools?: undefined | { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: undefined | Record<string, unknown>; output?: undefined | Record<string, unknown>; toolCallId?: undefined | string; errorText?: undefined | string }[]; attachments?: undefined | { id: string; type: "file" | "source-document"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[]; actions?: undefined | ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: undefined | string; tooltip?: undefined | string })[]; avatar?: undefined | { src?: undefined | string; fallback?: undefined | string; alt?: undefined | string }; feedback?: undefined | "like" | "dislike" }[];
|
|
101
102
|
/** Controlled value of the input. When set, the host owns the input text and must update it on `kai-value-change`; leave unset for uncontrolled behavior. */
|
|
102
103
|
value?: string;
|
|
103
104
|
/** Placeholder text shown in the empty input. */
|
|
@@ -185,6 +186,25 @@ export interface KaiCodeBlockElement extends HTMLElement {
|
|
|
185
186
|
proseSize?: "xs" | "sm" | "base" | "lg";
|
|
186
187
|
}
|
|
187
188
|
|
|
189
|
+
export interface KaiCompareElement extends HTMLElement {
|
|
190
|
+
/** Color mode (`auto` follows prefers-color-scheme). */
|
|
191
|
+
theme?: 'light' | 'dark' | 'auto';
|
|
192
|
+
/** The compare definition (prompt + the two candidates). Set as a JS PROPERTY: `el.data = { prompt, candidates: [A, B], collapse? }`. Import `ResponseCompareData` from `@kitn.ai/ui` for the full shape. */
|
|
193
|
+
data?: Record<string, unknown>;
|
|
194
|
+
/** Stable id correlating every emitted event. Attribute: `compare-id`. */
|
|
195
|
+
compareId?: string;
|
|
196
|
+
/** Re-hydrate / control the user's pick. Set as a JS PROPERTY: `el.selection = { chosenId, rejectedIds }`. Renders the collapsed winner. */
|
|
197
|
+
selection?: Record<string, unknown>;
|
|
198
|
+
/** Layout: `'auto'` (default — columns when wide, tabs when narrow, by CONTAINER width) | `'columns'` (side-by-side) | `'tabs'` (pills to switch). Attribute: `layout`. */
|
|
199
|
+
layout?: "auto" | "columns" | "tabs";
|
|
200
|
+
/** Prose/text size for the rendered candidates. Attribute: `prose-size`. */
|
|
201
|
+
proseSize?: "xs" | "sm" | "base" | "lg";
|
|
202
|
+
/** Shiki theme for code blocks in the candidates. Attribute: `code-theme`. */
|
|
203
|
+
codeTheme?: string;
|
|
204
|
+
/** Whether code blocks are syntax-highlighted. Attribute: `code-highlight`. */
|
|
205
|
+
codeHighlight?: boolean;
|
|
206
|
+
}
|
|
207
|
+
|
|
188
208
|
export interface KaiConfirmElement extends HTMLElement {
|
|
189
209
|
/** Color mode (`auto` follows prefers-color-scheme). */
|
|
190
210
|
theme?: 'light' | 'dark' | 'auto';
|
|
@@ -346,7 +366,7 @@ export interface KaiMessageElement extends HTMLElement {
|
|
|
346
366
|
/** Color mode (`auto` follows prefers-color-scheme). */
|
|
347
367
|
theme?: 'light' | 'dark' | 'auto';
|
|
348
368
|
/** The full message object. Set as a JS property. */
|
|
349
|
-
message?: { id: string; role: "user" | "assistant"; content: string; reasoning?: { text: string; label?: string }; tools?: { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: Record<string, unknown>; output?: Record<string, unknown>; toolCallId?: string; errorText?: string }[]; attachments?: { id: string; type: "file" | "source-document"; filename?: string; mediaType?: string; url?: string; title?: string }[]; actions?: ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: string; tooltip?: string })[]; avatar?: { src?: string; fallback?: string; alt?: string } };
|
|
369
|
+
message?: { id: string; role: "user" | "assistant"; content: string; reasoning?: { text: string; label?: string }; tools?: { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: Record<string, unknown>; output?: Record<string, unknown>; toolCallId?: string; errorText?: string }[]; attachments?: { id: string; type: "file" | "source-document"; filename?: string; mediaType?: string; url?: string; title?: string }[]; actions?: ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: string; tooltip?: string })[]; avatar?: { src?: string; fallback?: string; alt?: string }; feedback?: "like" | "dislike" };
|
|
350
370
|
/** Convenience for simple cases when not passing a `message` object. */
|
|
351
371
|
role?: "user" | "assistant";
|
|
352
372
|
/** Convenience content (used when `message` is not set). */
|
|
@@ -601,6 +621,21 @@ export interface KaiThinkingBarElement extends HTMLElement {
|
|
|
601
621
|
stopLabel?: string;
|
|
602
622
|
}
|
|
603
623
|
|
|
624
|
+
export interface KaiToastRegionElement extends HTMLElement {
|
|
625
|
+
/** Color mode (`auto` follows prefers-color-scheme). */
|
|
626
|
+
theme?: 'light' | 'dark' | 'auto';
|
|
627
|
+
/** The toasts to render. Newest is shown on top. Set as a JS property (array); pass a new array reference to update. */
|
|
628
|
+
toasts: { id: string; message: string; variant?: undefined | "neutral" | "success"; action?: undefined | { label: string; onAction: () => void | false }; duration?: undefined | number; dismissible?: undefined | boolean; target?: undefined | HTMLElement }[];
|
|
629
|
+
/** Stack anchor: `'top-center'` (default), `'top-right'`, `'bottom-center'`, … */
|
|
630
|
+
position?: "top-center" | "top-right" | "top-left" | "bottom-center" | "bottom-right" | "bottom-left";
|
|
631
|
+
/** Max simultaneously-visible toasts; the rest queue. Defaults to `3`. */
|
|
632
|
+
max?: number;
|
|
633
|
+
/** Stacking: 'expanded' (default, full column) | 'collapsed' (Sonner-style pile that expands on hover/focus). Attribute: stack. */
|
|
634
|
+
stack?: "expanded" | "collapsed";
|
|
635
|
+
/** Container element to anchor this region to (JS property). Set by the store for a scoped region; unset = the global viewport region. */
|
|
636
|
+
target?: HTMLElement;
|
|
637
|
+
}
|
|
638
|
+
|
|
604
639
|
export interface KaiToolElement extends HTMLElement {
|
|
605
640
|
/** Color mode (`auto` follows prefers-color-scheme). */
|
|
606
641
|
theme?: 'light' | 'dark' | 'auto';
|
|
@@ -629,7 +664,7 @@ export interface KaiWorkspaceElement extends HTMLElement {
|
|
|
629
664
|
/** Id of the open conversation, highlighted in the sidebar. */
|
|
630
665
|
activeId?: string;
|
|
631
666
|
/** The active conversation's message thread, newest last. Set as a JS property. */
|
|
632
|
-
messages: { id: string; role: "user" | "assistant"; content: string; reasoning?: undefined | { text: string; label?: undefined | string }; tools?: undefined | { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: undefined | Record<string, unknown>; output?: undefined | Record<string, unknown>; toolCallId?: undefined | string; errorText?: undefined | string }[]; attachments?: undefined | { id: string; type: "file" | "source-document"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[]; actions?: undefined | ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: undefined | string; tooltip?: undefined | string })[]; avatar?: undefined | { src?: undefined | string; fallback?: undefined | string; alt?: undefined | string } }[];
|
|
667
|
+
messages: { id: string; role: "user" | "assistant"; content: string; reasoning?: undefined | { text: string; label?: undefined | string }; tools?: undefined | { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: undefined | Record<string, unknown>; output?: undefined | Record<string, unknown>; toolCallId?: undefined | string; errorText?: undefined | string }[]; attachments?: undefined | { id: string; type: "file" | "source-document"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[]; actions?: undefined | ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: undefined | string; tooltip?: undefined | string })[]; avatar?: undefined | { src?: undefined | string; fallback?: undefined | string; alt?: undefined | string }; feedback?: undefined | "like" | "dislike" }[];
|
|
633
668
|
value?: string;
|
|
634
669
|
placeholder?: string;
|
|
635
670
|
loading?: boolean;
|
|
@@ -671,6 +706,7 @@ declare global {
|
|
|
671
706
|
'kai-checkpoint': KaiCheckpointElement;
|
|
672
707
|
'kai-choice': KaiChoiceElement;
|
|
673
708
|
'kai-code-block': KaiCodeBlockElement;
|
|
709
|
+
'kai-compare': KaiCompareElement;
|
|
674
710
|
'kai-confirm': KaiConfirmElement;
|
|
675
711
|
'kai-context': KaiContextElement;
|
|
676
712
|
'kai-conversations': KaiConversationsElement;
|
|
@@ -703,6 +739,7 @@ declare global {
|
|
|
703
739
|
'kai-tasks': KaiTasksElement;
|
|
704
740
|
'kai-text-shimmer': KaiTextShimmerElement;
|
|
705
741
|
'kai-thinking-bar': KaiThinkingBarElement;
|
|
742
|
+
'kai-toast-region': KaiToastRegionElement;
|
|
706
743
|
'kai-tool': KaiToolElement;
|
|
707
744
|
'kai-voice-input': KaiVoiceInputElement;
|
|
708
745
|
'kai-workspace': KaiWorkspaceElement;
|
|
@@ -113,6 +113,18 @@
|
|
|
113
113
|
"solid": "import { CodeBlock } from '@kitn.ai/ui';\n\n<CodeBlock\n code={code}\n/>"
|
|
114
114
|
}
|
|
115
115
|
},
|
|
116
|
+
{
|
|
117
|
+
"tag": "kai-compare",
|
|
118
|
+
"displayName": "Compare",
|
|
119
|
+
"hasSolid": false,
|
|
120
|
+
"snippets": {
|
|
121
|
+
"html": "<script type=\"module\" src=\"https://cdn.jsdelivr.net/npm/@kitn.ai/ui/dist/kitn-chat.es.js\"></script>\n\n<kai-compare></kai-compare>\n<script type=\"module\">\n const el = document.querySelector('kai-compare');\n el.addEventListener('kai-compare-select', (e) => console.log(e.detail));\n el.addEventListener('kai-error', (e) => console.log(e.detail));\n el.addEventListener('kai-ready', (e) => console.log(e.detail));\n</script>",
|
|
122
|
+
"react": "import { Compare } from '@kitn.ai/ui/react';\n\n<Compare\n onCompareSelect={(e) => console.log(e.detail)}\n onError={(e) => console.log(e.detail)}\n onReady={(e) => console.log(e.detail)}\n/>",
|
|
123
|
+
"vue": "<kai-compare\n @kai-compare-select=\"onCompareSelect\"\n @kai-error=\"onError\"\n @kai-ready=\"onReady\"\n/>",
|
|
124
|
+
"svelte": "<script>\n import '@kitn.ai/ui/elements';\n</script>\n\n<kai-compare\n on:kai-compare-select={onCompareSelect}\n on:kai-error={onError}\n on:kai-ready={onReady}\n></kai-compare>",
|
|
125
|
+
"angular": "<kai-compare\n (kai-compare-select)=\"onCompareSelect($event)\"\n (kai-error)=\"onError($event)\"\n (kai-ready)=\"onReady($event)\"\n></kai-compare>"
|
|
126
|
+
}
|
|
127
|
+
},
|
|
116
128
|
{
|
|
117
129
|
"tag": "kai-confirm",
|
|
118
130
|
"displayName": "Confirm",
|
|
@@ -522,6 +534,19 @@
|
|
|
522
534
|
"solid": "import { ThinkingBar } from '@kitn.ai/ui';\n\n<ThinkingBar\n onStop={(e) => console.log(e.detail)}\n/>"
|
|
523
535
|
}
|
|
524
536
|
},
|
|
537
|
+
{
|
|
538
|
+
"tag": "kai-toast-region",
|
|
539
|
+
"displayName": "ToastRegion",
|
|
540
|
+
"hasSolid": true,
|
|
541
|
+
"snippets": {
|
|
542
|
+
"html": "<script type=\"module\" src=\"https://cdn.jsdelivr.net/npm/@kitn.ai/ui/dist/kitn-chat.es.js\"></script>\n\n<kai-toast-region></kai-toast-region>\n<script type=\"module\">\n const el = document.querySelector('kai-toast-region');\n el.toasts = /* … */;\n el.addEventListener('kai-action', (e) => console.log(e.detail));\n el.addEventListener('kai-dismiss', (e) => console.log(e.detail));\n</script>",
|
|
543
|
+
"react": "import { ToastRegion } from '@kitn.ai/ui/react';\n\n<ToastRegion\n toasts={toasts}\n onAction={(e) => console.log(e.detail)}\n onDismiss={(e) => console.log(e.detail)}\n/>",
|
|
544
|
+
"vue": "<kai-toast-region\n :toasts.prop=\"toasts\"\n @kai-action=\"onAction\"\n @kai-dismiss=\"onDismiss\"\n/>",
|
|
545
|
+
"svelte": "<script>\n import '@kitn.ai/ui/elements';\n</script>\n\n<kai-toast-region\n {toasts}\n on:kai-action={onAction}\n on:kai-dismiss={onDismiss}\n></kai-toast-region>",
|
|
546
|
+
"angular": "<kai-toast-region\n [toasts]=\"toasts\"\n (kai-action)=\"onAction($event)\"\n (kai-dismiss)=\"onDismiss($event)\"\n></kai-toast-region>",
|
|
547
|
+
"solid": "import { ToastRegion } from '@kitn.ai/ui';\n\n<ToastRegion\n toasts={toasts}\n onAction={(e) => console.log(e.detail)}\n onDismiss={(e) => console.log(e.detail)}\n/>"
|
|
548
|
+
}
|
|
549
|
+
},
|
|
525
550
|
{
|
|
526
551
|
"tag": "kai-tool",
|
|
527
552
|
"displayName": "Tool",
|
package/src/elements/message.tsx
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Show, createSignal, onMount, onCleanup } from 'solid-js';
|
|
2
2
|
import { defineWebComponent } from './define';
|
|
3
3
|
import { ChatConfig, useChatConfig, type ProseSize } from '../primitives/chat-config';
|
|
4
|
-
import { Message, MessageAvatar,
|
|
5
|
-
import {
|
|
6
|
-
import { Tool } from '../components/tool';
|
|
7
|
-
import { Attachments, Attachment, AttachmentPreview, AttachmentInfo } from '../components/attachments';
|
|
4
|
+
import { Message, MessageAvatar, MessageBody } from '../components/message';
|
|
5
|
+
import { createMessageFeedback } from '../primitives/message-feedback';
|
|
8
6
|
import type { ChatMessage } from './chat-types';
|
|
9
7
|
|
|
10
8
|
interface Props extends Record<string, unknown> {
|
|
@@ -33,8 +31,10 @@ interface Props extends Record<string, unknown> {
|
|
|
33
31
|
|
|
34
32
|
/** Events fired by `<kai-message>`. */
|
|
35
33
|
interface Events {
|
|
36
|
-
/** An action button was clicked. `action` is the built-in name or custom id.
|
|
37
|
-
|
|
34
|
+
/** An action button was clicked. `action` is the built-in name or custom id.
|
|
35
|
+
* `state` is present only for the toggleable feedback votes: `'on'` when a
|
|
36
|
+
* like/dislike is set, `'off'` when re-tapped to clear. */
|
|
37
|
+
'kai-message-action': { messageId: string; action: string; state?: 'on' | 'off' };
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
/**
|
|
@@ -58,6 +58,12 @@ defineWebComponent<Props, Events>('kai-message', {
|
|
|
58
58
|
const outer = useChatConfig();
|
|
59
59
|
const msg = (): ChatMessage =>
|
|
60
60
|
props.message ?? { id: 'message', role: props.role ?? 'assistant', content: props.content ?? '' };
|
|
61
|
+
// Copy + vote state lives here (above the rendered body) so it survives a
|
|
62
|
+
// re-render when the host swaps in a fresh `message` object during streaming.
|
|
63
|
+
const feedback = createMessageFeedback({
|
|
64
|
+
emit: (detail) => dispatch('kai-message-action', detail),
|
|
65
|
+
target: () => element,
|
|
66
|
+
});
|
|
61
67
|
|
|
62
68
|
// Read declarative <kai-action> children from light DOM.
|
|
63
69
|
// Shadow DOM with no <slot> suppresses them visually — they're invisible data carriers.
|
|
@@ -89,45 +95,21 @@ defineWebComponent<Props, Events>('kai-message', {
|
|
|
89
95
|
element.hasAttribute('markdown') || props.markdown === true || props.markdown === false;
|
|
90
96
|
const useMarkdown = () => (markdownExplicit() ? flag('markdown') : !isUser());
|
|
91
97
|
|
|
98
|
+
const mergedActions = () => [...(msg().actions ?? []), ...slottedActions()];
|
|
92
99
|
const body = () => (
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
{(att) => (
|
|
107
|
-
<Attachment data={att}>
|
|
108
|
-
<AttachmentPreview />
|
|
109
|
-
<AttachmentInfo />
|
|
110
|
-
</Attachment>
|
|
111
|
-
)}
|
|
112
|
-
</For>
|
|
113
|
-
</Attachments>
|
|
114
|
-
</Show>
|
|
115
|
-
<MessageContent
|
|
116
|
-
markdown={useMarkdown()}
|
|
117
|
-
class={isUser()
|
|
118
|
-
? 'bg-muted text-primary max-w-[85%] rounded-2xl px-4 py-2'
|
|
119
|
-
: 'bg-transparent p-0'}
|
|
120
|
-
>
|
|
121
|
-
{msg().content}
|
|
122
|
-
</MessageContent>
|
|
123
|
-
<Show when={(msg().actions?.length ?? 0) > 0 || slottedActions().length > 0}>
|
|
124
|
-
<MessageActionBar
|
|
125
|
-
actions={[...(msg().actions ?? []), ...slottedActions()]}
|
|
126
|
-
reveal={reveal()}
|
|
127
|
-
onAction={(action) => dispatch('kai-message-action', { messageId: msg().id, action })}
|
|
128
|
-
/>
|
|
129
|
-
</Show>
|
|
130
|
-
</>
|
|
100
|
+
<MessageBody
|
|
101
|
+
content={msg().content}
|
|
102
|
+
reasoning={msg().reasoning}
|
|
103
|
+
tools={msg().tools}
|
|
104
|
+
attachments={msg().attachments}
|
|
105
|
+
isUser={isUser()}
|
|
106
|
+
markdown={useMarkdown()}
|
|
107
|
+
actions={mergedActions()}
|
|
108
|
+
actionsReveal={reveal()}
|
|
109
|
+
activeFeedback={feedback.resolveFeedback(msg())}
|
|
110
|
+
copied={feedback.isCopied(msg().id)}
|
|
111
|
+
onAction={(action) => feedback.handleAction(msg(), action)}
|
|
112
|
+
/>
|
|
131
113
|
);
|
|
132
114
|
|
|
133
115
|
// Row carries `group` so a hover-revealed action bar fades in on row hover.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Component registration implementation. Importing this file defines all kitn
|
|
2
|
+
// custom elements as a side effect. It is dynamically imported (browser-only)
|
|
3
|
+
// from ./register.ts so the elements entry is SSR-import-safe — see the comment
|
|
4
|
+
// there. This file is hand-maintained (the generator gen-element-api.mjs SKIPs
|
|
5
|
+
// register.ts AND this file); keep the component import list here in sync.
|
|
6
|
+
import './conversation-list';
|
|
7
|
+
import './prompt-input';
|
|
8
|
+
import './chat';
|
|
9
|
+
import './chat-workspace';
|
|
10
|
+
// Composable leaf elements (spike — see docs/handoff + examples/composable)
|
|
11
|
+
import './thinking-bar';
|
|
12
|
+
import './model-switcher';
|
|
13
|
+
import './attachments';
|
|
14
|
+
// Phase 1 — message-rendering core
|
|
15
|
+
import './message';
|
|
16
|
+
import './markdown';
|
|
17
|
+
import './code-block';
|
|
18
|
+
import './reasoning';
|
|
19
|
+
import './tool';
|
|
20
|
+
// Phase 2 — header / meta
|
|
21
|
+
import './context-meter';
|
|
22
|
+
import './feedback-bar';
|
|
23
|
+
import './chat-scope-picker';
|
|
24
|
+
// Phase 3 — input ecosystem
|
|
25
|
+
// (NB: SlashCommand is context-bound to PromptInput — it observes the input
|
|
26
|
+
// value via usePromptInput() — so it is NOT a standalone element. It will fold
|
|
27
|
+
// into <kai-prompt-input> as a `slash-commands` property in a later pass.)
|
|
28
|
+
import './prompt-suggestions';
|
|
29
|
+
import './file-upload';
|
|
30
|
+
import './voice-input';
|
|
31
|
+
// Phase 4 — indicators & leaves
|
|
32
|
+
import './loader';
|
|
33
|
+
import './text-shimmer';
|
|
34
|
+
import './image';
|
|
35
|
+
import './checkpoint';
|
|
36
|
+
import './message-skills';
|
|
37
|
+
import './source';
|
|
38
|
+
import './response-stream';
|
|
39
|
+
import './empty';
|
|
40
|
+
import './chain-of-thought';
|
|
41
|
+
import './resizable';
|
|
42
|
+
import './file-tree';
|
|
43
|
+
import './artifact';
|
|
44
|
+
import './scroll-button';
|
|
45
|
+
import './popover';
|
|
46
|
+
import './switch';
|
|
47
|
+
import './toast';
|
|
48
|
+
// Generative-UI cards (Card Contract)
|
|
49
|
+
import './card';
|
|
50
|
+
import './form';
|
|
51
|
+
import './link-preview';
|
|
52
|
+
import './embed';
|
|
53
|
+
import './confirm-card';
|
|
54
|
+
import './tasks';
|
|
55
|
+
import './choice';
|
|
56
|
+
import './cards';
|
|
57
|
+
// Dual-response comparison (preference capture)
|
|
58
|
+
import './compare';
|
package/src/elements/register.ts
CHANGED
|
@@ -1,56 +1,31 @@
|
|
|
1
1
|
// Single entry that registers all kitn custom elements. Importing this file
|
|
2
|
-
// (or the built bundle) defines the elements as a side effect
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
//
|
|
8
|
-
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
import './feedback-bar';
|
|
20
|
-
import './chat-scope-picker';
|
|
21
|
-
// Phase 3 — input ecosystem
|
|
22
|
-
// (NB: SlashCommand is context-bound to PromptInput — it observes the input
|
|
23
|
-
// value via usePromptInput() — so it is NOT a standalone element. It will fold
|
|
24
|
-
// into <kai-prompt-input> as a `slash-commands` property in a later pass.)
|
|
25
|
-
import './prompt-suggestions';
|
|
26
|
-
import './file-upload';
|
|
27
|
-
import './voice-input';
|
|
28
|
-
// Phase 4 — indicators & leaves
|
|
29
|
-
import './loader';
|
|
30
|
-
import './text-shimmer';
|
|
31
|
-
import './image';
|
|
32
|
-
import './checkpoint';
|
|
33
|
-
import './message-skills';
|
|
34
|
-
import './source';
|
|
35
|
-
import './response-stream';
|
|
36
|
-
import './empty';
|
|
37
|
-
import './chain-of-thought';
|
|
38
|
-
import './resizable';
|
|
39
|
-
import './file-tree';
|
|
40
|
-
import './artifact';
|
|
41
|
-
import './scroll-button';
|
|
42
|
-
import './popover';
|
|
43
|
-
import './switch';
|
|
44
|
-
// Generative-UI cards (Card Contract)
|
|
45
|
-
import './card';
|
|
46
|
-
import './form';
|
|
47
|
-
import './link-preview';
|
|
48
|
-
import './embed';
|
|
49
|
-
import './confirm-card';
|
|
50
|
-
import './tasks';
|
|
51
|
-
import './choice';
|
|
52
|
-
import './cards';
|
|
2
|
+
// (or the built bundle) defines the elements as a side effect — but ONLY in a
|
|
3
|
+
// browser/DOM context.
|
|
4
|
+
//
|
|
5
|
+
// SSR-safe: the kai-* elements bundle Solid's client runtime, which touches
|
|
6
|
+
// `window` at module-eval (delegateEvents(events, doc = window.document)). With
|
|
7
|
+
// no `window`, a static import would throw. So the actual component registration
|
|
8
|
+
// lives in ./register-impl and is loaded behind a browser check + dynamic
|
|
9
|
+
// import() — static ESM imports hoist + evaluate unconditionally, so a bare `if`
|
|
10
|
+
// cannot gate them; a dynamic import() can. On the server this module is inert
|
|
11
|
+
// (no DOM → no registration → no throw); in the browser it registers as before.
|
|
12
|
+
//
|
|
13
|
+
// Registration is async (a microtask after this module loads). Consumers that
|
|
14
|
+
// need the upgraded element (e.g. the React runtime) guard with
|
|
15
|
+
// customElements.whenDefined(), which resolves once the impl chunk has run.
|
|
16
|
+
if (typeof window !== 'undefined' && typeof customElements !== 'undefined') {
|
|
17
|
+
void import('./register-impl');
|
|
18
|
+
}
|
|
53
19
|
|
|
54
20
|
export type { ChatMessage, ChatMessageAction } from './chat-types';
|
|
55
21
|
export { configureCodeHighlighting, isCodeHighlightingEnabled } from '../primitives/highlighter';
|
|
56
22
|
export type { CodeHighlightingOptions } from '../primitives/highlighter';
|
|
23
|
+
|
|
24
|
+
// Imperative toast API — usable directly from the elements entry so consumers
|
|
25
|
+
// who only import the web-components bundle still get `toast()`. The store is
|
|
26
|
+
// SSR-safe (no DOM touched until the first toast is raised on the client).
|
|
27
|
+
export { toast, configureToasts } from '../primitives/toast-store';
|
|
28
|
+
export type {
|
|
29
|
+
ToastConfig,
|
|
30
|
+
ToastItem, ToastVariant, ToastAction, ToastOptions, ToastHandle,
|
|
31
|
+
} from '../primitives/toast-store';
|
package/src/elements/remote.tsx
CHANGED
|
@@ -81,6 +81,10 @@ function buildWrappedPolicy(element: HTMLElement, userPolicy: CardPolicy | undef
|
|
|
81
81
|
emit({ kind: 'dismiss', cardId });
|
|
82
82
|
userPolicy?.onDismiss?.(cardId);
|
|
83
83
|
},
|
|
84
|
+
onReopen(cardId) {
|
|
85
|
+
emit({ kind: 'reopen', cardId });
|
|
86
|
+
userPolicy?.onReopen?.(cardId);
|
|
87
|
+
},
|
|
84
88
|
onError(cardId, message) {
|
|
85
89
|
emit({ kind: 'error', cardId, message });
|
|
86
90
|
userPolicy?.onError?.(cardId, message);
|
package/src/elements/styles.css
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
/* Element-bundle stylesheet. Compiled to compiled.css and injected into each
|
|
2
2
|
custom element's shadow root. Mirrors .storybook/styles.css but scans src/. */
|
|
3
3
|
@import "tailwindcss";
|
|
4
|
+
/* tw-animate-css supplies the animate-in/animate-out + slide/fade/zoom utilities
|
|
5
|
+
the kit uses for every overlay enter/exit (toast, popover, tooltip, dropdown,
|
|
6
|
+
hover-card, the message action-row hide). Without this @import those classes
|
|
7
|
+
compile to nothing and all the animations are silently dead. Compiled into
|
|
8
|
+
compiled.css at build time, so it's a build-time dep only (no consumer import). */
|
|
9
|
+
@import "tw-animate-css";
|
|
4
10
|
@import "../../theme.css";
|
|
5
11
|
@plugin "@tailwindcss/typography";
|
|
6
12
|
|
|
@@ -65,6 +71,19 @@
|
|
|
65
71
|
}
|
|
66
72
|
*::-webkit-scrollbar-thumb:hover { background-color: var(--color-scrollbar-thumb-hover); }
|
|
67
73
|
*::-webkit-scrollbar-corner { background: transparent; }
|
|
74
|
+
|
|
75
|
+
/* Respect a user's reduced-motion preference: disable the tw-animate-css
|
|
76
|
+
enter/exit keyframe animations (toasts, overlays, cards) so they appear and
|
|
77
|
+
disappear instantly instead of sliding/fading. Targets the utility classes
|
|
78
|
+
tw-animate-css emits (.animate-in / .animate-out) plus any arbitrary
|
|
79
|
+
`animate-[…]` keyframe utility. */
|
|
80
|
+
@media (prefers-reduced-motion: reduce) {
|
|
81
|
+
.animate-in,
|
|
82
|
+
.animate-out,
|
|
83
|
+
[class*="animate-["] {
|
|
84
|
+
animation: none !important;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
68
87
|
}
|
|
69
88
|
|
|
70
89
|
@layer components {
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { defineWebComponent } from './define';
|
|
2
|
+
import { ToastRegion, type ToastDismissReason, type ToastPosition } from '../components/toast';
|
|
3
|
+
import { toast as toastStore, type ToastItem } from '../primitives/toast-store';
|
|
4
|
+
|
|
5
|
+
interface Props extends Record<string, unknown> {
|
|
6
|
+
/** The toasts to render. Newest is shown on top. Set as a JS property (array);
|
|
7
|
+
* pass a new array reference to update. */
|
|
8
|
+
toasts: ToastItem[];
|
|
9
|
+
/** Stack anchor: `'top-center'` (default), `'top-right'`, `'bottom-center'`, … */
|
|
10
|
+
position?: ToastPosition;
|
|
11
|
+
/** Max simultaneously-visible toasts; the rest queue. Defaults to `3`. */
|
|
12
|
+
max?: number;
|
|
13
|
+
/** Stacking: 'expanded' (default, full column) | 'collapsed' (Sonner-style
|
|
14
|
+
* pile that expands on hover/focus). Attribute: stack. */
|
|
15
|
+
stack?: 'expanded' | 'collapsed';
|
|
16
|
+
/** Container element to anchor this region to (JS property). Set by the store
|
|
17
|
+
* for a scoped region; unset = the global viewport region. */
|
|
18
|
+
target?: HTMLElement;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface Events {
|
|
22
|
+
/** A toast left the stack. `reason` is `'timeout' | 'close' | 'action'`. */
|
|
23
|
+
'kai-dismiss': { id: string; reason: ToastDismissReason };
|
|
24
|
+
/** A toast's action button was pressed. */
|
|
25
|
+
'kai-action': { id: string; label: string };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* `<kai-toast-region>` — the viewport overlay that renders the toast stack.
|
|
30
|
+
*
|
|
31
|
+
* It is the substrate behind the imperative `toast()` API: the store lazily
|
|
32
|
+
* mounts ONE of these on `document.body` and binds the list to `toasts`. It is
|
|
33
|
+
* also usable declaratively — set `el.toasts = [...]` (a JS property, never an
|
|
34
|
+
* attribute) and listen for `kai-dismiss` / `kai-action`.
|
|
35
|
+
*
|
|
36
|
+
* Because it is a real `kai-*` element it carries its own shadow root + the
|
|
37
|
+
* shared kit stylesheet, so it is viewport-positioned AND kit-styled.
|
|
38
|
+
*/
|
|
39
|
+
defineWebComponent<Props, Events>('kai-toast-region', {
|
|
40
|
+
toasts: [],
|
|
41
|
+
position: 'top-center',
|
|
42
|
+
max: 3,
|
|
43
|
+
stack: 'expanded',
|
|
44
|
+
target: undefined,
|
|
45
|
+
}, (props, { dispatch }) => {
|
|
46
|
+
// `max` may arrive as a string attribute (`<kai-toast-region max="2">`).
|
|
47
|
+
const max = () => {
|
|
48
|
+
const raw = props.max as unknown;
|
|
49
|
+
const n = typeof raw === 'string' ? parseInt(raw, 10) : raw;
|
|
50
|
+
return typeof n === 'number' && !Number.isNaN(n) ? n : 3;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const remove = (id: string) => {
|
|
54
|
+
// Drop from the shared store (imperative path). For purely-declarative
|
|
55
|
+
// consumers the store simply won't contain the id — the dispatched event
|
|
56
|
+
// is the signal for them to update their own `toasts` array.
|
|
57
|
+
toastStore.dismiss(id);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<ToastRegion
|
|
62
|
+
toasts={props.toasts ?? []}
|
|
63
|
+
position={props.position}
|
|
64
|
+
max={max()}
|
|
65
|
+
stack={props.stack as 'expanded' | 'collapsed' | undefined}
|
|
66
|
+
target={props.target as HTMLElement | undefined}
|
|
67
|
+
onDismiss={(id, reason) => {
|
|
68
|
+
remove(id);
|
|
69
|
+
dispatch('kai-dismiss', { id, reason });
|
|
70
|
+
}}
|
|
71
|
+
onAction={(id, label) => dispatch('kai-action', { id, label })}
|
|
72
|
+
/>
|
|
73
|
+
);
|
|
74
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -18,6 +18,16 @@ export type { CodeHighlightingOptions } from './primitives/highlighter';
|
|
|
18
18
|
export { configurePdfPreview, isPdfPreviewEnabled } from './primitives/pdf-preview';
|
|
19
19
|
export type { PdfPreviewOptions } from './primitives/pdf-preview';
|
|
20
20
|
|
|
21
|
+
// Toasts: imperative `toast()` API + the reactive store behind <kai-toast-region>
|
|
22
|
+
export { toast, configureToasts, ensureMounted as ensureToastRegion, getToasts } from './primitives/toast-store';
|
|
23
|
+
export type {
|
|
24
|
+
ToastItem, ToastVariant, ToastAction, ToastOptions, ToastHandle, ToastFn, ToastConfig,
|
|
25
|
+
} from './primitives/toast-store';
|
|
26
|
+
export { Toast, ToastRegion } from './components/toast';
|
|
27
|
+
export type {
|
|
28
|
+
ToastRegionProps, ToastDismissReason, ToastPosition,
|
|
29
|
+
} from './components/toast';
|
|
30
|
+
|
|
21
31
|
// Card Contract (generative-UI foundation)
|
|
22
32
|
export { CARD_CONTRACT_VERSION } from './primitives/card-contract';
|
|
23
33
|
export type {
|
|
@@ -27,6 +37,10 @@ export { applyResolution, resolutionFromEvent } from './primitives/card-resoluti
|
|
|
27
37
|
export { CardProvider, useCardHost } from './primitives/card-host';
|
|
28
38
|
export type { CardProviderProps } from './primitives/card-host';
|
|
29
39
|
export { CARD_EVENT_NAME, emitCardEvent, routeCardEvent, listenForCardEvents } from './primitives/card-routing';
|
|
40
|
+
export { dismissRecovery, defaultIsReopenable } from './primitives/card-recovery';
|
|
41
|
+
export type {
|
|
42
|
+
RecoveryToast, ReopenEnv, DismissRecoveryOptions,
|
|
43
|
+
} from './primitives/card-recovery';
|
|
30
44
|
export { validateAgainstSchema } from './primitives/card-validate';
|
|
31
45
|
export type { JsonSchema, ValidationResult } from './primitives/card-validate';
|
|
32
46
|
|
|
@@ -47,6 +61,8 @@ export type { CardComponent, CardComponentMap, CardTagMap } from './primitives/c
|
|
|
47
61
|
// Card: kai-card (base shell) + kai-form (JSON-Schema form renderer)
|
|
48
62
|
export { Card } from './components/card';
|
|
49
63
|
export type { CardProps } from './components/card';
|
|
64
|
+
export { DismissedStub, stubIntent } from './components/dismissed-stub';
|
|
65
|
+
export type { DismissedStubProps, DismissedCardType } from './components/dismissed-stub';
|
|
50
66
|
export { Form, validateForm, buildResult, widgetFor, orderedKeys, coerceValue } from './components/form';
|
|
51
67
|
export type {
|
|
52
68
|
FormProps,
|
|
@@ -168,6 +184,20 @@ export {
|
|
|
168
184
|
} from './components/chat-container';
|
|
169
185
|
export { Message, MessageAvatar, MessageContent, MessageActions, MessageAction, MessageCopyButton } from './components/message';
|
|
170
186
|
export type { MessageCopyButtonProps } from './components/message';
|
|
187
|
+
export { ResponseCompare, useResolved } from './components/response-compare';
|
|
188
|
+
export type { ResponseCompareProps, CompareLayout, ResolvedController } from './components/response-compare';
|
|
189
|
+
export {
|
|
190
|
+
normalizeCandidates,
|
|
191
|
+
buildSelection,
|
|
192
|
+
isAnyStreaming,
|
|
193
|
+
} from './components/response-compare';
|
|
194
|
+
export type {
|
|
195
|
+
CompareCandidate,
|
|
196
|
+
ComparePair,
|
|
197
|
+
CompareCollapse,
|
|
198
|
+
ResponseCompareData,
|
|
199
|
+
CompareSelection,
|
|
200
|
+
} from './components/response-compare';
|
|
171
201
|
export { MessageSkills } from './components/message-skills';
|
|
172
202
|
export type { Skill as MessageSkill } from './components/message-skills';
|
|
173
203
|
export {
|
|
@@ -38,18 +38,24 @@ export type CardEvent =
|
|
|
38
38
|
| { kind: 'resize'; cardId: string; height: number }
|
|
39
39
|
| { kind: 'state'; cardId: string; patch: unknown }
|
|
40
40
|
| { kind: 'dismiss'; cardId: string }
|
|
41
|
+
| { kind: 'reopen'; cardId: string }
|
|
41
42
|
| { kind: 'error'; cardId: string; message: string };
|
|
42
43
|
|
|
43
44
|
export type CardEventKind = CardEvent['kind'];
|
|
44
45
|
|
|
45
46
|
/** How a card was resolved by the user — the re-hydration channel for the chromed
|
|
46
|
-
* read-only state.
|
|
47
|
-
* resolution is just the event that resolved the
|
|
48
|
-
*
|
|
49
|
-
*
|
|
47
|
+
* read-only state. The terminal kinds (`action`/`submit`) mirror the two terminal
|
|
48
|
+
* CardEvents (minus `cardId`): the resolution is just the event that resolved the
|
|
49
|
+
* card. `dismissed` is a DEFERRED (non-terminal) state — the user set the card
|
|
50
|
+
* aside; it can be re-opened. `expired` is terminal — a dismissed card the host
|
|
51
|
+
* decided can no longer be re-opened (e.g. the agent proceeded, or it went stale).
|
|
52
|
+
* `at` is optional ISO-8601 provenance (data only; never rendered). Additive —
|
|
53
|
+
* does not bump the contract version. */
|
|
50
54
|
export type CardResolution =
|
|
51
55
|
| { kind: 'action'; action: string; payload?: unknown; at?: string }
|
|
52
|
-
| { kind: 'submit'; data: unknown; at?: string }
|
|
56
|
+
| { kind: 'submit'; data: unknown; at?: string }
|
|
57
|
+
| { kind: 'dismissed'; at?: string }
|
|
58
|
+
| { kind: 'expired'; reason?: string; at?: string };
|
|
53
59
|
|
|
54
60
|
/** What every card is handed (via native context or the iframe bridge). */
|
|
55
61
|
export interface CardHost {
|
|
@@ -65,6 +71,9 @@ export interface CardPolicy {
|
|
|
65
71
|
onOpen?: (url: string, target: 'tab' | 'artifact') => void;
|
|
66
72
|
onState?: (cardId: string, patch: unknown) => void;
|
|
67
73
|
onDismiss?: (cardId: string) => void;
|
|
74
|
+
/** A dismissed card asked to be re-opened. The host decides whether it can come
|
|
75
|
+
* back (clear the resolution → live again) or has expired (stamp `expired`). */
|
|
76
|
+
onReopen?: (cardId: string) => void;
|
|
68
77
|
onError?: (cardId: string, message: string) => void;
|
|
69
78
|
/** Cap on send-prompt: 'compose' (default) forbids silent sends. 'send' to allow. */
|
|
70
79
|
maxSendPromptMode?: 'compose' | 'send';
|