@vvedantb/ui 0.0.0-stage → 0.1.1
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/LICENSE +21 -0
- package/package.json +124 -4
- package/src/ai-elements/artifact.tsx +99 -0
- package/src/ai-elements/attachments.tsx +366 -0
- package/src/ai-elements/chain-of-thought.tsx +212 -0
- package/src/ai-elements/code-block.tsx +478 -0
- package/src/ai-elements/conversation.tsx +157 -0
- package/src/ai-elements/image.tsx +25 -0
- package/src/ai-elements/inline-citation.tsx +252 -0
- package/src/ai-elements/message.tsx +269 -0
- package/src/ai-elements/model-selector.tsx +211 -0
- package/src/ai-elements/prompt-input.tsx +1018 -0
- package/src/ai-elements/queue.tsx +251 -0
- package/src/ai-elements/reasoning.tsx +178 -0
- package/src/ai-elements/shimmer.tsx +56 -0
- package/src/ai-elements/sources.tsx +77 -0
- package/src/ai-elements/speech-input.tsx +290 -0
- package/src/ai-elements/suggestion.tsx +191 -0
- package/src/css.d.ts +2 -0
- package/src/index.ts +96 -0
- package/src/motion/presets.ts +35 -0
- package/src/motion/presets.vibot.ts +105 -0
- package/src/ui/_menu-classes.ts +30 -0
- package/src/ui/_menu-classes.vibot.ts +33 -0
- package/src/ui/accordion.tsx +81 -0
- package/src/ui/accordion.verve.tsx +56 -0
- package/src/ui/badge.tsx +34 -0
- package/src/ui/breadcrumb.tsx +83 -0
- package/src/ui/button-group.tsx +84 -0
- package/src/ui/button.tsx +57 -0
- package/src/ui/card.tsx +27 -0
- package/src/ui/carousel.tsx +211 -0
- package/src/ui/checkbox.tsx +27 -0
- package/src/ui/clear-input.tsx +170 -0
- package/src/ui/clear-input.vibot.tsx +76 -0
- package/src/ui/clearInputDissolve.ts +214 -0
- package/src/ui/collapsible.tsx +7 -0
- package/src/ui/command.tsx +148 -0
- package/src/ui/context-menu.tsx +173 -0
- package/src/ui/dialog.tsx +149 -0
- package/src/ui/dropdown-menu.tsx +178 -0
- package/src/ui/hover-card.tsx +31 -0
- package/src/ui/input-group.tsx +162 -0
- package/src/ui/input-group.verve.tsx +150 -0
- package/src/ui/input.tsx +21 -0
- package/src/ui/kbd.tsx +18 -0
- package/src/ui/label.tsx +20 -0
- package/src/ui/labeled-switch-row.tsx +53 -0
- package/src/ui/modalTransition.ts +85 -0
- package/src/ui/pagination.tsx +47 -0
- package/src/ui/popover.tsx +33 -0
- package/src/ui/progress.tsx +25 -0
- package/src/ui/radix-select.tsx +202 -0
- package/src/ui/scroll-area.tsx +55 -0
- package/src/ui/scroll-area.verve.tsx +43 -0
- package/src/ui/search-input.tsx +29 -0
- package/src/ui/select.tsx +163 -0
- package/src/ui/separator.tsx +28 -0
- package/src/ui/sheet.tsx +87 -0
- package/src/ui/skeleton.tsx +18 -0
- package/src/ui/sonner.css +16 -0
- package/src/ui/sonner.tsx +47 -0
- package/src/ui/spinner.tsx +27 -0
- package/src/ui/surface-classes.ts +55 -0
- package/src/ui/switch.tsx +26 -0
- package/src/ui/table.tsx +123 -0
- package/src/ui/tabs.tsx +140 -0
- package/src/ui/tabsSliding.ts +56 -0
- package/src/ui/textarea.tsx +21 -0
- package/src/ui/time-picker.tsx +170 -0
- package/src/ui/tooltip.tsx +25 -0
- package/src/ui/visually-hidden.tsx +3 -0
- package/src/utils/cn.ts +16 -0
- package/src/utils/ref.ts +10 -0
- package/README.md +0 -3
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { IconCheck, IconChevronDown, IconChevronUp } from "@tabler/icons-react";
|
|
3
|
+
import { Select as SelectPrimitive } from "radix-ui";
|
|
4
|
+
|
|
5
|
+
import { cn } from "../utils/cn";
|
|
6
|
+
import {
|
|
7
|
+
floatingSurfaceAnimateClass,
|
|
8
|
+
floatingSurfaceClass,
|
|
9
|
+
menuItemClass,
|
|
10
|
+
} from "./_menu-classes";
|
|
11
|
+
|
|
12
|
+
function Select({
|
|
13
|
+
...props
|
|
14
|
+
}: React.ComponentProps<typeof SelectPrimitive.Root>) {
|
|
15
|
+
return <SelectPrimitive.Root data-slot="select" {...props} />;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function SelectGroup({
|
|
19
|
+
...props
|
|
20
|
+
}: React.ComponentProps<typeof SelectPrimitive.Group>) {
|
|
21
|
+
return <SelectPrimitive.Group data-slot="select-group" {...props} />;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function SelectValue({
|
|
25
|
+
...props
|
|
26
|
+
}: React.ComponentProps<typeof SelectPrimitive.Value>) {
|
|
27
|
+
return <SelectPrimitive.Value data-slot="select-value" {...props} />;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function SelectTrigger({
|
|
31
|
+
className,
|
|
32
|
+
size = "default",
|
|
33
|
+
children,
|
|
34
|
+
...props
|
|
35
|
+
}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
|
|
36
|
+
size?: "sm" | "default";
|
|
37
|
+
}) {
|
|
38
|
+
return (
|
|
39
|
+
<SelectPrimitive.Trigger
|
|
40
|
+
data-slot="select-trigger"
|
|
41
|
+
data-size={size}
|
|
42
|
+
className={cn(
|
|
43
|
+
"flex w-fit items-center justify-between gap-2 rounded-field border border-border bg-field-background px-3.5 py-2 text-sm whitespace-nowrap ring-offset-background transition-[border-color,box-shadow,background-color,transform] duration-200 ease-smooth active:duration-100 active:ease-out active:scale-[0.98] placeholder:text-field-placeholder focus-visible:border-focus-border focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-focus-ring disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-danger data-placeholder:text-muted [&_svg:not([class*='text-'])]:text-muted data-[size=default]:h-10 data-[size=sm]:h-8 data-[slot=select-value]:*:line-clamp-1 data-[slot=select-value]:*:flex data-[slot=select-value]:*:items-center data-[slot=select-value]:*:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
44
|
+
className,
|
|
45
|
+
)}
|
|
46
|
+
{...props}
|
|
47
|
+
>
|
|
48
|
+
{children}
|
|
49
|
+
<SelectPrimitive.Icon asChild>
|
|
50
|
+
<IconChevronDown className="size-4 opacity-50" />
|
|
51
|
+
</SelectPrimitive.Icon>
|
|
52
|
+
</SelectPrimitive.Trigger>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function SelectContent({
|
|
57
|
+
className,
|
|
58
|
+
children,
|
|
59
|
+
position = "item-aligned",
|
|
60
|
+
align = "center",
|
|
61
|
+
...props
|
|
62
|
+
}: React.ComponentProps<typeof SelectPrimitive.Content>) {
|
|
63
|
+
return (
|
|
64
|
+
<SelectPrimitive.Portal>
|
|
65
|
+
<SelectPrimitive.Content
|
|
66
|
+
data-slot="select-content"
|
|
67
|
+
className={cn(
|
|
68
|
+
"relative z-50 max-h-(--radix-select-content-available-height) min-w-32 origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto",
|
|
69
|
+
floatingSurfaceClass,
|
|
70
|
+
floatingSurfaceAnimateClass,
|
|
71
|
+
position === "popper" &&
|
|
72
|
+
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
73
|
+
className,
|
|
74
|
+
)}
|
|
75
|
+
position={position}
|
|
76
|
+
align={align}
|
|
77
|
+
{...props}
|
|
78
|
+
>
|
|
79
|
+
<SelectScrollUpButton />
|
|
80
|
+
<SelectPrimitive.Viewport
|
|
81
|
+
className={cn(
|
|
82
|
+
"p-1.5",
|
|
83
|
+
position === "popper" &&
|
|
84
|
+
"h-(--radix-select-trigger-height) w-full min-w-(--radix-select-trigger-width) scroll-my-1",
|
|
85
|
+
)}
|
|
86
|
+
>
|
|
87
|
+
{children}
|
|
88
|
+
</SelectPrimitive.Viewport>
|
|
89
|
+
<SelectScrollDownButton />
|
|
90
|
+
</SelectPrimitive.Content>
|
|
91
|
+
</SelectPrimitive.Portal>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function SelectLabel({
|
|
96
|
+
className,
|
|
97
|
+
...props
|
|
98
|
+
}: React.ComponentProps<typeof SelectPrimitive.Label>) {
|
|
99
|
+
return (
|
|
100
|
+
<SelectPrimitive.Label
|
|
101
|
+
data-slot="select-label"
|
|
102
|
+
className={cn(
|
|
103
|
+
"text-muted px-2.5 py-1.5 text-xs font-semibold uppercase tracking-widest",
|
|
104
|
+
className,
|
|
105
|
+
)}
|
|
106
|
+
{...props}
|
|
107
|
+
/>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function SelectItem({
|
|
112
|
+
className,
|
|
113
|
+
children,
|
|
114
|
+
...props
|
|
115
|
+
}: React.ComponentProps<typeof SelectPrimitive.Item>) {
|
|
116
|
+
return (
|
|
117
|
+
<SelectPrimitive.Item
|
|
118
|
+
data-slot="select-item"
|
|
119
|
+
className={cn(
|
|
120
|
+
"[&_svg:not([class*='text-'])]:text-muted relative flex w-full cursor-pointer select-none items-center gap-2 rounded-lg py-2 pl-2.5 pr-8 text-sm outline-hidden [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 last:[span]:*:flex last:[span]:*:items-center last:[span]:*:gap-2",
|
|
121
|
+
menuItemClass,
|
|
122
|
+
className,
|
|
123
|
+
)}
|
|
124
|
+
{...props}
|
|
125
|
+
>
|
|
126
|
+
<span
|
|
127
|
+
data-slot="select-item-indicator"
|
|
128
|
+
className="absolute right-2 flex size-3.5 items-center justify-center"
|
|
129
|
+
>
|
|
130
|
+
<SelectPrimitive.ItemIndicator>
|
|
131
|
+
<IconCheck className="size-4" />
|
|
132
|
+
</SelectPrimitive.ItemIndicator>
|
|
133
|
+
</span>
|
|
134
|
+
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
|
135
|
+
</SelectPrimitive.Item>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function SelectSeparator({
|
|
140
|
+
className,
|
|
141
|
+
...props
|
|
142
|
+
}: React.ComponentProps<typeof SelectPrimitive.Separator>) {
|
|
143
|
+
return (
|
|
144
|
+
<SelectPrimitive.Separator
|
|
145
|
+
data-slot="select-separator"
|
|
146
|
+
className={cn(
|
|
147
|
+
"bg-separator pointer-events-none -mx-1.5 my-1 h-px",
|
|
148
|
+
className,
|
|
149
|
+
)}
|
|
150
|
+
{...props}
|
|
151
|
+
/>
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function SelectScrollUpButton({
|
|
156
|
+
className,
|
|
157
|
+
...props
|
|
158
|
+
}: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {
|
|
159
|
+
return (
|
|
160
|
+
<SelectPrimitive.ScrollUpButton
|
|
161
|
+
data-slot="select-scroll-up-button"
|
|
162
|
+
className={cn(
|
|
163
|
+
"flex cursor-default items-center justify-center py-1",
|
|
164
|
+
className,
|
|
165
|
+
)}
|
|
166
|
+
{...props}
|
|
167
|
+
>
|
|
168
|
+
<IconChevronUp className="size-4" />
|
|
169
|
+
</SelectPrimitive.ScrollUpButton>
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function SelectScrollDownButton({
|
|
174
|
+
className,
|
|
175
|
+
...props
|
|
176
|
+
}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
|
|
177
|
+
return (
|
|
178
|
+
<SelectPrimitive.ScrollDownButton
|
|
179
|
+
data-slot="select-scroll-down-button"
|
|
180
|
+
className={cn(
|
|
181
|
+
"flex cursor-default items-center justify-center py-1",
|
|
182
|
+
className,
|
|
183
|
+
)}
|
|
184
|
+
{...props}
|
|
185
|
+
>
|
|
186
|
+
<IconChevronDown className="size-4" />
|
|
187
|
+
</SelectPrimitive.ScrollDownButton>
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export {
|
|
192
|
+
Select,
|
|
193
|
+
SelectContent,
|
|
194
|
+
SelectGroup,
|
|
195
|
+
SelectItem,
|
|
196
|
+
SelectLabel,
|
|
197
|
+
SelectScrollDownButton,
|
|
198
|
+
SelectScrollUpButton,
|
|
199
|
+
SelectSeparator,
|
|
200
|
+
SelectTrigger,
|
|
201
|
+
SelectValue,
|
|
202
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { ScrollArea as ScrollAreaPrimitive } from "radix-ui";
|
|
3
|
+
import { cn } from "../utils/cn";
|
|
4
|
+
|
|
5
|
+
function ScrollArea({
|
|
6
|
+
className,
|
|
7
|
+
children,
|
|
8
|
+
...props
|
|
9
|
+
}: React.ComponentProps<typeof ScrollAreaPrimitive.Root>) {
|
|
10
|
+
return (
|
|
11
|
+
<ScrollAreaPrimitive.Root
|
|
12
|
+
data-slot="scroll-area"
|
|
13
|
+
className={cn("relative", className)}
|
|
14
|
+
{...props}
|
|
15
|
+
>
|
|
16
|
+
<ScrollAreaPrimitive.Viewport
|
|
17
|
+
data-slot="scroll-area-viewport"
|
|
18
|
+
className="size-full rounded-[inherit] outline-hidden"
|
|
19
|
+
>
|
|
20
|
+
{children}
|
|
21
|
+
</ScrollAreaPrimitive.Viewport>
|
|
22
|
+
<ScrollBar />
|
|
23
|
+
<ScrollAreaPrimitive.Corner />
|
|
24
|
+
</ScrollAreaPrimitive.Root>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function ScrollBar({
|
|
29
|
+
className,
|
|
30
|
+
orientation = "vertical",
|
|
31
|
+
...props
|
|
32
|
+
}: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>) {
|
|
33
|
+
return (
|
|
34
|
+
<ScrollAreaPrimitive.ScrollAreaScrollbar
|
|
35
|
+
data-slot="scroll-area-scrollbar"
|
|
36
|
+
orientation={orientation}
|
|
37
|
+
className={cn(
|
|
38
|
+
"flex touch-none p-px transition-colors select-none",
|
|
39
|
+
orientation === "vertical" &&
|
|
40
|
+
"h-full w-2.5 border-l border-l-transparent",
|
|
41
|
+
orientation === "horizontal" &&
|
|
42
|
+
"h-2.5 flex-col border-t border-t-transparent",
|
|
43
|
+
className,
|
|
44
|
+
)}
|
|
45
|
+
{...props}
|
|
46
|
+
>
|
|
47
|
+
<ScrollAreaPrimitive.ScrollAreaThumb
|
|
48
|
+
data-slot="scroll-area-thumb"
|
|
49
|
+
className="bg-scrollbar/35 hover:bg-scrollbar/55 relative flex-1 rounded-full transition-colors"
|
|
50
|
+
/>
|
|
51
|
+
</ScrollAreaPrimitive.ScrollAreaScrollbar>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { ScrollArea, ScrollBar };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
|
|
3
|
+
import { cn } from "../utils/cn";
|
|
4
|
+
|
|
5
|
+
const ScrollArea = React.forwardRef<
|
|
6
|
+
React.ComponentRef<typeof ScrollAreaPrimitive.Root>,
|
|
7
|
+
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
|
|
8
|
+
>(({ className, children, ...props }, ref) => (
|
|
9
|
+
<ScrollAreaPrimitive.Root
|
|
10
|
+
ref={ref}
|
|
11
|
+
className={cn("relative overflow-hidden", className)}
|
|
12
|
+
{...props}
|
|
13
|
+
>
|
|
14
|
+
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
|
|
15
|
+
{children}
|
|
16
|
+
</ScrollAreaPrimitive.Viewport>
|
|
17
|
+
<ScrollBar />
|
|
18
|
+
<ScrollAreaPrimitive.Corner />
|
|
19
|
+
</ScrollAreaPrimitive.Root>
|
|
20
|
+
));
|
|
21
|
+
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
|
|
22
|
+
|
|
23
|
+
const ScrollBar = React.forwardRef<
|
|
24
|
+
React.ComponentRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
|
|
25
|
+
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
|
|
26
|
+
>(({ className, orientation = "vertical", ...props }, ref) => (
|
|
27
|
+
<ScrollAreaPrimitive.ScrollAreaScrollbar
|
|
28
|
+
ref={ref}
|
|
29
|
+
orientation={orientation}
|
|
30
|
+
className={cn(
|
|
31
|
+
"flex touch-none select-none transition-colors",
|
|
32
|
+
orientation === "vertical" && "h-full w-2.5 p-px",
|
|
33
|
+
orientation === "horizontal" && "h-2.5 flex-col p-px",
|
|
34
|
+
className,
|
|
35
|
+
)}
|
|
36
|
+
{...props}
|
|
37
|
+
>
|
|
38
|
+
<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-scrollbar/80" />
|
|
39
|
+
</ScrollAreaPrimitive.ScrollAreaScrollbar>
|
|
40
|
+
));
|
|
41
|
+
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
|
|
42
|
+
|
|
43
|
+
export { ScrollArea, ScrollBar };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { IconSearch } from "@tabler/icons-react";
|
|
5
|
+
import { cn } from "../utils/cn";
|
|
6
|
+
import { ClearInput, type ClearInputProps } from "./clear-input";
|
|
7
|
+
|
|
8
|
+
export type SearchInputProps = Omit<ClearInputProps, "leading">;
|
|
9
|
+
|
|
10
|
+
const SearchInput = React.forwardRef<HTMLInputElement, SearchInputProps>(
|
|
11
|
+
({ className, ...props }, ref) => {
|
|
12
|
+
return (
|
|
13
|
+
<ClearInput
|
|
14
|
+
ref={ref}
|
|
15
|
+
className={cn("h-8 pl-8 text-sm", className)}
|
|
16
|
+
leading={
|
|
17
|
+
<IconSearch
|
|
18
|
+
size={16}
|
|
19
|
+
className="pointer-events-none absolute left-2 top-1/2 -translate-y-1/2 shrink-0 text-muted"
|
|
20
|
+
/>
|
|
21
|
+
}
|
|
22
|
+
{...props}
|
|
23
|
+
/>
|
|
24
|
+
);
|
|
25
|
+
},
|
|
26
|
+
);
|
|
27
|
+
SearchInput.displayName = "SearchInput";
|
|
28
|
+
|
|
29
|
+
export { SearchInput };
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as SelectPrimitive from "@radix-ui/react-select";
|
|
3
|
+
import { IconCheck, IconChevronDown, IconChevronUp } from "@tabler/icons-react";
|
|
4
|
+
import { cn } from "../utils/cn";
|
|
5
|
+
import {
|
|
6
|
+
floatingSurfaceAnimateClass,
|
|
7
|
+
floatingSurfaceClass,
|
|
8
|
+
} from "./_menu-classes";
|
|
9
|
+
|
|
10
|
+
const Select = SelectPrimitive.Root;
|
|
11
|
+
const SelectGroup = SelectPrimitive.Group;
|
|
12
|
+
const SelectValue = SelectPrimitive.Value;
|
|
13
|
+
|
|
14
|
+
const SelectTrigger = React.forwardRef<
|
|
15
|
+
React.ComponentRef<typeof SelectPrimitive.Trigger>,
|
|
16
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
|
|
17
|
+
>(({ className, children, ...props }, ref) => (
|
|
18
|
+
<SelectPrimitive.Trigger
|
|
19
|
+
ref={ref}
|
|
20
|
+
className={cn(
|
|
21
|
+
"flex h-10 w-full max-sm:min-w-0 items-center justify-between whitespace-nowrap rounded-field border border-border bg-field-background px-3.5 py-2 text-base sm:text-sm ring-offset-background placeholder:text-field-placeholder transition-[border-color,box-shadow,background-color] duration-200 ease-smooth focus-visible:border-focus-border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
|
22
|
+
className,
|
|
23
|
+
)}
|
|
24
|
+
{...props}
|
|
25
|
+
>
|
|
26
|
+
{children}
|
|
27
|
+
<SelectPrimitive.Icon asChild>
|
|
28
|
+
<IconChevronDown className="h-4 w-4 text-muted/85" />
|
|
29
|
+
</SelectPrimitive.Icon>
|
|
30
|
+
</SelectPrimitive.Trigger>
|
|
31
|
+
));
|
|
32
|
+
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
33
|
+
|
|
34
|
+
const SelectScrollUpButton = React.forwardRef<
|
|
35
|
+
React.ComponentRef<typeof SelectPrimitive.ScrollUpButton>,
|
|
36
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
|
|
37
|
+
>(({ className, ...props }, ref) => (
|
|
38
|
+
<SelectPrimitive.ScrollUpButton
|
|
39
|
+
ref={ref}
|
|
40
|
+
className={cn(
|
|
41
|
+
"flex cursor-default items-center justify-center py-1 text-muted",
|
|
42
|
+
className,
|
|
43
|
+
)}
|
|
44
|
+
{...props}
|
|
45
|
+
>
|
|
46
|
+
<IconChevronUp className="h-4 w-4" />
|
|
47
|
+
</SelectPrimitive.ScrollUpButton>
|
|
48
|
+
));
|
|
49
|
+
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
|
50
|
+
|
|
51
|
+
const SelectScrollDownButton = React.forwardRef<
|
|
52
|
+
React.ComponentRef<typeof SelectPrimitive.ScrollDownButton>,
|
|
53
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
|
|
54
|
+
>(({ className, ...props }, ref) => (
|
|
55
|
+
<SelectPrimitive.ScrollDownButton
|
|
56
|
+
ref={ref}
|
|
57
|
+
className={cn(
|
|
58
|
+
"flex cursor-default items-center justify-center py-1 text-muted",
|
|
59
|
+
className,
|
|
60
|
+
)}
|
|
61
|
+
{...props}
|
|
62
|
+
>
|
|
63
|
+
<IconChevronDown className="h-4 w-4" />
|
|
64
|
+
</SelectPrimitive.ScrollDownButton>
|
|
65
|
+
));
|
|
66
|
+
SelectScrollDownButton.displayName =
|
|
67
|
+
SelectPrimitive.ScrollDownButton.displayName;
|
|
68
|
+
|
|
69
|
+
const SelectContent = React.forwardRef<
|
|
70
|
+
React.ComponentRef<typeof SelectPrimitive.Content>,
|
|
71
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
|
|
72
|
+
>(({ className, children, position = "popper", ...props }, ref) => (
|
|
73
|
+
<SelectPrimitive.Portal>
|
|
74
|
+
<SelectPrimitive.Content
|
|
75
|
+
ref={ref}
|
|
76
|
+
className={cn(
|
|
77
|
+
"relative z-50 max-h-96 w-36 overflow-hidden outline-none",
|
|
78
|
+
floatingSurfaceClass,
|
|
79
|
+
floatingSurfaceAnimateClass,
|
|
80
|
+
position === "popper" &&
|
|
81
|
+
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
82
|
+
className,
|
|
83
|
+
)}
|
|
84
|
+
position={position}
|
|
85
|
+
{...props}
|
|
86
|
+
>
|
|
87
|
+
<SelectScrollUpButton />
|
|
88
|
+
<SelectPrimitive.Viewport
|
|
89
|
+
className={cn(
|
|
90
|
+
"p-1.5",
|
|
91
|
+
position === "popper" &&
|
|
92
|
+
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]",
|
|
93
|
+
)}
|
|
94
|
+
>
|
|
95
|
+
{children}
|
|
96
|
+
</SelectPrimitive.Viewport>
|
|
97
|
+
<SelectScrollDownButton />
|
|
98
|
+
</SelectPrimitive.Content>
|
|
99
|
+
</SelectPrimitive.Portal>
|
|
100
|
+
));
|
|
101
|
+
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
102
|
+
|
|
103
|
+
const SelectLabel = React.forwardRef<
|
|
104
|
+
React.ComponentRef<typeof SelectPrimitive.Label>,
|
|
105
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
|
|
106
|
+
>(({ className, ...props }, ref) => (
|
|
107
|
+
<SelectPrimitive.Label
|
|
108
|
+
ref={ref}
|
|
109
|
+
className={cn(
|
|
110
|
+
"px-2.5 py-1.5 text-xs font-semibold uppercase tracking-widest text-muted",
|
|
111
|
+
className,
|
|
112
|
+
)}
|
|
113
|
+
{...props}
|
|
114
|
+
/>
|
|
115
|
+
));
|
|
116
|
+
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
|
117
|
+
|
|
118
|
+
const SelectItem = React.forwardRef<
|
|
119
|
+
React.ComponentRef<typeof SelectPrimitive.Item>,
|
|
120
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
|
|
121
|
+
>(({ className, children, ...props }, ref) => (
|
|
122
|
+
<SelectPrimitive.Item
|
|
123
|
+
ref={ref}
|
|
124
|
+
className={cn(
|
|
125
|
+
"relative flex w-full cursor-pointer select-none items-center rounded-lg py-2 pl-2.5 pr-8 text-sm outline-none transition-[background-color,color] focus:bg-default focus:text-foreground data-[highlighted]:bg-default data-[highlighted]:text-foreground data-[disabled]:pointer-events-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50",
|
|
126
|
+
className,
|
|
127
|
+
)}
|
|
128
|
+
{...props}
|
|
129
|
+
>
|
|
130
|
+
<span className="absolute right-2.5 flex h-3.5 w-3.5 items-center justify-center">
|
|
131
|
+
<SelectPrimitive.ItemIndicator>
|
|
132
|
+
<IconCheck className="h-4 w-4" />
|
|
133
|
+
</SelectPrimitive.ItemIndicator>
|
|
134
|
+
</span>
|
|
135
|
+
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
|
136
|
+
</SelectPrimitive.Item>
|
|
137
|
+
));
|
|
138
|
+
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
139
|
+
|
|
140
|
+
const SelectSeparator = React.forwardRef<
|
|
141
|
+
React.ComponentRef<typeof SelectPrimitive.Separator>,
|
|
142
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
|
|
143
|
+
>(({ className, ...props }, ref) => (
|
|
144
|
+
<SelectPrimitive.Separator
|
|
145
|
+
ref={ref}
|
|
146
|
+
className={cn("-mx-1.5 my-1 h-px bg-separator", className)}
|
|
147
|
+
{...props}
|
|
148
|
+
/>
|
|
149
|
+
));
|
|
150
|
+
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
|
151
|
+
|
|
152
|
+
export {
|
|
153
|
+
Select,
|
|
154
|
+
SelectGroup,
|
|
155
|
+
SelectValue,
|
|
156
|
+
SelectTrigger,
|
|
157
|
+
SelectContent,
|
|
158
|
+
SelectLabel,
|
|
159
|
+
SelectItem,
|
|
160
|
+
SelectSeparator,
|
|
161
|
+
SelectScrollUpButton,
|
|
162
|
+
SelectScrollDownButton,
|
|
163
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
|
3
|
+
import { cn } from "../utils/cn";
|
|
4
|
+
|
|
5
|
+
const Separator = React.forwardRef<
|
|
6
|
+
React.ComponentRef<typeof SeparatorPrimitive.Root>,
|
|
7
|
+
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
|
|
8
|
+
>(
|
|
9
|
+
(
|
|
10
|
+
{ className, orientation = "horizontal", decorative = true, ...props },
|
|
11
|
+
ref,
|
|
12
|
+
) => (
|
|
13
|
+
<SeparatorPrimitive.Root
|
|
14
|
+
ref={ref}
|
|
15
|
+
decorative={decorative}
|
|
16
|
+
orientation={orientation}
|
|
17
|
+
className={cn(
|
|
18
|
+
"shrink-0 bg-separator",
|
|
19
|
+
orientation === "horizontal" ? "h-px w-full" : "h-full w-px",
|
|
20
|
+
className,
|
|
21
|
+
)}
|
|
22
|
+
{...props}
|
|
23
|
+
/>
|
|
24
|
+
),
|
|
25
|
+
);
|
|
26
|
+
Separator.displayName = SeparatorPrimitive.Root.displayName;
|
|
27
|
+
|
|
28
|
+
export { Separator };
|
package/src/ui/sheet.tsx
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Drawer as DrawerPrimitive } from "vaul";
|
|
5
|
+
import { cn } from "../utils/cn";
|
|
6
|
+
|
|
7
|
+
type SheetSide = "top" | "bottom" | "left" | "right";
|
|
8
|
+
|
|
9
|
+
function Sheet({
|
|
10
|
+
shouldScaleBackground = false,
|
|
11
|
+
...props
|
|
12
|
+
}: React.ComponentProps<typeof DrawerPrimitive.Root>) {
|
|
13
|
+
return (
|
|
14
|
+
<DrawerPrimitive.Root
|
|
15
|
+
shouldScaleBackground={shouldScaleBackground}
|
|
16
|
+
{...props}
|
|
17
|
+
/>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const SheetTrigger = DrawerPrimitive.Trigger;
|
|
22
|
+
const SheetPortal = DrawerPrimitive.Portal;
|
|
23
|
+
const SheetClose = DrawerPrimitive.Close;
|
|
24
|
+
const SheetHandle = DrawerPrimitive.Handle;
|
|
25
|
+
const SheetTitle = DrawerPrimitive.Title;
|
|
26
|
+
const SheetDescription = DrawerPrimitive.Description;
|
|
27
|
+
|
|
28
|
+
const SheetOverlay = React.forwardRef<
|
|
29
|
+
React.ComponentRef<typeof DrawerPrimitive.Overlay>,
|
|
30
|
+
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay>
|
|
31
|
+
>(({ className, ...props }, ref) => (
|
|
32
|
+
<DrawerPrimitive.Overlay
|
|
33
|
+
ref={ref}
|
|
34
|
+
className={cn(
|
|
35
|
+
"fixed inset-0 z-50 bg-backdrop backdrop-blur-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
36
|
+
className,
|
|
37
|
+
)}
|
|
38
|
+
{...props}
|
|
39
|
+
/>
|
|
40
|
+
));
|
|
41
|
+
SheetOverlay.displayName = "SheetOverlay";
|
|
42
|
+
|
|
43
|
+
const sheetSideClass: Record<SheetSide, string> = {
|
|
44
|
+
bottom: "inset-x-0 bottom-0 mt-24 flex h-auto flex-col rounded-t-2xl",
|
|
45
|
+
top: "inset-x-0 top-0 mb-24 flex h-auto flex-col rounded-b-2xl",
|
|
46
|
+
left: "inset-y-2 left-2 right-auto flex h-auto w-80 max-w-[88vw] flex-col rounded-2xl",
|
|
47
|
+
right:
|
|
48
|
+
"inset-y-2 left-auto right-2 flex h-auto w-80 max-w-[88vw] flex-col rounded-2xl",
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const SheetContent = React.forwardRef<
|
|
52
|
+
React.ComponentRef<typeof DrawerPrimitive.Content>,
|
|
53
|
+
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Content> & {
|
|
54
|
+
side?: SheetSide;
|
|
55
|
+
}
|
|
56
|
+
>(({ className, children, side = "bottom", ...props }, ref) => (
|
|
57
|
+
<SheetPortal>
|
|
58
|
+
<SheetOverlay />
|
|
59
|
+
<DrawerPrimitive.Content
|
|
60
|
+
ref={ref}
|
|
61
|
+
className={cn(
|
|
62
|
+
"fixed z-50 bg-overlay/95 text-overlay-foreground smooth-shadow-ring-xl outline-hidden backdrop-blur-xl",
|
|
63
|
+
sheetSideClass[side],
|
|
64
|
+
className,
|
|
65
|
+
)}
|
|
66
|
+
{...props}
|
|
67
|
+
>
|
|
68
|
+
{side === "bottom" || side === "top" ? (
|
|
69
|
+
<SheetHandle className="mx-auto mt-3 mb-1 h-1 w-12 shrink-0 rounded-full bg-surface-tertiary" />
|
|
70
|
+
) : null}
|
|
71
|
+
{children}
|
|
72
|
+
</DrawerPrimitive.Content>
|
|
73
|
+
</SheetPortal>
|
|
74
|
+
));
|
|
75
|
+
SheetContent.displayName = "SheetContent";
|
|
76
|
+
|
|
77
|
+
export {
|
|
78
|
+
Sheet,
|
|
79
|
+
SheetPortal,
|
|
80
|
+
SheetOverlay,
|
|
81
|
+
SheetTrigger,
|
|
82
|
+
SheetClose,
|
|
83
|
+
SheetContent,
|
|
84
|
+
SheetHandle,
|
|
85
|
+
SheetTitle,
|
|
86
|
+
SheetDescription,
|
|
87
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { cn } from "../utils/cn";
|
|
2
|
+
|
|
3
|
+
function Skeleton({
|
|
4
|
+
className,
|
|
5
|
+
...props
|
|
6
|
+
}: React.HTMLAttributes<HTMLDivElement>) {
|
|
7
|
+
return (
|
|
8
|
+
<div
|
|
9
|
+
className={cn(
|
|
10
|
+
"animate-pulse rounded-lg bg-surface-secondary/70",
|
|
11
|
+
className,
|
|
12
|
+
)}
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { Skeleton };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unstyled toasts skip Sonner's data-styled rules, so stacked back toasts show
|
|
3
|
+
* full overlapping content. Mirror the styled-mode stack: hide inner content on
|
|
4
|
+
* collapsed back cards, expand spacing on hover (data-expanded on the toaster).
|
|
5
|
+
*/
|
|
6
|
+
[data-sonner-toaster]
|
|
7
|
+
[data-sonner-toast][data-expanded="false"][data-front="false"] {
|
|
8
|
+
overflow: hidden;
|
|
9
|
+
pointer-events: none;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
[data-sonner-toaster]
|
|
13
|
+
[data-sonner-toast][data-expanded="false"][data-front="false"]
|
|
14
|
+
> * {
|
|
15
|
+
opacity: 0;
|
|
16
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Toaster, type ToasterProps } from "sonner";
|
|
2
|
+
import "./sonner.css";
|
|
3
|
+
|
|
4
|
+
// sonner toaster aligned with flat tonal surfaces `unstyled: true` strips sonner's default visual styling so our classes are
|
|
5
|
+
// the single source of truth toast surfaces use `glass, panel, strong` (flat
|
|
6
|
+
// popover fill) plus `smooth-shadow-ring-md` `!font, sans` is forced on the toaster section because sonner sets its own
|
|
7
|
+
// `font, family` on `[data, sonner, toaster]` from a stylesheet that ships with
|
|
8
|
+
// the package (loaded after our globals), so plain inheritance from `<body>`
|
|
9
|
+
// loses the cascade the `!important` here guarantees instrument sans wins, toasts inherit from the section, so this single class covers everything variant icons (success / error / warning / info) are tinted via a
|
|
10
|
+
// `data, icon` descendant selector, leaving the rest of the toast neutral callers should pass `theme` from `next, themes` so sonner's internal
|
|
11
|
+
// `data, theme` attribute matches the active app theme (used by its focus
|
|
12
|
+
// ring and a few internal states that aren't reachable via classnames) stacking: `expand={false}` keeps toasts collapsed (offset + scale) hovering
|
|
13
|
+
// the stack expands them `sonner.css` hides back, toast content while collapsed
|
|
14
|
+
// because `unstyled` disables sonner's built, in `data, styled` stack rules
|
|
15
|
+
function SonnerToaster(props: ToasterProps) {
|
|
16
|
+
return (
|
|
17
|
+
<Toaster
|
|
18
|
+
expand={false}
|
|
19
|
+
visibleToasts={4}
|
|
20
|
+
gap={12}
|
|
21
|
+
className="toaster group !font-sans"
|
|
22
|
+
toastOptions={{
|
|
23
|
+
unstyled: true,
|
|
24
|
+
classNames: {
|
|
25
|
+
toast:
|
|
26
|
+
"group toast glass-panel-strong flex w-full items-center gap-3 rounded-lg px-4 py-3 text-sm text-foreground smooth-shadow-ring-md",
|
|
27
|
+
title: "font-medium leading-snug",
|
|
28
|
+
description: "text-[13px] leading-snug text-muted",
|
|
29
|
+
actionButton:
|
|
30
|
+
"rounded-lg bg-accent px-2.5 py-1 text-xs font-medium text-accent-foreground transition-opacity hover:opacity-90",
|
|
31
|
+
cancelButton:
|
|
32
|
+
"rounded-lg bg-surface-secondary px-2.5 py-1 text-xs font-medium text-muted transition-colors hover:bg-surface-tertiary",
|
|
33
|
+
closeButton:
|
|
34
|
+
"rounded-lg bg-default px-2.5 py-1 text-xs font-medium text-foreground transition-colors hover:bg-default/78",
|
|
35
|
+
loader: "text-muted",
|
|
36
|
+
success: "[&_[data-icon]]:text-success",
|
|
37
|
+
error: "[&_[data-icon]]:text-danger",
|
|
38
|
+
warning: "[&_[data-icon]]:text-warning",
|
|
39
|
+
info: "[&_[data-icon]]:text-accent",
|
|
40
|
+
},
|
|
41
|
+
}}
|
|
42
|
+
{...props}
|
|
43
|
+
/>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export { SonnerToaster };
|