@vvedantb/ui 0.1.1 → 0.1.2

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 +87 -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,157 +1,157 @@
1
- "use client";
2
- import type { ComponentProps } from "react";
3
- import { AnimatePresence, motion } from "motion/react";
4
- import { IconArrowDown, IconDownload } from "@tabler/icons-react";
5
- import { Button } from "../ui/button";
6
- import { cn } from "../utils/cn";
7
- import { flatInteractiveClass } from "../ui/surface-classes";
8
- import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
9
- import { fastTransition } from "../motion/presets.vibot";
10
- export type ConversationProps = ComponentProps<typeof StickToBottom>;
11
- export const Conversation = ({ className, ...props }: ConversationProps) => (
12
- <StickToBottom
13
- className={cn("relative flex-1 overflow-y-hidden", className)}
14
- initial="instant"
15
- resize="smooth"
16
- role="log"
17
- {...props}
18
- />
19
- );
20
- export type ConversationContentProps = ComponentProps<
21
- typeof StickToBottom.Content
22
- >;
23
- export const ConversationContent = ({
24
- className,
25
- ...props
26
- }: ConversationContentProps) => (
27
- <StickToBottom.Content
28
- className={cn("flex flex-col gap-4 px-3 py-3", className)}
29
- {...props}
30
- />
31
- );
32
- export type ConversationEmptyStateProps = ComponentProps<"div"> & {
33
- title?: string;
34
- description?: string;
35
- icon?: React.ReactNode;
36
- };
37
- export const ConversationEmptyState = ({
38
- className,
39
- title = "No messages yet",
40
- description = "Start a conversation to see messages here",
41
- icon,
42
- children,
43
- ...props
44
- }: ConversationEmptyStateProps) => (
45
- <div
46
- className={cn(
47
- "flex size-full flex-col items-center justify-center gap-3 p-8 text-center",
48
- className,
49
- )}
50
- {...props}
51
- >
52
- {children ?? (
53
- <>
54
- {icon && <div className="text-muted">{icon}</div>}
55
- <div className="space-y-1">
56
- <h3 className="font-medium text-sm">{title}</h3>
57
- {description && <p className="text-muted text-sm">{description}</p>}
58
- </div>
59
- </>
60
- )}
61
- </div>
62
- );
63
- export type ConversationScrollButtonProps = ComponentProps<typeof Button>;
64
- export const ConversationScrollButton = ({
65
- className,
66
- ...props
67
- }: ConversationScrollButtonProps) => {
68
- const { isAtBottom, scrollToBottom } = useStickToBottomContext();
69
- const handleScrollToBottom = () => {
70
- scrollToBottom();
71
- };
72
- return (
73
- <AnimatePresence initial={false}>
74
- {isAtBottom ? null : (
75
- <motion.div
76
- key="scroll-to-bottom"
77
- className="absolute bottom-4 left-0 right-0 z-10 flex justify-center"
78
- initial={{ opacity: 0, y: 8 }}
79
- animate={{ opacity: 1, y: 0 }}
80
- exit={{ opacity: 0, y: 8 }}
81
- transition={fastTransition}
82
- >
83
- <Button
84
- className={cn(flatInteractiveClass, "rounded-full", className)}
85
- onClick={handleScrollToBottom}
86
- size="icon"
87
- type="button"
88
- variant="outline"
89
- {...props}
90
- >
91
- <IconArrowDown className="size-4" />
92
- </Button>
93
- </motion.div>
94
- )}
95
- </AnimatePresence>
96
- );
97
- };
98
- export interface ConversationMessage {
99
- role: "user" | "assistant" | "system" | "data" | "tool";
100
- content: string;
101
- }
102
- export type ConversationDownloadProps = Omit<
103
- ComponentProps<typeof Button>,
104
- "onClick"
105
- > & {
106
- messages: ConversationMessage[];
107
- filename?: string;
108
- formatMessage?: (message: ConversationMessage, index: number) => string;
109
- };
110
- const defaultFormatMessage = (message: ConversationMessage): string => {
111
- const roleLabel =
112
- message.role.charAt(0).toUpperCase() + message.role.slice(1);
113
- return `**${roleLabel}:** ${message.content}`;
114
- };
115
- export const messagesToMarkdown = (
116
- messages: ConversationMessage[],
117
- formatMessage: (
118
- message: ConversationMessage,
119
- index: number,
120
- ) => string = defaultFormatMessage,
121
- ): string => messages.map((msg, i) => formatMessage(msg, i)).join("\n\n");
122
- export const ConversationDownload = ({
123
- messages,
124
- filename = "conversation.md",
125
- formatMessage = defaultFormatMessage,
126
- className,
127
- children,
128
- ...props
129
- }: ConversationDownloadProps) => {
130
- const handleDownload = () => {
131
- const markdown = messagesToMarkdown(messages, formatMessage);
132
- const blob = new Blob([markdown], { type: "text/markdown" });
133
- const url = URL.createObjectURL(blob);
134
- const link = document.createElement("a");
135
- link.href = url;
136
- link.download = filename;
137
- document.body.append(link);
138
- link.click();
139
- link.remove();
140
- URL.revokeObjectURL(url);
141
- };
142
- return (
143
- <Button
144
- className={cn(
145
- cn(flatInteractiveClass, "absolute top-4 right-4 rounded-full"),
146
- className,
147
- )}
148
- onClick={handleDownload}
149
- size="icon"
150
- type="button"
151
- variant="outline"
152
- {...props}
153
- >
154
- {children ?? <IconDownload className="size-4" />}
155
- </Button>
156
- );
157
- };
1
+ "use client";
2
+ import type { ComponentProps } from "react";
3
+ import { AnimatePresence, motion } from "motion/react";
4
+ import { IconArrowDown, IconDownload } from "@tabler/icons-react";
5
+ import { Button } from "../ui/button";
6
+ import { cn } from "../utils/cn";
7
+ import { flatInteractiveClass } from "../ui/surface-classes";
8
+ import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
9
+ import { fastTransition } from "../motion/presets.vibot";
10
+ export type ConversationProps = ComponentProps<typeof StickToBottom>;
11
+ export const Conversation = ({ className, ...props }: ConversationProps) => (
12
+ <StickToBottom
13
+ className={cn("relative flex-1 overflow-y-hidden", className)}
14
+ initial="instant"
15
+ resize="smooth"
16
+ role="log"
17
+ {...props}
18
+ />
19
+ );
20
+ export type ConversationContentProps = ComponentProps<
21
+ typeof StickToBottom.Content
22
+ >;
23
+ export const ConversationContent = ({
24
+ className,
25
+ ...props
26
+ }: ConversationContentProps) => (
27
+ <StickToBottom.Content
28
+ className={cn("flex flex-col gap-4 px-3 py-3", className)}
29
+ {...props}
30
+ />
31
+ );
32
+ export type ConversationEmptyStateProps = ComponentProps<"div"> & {
33
+ title?: string;
34
+ description?: string;
35
+ icon?: React.ReactNode;
36
+ };
37
+ export const ConversationEmptyState = ({
38
+ className,
39
+ title = "No messages yet",
40
+ description = "Start a conversation to see messages here",
41
+ icon,
42
+ children,
43
+ ...props
44
+ }: ConversationEmptyStateProps) => (
45
+ <div
46
+ className={cn(
47
+ "flex size-full flex-col items-center justify-center gap-3 p-8 text-center",
48
+ className,
49
+ )}
50
+ {...props}
51
+ >
52
+ {children ?? (
53
+ <>
54
+ {icon && <div className="text-muted">{icon}</div>}
55
+ <div className="space-y-1">
56
+ <h3 className="font-medium text-sm">{title}</h3>
57
+ {description && <p className="text-muted text-sm">{description}</p>}
58
+ </div>
59
+ </>
60
+ )}
61
+ </div>
62
+ );
63
+ export type ConversationScrollButtonProps = ComponentProps<typeof Button>;
64
+ export const ConversationScrollButton = ({
65
+ className,
66
+ ...props
67
+ }: ConversationScrollButtonProps) => {
68
+ const { isAtBottom, scrollToBottom } = useStickToBottomContext();
69
+ const handleScrollToBottom = () => {
70
+ scrollToBottom();
71
+ };
72
+ return (
73
+ <AnimatePresence initial={false}>
74
+ {isAtBottom ? null : (
75
+ <motion.div
76
+ key="scroll-to-bottom"
77
+ className="absolute bottom-4 left-0 right-0 z-10 flex justify-center"
78
+ initial={{ opacity: 0, y: 8 }}
79
+ animate={{ opacity: 1, y: 0 }}
80
+ exit={{ opacity: 0, y: 8 }}
81
+ transition={fastTransition}
82
+ >
83
+ <Button
84
+ className={cn(flatInteractiveClass, "rounded-full", className)}
85
+ onClick={handleScrollToBottom}
86
+ size="icon"
87
+ type="button"
88
+ variant="outline"
89
+ {...props}
90
+ >
91
+ <IconArrowDown className="size-4" />
92
+ </Button>
93
+ </motion.div>
94
+ )}
95
+ </AnimatePresence>
96
+ );
97
+ };
98
+ export interface ConversationMessage {
99
+ role: "user" | "assistant" | "system" | "data" | "tool";
100
+ content: string;
101
+ }
102
+ export type ConversationDownloadProps = Omit<
103
+ ComponentProps<typeof Button>,
104
+ "onClick"
105
+ > & {
106
+ messages: ConversationMessage[];
107
+ filename?: string;
108
+ formatMessage?: (message: ConversationMessage, index: number) => string;
109
+ };
110
+ const defaultFormatMessage = (message: ConversationMessage): string => {
111
+ const roleLabel =
112
+ message.role.charAt(0).toUpperCase() + message.role.slice(1);
113
+ return `**${roleLabel}:** ${message.content}`;
114
+ };
115
+ export const messagesToMarkdown = (
116
+ messages: ConversationMessage[],
117
+ formatMessage: (
118
+ message: ConversationMessage,
119
+ index: number,
120
+ ) => string = defaultFormatMessage,
121
+ ): string => messages.map((msg, i) => formatMessage(msg, i)).join("\n\n");
122
+ export const ConversationDownload = ({
123
+ messages,
124
+ filename = "conversation.md",
125
+ formatMessage = defaultFormatMessage,
126
+ className,
127
+ children,
128
+ ...props
129
+ }: ConversationDownloadProps) => {
130
+ const handleDownload = () => {
131
+ const markdown = messagesToMarkdown(messages, formatMessage);
132
+ const blob = new Blob([markdown], { type: "text/markdown" });
133
+ const url = URL.createObjectURL(blob);
134
+ const link = document.createElement("a");
135
+ link.href = url;
136
+ link.download = filename;
137
+ document.body.append(link);
138
+ link.click();
139
+ link.remove();
140
+ URL.revokeObjectURL(url);
141
+ };
142
+ return (
143
+ <Button
144
+ className={cn(
145
+ cn(flatInteractiveClass, "absolute top-4 right-4 rounded-full"),
146
+ className,
147
+ )}
148
+ onClick={handleDownload}
149
+ size="icon"
150
+ type="button"
151
+ variant="outline"
152
+ {...props}
153
+ >
154
+ {children ?? <IconDownload className="size-4" />}
155
+ </Button>
156
+ );
157
+ };
@@ -1,25 +1,25 @@
1
- import type { Experimental_GeneratedImage } from "ai";
2
-
3
- import { cn } from "../utils/cn";
4
-
5
- export type ImageProps = Experimental_GeneratedImage & {
6
- className?: string;
7
- alt?: string;
8
- };
9
-
10
- export const Image = ({
11
- base64,
12
- uint8Array: _uint8Array,
13
- mediaType,
14
- ...props
15
- }: ImageProps) => (
16
- <img
17
- {...props}
18
- alt={props.alt}
19
- className={cn(
20
- "h-auto max-w-full overflow-hidden rounded-md",
21
- props.className,
22
- )}
23
- src={`data:${mediaType};base64,${base64}`}
24
- />
25
- );
1
+ import type { Experimental_GeneratedImage } from "ai";
2
+
3
+ import { cn } from "../utils/cn";
4
+
5
+ export type ImageProps = Experimental_GeneratedImage & {
6
+ className?: string;
7
+ alt?: string;
8
+ };
9
+
10
+ export const Image = ({
11
+ base64,
12
+ uint8Array: _uint8Array,
13
+ mediaType,
14
+ ...props
15
+ }: ImageProps) => (
16
+ <img
17
+ {...props}
18
+ alt={props.alt}
19
+ className={cn(
20
+ "h-auto max-w-full overflow-hidden rounded-md",
21
+ props.className,
22
+ )}
23
+ src={`data:${mediaType};base64,${base64}`}
24
+ />
25
+ );