@vvedantb/ui 0.1.1 → 0.1.3

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 (74) hide show
  1. package/LICENSE +21 -21
  2. package/package.json +3 -2
  3. package/src/ai-elements/artifact.tsx +99 -99
  4. package/src/ai-elements/attachments.tsx +366 -366
  5. package/src/ai-elements/chain-of-thought.tsx +212 -212
  6. package/src/ai-elements/code-block.tsx +478 -478
  7. package/src/ai-elements/conversation.tsx +157 -157
  8. package/src/ai-elements/image.tsx +25 -25
  9. package/src/ai-elements/inline-citation.tsx +252 -252
  10. package/src/ai-elements/message.tsx +269 -269
  11. package/src/ai-elements/model-selector.tsx +211 -211
  12. package/src/ai-elements/prompt-input.tsx +1018 -1018
  13. package/src/ai-elements/queue.tsx +251 -251
  14. package/src/ai-elements/reasoning.tsx +178 -178
  15. package/src/ai-elements/shimmer.tsx +56 -56
  16. package/src/ai-elements/sources.tsx +77 -77
  17. package/src/ai-elements/speech-input.tsx +290 -290
  18. package/src/ai-elements/suggestion.tsx +191 -191
  19. package/src/css.d.ts +2 -2
  20. package/src/index.ts +96 -96
  21. package/src/motion/presets.ts +35 -35
  22. package/src/motion/presets.vibot.ts +105 -105
  23. package/src/ui/_menu-classes.ts +30 -30
  24. package/src/ui/_menu-classes.vibot.ts +33 -33
  25. package/src/ui/accordion.tsx +81 -81
  26. package/src/ui/accordion.verve.tsx +56 -56
  27. package/src/ui/badge.tsx +34 -34
  28. package/src/ui/breadcrumb.tsx +83 -83
  29. package/src/ui/button-group.tsx +84 -84
  30. package/src/ui/button.tsx +57 -57
  31. package/src/ui/card.tsx +27 -27
  32. package/src/ui/carousel.tsx +211 -211
  33. package/src/ui/checkbox.tsx +27 -27
  34. package/src/ui/clear-input.tsx +170 -170
  35. package/src/ui/clear-input.vibot.tsx +76 -76
  36. package/src/ui/clearInputDissolve.ts +214 -214
  37. package/src/ui/collapsible.tsx +7 -7
  38. package/src/ui/command.tsx +148 -148
  39. package/src/ui/context-menu.tsx +173 -173
  40. package/src/ui/dialog.tsx +149 -149
  41. package/src/ui/dropdown-menu.tsx +178 -178
  42. package/src/ui/hover-card.tsx +31 -31
  43. package/src/ui/input-group.tsx +162 -162
  44. package/src/ui/input-group.verve.tsx +150 -150
  45. package/src/ui/input.tsx +21 -21
  46. package/src/ui/kbd.tsx +18 -18
  47. package/src/ui/label.tsx +20 -20
  48. package/src/ui/labeled-switch-row.tsx +53 -53
  49. package/src/ui/modalTransition.ts +85 -85
  50. package/src/ui/pagination.tsx +47 -47
  51. package/src/ui/popover.tsx +33 -33
  52. package/src/ui/progress.tsx +25 -25
  53. package/src/ui/radix-select.tsx +202 -202
  54. package/src/ui/scroll-area.tsx +55 -55
  55. package/src/ui/scroll-area.verve.tsx +43 -43
  56. package/src/ui/search-input.tsx +29 -29
  57. package/src/ui/select.tsx +163 -163
  58. package/src/ui/separator.tsx +28 -28
  59. package/src/ui/sheet.tsx +100 -87
  60. package/src/ui/skeleton.tsx +18 -18
  61. package/src/ui/sonner.css +16 -16
  62. package/src/ui/sonner.tsx +47 -47
  63. package/src/ui/spinner.tsx +27 -27
  64. package/src/ui/surface-classes.ts +55 -55
  65. package/src/ui/switch.tsx +26 -26
  66. package/src/ui/table.tsx +123 -123
  67. package/src/ui/tabs.tsx +140 -140
  68. package/src/ui/tabsSliding.ts +56 -56
  69. package/src/ui/textarea.tsx +21 -21
  70. package/src/ui/time-picker.tsx +170 -170
  71. package/src/ui/tooltip.tsx +25 -25
  72. package/src/ui/visually-hidden.tsx +3 -3
  73. package/src/utils/cn.ts +16 -16
  74. package/src/utils/ref.ts +10 -10
@@ -1,251 +1,251 @@
1
- "use client";
2
-
3
- import { useState, type ReactNode } from "react";
4
- import { motion, AnimatePresence } from "motion/react";
5
- import { cn } from "../utils/cn";
6
- import {
7
- flatPanelSubtleClass,
8
- flatPanelSubtleHoverClass,
9
- } from "../ui/surface-classes";
10
- import { Button } from "../ui/button";
11
- import { Badge } from "../ui/badge";
12
- import { ScrollArea } from "../ui/scroll-area";
13
- import { Textarea } from "../ui/textarea";
14
- import {
15
- IconChevronDown,
16
- IconEdit,
17
- IconTrash,
18
- IconCheck,
19
- IconX,
20
- IconStack2,
21
- } from "@tabler/icons-react";
22
-
23
- export interface QueueProps {
24
- className?: string;
25
- children?: ReactNode;
26
- count: number;
27
- }
28
-
29
- export function Queue({ className, children, count }: QueueProps) {
30
- return (
31
- <AnimatePresence initial={false}>
32
- {count > 0 ? (
33
- <motion.div
34
- key="queue"
35
- initial={{ height: 0, opacity: 0 }}
36
- animate={{ height: "auto", opacity: 1 }}
37
- exit={{ height: 0, opacity: 0 }}
38
- transition={{ type: "spring", bounce: 0, duration: 0.35 }}
39
- className={cn("w-full overflow-hidden", className)}
40
- >
41
- {children}
42
- </motion.div>
43
- ) : null}
44
- </AnimatePresence>
45
- );
46
- }
47
-
48
- export interface QueueHeaderProps {
49
- count: number;
50
- isOpen: boolean;
51
- onToggle: () => void;
52
- className?: string;
53
- }
54
-
55
- export function QueueHeader({
56
- count,
57
- isOpen,
58
- onToggle,
59
- className,
60
- }: QueueHeaderProps) {
61
- return (
62
- <button
63
- type="button"
64
- onClick={onToggle}
65
- className={cn(
66
- "flex items-center justify-between w-full",
67
- "px-4 py-2.5",
68
- flatPanelSubtleClass,
69
- flatPanelSubtleHoverClass,
70
- "rounded-t-2xl",
71
- "group",
72
- className,
73
- )}
74
- >
75
- <div className="flex items-center gap-2">
76
- <IconStack2 size={16} className="text-muted" />
77
- <span className="text-sm font-medium text-foreground">
78
- Queued Messages
79
- </span>
80
- <Badge variant="secondary" className="text-xs">
81
- {count}
82
- </Badge>
83
- </div>
84
- <IconChevronDown
85
- size={16}
86
- className={cn(
87
- "text-muted transition-transform duration-200 ease-out",
88
- isOpen && "rotate-180",
89
- )}
90
- />
91
- </button>
92
- );
93
- }
94
-
95
- export interface QueueListProps {
96
- className?: string;
97
- children?: ReactNode;
98
- open?: boolean;
99
- }
100
-
101
- export function QueueList({
102
- className,
103
- children,
104
- open = true,
105
- }: QueueListProps) {
106
- return (
107
- <AnimatePresence initial={false}>
108
- {open ? (
109
- <motion.div
110
- key="queue-list"
111
- initial={{ height: 0, opacity: 0 }}
112
- animate={{ height: "auto", opacity: 1 }}
113
- exit={{ height: 0, opacity: 0 }}
114
- transition={{ type: "spring", bounce: 0, duration: 0.35 }}
115
- className="overflow-hidden"
116
- >
117
- <div className={cn(flatPanelSubtleClass, "rounded-b-2xl", className)}>
118
- <ScrollArea className="max-h-[240px]">
119
- <div className="p-2 space-y-1.5">{children}</div>
120
- </ScrollArea>
121
- </div>
122
- </motion.div>
123
- ) : null}
124
- </AnimatePresence>
125
- );
126
- }
127
-
128
- export interface QueueItemProps {
129
- text: string;
130
- model?: string;
131
- personalityName?: string;
132
- personaName?: string;
133
- personaImage?: string;
134
- onEdit: (newText: string) => void;
135
- onRemove: () => void;
136
- className?: string;
137
- }
138
-
139
- export function QueueItem({
140
- text,
141
- model,
142
- personalityName,
143
- personaName,
144
- personaImage,
145
- onEdit,
146
- onRemove,
147
- className,
148
- }: QueueItemProps) {
149
- const [isEditing, setIsEditing] = useState(false);
150
- const [editText, setEditText] = useState(text);
151
-
152
- const handleSaveEdit = () => {
153
- if (editText.trim()) {
154
- onEdit(editText.trim());
155
- setIsEditing(false);
156
- }
157
- };
158
-
159
- const handleCancelEdit = () => {
160
- setEditText(text);
161
- setIsEditing(false);
162
- };
163
-
164
- return (
165
- <div
166
- className={cn(
167
- "group relative",
168
- "p-2.5 rounded-lg",
169
- "transition-[background-color,transform] duration-150 ease-out active:scale-[0.99] hover:bg-surface-secondary",
170
- className,
171
- )}
172
- >
173
- {isEditing ? (
174
- <div className="flex flex-col gap-2">
175
- <Textarea
176
- value={editText}
177
- onChange={(e) => setEditText(e.currentTarget.value)}
178
- className="min-h-[60px] text-sm"
179
- autoFocus
180
- />
181
- <div className="flex justify-end gap-2">
182
- <Button
183
- size="sm"
184
- variant="ghost"
185
- onClick={handleCancelEdit}
186
- className="h-7 px-2"
187
- >
188
- <IconX size={14} />
189
- <span className="ml-1 text-xs">Cancel</span>
190
- </Button>
191
- <Button
192
- size="sm"
193
- onClick={handleSaveEdit}
194
- disabled={!editText.trim()}
195
- className="h-7 px-2"
196
- >
197
- <IconCheck size={14} />
198
- <span className="ml-1 text-xs">Save</span>
199
- </Button>
200
- </div>
201
- </div>
202
- ) : (
203
- <div className="flex items-center gap-2">
204
- {personaImage && (
205
- <img
206
- src={personaImage}
207
- alt={personaName || "Persona"}
208
- className="size-5 rounded-full shrink-0"
209
- />
210
- )}
211
- <p className="text-sm text-foreground/90 flex-1 truncate">{text}</p>
212
- <div className="flex items-center gap-1.5 shrink-0">
213
- {model && (
214
- <Badge variant="outline" className="text-xs h-5 px-1.5">
215
- {model.split("/").pop()}
216
- </Badge>
217
- )}
218
- {personalityName && (
219
- <Badge variant="outline" className="text-xs h-5 px-1.5">
220
- {personalityName}
221
- </Badge>
222
- )}
223
- {personaName && !personaImage && (
224
- <Badge variant="outline" className="text-xs h-5 px-1.5">
225
- {personaName}
226
- </Badge>
227
- )}
228
- </div>
229
- <div className="flex items-center gap-1 shrink-0 opacity-0 group-hover:opacity-100 transition-opacity">
230
- <Button
231
- size="sm"
232
- variant="ghost"
233
- onClick={() => setIsEditing(true)}
234
- className="h-6 w-6 p-0"
235
- >
236
- <IconEdit size={13} />
237
- </Button>
238
- <Button
239
- size="sm"
240
- variant="ghost"
241
- onClick={onRemove}
242
- className="h-6 w-6 p-0 text-danger hover:text-danger"
243
- >
244
- <IconTrash size={13} />
245
- </Button>
246
- </div>
247
- </div>
248
- )}
249
- </div>
250
- );
251
- }
1
+ "use client";
2
+
3
+ import { useState, type ReactNode } from "react";
4
+ import { motion, AnimatePresence } from "motion/react";
5
+ import { cn } from "../utils/cn";
6
+ import {
7
+ flatPanelSubtleClass,
8
+ flatPanelSubtleHoverClass,
9
+ } from "../ui/surface-classes";
10
+ import { Button } from "../ui/button";
11
+ import { Badge } from "../ui/badge";
12
+ import { ScrollArea } from "../ui/scroll-area";
13
+ import { Textarea } from "../ui/textarea";
14
+ import {
15
+ IconChevronDown,
16
+ IconEdit,
17
+ IconTrash,
18
+ IconCheck,
19
+ IconX,
20
+ IconStack2,
21
+ } from "@tabler/icons-react";
22
+
23
+ export interface QueueProps {
24
+ className?: string;
25
+ children?: ReactNode;
26
+ count: number;
27
+ }
28
+
29
+ export function Queue({ className, children, count }: QueueProps) {
30
+ return (
31
+ <AnimatePresence initial={false}>
32
+ {count > 0 ? (
33
+ <motion.div
34
+ key="queue"
35
+ initial={{ height: 0, opacity: 0 }}
36
+ animate={{ height: "auto", opacity: 1 }}
37
+ exit={{ height: 0, opacity: 0 }}
38
+ transition={{ type: "spring", bounce: 0, duration: 0.35 }}
39
+ className={cn("w-full overflow-hidden", className)}
40
+ >
41
+ {children}
42
+ </motion.div>
43
+ ) : null}
44
+ </AnimatePresence>
45
+ );
46
+ }
47
+
48
+ export interface QueueHeaderProps {
49
+ count: number;
50
+ isOpen: boolean;
51
+ onToggle: () => void;
52
+ className?: string;
53
+ }
54
+
55
+ export function QueueHeader({
56
+ count,
57
+ isOpen,
58
+ onToggle,
59
+ className,
60
+ }: QueueHeaderProps) {
61
+ return (
62
+ <button
63
+ type="button"
64
+ onClick={onToggle}
65
+ className={cn(
66
+ "flex items-center justify-between w-full",
67
+ "px-4 py-2.5",
68
+ flatPanelSubtleClass,
69
+ flatPanelSubtleHoverClass,
70
+ "rounded-t-2xl",
71
+ "group",
72
+ className,
73
+ )}
74
+ >
75
+ <div className="flex items-center gap-2">
76
+ <IconStack2 size={16} className="text-muted" />
77
+ <span className="text-sm font-medium text-foreground">
78
+ Queued Messages
79
+ </span>
80
+ <Badge variant="secondary" className="text-xs">
81
+ {count}
82
+ </Badge>
83
+ </div>
84
+ <IconChevronDown
85
+ size={16}
86
+ className={cn(
87
+ "text-muted transition-transform duration-200 ease-out",
88
+ isOpen && "rotate-180",
89
+ )}
90
+ />
91
+ </button>
92
+ );
93
+ }
94
+
95
+ export interface QueueListProps {
96
+ className?: string;
97
+ children?: ReactNode;
98
+ open?: boolean;
99
+ }
100
+
101
+ export function QueueList({
102
+ className,
103
+ children,
104
+ open = true,
105
+ }: QueueListProps) {
106
+ return (
107
+ <AnimatePresence initial={false}>
108
+ {open ? (
109
+ <motion.div
110
+ key="queue-list"
111
+ initial={{ height: 0, opacity: 0 }}
112
+ animate={{ height: "auto", opacity: 1 }}
113
+ exit={{ height: 0, opacity: 0 }}
114
+ transition={{ type: "spring", bounce: 0, duration: 0.35 }}
115
+ className="overflow-hidden"
116
+ >
117
+ <div className={cn(flatPanelSubtleClass, "rounded-b-2xl", className)}>
118
+ <ScrollArea className="max-h-[240px]">
119
+ <div className="p-2 space-y-1.5">{children}</div>
120
+ </ScrollArea>
121
+ </div>
122
+ </motion.div>
123
+ ) : null}
124
+ </AnimatePresence>
125
+ );
126
+ }
127
+
128
+ export interface QueueItemProps {
129
+ text: string;
130
+ model?: string;
131
+ personalityName?: string;
132
+ personaName?: string;
133
+ personaImage?: string;
134
+ onEdit: (newText: string) => void;
135
+ onRemove: () => void;
136
+ className?: string;
137
+ }
138
+
139
+ export function QueueItem({
140
+ text,
141
+ model,
142
+ personalityName,
143
+ personaName,
144
+ personaImage,
145
+ onEdit,
146
+ onRemove,
147
+ className,
148
+ }: QueueItemProps) {
149
+ const [isEditing, setIsEditing] = useState(false);
150
+ const [editText, setEditText] = useState(text);
151
+
152
+ const handleSaveEdit = () => {
153
+ if (editText.trim()) {
154
+ onEdit(editText.trim());
155
+ setIsEditing(false);
156
+ }
157
+ };
158
+
159
+ const handleCancelEdit = () => {
160
+ setEditText(text);
161
+ setIsEditing(false);
162
+ };
163
+
164
+ return (
165
+ <div
166
+ className={cn(
167
+ "group relative",
168
+ "p-2.5 rounded-lg",
169
+ "transition-[background-color,transform] duration-150 ease-out active:scale-[0.99] hover:bg-surface-secondary",
170
+ className,
171
+ )}
172
+ >
173
+ {isEditing ? (
174
+ <div className="flex flex-col gap-2">
175
+ <Textarea
176
+ value={editText}
177
+ onChange={(e) => setEditText(e.currentTarget.value)}
178
+ className="min-h-[60px] text-sm"
179
+ autoFocus
180
+ />
181
+ <div className="flex justify-end gap-2">
182
+ <Button
183
+ size="sm"
184
+ variant="ghost"
185
+ onClick={handleCancelEdit}
186
+ className="h-7 px-2"
187
+ >
188
+ <IconX size={14} />
189
+ <span className="ml-1 text-xs">Cancel</span>
190
+ </Button>
191
+ <Button
192
+ size="sm"
193
+ onClick={handleSaveEdit}
194
+ disabled={!editText.trim()}
195
+ className="h-7 px-2"
196
+ >
197
+ <IconCheck size={14} />
198
+ <span className="ml-1 text-xs">Save</span>
199
+ </Button>
200
+ </div>
201
+ </div>
202
+ ) : (
203
+ <div className="flex items-center gap-2">
204
+ {personaImage && (
205
+ <img
206
+ src={personaImage}
207
+ alt={personaName || "Persona"}
208
+ className="size-5 rounded-full shrink-0"
209
+ />
210
+ )}
211
+ <p className="text-sm text-foreground/90 flex-1 truncate">{text}</p>
212
+ <div className="flex items-center gap-1.5 shrink-0">
213
+ {model && (
214
+ <Badge variant="outline" className="text-xs h-5 px-1.5">
215
+ {model.split("/").pop()}
216
+ </Badge>
217
+ )}
218
+ {personalityName && (
219
+ <Badge variant="outline" className="text-xs h-5 px-1.5">
220
+ {personalityName}
221
+ </Badge>
222
+ )}
223
+ {personaName && !personaImage && (
224
+ <Badge variant="outline" className="text-xs h-5 px-1.5">
225
+ {personaName}
226
+ </Badge>
227
+ )}
228
+ </div>
229
+ <div className="flex items-center gap-1 shrink-0 opacity-0 group-hover:opacity-100 transition-opacity">
230
+ <Button
231
+ size="sm"
232
+ variant="ghost"
233
+ onClick={() => setIsEditing(true)}
234
+ className="h-6 w-6 p-0"
235
+ >
236
+ <IconEdit size={13} />
237
+ </Button>
238
+ <Button
239
+ size="sm"
240
+ variant="ghost"
241
+ onClick={onRemove}
242
+ className="h-6 w-6 p-0 text-danger hover:text-danger"
243
+ >
244
+ <IconTrash size={13} />
245
+ </Button>
246
+ </div>
247
+ </div>
248
+ )}
249
+ </div>
250
+ );
251
+ }