@kitnai/chat 0.7.0 → 0.8.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 +9 -9
- package/dist/custom-elements.json +1626 -883
- package/dist/kitn-chat.es.js +36 -36
- package/dist/llms/llms-full.txt +303 -142
- package/dist/llms/llms.txt +18 -18
- package/dist/schemas/card-envelope.schema.json +14 -0
- package/dist/schemas/card-event.schema.json +12 -0
- package/dist/schemas/confirm.schema.json +65 -0
- package/dist/schemas/embed.schema.json +65 -0
- package/dist/schemas/form.result.schema.json +7 -0
- package/dist/schemas/form.schema.json +33 -0
- package/dist/schemas/link.schema.json +56 -0
- package/dist/schemas/task-list.result.schema.json +16 -0
- package/dist/schemas/task-list.schema.json +78 -0
- package/dist/theme.tokens.css +65 -65
- package/dist/tsx-B8rCNbgL.js +1 -0
- package/dist/typescript-RycA9KXf.js +1 -0
- package/frameworks/react/index.tsx +356 -189
- package/frameworks/react/runtime.tsx +2 -2
- package/llms-full.txt +303 -142
- package/llms.txt +18 -18
- package/package.json +5 -2
- package/src/components/artifact.stories.tsx +138 -0
- package/src/components/artifact.tsx +581 -0
- package/src/components/attachments.stories.tsx +7 -8
- package/src/components/attachments.tsx +2 -2
- package/src/components/card.tsx +110 -0
- package/src/components/chain-of-thought.stories.tsx +7 -8
- package/src/components/chat-container.stories.tsx +7 -8
- package/src/components/chat-container.tsx +4 -0
- package/src/components/checkpoint.stories.tsx +7 -8
- package/src/components/code-block.stories.tsx +8 -9
- package/src/components/component-meta.json +3411 -0
- package/src/components/confirm-card.stories.tsx +74 -0
- package/src/components/confirm-card.tsx +299 -0
- package/src/components/context.stories.tsx +7 -8
- package/src/components/conversation-item.stories.tsx +7 -8
- package/src/components/conversation-item.tsx +2 -2
- package/src/components/conversation-list.stories.tsx +7 -8
- package/src/components/conversation-list.tsx +1 -1
- package/src/components/embed.tsx +196 -0
- package/src/components/empty.stories.tsx +8 -9
- package/src/components/feedback-bar.stories.tsx +7 -8
- package/src/components/file-tree.stories.tsx +73 -0
- package/src/components/file-tree.tsx +383 -0
- package/src/components/file-upload.stories.tsx +7 -8
- package/src/components/form-widgets.tsx +461 -0
- package/src/components/form.tsx +796 -0
- package/src/components/image.stories.tsx +7 -8
- package/src/components/link-card.tsx +194 -0
- package/src/components/loader.stories.tsx +7 -8
- package/src/components/markdown.stories.tsx +7 -8
- package/src/components/message-narrow.stories.tsx +12 -13
- package/src/components/message-skills.stories.tsx +16 -17
- package/src/components/message.stories.tsx +17 -18
- package/src/components/model-switcher.stories.tsx +7 -8
- package/src/components/prompt-input.stories.tsx +8 -9
- package/src/components/prompt-suggestion.stories.tsx +7 -8
- package/src/components/prompt-suggestion.tsx +3 -3
- package/src/components/reasoning.stories.tsx +7 -8
- package/src/components/scroll-button.stories.tsx +7 -8
- package/src/components/slash-command.stories.tsx +8 -9
- package/src/components/slash-command.tsx +2 -2
- package/src/components/source.stories.tsx +7 -8
- package/src/components/source.tsx +1 -1
- package/src/components/task-list-card.stories.tsx +78 -0
- package/src/components/task-list-card.tsx +388 -0
- package/src/components/text-shimmer.stories.tsx +7 -8
- package/src/components/thinking-bar.stories.tsx +7 -8
- package/src/components/tool.stories.tsx +7 -8
- package/src/components/tool.tsx +2 -2
- package/src/components/voice-input.stories.tsx +7 -8
- package/src/elements/artifact.stories.tsx +291 -0
- package/src/elements/artifact.tsx +72 -0
- package/src/elements/{kitn-attachments.stories.tsx → attachments.stories.tsx} +11 -20
- package/src/elements/attachments.tsx +4 -4
- package/src/elements/card.stories.tsx +118 -0
- package/src/elements/card.tsx +40 -0
- package/src/elements/catalog.stories.tsx +491 -0
- package/src/elements/{kitn-chain-of-thought.stories.tsx → chain-of-thought.stories.tsx} +13 -22
- package/src/elements/chain-of-thought.tsx +3 -3
- package/src/elements/{kitn-chat-scope-picker.stories.tsx → chat-scope-picker.stories.tsx} +10 -19
- package/src/elements/chat-scope-picker.tsx +4 -4
- package/src/elements/{kitn-chat-workspace.stories.tsx → chat-workspace.stories.tsx} +15 -23
- package/src/elements/chat-workspace.tsx +2 -2
- package/src/elements/{kitn-chat.stories.tsx → chat.stories.tsx} +12 -20
- package/src/elements/chat.tsx +2 -2
- package/src/elements/{kitn-checkpoint.stories.tsx → checkpoint.stories.tsx} +11 -20
- package/src/elements/checkpoint.tsx +4 -4
- package/src/elements/{kitn-code-block.stories.tsx → code-block.stories.tsx} +10 -19
- package/src/elements/code-block.tsx +3 -3
- package/src/elements/compiled.css +1 -1
- package/src/elements/composed-shell.stories.tsx +316 -0
- package/src/elements/confirm-card.stories.tsx +186 -0
- package/src/elements/confirm-card.tsx +45 -0
- package/src/elements/{kitn-context-meter.stories.tsx → context-meter.stories.tsx} +10 -19
- package/src/elements/context-meter.tsx +3 -3
- package/src/elements/{kitn-conversation-list.stories.tsx → conversation-list.stories.tsx} +12 -20
- package/src/elements/conversation-list.tsx +2 -2
- package/src/elements/css.ts +1 -1
- package/src/elements/define.tsx +10 -10
- package/src/elements/element-meta.json +1379 -733
- package/src/elements/element-types.d.ts +251 -125
- package/src/elements/embed.stories.tsx +197 -0
- package/src/elements/embed.tsx +35 -0
- package/src/elements/{kitn-empty.stories.tsx → empty.stories.tsx} +12 -21
- package/src/elements/empty.tsx +3 -3
- package/src/elements/{kitn-feedback-bar.stories.tsx → feedback-bar.stories.tsx} +11 -20
- package/src/elements/feedback-bar.tsx +4 -4
- package/src/elements/file-tree.stories.tsx +133 -0
- package/src/elements/file-tree.tsx +52 -0
- package/src/elements/{kitn-file-upload.stories.tsx → file-upload.stories.tsx} +12 -21
- package/src/elements/file-upload.tsx +4 -4
- package/src/elements/form.stories.tsx +204 -0
- package/src/elements/form.tsx +37 -0
- package/src/elements/{kitn-image.stories.tsx → image.stories.tsx} +10 -19
- package/src/elements/image.tsx +3 -3
- package/src/elements/link-card.stories.tsx +193 -0
- package/src/elements/link-card.tsx +34 -0
- package/src/elements/{kitn-loader.stories.tsx → loader.stories.tsx} +11 -20
- package/src/elements/loader.tsx +3 -3
- package/src/elements/{kitn-markdown.stories.tsx → markdown.stories.tsx} +10 -19
- package/src/elements/markdown.tsx +3 -3
- package/src/elements/{kitn-message-skills.stories.tsx → message-skills.stories.tsx} +10 -19
- package/src/elements/message-skills.tsx +3 -3
- package/src/elements/{kitn-message.stories.tsx → message.stories.tsx} +12 -21
- package/src/elements/message.tsx +5 -5
- package/src/elements/{kitn-model-switcher.stories.tsx → model-switcher.stories.tsx} +10 -19
- package/src/elements/model-switcher.tsx +5 -5
- package/src/elements/{kitn-prompt-input.stories.tsx → prompt-input.stories.tsx} +14 -22
- package/src/elements/prompt-input.tsx +3 -3
- package/src/elements/{kitn-prompt-suggestions.stories.tsx → prompt-suggestions.stories.tsx} +13 -22
- package/src/elements/prompt-suggestions.tsx +4 -4
- package/src/elements/{kitn-reasoning.stories.tsx → reasoning.stories.tsx} +10 -19
- package/src/elements/reasoning.tsx +4 -4
- package/src/elements/register.ts +11 -1
- package/src/elements/resizable.stories.tsx +200 -0
- package/src/elements/resizable.tsx +264 -0
- package/src/elements/{kitn-response-stream.stories.tsx → response-stream.stories.tsx} +10 -19
- package/src/elements/response-stream.tsx +4 -4
- package/src/elements/{kitn-source-list.stories.tsx → source-list.stories.tsx} +11 -20
- package/src/elements/{kitn-source.stories.tsx → source.stories.tsx} +12 -21
- package/src/elements/source.tsx +5 -5
- package/src/elements/styles.css +140 -1
- package/src/elements/task-list-card.stories.tsx +194 -0
- package/src/elements/task-list-card.tsx +40 -0
- package/src/elements/{kitn-text-shimmer.stories.tsx → text-shimmer.stories.tsx} +10 -19
- package/src/elements/text-shimmer.tsx +3 -3
- package/src/elements/{kitn-thinking-bar.stories.tsx → thinking-bar.stories.tsx} +11 -20
- package/src/elements/thinking-bar.tsx +5 -5
- package/src/elements/{kitn-tool.stories.tsx → tool.stories.tsx} +10 -19
- package/src/elements/tool.tsx +3 -3
- package/src/elements/{kitn-voice-input.stories.tsx → voice-input.stories.tsx} +10 -19
- package/src/elements/voice-input.tsx +4 -4
- package/src/index.ts +94 -2
- package/src/primitives/card-contract.ts +60 -0
- package/src/primitives/card-host.tsx +35 -0
- package/src/primitives/card-routing.ts +79 -0
- package/src/primitives/card-schemas/card-envelope.schema.json +14 -0
- package/src/primitives/card-schemas/card-event.schema.json +12 -0
- package/src/primitives/card-schemas/confirm.schema.json +65 -0
- package/src/primitives/card-schemas/embed.schema.json +65 -0
- package/src/primitives/card-schemas/form.result.schema.json +7 -0
- package/src/primitives/card-schemas/form.schema.json +33 -0
- package/src/primitives/card-schemas/link.schema.json +56 -0
- package/src/primitives/card-schemas/task-list.result.schema.json +16 -0
- package/src/primitives/card-schemas/task-list.schema.json +78 -0
- package/src/primitives/card-validate.ts +95 -0
- package/src/primitives/embed-providers.ts +254 -0
- package/src/primitives/highlighter.ts +4 -0
- package/src/primitives/link-preview.ts +87 -0
- package/src/primitives/pdf-preview.ts +121 -0
- package/src/stories/chat-panel-layout.stories.tsx +2 -1
- package/src/stories/chat-scene.tsx +22 -21
- package/src/stories/checkpoint-restore.stories.tsx +10 -10
- package/src/stories/conversation-with-reasoning.stories.tsx +4 -4
- package/src/stories/conversation-with-sources.stories.tsx +7 -7
- package/src/stories/docs/Accessibility.mdx +2 -2
- package/src/stories/docs/ForAIAgents.mdx +3 -3
- package/src/stories/docs/GettingStarted.mdx +2 -2
- package/src/stories/docs/Installation.mdx +2 -2
- package/src/stories/docs/Integrations.mdx +29 -29
- package/src/stories/docs/Introduction.mdx +3 -3
- package/src/stories/docs/Theming.mdx +2 -2
- package/src/stories/docs/element-controls.ts +32 -0
- package/src/stories/docs/theme-editor/theme-editor.tsx +1 -0
- package/src/stories/examples/ChoosingComponents.mdx +94 -0
- package/src/stories/examples/sample-data.ts +79 -0
- package/src/stories/message-actions.stories.tsx +13 -13
- package/src/stories/pattern-centered-conversation.stories.tsx +3 -3
- package/src/stories/pattern-docked-widget.stories.tsx +1 -1
- package/src/stories/pattern-empty-state.stories.tsx +3 -3
- package/src/stories/prompt-input-variants.stories.tsx +13 -13
- package/src/stories/streaming-response.stories.tsx +3 -3
- package/src/stories/typography.stories.tsx +4 -4
- package/src/ui/avatar.stories.tsx +7 -8
- package/src/ui/badge.stories.tsx +7 -8
- package/src/ui/button.stories.tsx +8 -9
- package/src/ui/button.tsx +1 -0
- package/src/ui/collapsible.stories.tsx +6 -7
- package/src/ui/dropdown.stories.tsx +6 -7
- package/src/ui/hover-card.stories.tsx +6 -7
- package/src/ui/resizable.stories.tsx +74 -9
- package/src/ui/resizable.tsx +351 -71
- package/src/ui/scroll-area.stories.tsx +6 -7
- package/src/ui/scroll-area.tsx +3 -1
- package/src/ui/separator.stories.tsx +7 -8
- package/src/ui/skeleton.stories.tsx +7 -8
- package/src/ui/textarea.stories.tsx +6 -7
- package/src/ui/tooltip.stories.tsx +8 -9
- package/theme.css +65 -65
- package/src/stories/docs/element-spec.tsx +0 -86
package/src/elements/styles.css
CHANGED
|
@@ -10,9 +10,17 @@
|
|
|
10
10
|
:host { display: block; }
|
|
11
11
|
* { border-color: var(--color-border); }
|
|
12
12
|
|
|
13
|
+
/* Native controls (date/time pickers, <select>, number spinners, the
|
|
14
|
+
checkbox/radio fallbacks, scrollbars) must follow the kit's light/dark
|
|
15
|
+
mode — NOT the OS — so e.g. the native calendar icon never renders black
|
|
16
|
+
on a dark surface. `color-scheme` drives that native rendering; we set it
|
|
17
|
+
from the resolved mode (the `.dark` scope the element factory toggles). */
|
|
18
|
+
:host { color-scheme: light; }
|
|
19
|
+
.dark { color-scheme: dark; }
|
|
20
|
+
|
|
13
21
|
/* One token-driven focus ring for EVERY focusable element in the shadow root.
|
|
14
22
|
Blue by default (via --color-ring), consistent in light + dark, and
|
|
15
|
-
overridable through --
|
|
23
|
+
overridable through --kc-color-ring. Uses `outline` (not a box-shadow
|
|
16
24
|
ring) so it never clips on overflow and follows the element's radius;
|
|
17
25
|
`:focus-visible` so it only appears for keyboard navigation, never on a
|
|
18
26
|
mouse click. Components that render their own ring set
|
|
@@ -45,3 +53,134 @@
|
|
|
45
53
|
*::-webkit-scrollbar-thumb:hover { background-color: var(--color-scrollbar-thumb-hover); }
|
|
46
54
|
*::-webkit-scrollbar-corner { background: transparent; }
|
|
47
55
|
}
|
|
56
|
+
|
|
57
|
+
@layer components {
|
|
58
|
+
/* Designed radio + checkbox (appearance-none) so the form controls read as
|
|
59
|
+
intentional, theme correctly in light/dark, and have comfortable targets —
|
|
60
|
+
replacing the weak native defaults. Used via `.kc-radio` / `.kc-checkbox`. */
|
|
61
|
+
.kc-radio,
|
|
62
|
+
.kc-checkbox {
|
|
63
|
+
appearance: none;
|
|
64
|
+
-webkit-appearance: none;
|
|
65
|
+
inline-size: 1.125rem;
|
|
66
|
+
block-size: 1.125rem;
|
|
67
|
+
margin: 0;
|
|
68
|
+
flex-shrink: 0;
|
|
69
|
+
cursor: pointer;
|
|
70
|
+
border: 1.5px solid var(--color-input);
|
|
71
|
+
background-color: var(--color-background);
|
|
72
|
+
display: inline-grid;
|
|
73
|
+
place-content: center;
|
|
74
|
+
box-shadow: 0 1px 2px rgb(0 0 0 / 0.04);
|
|
75
|
+
transition: border-color 0.18s ease, background-color 0.18s ease, box-shadow 0.18s ease,
|
|
76
|
+
transform 0.1s ease;
|
|
77
|
+
}
|
|
78
|
+
.kc-radio { border-radius: 9999px; }
|
|
79
|
+
.kc-checkbox { border-radius: 0.3rem; }
|
|
80
|
+
.kc-radio::after {
|
|
81
|
+
content: "";
|
|
82
|
+
inline-size: 0.5rem;
|
|
83
|
+
block-size: 0.5rem;
|
|
84
|
+
border-radius: 9999px;
|
|
85
|
+
background-color: var(--color-primary);
|
|
86
|
+
transform: scale(0);
|
|
87
|
+
transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
88
|
+
}
|
|
89
|
+
.kc-radio:checked { border-color: var(--color-primary); }
|
|
90
|
+
.kc-radio:checked::after { transform: scale(1); }
|
|
91
|
+
.kc-checkbox:checked {
|
|
92
|
+
background-color: var(--color-primary);
|
|
93
|
+
border-color: var(--color-primary);
|
|
94
|
+
}
|
|
95
|
+
.kc-checkbox::after {
|
|
96
|
+
content: "";
|
|
97
|
+
inline-size: 0.8rem;
|
|
98
|
+
block-size: 0.8rem;
|
|
99
|
+
background-color: var(--color-primary-foreground);
|
|
100
|
+
transform: scale(0);
|
|
101
|
+
transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
102
|
+
-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='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
103
|
+
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='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
104
|
+
}
|
|
105
|
+
.kc-checkbox:checked::after { transform: scale(1); }
|
|
106
|
+
.kc-radio:hover:not(:disabled),
|
|
107
|
+
.kc-checkbox:hover:not(:disabled) {
|
|
108
|
+
border-color: var(--color-primary);
|
|
109
|
+
box-shadow: 0 0 0 4px color-mix(in srgb, var(--color-primary) 9%, transparent);
|
|
110
|
+
}
|
|
111
|
+
.kc-radio:active:not(:disabled),
|
|
112
|
+
.kc-checkbox:active:not(:disabled) { transform: scale(0.92); }
|
|
113
|
+
.kc-checkbox:checked {
|
|
114
|
+
box-shadow: 0 1px 4px color-mix(in srgb, var(--color-primary) 26%, transparent);
|
|
115
|
+
}
|
|
116
|
+
.kc-radio:disabled,
|
|
117
|
+
.kc-checkbox:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
118
|
+
|
|
119
|
+
/* Custom range slider: a filled track (--kc-range-fill set by the widget) and a
|
|
120
|
+
refined thumb that scales on hover/press with a focus halo — no native chrome. */
|
|
121
|
+
.kc-range {
|
|
122
|
+
appearance: none;
|
|
123
|
+
-webkit-appearance: none;
|
|
124
|
+
inline-size: 100%;
|
|
125
|
+
block-size: 1.25rem;
|
|
126
|
+
background: transparent;
|
|
127
|
+
cursor: pointer;
|
|
128
|
+
margin: 0;
|
|
129
|
+
}
|
|
130
|
+
.kc-range::-webkit-slider-runnable-track {
|
|
131
|
+
block-size: 0.375rem;
|
|
132
|
+
border-radius: 9999px;
|
|
133
|
+
border: none;
|
|
134
|
+
box-shadow: none;
|
|
135
|
+
background: linear-gradient(
|
|
136
|
+
to right,
|
|
137
|
+
var(--color-primary) var(--kc-range-fill, 0%),
|
|
138
|
+
var(--color-muted) var(--kc-range-fill, 0%)
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
.kc-range::-moz-range-track {
|
|
142
|
+
block-size: 0.375rem;
|
|
143
|
+
border-radius: 9999px;
|
|
144
|
+
border: none;
|
|
145
|
+
box-shadow: none;
|
|
146
|
+
background: var(--color-muted);
|
|
147
|
+
}
|
|
148
|
+
.kc-range::-moz-range-progress {
|
|
149
|
+
block-size: 0.375rem;
|
|
150
|
+
border-radius: 9999px;
|
|
151
|
+
background: var(--color-primary);
|
|
152
|
+
}
|
|
153
|
+
.kc-range::-webkit-slider-thumb {
|
|
154
|
+
appearance: none;
|
|
155
|
+
-webkit-appearance: none;
|
|
156
|
+
inline-size: 1.125rem;
|
|
157
|
+
block-size: 1.125rem;
|
|
158
|
+
border-radius: 9999px;
|
|
159
|
+
background: var(--color-background);
|
|
160
|
+
border: 2px solid var(--color-primary);
|
|
161
|
+
box-shadow: 0 1px 3px rgb(0 0 0 / 0.18);
|
|
162
|
+
margin-block-start: -0.375rem;
|
|
163
|
+
transition: transform 0.12s ease, box-shadow 0.12s ease;
|
|
164
|
+
}
|
|
165
|
+
.kc-range::-moz-range-thumb {
|
|
166
|
+
inline-size: 1.125rem;
|
|
167
|
+
block-size: 1.125rem;
|
|
168
|
+
border-radius: 9999px;
|
|
169
|
+
background: var(--color-background);
|
|
170
|
+
border: 2px solid var(--color-primary);
|
|
171
|
+
box-shadow: 0 1px 3px rgb(0 0 0 / 0.18);
|
|
172
|
+
transition: transform 0.12s ease, box-shadow 0.12s ease;
|
|
173
|
+
}
|
|
174
|
+
.kc-range:hover::-webkit-slider-thumb { transform: scale(1.12); }
|
|
175
|
+
.kc-range:hover::-moz-range-thumb { transform: scale(1.12); }
|
|
176
|
+
.kc-range:focus-visible { outline: none; }
|
|
177
|
+
.kc-range:focus-visible::-webkit-slider-thumb,
|
|
178
|
+
.kc-range:active::-webkit-slider-thumb {
|
|
179
|
+
box-shadow: 0 0 0 6px color-mix(in srgb, var(--color-primary) 14%, transparent);
|
|
180
|
+
}
|
|
181
|
+
.kc-range:focus-visible::-moz-range-thumb,
|
|
182
|
+
.kc-range:active::-moz-range-thumb {
|
|
183
|
+
box-shadow: 0 0 0 6px color-mix(in srgb, var(--color-primary) 14%, transparent);
|
|
184
|
+
}
|
|
185
|
+
.kc-range:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
186
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from 'storybook-solidjs-vite';
|
|
2
|
+
import { createSignal, onMount, type JSX } from 'solid-js';
|
|
3
|
+
import './task-list-card';
|
|
4
|
+
import { argTypesFor, specDescription } from '../stories/docs/element-controls';
|
|
5
|
+
import type { TaskListCardData } from '../components/task-list-card';
|
|
6
|
+
import type { CardEvent } from '../primitives/card-contract';
|
|
7
|
+
|
|
8
|
+
declare module 'solid-js' {
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
10
|
+
namespace JSX {
|
|
11
|
+
interface IntrinsicElements {
|
|
12
|
+
'kc-task-list': JSX.HTMLAttributes<HTMLElement> & {
|
|
13
|
+
heading?: string;
|
|
14
|
+
'card-id'?: string;
|
|
15
|
+
ref?: (el: HTMLElement) => void;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type TaskListEl = HTMLElement & { data?: TaskListCardData };
|
|
22
|
+
|
|
23
|
+
function Frame(props: { children: JSX.Element }) {
|
|
24
|
+
return <div style={{ 'max-width': '460px' }}>{props.children}</div>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Mounts a <kc-task-list>, sets `.data`, logs the emitted CardEvent under the render. */
|
|
28
|
+
function TaskListDemo(props: { def: TaskListCardData; cardId: string; heading?: string }) {
|
|
29
|
+
const [log, setLog] = createSignal<CardEvent[]>([]);
|
|
30
|
+
let el: TaskListEl | undefined;
|
|
31
|
+
onMount(() => {
|
|
32
|
+
if (!el) return;
|
|
33
|
+
el.data = props.def;
|
|
34
|
+
el.addEventListener('kc-card', (e) => {
|
|
35
|
+
const detail = (e as CustomEvent<CardEvent>).detail;
|
|
36
|
+
setLog((prev) => [...prev, detail]);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
return (
|
|
40
|
+
<Frame>
|
|
41
|
+
<div style={{ display: 'flex', 'flex-direction': 'column', gap: '12px' }}>
|
|
42
|
+
<kc-task-list ref={(e) => (el = e as TaskListEl)} card-id={props.cardId} heading={props.heading} />
|
|
43
|
+
<pre
|
|
44
|
+
style={{
|
|
45
|
+
margin: 0,
|
|
46
|
+
'max-height': '180px',
|
|
47
|
+
overflow: 'auto',
|
|
48
|
+
background: 'var(--color-muted, #f4f4f5)',
|
|
49
|
+
'border-radius': '8px',
|
|
50
|
+
padding: '8px',
|
|
51
|
+
'font-size': '12px',
|
|
52
|
+
}}
|
|
53
|
+
>
|
|
54
|
+
{log().length === 0 ? '// emitted CardEvents appear here' : JSON.stringify(log(), null, 2)}
|
|
55
|
+
</pre>
|
|
56
|
+
</div>
|
|
57
|
+
</Frame>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const PLAN: TaskListCardData = {
|
|
62
|
+
mode: 'select',
|
|
63
|
+
selectAll: true,
|
|
64
|
+
confirmLabel: 'Run selected',
|
|
65
|
+
tasks: [
|
|
66
|
+
{ id: 'lint', label: 'Run linter', checked: true },
|
|
67
|
+
{ id: 'test', label: 'Run unit tests', checked: true },
|
|
68
|
+
{ id: 'build', label: 'Build production bundle' },
|
|
69
|
+
{ id: 'deploy', label: 'Deploy to staging', description: 'Reversible; staging only' },
|
|
70
|
+
],
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const REQUIRE_ONE: TaskListCardData = {
|
|
74
|
+
confirmLabel: 'Apply',
|
|
75
|
+
allowEmpty: false,
|
|
76
|
+
tasks: [
|
|
77
|
+
{ id: 'cache', label: 'Clear the CDN cache' },
|
|
78
|
+
{ id: 'reindex', label: 'Rebuild the search index' },
|
|
79
|
+
{ id: 'restart', label: 'Restart the workers' },
|
|
80
|
+
],
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const BOUNDED: TaskListCardData = {
|
|
84
|
+
heading: 'Pick up to 2 reviewers',
|
|
85
|
+
confirmLabel: 'Request review',
|
|
86
|
+
min: 1,
|
|
87
|
+
max: 2,
|
|
88
|
+
tasks: [
|
|
89
|
+
{ id: 'ana', label: 'Ana' },
|
|
90
|
+
{ id: 'ben', label: 'Ben' },
|
|
91
|
+
{ id: 'cat', label: 'Cat' },
|
|
92
|
+
{ id: 'dan', label: 'Dan' },
|
|
93
|
+
],
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const WITH_DESCRIPTIONS: TaskListCardData = {
|
|
97
|
+
selectAll: true,
|
|
98
|
+
confirmLabel: 'Run cleanup',
|
|
99
|
+
tasks: [
|
|
100
|
+
{ id: 'tmp', label: 'Delete temp files', description: 'Frees ~2.1 GB; safe to remove' },
|
|
101
|
+
{ id: 'logs', label: 'Rotate logs', description: 'Archives logs older than 30 days' },
|
|
102
|
+
{ id: 'orphans', label: 'Prune orphaned blobs', description: 'Unreferenced uploads only' },
|
|
103
|
+
],
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const HEADING_MAP: Record<string, string | undefined> = {
|
|
107
|
+
'card-plan': 'Approve the plan steps',
|
|
108
|
+
'card-require': 'Choose maintenance steps',
|
|
109
|
+
'card-bounded': undefined,
|
|
110
|
+
'card-desc': 'Storage cleanup',
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const HTML_SNIPPET = (def: TaskListCardData, cardId: string) => {
|
|
114
|
+
const heading = HEADING_MAP[cardId];
|
|
115
|
+
return `<kc-task-list${heading ? ` heading="${heading}"` : ''}></kc-task-list>
|
|
116
|
+
<script type="module">
|
|
117
|
+
import '@kitnai/chat/elements'; // registers the custom elements
|
|
118
|
+
|
|
119
|
+
const el = document.querySelector('kc-task-list');
|
|
120
|
+
// \`data\` is the CardEnvelope.data (set as a property).
|
|
121
|
+
el.data = ${JSON.stringify(def, null, 2)};
|
|
122
|
+
|
|
123
|
+
// Toggling rows is local; only CONFIRM emits — a single bubbling \`kc-card\` event.
|
|
124
|
+
el.addEventListener('kc-card', (e) => {
|
|
125
|
+
const ev = e.detail; // { kind:'submit-data', cardId, data:{ selected } } | ...
|
|
126
|
+
if (ev.kind === 'submit-data') console.log('selected', ev.data.selected);
|
|
127
|
+
});
|
|
128
|
+
</script>`;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const meta = {
|
|
132
|
+
title: 'Generative UI/Cards/kc-task-list',
|
|
133
|
+
tags: ['autodocs'],
|
|
134
|
+
argTypes: argTypesFor('kc-task-list'),
|
|
135
|
+
parameters: {
|
|
136
|
+
layout: 'padded',
|
|
137
|
+
docs: {
|
|
138
|
+
description: specDescription('kc-task-list', [
|
|
139
|
+
"`<kc-task-list>` is a **selectable** task/plan list (set via the `data` **property**): checkbox rows + an optional select-all + a confirm button. The user picks a subset, confirms, and the card emits the Card contract's **`submit-data`** verb up a bubbling **`kc-card`** CustomEvent of `{ kind: 'submit-data', cardId, data: { selected } }` — the checked ids in **input order**. Toggling rows is local UI state; **only the final confirm emits** (the wire stays quiet, the result atomic).",
|
|
140
|
+
'**Gating:** confirm is enabled when `selectedCount >= (min ?? (allowEmpty ? 0 : 1))` and `<= (max ?? ∞)`. Select-all checks every toggleable (non-`disabled`) row and shows an **indeterminate** (`aria-checked="mixed"`) state when only some are checked. When `max` is reached, unchecked rows become non-toggleable. v1 is **select/approve only** (a future `mode:\'progress\'` is reserved in the schema).',
|
|
141
|
+
'**Events** (all frozen Card-contract verbs): `ready` on mount, `submit-data` on confirm, `error` for a malformed definition (renders the inline `kc-card` error). It **never invents events**. The same shapes flow over the remote iframe transport unchanged.',
|
|
142
|
+
]),
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
} satisfies Meta;
|
|
146
|
+
|
|
147
|
+
export default meta;
|
|
148
|
+
type Story = StoryObj;
|
|
149
|
+
|
|
150
|
+
/** Select a plan (select-all on, a few pre-checked). */
|
|
151
|
+
export const SelectAPlan: Story = {
|
|
152
|
+
render: () => <TaskListDemo def={PLAN} cardId="card-plan" heading="Approve the plan steps" />,
|
|
153
|
+
parameters: { docs: { source: { code: HTML_SNIPPET(PLAN, 'card-plan'), language: 'html' } } },
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
/** Require at least one (`allowEmpty:false`, the default) — confirm stays disabled until a row is checked. */
|
|
157
|
+
export const RequireAtLeastOne: Story = {
|
|
158
|
+
render: () => <TaskListDemo def={REQUIRE_ONE} cardId="card-require" heading="Choose maintenance steps" />,
|
|
159
|
+
parameters: { docs: { source: { code: HTML_SNIPPET(REQUIRE_ONE, 'card-require'), language: 'html' } } },
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
/** Bounded (`min`/`max`) — confirm gating + max-reached row disabling. */
|
|
163
|
+
export const Bounded: Story = {
|
|
164
|
+
render: () => <TaskListDemo def={BOUNDED} cardId="card-bounded" />,
|
|
165
|
+
parameters: { docs: { source: { code: HTML_SNIPPET(BOUNDED, 'card-bounded'), language: 'html' } } },
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
/** Rows with secondary descriptions (linked via aria-describedby). */
|
|
169
|
+
export const WithDescriptions: Story = {
|
|
170
|
+
render: () => <TaskListDemo def={WITH_DESCRIPTIONS} cardId="card-desc" heading="Storage cleanup" />,
|
|
171
|
+
parameters: { docs: { source: { code: HTML_SNIPPET(WITH_DESCRIPTIONS, 'card-desc'), language: 'html' } } },
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
/** A malformed `data` (empty `tasks`) → the inline error state + an `error` event. */
|
|
175
|
+
export const ErrorState: Story = {
|
|
176
|
+
render: () => <TaskListDemo def={{ tasks: [] } as unknown as TaskListCardData} cardId="card-bad" />,
|
|
177
|
+
parameters: {
|
|
178
|
+
docs: {
|
|
179
|
+
source: {
|
|
180
|
+
code: `<kc-task-list></kc-task-list>
|
|
181
|
+
<script type="module">
|
|
182
|
+
import '@kitnai/chat/elements';
|
|
183
|
+
const el = document.querySelector('kc-task-list');
|
|
184
|
+
// No tasks → inline error state + an \`error\` event.
|
|
185
|
+
el.data = { tasks: [] };
|
|
186
|
+
el.addEventListener('kc-card', (e) => {
|
|
187
|
+
if (e.detail.kind === 'error') console.warn('task-list error:', e.detail.message);
|
|
188
|
+
});
|
|
189
|
+
</script>`,
|
|
190
|
+
language: 'html',
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { defineWebComponent } from './define';
|
|
2
|
+
import { TaskListCard, type TaskListCardData } from '../components/task-list-card';
|
|
3
|
+
|
|
4
|
+
interface Props extends Record<string, unknown> {
|
|
5
|
+
/** The task-list definition (the CardEnvelope.data). Set as a JS PROPERTY:
|
|
6
|
+
* `el.data = { tasks:[…], selectAll, confirmLabel, … }`. Import
|
|
7
|
+
* `TaskListCardData` from `@kitnai/chat` for the full shape. */
|
|
8
|
+
data?: Record<string, unknown>;
|
|
9
|
+
/** Stable card id correlating every emitted CardEvent. Attribute: `card-id`. */
|
|
10
|
+
cardId?: string;
|
|
11
|
+
/** Heading rendered in the card chrome (= CardEnvelope.title). Attribute: `heading`. */
|
|
12
|
+
heading?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* `<kc-task-list>` — a **selectable** task/plan list (set via the `data` property):
|
|
17
|
+
* checkbox rows + an optional select-all + a confirm button. Toggling rows is local
|
|
18
|
+
* UI state; only the final confirm emits the Card contract's **`submit-data`** verb
|
|
19
|
+
* up a bubbling **`kc-card`** CustomEvent (`{ kind:'submit-data', cardId,
|
|
20
|
+
* data:{ selected } }`) with the checked ids in input order. Also emits `ready` on
|
|
21
|
+
* mount and `error` for a malformed definition (inline error). v1 = select/approve
|
|
22
|
+
* mode only. Routes through a `CardProvider` when present, else the bubbling
|
|
23
|
+
* `kc-card` event. Isolated in Shadow DOM; theme-aware via the shared kit tokens.
|
|
24
|
+
*/
|
|
25
|
+
defineWebComponent<Props>(
|
|
26
|
+
'kc-task-list',
|
|
27
|
+
{
|
|
28
|
+
data: undefined,
|
|
29
|
+
cardId: undefined,
|
|
30
|
+
heading: undefined,
|
|
31
|
+
},
|
|
32
|
+
(props, { element }) => (
|
|
33
|
+
<TaskListCard
|
|
34
|
+
data={props.data as TaskListCardData | undefined}
|
|
35
|
+
cardId={props.cardId ?? (element.id || 'kc-task-list')}
|
|
36
|
+
heading={props.heading}
|
|
37
|
+
hostElement={element}
|
|
38
|
+
/>
|
|
39
|
+
),
|
|
40
|
+
);
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from 'storybook-solidjs-vite';
|
|
2
2
|
import './register'; // side effect: registers the custom elements
|
|
3
|
-
import {
|
|
4
|
-
import { argTypesFor } from '../stories/docs/element-controls';
|
|
3
|
+
import { argTypesFor, specDescription } from '../stories/docs/element-controls';
|
|
5
4
|
|
|
6
5
|
// The web components are custom DOM elements, so declare the tags for JSX.
|
|
7
6
|
declare module 'solid-js' {
|
|
8
7
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
9
8
|
namespace JSX {
|
|
10
9
|
interface IntrinsicElements {
|
|
11
|
-
'
|
|
10
|
+
'kc-text-shimmer': JSX.HTMLAttributes<HTMLElement> & {
|
|
12
11
|
text?: string;
|
|
13
12
|
duration?: number;
|
|
14
13
|
spread?: number;
|
|
@@ -18,27 +17,25 @@ declare module 'solid-js' {
|
|
|
18
17
|
}
|
|
19
18
|
|
|
20
19
|
const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
|
|
21
|
-
<
|
|
20
|
+
<kc-text-shimmer text="Thinking…" duration="3" spread="20"></kc-text-shimmer>
|
|
22
21
|
|
|
23
22
|
<script type="module">
|
|
24
23
|
import '@kitnai/chat/elements'; // registers the custom elements
|
|
25
24
|
</script>`;
|
|
26
25
|
|
|
27
26
|
const meta = {
|
|
28
|
-
title: 'Web Components/
|
|
27
|
+
title: 'Web Components/kc-text-shimmer',
|
|
29
28
|
tags: ['autodocs'],
|
|
30
|
-
argTypes: argTypesFor('
|
|
29
|
+
argTypes: argTypesFor('kc-text-shimmer'),
|
|
31
30
|
parameters: {
|
|
32
31
|
layout: 'fullscreen',
|
|
33
32
|
docs: {
|
|
34
|
-
description:
|
|
35
|
-
|
|
36
|
-
'`<kitn-text-shimmer>` is the framework-agnostic **web component** for animated shimmering text — a gradient sweep across a label, isolated in **Shadow DOM**.',
|
|
33
|
+
description: specDescription('kc-text-shimmer', [
|
|
34
|
+
'`<kc-text-shimmer>` is the framework-agnostic **web component** for animated shimmering text — a gradient sweep across a label, isolated in **Shadow DOM**.',
|
|
37
35
|
'**When to use:** signalling a quiet, in-progress state ("Thinking…", "Generating…") inline. In SolidJS, use the `TextShimmer` primitive.',
|
|
38
36
|
"**How to use:** register once with `import '@kitnai/chat/elements'`, set the `text` attribute, and tune `duration` (seconds) and `spread` (gradient width, 5–45).",
|
|
39
37
|
'See the **Code** tab for HTML usage.',
|
|
40
|
-
]
|
|
41
|
-
},
|
|
38
|
+
]),
|
|
42
39
|
},
|
|
43
40
|
},
|
|
44
41
|
} satisfies Meta;
|
|
@@ -46,17 +43,11 @@ const meta = {
|
|
|
46
43
|
export default meta;
|
|
47
44
|
type Story = StoryObj;
|
|
48
45
|
|
|
49
|
-
/** Full generated API reference — properties, events, tokens, and composed-from. */
|
|
50
|
-
export const API: Story = {
|
|
51
|
-
render: () => <ElementSpec tag="kitn-text-shimmer" />,
|
|
52
|
-
parameters: { layout: 'padded' },
|
|
53
|
-
};
|
|
54
|
-
|
|
55
46
|
/** Default shimmer. */
|
|
56
47
|
export const Default: Story = {
|
|
57
48
|
render: () => (
|
|
58
49
|
<div style={{ padding: '24px', 'font-size': '18px' }}>
|
|
59
|
-
<
|
|
50
|
+
<kc-text-shimmer text="Thinking…" />
|
|
60
51
|
</div>
|
|
61
52
|
),
|
|
62
53
|
parameters: { docs: { source: { code: HTML_SNIPPET, language: 'html' } } },
|
|
@@ -66,7 +57,7 @@ export const Default: Story = {
|
|
|
66
57
|
export const Tuned: Story = {
|
|
67
58
|
render: () => (
|
|
68
59
|
<div style={{ padding: '24px', 'font-size': '18px' }}>
|
|
69
|
-
<
|
|
60
|
+
<kc-text-shimmer text="Generating response…" duration={2} spread={35} />
|
|
70
61
|
</div>
|
|
71
62
|
),
|
|
72
63
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineWebComponent } from './define';
|
|
2
2
|
import { TextShimmer } from '../components/text-shimmer';
|
|
3
3
|
|
|
4
4
|
interface Props extends Record<string, unknown> {
|
|
@@ -13,10 +13,10 @@ interface Props extends Record<string, unknown> {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
* `<
|
|
16
|
+
* `<kc-text-shimmer>` — animated shimmering text. Text via the `text`
|
|
17
17
|
* attribute; `duration`/`spread` tune the effect.
|
|
18
18
|
*/
|
|
19
|
-
|
|
19
|
+
defineWebComponent<Props>('kc-text-shimmer', {
|
|
20
20
|
text: '',
|
|
21
21
|
as: 'span',
|
|
22
22
|
duration: 4,
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from 'storybook-solidjs-vite';
|
|
2
2
|
import './register'; // side effect: registers the custom elements
|
|
3
|
-
import {
|
|
4
|
-
import { argTypesFor } from '../stories/docs/element-controls';
|
|
3
|
+
import { argTypesFor, specDescription } from '../stories/docs/element-controls';
|
|
5
4
|
|
|
6
5
|
// The web components are custom DOM elements, so declare the tags for JSX.
|
|
7
6
|
declare module 'solid-js' {
|
|
8
7
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
9
8
|
namespace JSX {
|
|
10
9
|
interface IntrinsicElements {
|
|
11
|
-
'
|
|
10
|
+
'kc-thinking-bar': JSX.HTMLAttributes<HTMLElement> & {
|
|
12
11
|
text?: string;
|
|
13
12
|
stoppable?: boolean | string;
|
|
14
13
|
'stop-label'?: string;
|
|
@@ -19,30 +18,28 @@ declare module 'solid-js' {
|
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
|
|
22
|
-
<
|
|
21
|
+
<kc-thinking-bar text="Thinking" stoppable stop-label="Answer now"></kc-thinking-bar>
|
|
23
22
|
|
|
24
23
|
<script type="module">
|
|
25
24
|
import '@kitnai/chat/elements'; // registers the custom elements
|
|
26
25
|
|
|
27
|
-
document.querySelector('
|
|
26
|
+
document.querySelector('kc-thinking-bar')
|
|
28
27
|
.addEventListener('stop', () => console.log('user asked to stop'));
|
|
29
28
|
</script>`;
|
|
30
29
|
|
|
31
30
|
const meta = {
|
|
32
|
-
title: 'Web Components/
|
|
31
|
+
title: 'Web Components/kc-thinking-bar',
|
|
33
32
|
tags: ['autodocs'],
|
|
34
|
-
argTypes: argTypesFor('
|
|
33
|
+
argTypes: argTypesFor('kc-thinking-bar'),
|
|
35
34
|
parameters: {
|
|
36
35
|
layout: 'fullscreen',
|
|
37
36
|
docs: {
|
|
38
|
-
description:
|
|
39
|
-
|
|
40
|
-
'`<kitn-thinking-bar>` is the framework-agnostic **web component** for an animated "thinking" indicator with an optional stop affordance — a pure leaf element isolated in **Shadow DOM**. (`<kitn-chat>` does not surface this; compose it yourself.)',
|
|
37
|
+
description: specDescription('kc-thinking-bar', [
|
|
38
|
+
'`<kc-thinking-bar>` is the framework-agnostic **web component** for an animated "thinking" indicator with an optional stop affordance — a pure leaf element isolated in **Shadow DOM**. (`<kc-chat>` does not surface this; compose it yourself.)',
|
|
41
39
|
'**When to use:** showing that the assistant is reasoning, optionally letting the user interrupt with "Answer now". In SolidJS, use the `ThinkingBar` primitive.',
|
|
42
40
|
"**How to use:** register once with `import '@kitnai/chat/elements'`, set the `text`/`stop-label` attributes, add the `stoppable` flag to show the stop button, and listen for the `stop` **CustomEvent**.",
|
|
43
41
|
'See the **Code** tab for HTML usage.',
|
|
44
|
-
]
|
|
45
|
-
},
|
|
42
|
+
]),
|
|
46
43
|
},
|
|
47
44
|
},
|
|
48
45
|
} satisfies Meta;
|
|
@@ -50,17 +47,11 @@ const meta = {
|
|
|
50
47
|
export default meta;
|
|
51
48
|
type Story = StoryObj;
|
|
52
49
|
|
|
53
|
-
/** Full generated API reference — properties, events, tokens, and composed-from. */
|
|
54
|
-
export const API: Story = {
|
|
55
|
-
render: () => <ElementSpec tag="kitn-thinking-bar" />,
|
|
56
|
-
parameters: { layout: 'padded' },
|
|
57
|
-
};
|
|
58
|
-
|
|
59
50
|
/** A plain thinking indicator. */
|
|
60
51
|
export const Default: Story = {
|
|
61
52
|
render: () => (
|
|
62
53
|
<div style={{ padding: '24px' }}>
|
|
63
|
-
<
|
|
54
|
+
<kc-thinking-bar text="Thinking" />
|
|
64
55
|
</div>
|
|
65
56
|
),
|
|
66
57
|
parameters: { docs: { source: { code: HTML_SNIPPET, language: 'html' } } },
|
|
@@ -70,7 +61,7 @@ export const Default: Story = {
|
|
|
70
61
|
export const Stoppable: Story = {
|
|
71
62
|
render: () => (
|
|
72
63
|
<div style={{ padding: '24px' }}>
|
|
73
|
-
<
|
|
64
|
+
<kc-thinking-bar
|
|
74
65
|
text="Reasoning"
|
|
75
66
|
stoppable
|
|
76
67
|
stop-label="Answer now"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineWebComponent } from './define';
|
|
2
2
|
import { ThinkingBar } from '../components/thinking-bar';
|
|
3
3
|
|
|
4
4
|
interface Props extends Record<string, unknown> {
|
|
@@ -10,18 +10,18 @@ interface Props extends Record<string, unknown> {
|
|
|
10
10
|
stopLabel?: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
/** Events fired by `<
|
|
13
|
+
/** Events fired by `<kc-thinking-bar>`. */
|
|
14
14
|
interface Events {
|
|
15
15
|
/** The "stop / answer now" affordance was clicked. */
|
|
16
16
|
stop: void;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* `<
|
|
21
|
-
* (one of the primitives the batteries-included `<
|
|
20
|
+
* `<kc-thinking-bar>` — a pure leaf element: an animated "thinking" indicator
|
|
21
|
+
* (one of the primitives the batteries-included `<kc-chat>` does NOT surface).
|
|
22
22
|
* Config via attributes, the only interaction (`stop`) comes back as an event.
|
|
23
23
|
*/
|
|
24
|
-
|
|
24
|
+
defineWebComponent<Props, Events>('kc-thinking-bar', {
|
|
25
25
|
text: 'Thinking',
|
|
26
26
|
stoppable: false,
|
|
27
27
|
stopLabel: 'Answer now',
|