@kitnai/chat 0.1.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.
Files changed (138) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +314 -0
  3. package/dist/bash-InADTalH.js +6 -0
  4. package/dist/core-AYMC6_lb.js +5874 -0
  5. package/dist/engine-javascript-vq0WuIJl.js +2643 -0
  6. package/dist/github-dark-dimmed-DUshB20C.js +4 -0
  7. package/dist/github-light-JYsPkUQd.js +4 -0
  8. package/dist/javascript-C25yR2R2.js +6 -0
  9. package/dist/json-DxJze_jm.js +6 -0
  10. package/dist/kitn-chat.es.js +6632 -0
  11. package/dist/tsx-B8rCNbgL.js +6 -0
  12. package/dist/typescript-RycA9KXf.js +6 -0
  13. package/package.json +80 -0
  14. package/src/components/attachments.stories.tsx +304 -0
  15. package/src/components/attachments.tsx +394 -0
  16. package/src/components/chain-of-thought.stories.tsx +212 -0
  17. package/src/components/chain-of-thought.tsx +139 -0
  18. package/src/components/chat-container.stories.tsx +188 -0
  19. package/src/components/chat-container.tsx +78 -0
  20. package/src/components/chat-scope-picker.tsx +47 -0
  21. package/src/components/checkpoint.stories.tsx +103 -0
  22. package/src/components/checkpoint.tsx +81 -0
  23. package/src/components/code-block.stories.tsx +151 -0
  24. package/src/components/code-block.tsx +99 -0
  25. package/src/components/context.stories.tsx +180 -0
  26. package/src/components/context.tsx +323 -0
  27. package/src/components/conversation-item.stories.tsx +126 -0
  28. package/src/components/conversation-item.tsx +18 -0
  29. package/src/components/conversation-list.stories.tsx +134 -0
  30. package/src/components/conversation-list.tsx +100 -0
  31. package/src/components/empty.stories.tsx +435 -0
  32. package/src/components/empty.tsx +166 -0
  33. package/src/components/feedback-bar.stories.tsx +101 -0
  34. package/src/components/feedback-bar.tsx +58 -0
  35. package/src/components/file-upload.stories.tsx +157 -0
  36. package/src/components/file-upload.tsx +161 -0
  37. package/src/components/image.stories.tsx +90 -0
  38. package/src/components/image.tsx +67 -0
  39. package/src/components/loader.stories.tsx +182 -0
  40. package/src/components/loader.tsx +333 -0
  41. package/src/components/markdown.stories.tsx +181 -0
  42. package/src/components/markdown.tsx +81 -0
  43. package/src/components/message-narrow.stories.tsx +330 -0
  44. package/src/components/message-skills.stories.tsx +212 -0
  45. package/src/components/message-skills.tsx +36 -0
  46. package/src/components/message.stories.tsx +282 -0
  47. package/src/components/message.tsx +149 -0
  48. package/src/components/model-switcher.stories.tsx +98 -0
  49. package/src/components/model-switcher.tsx +36 -0
  50. package/src/components/prompt-input.stories.tsx +223 -0
  51. package/src/components/prompt-input.tsx +190 -0
  52. package/src/components/prompt-suggestion.stories.tsx +143 -0
  53. package/src/components/prompt-suggestion.tsx +115 -0
  54. package/src/components/reasoning.stories.tsx +141 -0
  55. package/src/components/reasoning.tsx +157 -0
  56. package/src/components/response-stream.tsx +103 -0
  57. package/src/components/scroll-button.stories.tsx +101 -0
  58. package/src/components/scroll-button.tsx +33 -0
  59. package/src/components/slash-command.stories.tsx +164 -0
  60. package/src/components/slash-command.tsx +223 -0
  61. package/src/components/source.stories.tsx +125 -0
  62. package/src/components/source.tsx +129 -0
  63. package/src/components/text-shimmer.stories.tsx +88 -0
  64. package/src/components/text-shimmer.tsx +37 -0
  65. package/src/components/thinking-bar.stories.tsx +88 -0
  66. package/src/components/thinking-bar.tsx +50 -0
  67. package/src/components/tool.stories.tsx +154 -0
  68. package/src/components/tool.tsx +173 -0
  69. package/src/components/voice-input.stories.tsx +84 -0
  70. package/src/components/voice-input.tsx +103 -0
  71. package/src/elements/chat-types.ts +14 -0
  72. package/src/elements/chat.tsx +111 -0
  73. package/src/elements/compiled.css +2 -0
  74. package/src/elements/conversation-list.tsx +26 -0
  75. package/src/elements/css.ts +5 -0
  76. package/src/elements/default-input.tsx +53 -0
  77. package/src/elements/define.tsx +54 -0
  78. package/src/elements/kitn-chat.stories.tsx +105 -0
  79. package/src/elements/kitn-conversation-list.stories.tsx +177 -0
  80. package/src/elements/kitn-prompt-input.stories.tsx +123 -0
  81. package/src/elements/prompt-input.tsx +39 -0
  82. package/src/elements/register.ts +9 -0
  83. package/src/elements/styles.css +12 -0
  84. package/src/index.ts +128 -0
  85. package/src/primitives/chat-config.tsx +76 -0
  86. package/src/primitives/highlighter.ts +150 -0
  87. package/src/primitives/use-auto-resize.ts +31 -0
  88. package/src/primitives/use-stick-to-bottom.ts +43 -0
  89. package/src/primitives/use-text-stream.ts +112 -0
  90. package/src/primitives/use-voice-recorder.ts +50 -0
  91. package/src/stories/chat-panel-layout.stories.tsx +144 -0
  92. package/src/stories/chat-scene.tsx +570 -0
  93. package/src/stories/checkpoint-restore.stories.tsx +224 -0
  94. package/src/stories/context-usage.stories.tsx +155 -0
  95. package/src/stories/conversation-with-reasoning.stories.tsx +151 -0
  96. package/src/stories/conversation-with-sources.stories.tsx +165 -0
  97. package/src/stories/docs/GettingStarted.mdx +76 -0
  98. package/src/stories/docs/Installation.mdx +48 -0
  99. package/src/stories/docs/Integrations.mdx +110 -0
  100. package/src/stories/docs/Introduction.mdx +29 -0
  101. package/src/stories/docs/Theming.mdx +87 -0
  102. package/src/stories/docs/theme-editor/canvas.tsx +32 -0
  103. package/src/stories/docs/theme-editor/inspector.tsx +66 -0
  104. package/src/stories/docs/theme-editor/presets.test.ts +32 -0
  105. package/src/stories/docs/theme-editor/presets.ts +64 -0
  106. package/src/stories/docs/theme-editor/theme-css.test.ts +19 -0
  107. package/src/stories/docs/theme-editor/theme-css.ts +15 -0
  108. package/src/stories/docs/theme-editor/theme-editor.tsx +145 -0
  109. package/src/stories/docs/theme-tokens.tsx +174 -0
  110. package/src/stories/full-chat.stories.tsx +18 -0
  111. package/src/stories/message-actions.stories.tsx +167 -0
  112. package/src/stories/prompt-input-variants.stories.tsx +179 -0
  113. package/src/stories/streaming-response.stories.tsx +234 -0
  114. package/src/stories/theme-editor.stories.tsx +16 -0
  115. package/src/stories/token-reference.stories.tsx +18 -0
  116. package/src/types.ts +41 -0
  117. package/src/ui/avatar.stories.tsx +104 -0
  118. package/src/ui/avatar.tsx +23 -0
  119. package/src/ui/badge.stories.tsx +87 -0
  120. package/src/ui/badge.tsx +21 -0
  121. package/src/ui/button.stories.tsx +146 -0
  122. package/src/ui/button.tsx +37 -0
  123. package/src/ui/collapsible.tsx +14 -0
  124. package/src/ui/dialog.tsx +21 -0
  125. package/src/ui/dropdown.tsx +26 -0
  126. package/src/ui/hover-card.tsx +48 -0
  127. package/src/ui/resizable.stories.tsx +171 -0
  128. package/src/ui/resizable.tsx +219 -0
  129. package/src/ui/scroll-area.tsx +13 -0
  130. package/src/ui/separator.stories.tsx +82 -0
  131. package/src/ui/separator.tsx +10 -0
  132. package/src/ui/skeleton.stories.tsx +338 -0
  133. package/src/ui/skeleton.tsx +16 -0
  134. package/src/ui/textarea.tsx +21 -0
  135. package/src/ui/tooltip.stories.tsx +75 -0
  136. package/src/ui/tooltip.tsx +22 -0
  137. package/src/utils/cn.ts +6 -0
  138. package/theme.css +115 -0
@@ -0,0 +1,21 @@
1
+ import { type JSX, splitProps } from 'solid-js';
2
+ import { cn } from '../utils/cn';
3
+ import { useAutoResize } from '../primitives/use-auto-resize';
4
+
5
+ export interface TextareaProps extends JSX.TextareaHTMLAttributes<HTMLTextAreaElement> {
6
+ maxHeight?: number;
7
+ autoResize?: boolean;
8
+ }
9
+
10
+ export function Textarea(props: TextareaProps) {
11
+ const [local, rest] = splitProps(props, ['class', 'maxHeight', 'autoResize']);
12
+ const { ref } = useAutoResize({ maxHeight: local.maxHeight });
13
+ return (
14
+ <textarea
15
+ ref={local.autoResize !== false ? ref : undefined}
16
+ class={cn('w-full resize-none bg-transparent text-sm text-foreground placeholder:text-muted-foreground focus:outline-none', local.class)}
17
+ rows={1}
18
+ {...rest}
19
+ />
20
+ );
21
+ }
@@ -0,0 +1,75 @@
1
+ import type { Meta, StoryObj } from 'storybook-solidjs-vite';
2
+ import { Tooltip } from './tooltip';
3
+ import { Button } from './button';
4
+
5
+ const meta = {
6
+ title: 'UI/Tooltip',
7
+ component: Tooltip,
8
+ tags: ['autodocs'],
9
+ parameters: {
10
+ layout: 'padded',
11
+ docs: {
12
+ description: {
13
+ component: [
14
+ 'A small floating label that appears on hover/focus of its trigger element, built on Kobalte `Tooltip` with an arrow.',
15
+ '**When to use:** to clarify the purpose of icon-only buttons or terse controls — short, supplementary hints that are not essential to complete the action.',
16
+ '**How to use:** wrap a single interactive `children` element and set `content` to the hint text. The child becomes the trigger.',
17
+ '**Placement:** toolbars, message action rows, and any compact icon control where a label would not otherwise fit.',
18
+ ].join('\n\n'),
19
+ },
20
+ controls: { exclude: ['use:eventListener'] },
21
+ },
22
+ },
23
+ argTypes: {
24
+ content: {
25
+ control: 'text',
26
+ description: 'Text shown inside the tooltip bubble.',
27
+ },
28
+ children: {
29
+ control: false,
30
+ description: 'The trigger element the tooltip is attached to.',
31
+ },
32
+ class: {
33
+ control: 'text',
34
+ description: 'Extra classes applied to the tooltip content bubble.',
35
+ },
36
+ },
37
+ args: {
38
+ content: 'This is a tooltip',
39
+ children: <Button variant="outline">Hover me</Button>,
40
+ },
41
+ render: (args) => <Tooltip {...args} />,
42
+ } satisfies Meta<typeof Tooltip>;
43
+
44
+ export default meta;
45
+ type Story = StoryObj<typeof meta>;
46
+
47
+ const IMPORT = `import { Tooltip } from '@kitnai/chat';`;
48
+ const src = (code: string) => ({
49
+ parameters: { docs: { source: { code: `${IMPORT}\n\n${code}`, language: 'tsx' } } },
50
+ });
51
+
52
+ /** Interactive playground — set the tooltip text and hover the trigger. */
53
+ export const Playground: Story = {
54
+ ...src(`<Tooltip content="This is a tooltip">
55
+ <Button variant="outline">Hover me</Button>
56
+ </Tooltip>`),
57
+ };
58
+
59
+ export const OnIconButton: Story = {
60
+ render: () => (
61
+ <Tooltip content="Add new item">
62
+ <Button variant="ghost" size="icon-sm">
63
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
64
+ <line x1="12" y1="5" x2="12" y2="19" />
65
+ <line x1="5" y1="12" x2="19" y2="12" />
66
+ </svg>
67
+ </Button>
68
+ </Tooltip>
69
+ ),
70
+ ...src(`<Tooltip content="Add new item">
71
+ <Button variant="ghost" size="icon-sm">
72
+ <PlusIcon />
73
+ </Button>
74
+ </Tooltip>`),
75
+ };
@@ -0,0 +1,22 @@
1
+ import { Tooltip as KTooltip } from '@kobalte/core/tooltip';
2
+ import { type JSX, splitProps } from 'solid-js';
3
+ import { cn } from '../utils/cn';
4
+ import { useChatConfig } from '../primitives/chat-config';
5
+
6
+ export interface TooltipProps { content: string; children: JSX.Element; class?: string; }
7
+
8
+ export function Tooltip(props: TooltipProps) {
9
+ const [local] = splitProps(props, ['content', 'children', 'class']);
10
+ const config = useChatConfig();
11
+ return (
12
+ <KTooltip>
13
+ <KTooltip.Trigger as="span">{local.children}</KTooltip.Trigger>
14
+ <KTooltip.Portal mount={config.portalMount()}>
15
+ <KTooltip.Content class={cn('z-50 rounded-md bg-foreground px-2.5 py-1 text-xs text-background shadow-md animate-in fade-in-0 zoom-in-95', local.class)}>
16
+ <KTooltip.Arrow />
17
+ {local.content}
18
+ </KTooltip.Content>
19
+ </KTooltip.Portal>
20
+ </KTooltip>
21
+ );
22
+ }
@@ -0,0 +1,6 @@
1
+ import { clsx, type ClassValue } from 'clsx';
2
+ import { twMerge } from 'tailwind-merge';
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+ }
package/theme.css ADDED
@@ -0,0 +1,115 @@
1
+ /* @kitnai/chat design system — import after `@import "tailwindcss"`.
2
+ Defines ONLY namespaced (--color-*) tokens, component keyframes, animation
3
+ utilities, and the .chat-markdown styles. Contains NO global base/reset rules,
4
+ so importing it restyles nothing on its own — a host opts in via the kit's
5
+ components + classes. Rebrand by overriding the --color-* values (optionally
6
+ scoped to a subtree). */
7
+ @import "tw-animate-css";
8
+
9
+ @custom-variant dark (&:is(.dark *));
10
+
11
+ @theme {
12
+ --color-background: hsl(0 0% 100%);
13
+ --color-foreground: hsl(240 10% 3.9%);
14
+ --color-card: hsl(0 0% 100%);
15
+ --color-card-foreground: hsl(240 10% 3.9%);
16
+ --color-popover: hsl(0 0% 100%);
17
+ --color-popover-foreground: hsl(240 10% 3.9%);
18
+ --color-primary: hsl(240 5.9% 10%);
19
+ --color-primary-foreground: hsl(0 0% 98%);
20
+ --color-secondary: hsl(240 4.8% 95.9%);
21
+ --color-secondary-foreground: hsl(240 5.9% 10%);
22
+ --color-muted: hsl(240 4.8% 95.9%);
23
+ --color-muted-foreground: hsl(240 3.8% 46.1%);
24
+ --color-accent: hsl(240 4.8% 95.9%);
25
+ --color-accent-foreground: hsl(240 5.9% 10%);
26
+ --color-destructive: hsl(0 84.2% 60.2%);
27
+ --color-destructive-foreground: hsl(0 0% 98%);
28
+ --color-border: hsl(240 5.9% 90%);
29
+ --color-input: hsl(240 5.9% 90%);
30
+ --color-ring: hsl(240 10% 3.9%);
31
+ --color-sidebar: hsl(0 0% 100%);
32
+
33
+ /* Inline `code` accent. Blue text on a translucent blue chip. */
34
+ --color-code-foreground: hsl(224.3 76.3% 48%);
35
+
36
+ --radius: 0.6rem;
37
+ --radius-sm: calc(var(--radius) - 4px);
38
+ --radius-md: calc(var(--radius) - 2px);
39
+ --radius-lg: var(--radius);
40
+ --radius-xl: calc(var(--radius) + 4px);
41
+
42
+ @keyframes typing { 0%,100% { transform: translateY(0); opacity: .5 } 50% { transform: translateY(-2px); opacity: 1 } }
43
+ @keyframes loading-dots { 0%,100% { opacity: 0 } 50% { opacity: 1 } }
44
+ @keyframes wave { 0%,100% { transform: scaleY(1) } 50% { transform: scaleY(.6) } }
45
+ @keyframes blink { 0%,100% { opacity: 1 } 50% { opacity: 0 } }
46
+ @keyframes text-blink { 0%,100% { color: var(--color-primary) } 50% { color: var(--color-muted-foreground) } }
47
+ @keyframes bounce-dots { 0%,100% { transform: scale(.8); opacity: .5 } 50% { transform: scale(1.2); opacity: 1 } }
48
+ @keyframes thin-pulse { 0%,100% { transform: scale(.95); opacity: .8 } 50% { transform: scale(1.05); opacity: .4 } }
49
+ @keyframes pulse-dot { 0%,100% { transform: scale(1); opacity: .8 } 50% { transform: scale(1.5); opacity: 1 } }
50
+ @keyframes shimmer-text { 0% { background-position: 150% center } 100% { background-position: -150% center } }
51
+ @keyframes wave-bars { 0%,100% { transform: scaleY(1); opacity: .5 } 50% { transform: scaleY(.6); opacity: 1 } }
52
+ @keyframes shimmer { 0% { background-position: 200% 50% } 100% { background-position: -200% 50% } }
53
+ @keyframes spinner-fade { 0% { opacity: 0 } 100% { opacity: 1 } }
54
+ @keyframes collapsible-down { from { height: 0; opacity: 0 } to { height: var(--kb-collapsible-content-height); opacity: 1 } }
55
+ @keyframes collapsible-up { from { height: var(--kb-collapsible-content-height); opacity: 1 } to { height: 0; opacity: 0 } }
56
+ }
57
+
58
+ .dark {
59
+ --color-background: hsl(50 2% 9%);
60
+ --color-foreground: hsl(0 0% 98%);
61
+ --color-card: hsl(240 10% 3.9%);
62
+ --color-card-foreground: hsl(0 0% 98%);
63
+ --color-popover: hsl(240 10% 3.9%);
64
+ --color-popover-foreground: hsl(0 0% 98%);
65
+ --color-primary: hsl(0 0% 98%);
66
+ --color-primary-foreground: hsl(240 5.9% 10%);
67
+ --color-secondary: hsl(240 3.7% 15.9%);
68
+ --color-secondary-foreground: hsl(0 0% 98%);
69
+ --color-muted: hsl(240 3.7% 15.9%);
70
+ --color-muted-foreground: hsl(240 5% 64.9%);
71
+ --color-accent: hsl(240 3.7% 15.9%);
72
+ --color-accent-foreground: hsl(0 0% 98%);
73
+ --color-destructive: hsl(0 62.8% 30.6%);
74
+ --color-destructive-foreground: hsl(0 0% 98%);
75
+ --color-border: hsl(240 3.7% 15.9%);
76
+ --color-input: hsl(240 3.7% 15.9%);
77
+ --color-ring: hsl(240 4.9% 83.9%);
78
+ --color-sidebar: hsl(50 2% 7%);
79
+ --color-code-foreground: hsl(213 94% 78%);
80
+ }
81
+
82
+ /* Self-contained markdown styling — replaces the typography plugin's `prose`.
83
+ Keyed on --color-* tokens so it themes with the rest of the kit. */
84
+ .chat-markdown { color: var(--color-foreground); line-height: 1.6; }
85
+ .chat-markdown > div:first-child > :first-child { margin-top: 0; }
86
+ .chat-markdown > div:last-child > :last-child { margin-bottom: 0; }
87
+ .chat-markdown p { margin: 0 0 0.75em; }
88
+ .chat-markdown p:last-child { margin-bottom: 0; }
89
+ .chat-markdown h1, .chat-markdown h2, .chat-markdown h3, .chat-markdown h4 {
90
+ margin: 1.2em 0 0.5em; font-weight: 600; line-height: 1.3; color: var(--color-foreground);
91
+ }
92
+ .chat-markdown h1 { font-size: 1.4em; } .chat-markdown h2 { font-size: 1.25em; }
93
+ .chat-markdown h3 { font-size: 1.1em; } .chat-markdown h4 { font-size: 1em; }
94
+ .chat-markdown ul, .chat-markdown ol { margin: 0 0 0.75em; padding-left: 1.4em; }
95
+ .chat-markdown li { margin: 0.2em 0; }
96
+ .chat-markdown ul { list-style: disc; } .chat-markdown ol { list-style: decimal; }
97
+ .chat-markdown a { color: var(--color-primary); text-decoration: underline; text-underline-offset: 2px; }
98
+ .chat-markdown strong { font-weight: 600; color: var(--color-foreground); }
99
+ .chat-markdown em { font-style: italic; }
100
+ .chat-markdown blockquote {
101
+ margin: 0 0 0.75em; padding-left: 0.9em; border-left: 2px solid var(--color-border);
102
+ color: var(--color-muted-foreground);
103
+ }
104
+ .chat-markdown hr { margin: 1em 0; border: 0; border-top: 1px solid var(--color-border); }
105
+ .chat-markdown code:not(pre code) {
106
+ background: color-mix(in oklab, var(--color-code-foreground) 15%, transparent);
107
+ color: var(--color-code-foreground);
108
+ border-radius: 4px; padding: 0.1em 0.35em; font-size: 0.875em;
109
+ font-family: ui-monospace, "SF Mono", Menlo, monospace;
110
+ }
111
+ .chat-markdown table { width: 100%; border-collapse: collapse; margin: 0 0 0.75em; font-size: 0.9em; }
112
+ .chat-markdown th, .chat-markdown td { border: 1px solid var(--color-border); padding: 0.4em 0.6em; text-align: left; }
113
+ .chat-markdown th { font-weight: 600; background: color-mix(in oklab, var(--color-muted-foreground) 8%, transparent); }
114
+
115
+ .scrollbar-thin { scrollbar-width: thin; scrollbar-color: var(--color-muted) transparent; }