@oppulence/design-system 1.0.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.
- package/README.md +115 -0
- package/components.json +21 -0
- package/hooks/use-mobile.tsx +21 -0
- package/lib/utils.ts +6 -0
- package/package.json +104 -0
- package/postcss.config.mjs +8 -0
- package/src/components/atoms/aspect-ratio.tsx +21 -0
- package/src/components/atoms/avatar.tsx +91 -0
- package/src/components/atoms/badge.tsx +47 -0
- package/src/components/atoms/button.tsx +128 -0
- package/src/components/atoms/checkbox.tsx +24 -0
- package/src/components/atoms/container.tsx +42 -0
- package/src/components/atoms/heading.tsx +56 -0
- package/src/components/atoms/index.ts +21 -0
- package/src/components/atoms/input.tsx +18 -0
- package/src/components/atoms/kbd.tsx +23 -0
- package/src/components/atoms/label.tsx +15 -0
- package/src/components/atoms/logo.tsx +52 -0
- package/src/components/atoms/progress.tsx +79 -0
- package/src/components/atoms/separator.tsx +17 -0
- package/src/components/atoms/skeleton.tsx +13 -0
- package/src/components/atoms/slider.tsx +56 -0
- package/src/components/atoms/spinner.tsx +14 -0
- package/src/components/atoms/stack.tsx +126 -0
- package/src/components/atoms/switch.tsx +26 -0
- package/src/components/atoms/text.tsx +69 -0
- package/src/components/atoms/textarea.tsx +19 -0
- package/src/components/atoms/toggle.tsx +40 -0
- package/src/components/molecules/accordion.tsx +72 -0
- package/src/components/molecules/ai-chat.tsx +251 -0
- package/src/components/molecules/alert.tsx +131 -0
- package/src/components/molecules/breadcrumb.tsx +301 -0
- package/src/components/molecules/button-group.tsx +96 -0
- package/src/components/molecules/card.tsx +184 -0
- package/src/components/molecules/collapsible.tsx +21 -0
- package/src/components/molecules/command-search.tsx +148 -0
- package/src/components/molecules/empty.tsx +98 -0
- package/src/components/molecules/field.tsx +217 -0
- package/src/components/molecules/grid.tsx +141 -0
- package/src/components/molecules/hover-card.tsx +45 -0
- package/src/components/molecules/index.ts +29 -0
- package/src/components/molecules/input-group.tsx +151 -0
- package/src/components/molecules/input-otp.tsx +74 -0
- package/src/components/molecules/item.tsx +194 -0
- package/src/components/molecules/page-header.tsx +89 -0
- package/src/components/molecules/pagination.tsx +130 -0
- package/src/components/molecules/popover.tsx +96 -0
- package/src/components/molecules/radio-group.tsx +37 -0
- package/src/components/molecules/resizable.tsx +52 -0
- package/src/components/molecules/scroll-area.tsx +45 -0
- package/src/components/molecules/section.tsx +108 -0
- package/src/components/molecules/select.tsx +201 -0
- package/src/components/molecules/settings.tsx +197 -0
- package/src/components/molecules/table.tsx +111 -0
- package/src/components/molecules/tabs.tsx +74 -0
- package/src/components/molecules/theme-switcher.tsx +187 -0
- package/src/components/molecules/toggle-group.tsx +89 -0
- package/src/components/molecules/tooltip.tsx +66 -0
- package/src/components/organisms/alert-dialog.tsx +152 -0
- package/src/components/organisms/app-shell.tsx +939 -0
- package/src/components/organisms/calendar.tsx +212 -0
- package/src/components/organisms/carousel.tsx +230 -0
- package/src/components/organisms/chart.tsx +333 -0
- package/src/components/organisms/combobox.tsx +274 -0
- package/src/components/organisms/command.tsx +200 -0
- package/src/components/organisms/context-menu.tsx +229 -0
- package/src/components/organisms/dialog.tsx +134 -0
- package/src/components/organisms/drawer.tsx +123 -0
- package/src/components/organisms/dropdown-menu.tsx +256 -0
- package/src/components/organisms/index.ts +17 -0
- package/src/components/organisms/menubar.tsx +203 -0
- package/src/components/organisms/navigation-menu.tsx +143 -0
- package/src/components/organisms/page-layout.tsx +105 -0
- package/src/components/organisms/sheet.tsx +126 -0
- package/src/components/organisms/sidebar.tsx +723 -0
- package/src/components/organisms/sonner.tsx +41 -0
- package/src/components/ui/index.ts +3 -0
- package/src/index.ts +3 -0
- package/src/styles/globals.css +297 -0
- package/tailwind.config.ts +77 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { Popover as PopoverPrimitive } from "@base-ui/react/popover";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
|
|
4
|
+
import { cn } from "../../../lib/utils";
|
|
5
|
+
|
|
6
|
+
function Popover({ ...props }: PopoverPrimitive.Root.Props) {
|
|
7
|
+
return <PopoverPrimitive.Root data-slot="popover" {...props} />;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function PopoverTrigger({
|
|
11
|
+
className,
|
|
12
|
+
...props
|
|
13
|
+
}: PopoverPrimitive.Trigger.Props) {
|
|
14
|
+
return (
|
|
15
|
+
<PopoverPrimitive.Trigger
|
|
16
|
+
data-slot="popover-trigger"
|
|
17
|
+
className={cn(className)}
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function PopoverContent({
|
|
24
|
+
align = "center",
|
|
25
|
+
alignOffset = 0,
|
|
26
|
+
side = "bottom",
|
|
27
|
+
sideOffset = 4,
|
|
28
|
+
...props
|
|
29
|
+
}: Omit<PopoverPrimitive.Popup.Props, "className"> &
|
|
30
|
+
Pick<
|
|
31
|
+
PopoverPrimitive.Positioner.Props,
|
|
32
|
+
"align" | "alignOffset" | "side" | "sideOffset"
|
|
33
|
+
>) {
|
|
34
|
+
return (
|
|
35
|
+
<PopoverPrimitive.Portal>
|
|
36
|
+
<PopoverPrimitive.Positioner
|
|
37
|
+
align={align}
|
|
38
|
+
alignOffset={alignOffset}
|
|
39
|
+
side={side}
|
|
40
|
+
sideOffset={sideOffset}
|
|
41
|
+
className="isolate z-50"
|
|
42
|
+
>
|
|
43
|
+
<PopoverPrimitive.Popup
|
|
44
|
+
data-slot="popover-content"
|
|
45
|
+
className="bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 flex flex-col gap-2.5 rounded-lg p-2.5 text-sm shadow-md ring-1 duration-100 z-50 w-72 origin-(--transform-origin) outline-hidden"
|
|
46
|
+
{...props}
|
|
47
|
+
/>
|
|
48
|
+
</PopoverPrimitive.Positioner>
|
|
49
|
+
</PopoverPrimitive.Portal>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function PopoverHeader({
|
|
54
|
+
...props
|
|
55
|
+
}: Omit<React.ComponentProps<"div">, "className">) {
|
|
56
|
+
return (
|
|
57
|
+
<div
|
|
58
|
+
data-slot="popover-header"
|
|
59
|
+
className="flex flex-col gap-0.5 text-sm"
|
|
60
|
+
{...props}
|
|
61
|
+
/>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function PopoverTitle({
|
|
66
|
+
...props
|
|
67
|
+
}: Omit<PopoverPrimitive.Title.Props, "className">) {
|
|
68
|
+
return (
|
|
69
|
+
<PopoverPrimitive.Title
|
|
70
|
+
data-slot="popover-title"
|
|
71
|
+
className="font-medium"
|
|
72
|
+
{...props}
|
|
73
|
+
/>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function PopoverDescription({
|
|
78
|
+
...props
|
|
79
|
+
}: Omit<PopoverPrimitive.Description.Props, "className">) {
|
|
80
|
+
return (
|
|
81
|
+
<PopoverPrimitive.Description
|
|
82
|
+
data-slot="popover-description"
|
|
83
|
+
className="text-muted-foreground"
|
|
84
|
+
{...props}
|
|
85
|
+
/>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export {
|
|
90
|
+
Popover,
|
|
91
|
+
PopoverContent,
|
|
92
|
+
PopoverDescription,
|
|
93
|
+
PopoverHeader,
|
|
94
|
+
PopoverTitle,
|
|
95
|
+
PopoverTrigger,
|
|
96
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Radio as RadioPrimitive } from "@base-ui/react/radio";
|
|
2
|
+
import { RadioGroup as RadioGroupPrimitive } from "@base-ui/react/radio-group";
|
|
3
|
+
|
|
4
|
+
import { CircleIcon } from "lucide-react";
|
|
5
|
+
|
|
6
|
+
function RadioGroup({
|
|
7
|
+
...props
|
|
8
|
+
}: Omit<RadioGroupPrimitive.Props, "className">) {
|
|
9
|
+
return (
|
|
10
|
+
<RadioGroupPrimitive
|
|
11
|
+
data-slot="radio-group"
|
|
12
|
+
className="grid gap-2 w-full"
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function RadioGroupItem({
|
|
19
|
+
...props
|
|
20
|
+
}: Omit<RadioPrimitive.Root.Props, "className">) {
|
|
21
|
+
return (
|
|
22
|
+
<RadioPrimitive.Root
|
|
23
|
+
data-slot="radio-group-item"
|
|
24
|
+
className="border-input text-primary dark:bg-input/30 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 flex size-4 rounded-full shadow-xs focus-visible:ring-[3px] aria-invalid:ring-[3px] group/radio-group-item peer relative aspect-square shrink-0 border outline-none after:absolute after:-inset-x-3 after:-inset-y-2 disabled:cursor-not-allowed disabled:opacity-50"
|
|
25
|
+
{...props}
|
|
26
|
+
>
|
|
27
|
+
<RadioPrimitive.Indicator
|
|
28
|
+
data-slot="radio-group-indicator"
|
|
29
|
+
className="group-aria-invalid/radio-group-item:text-destructive text-primary flex size-4 items-center justify-center"
|
|
30
|
+
>
|
|
31
|
+
<CircleIcon className="absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 fill-current" />
|
|
32
|
+
</RadioPrimitive.Indicator>
|
|
33
|
+
</RadioPrimitive.Root>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export { RadioGroup, RadioGroupItem };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as ResizablePrimitive from "react-resizable-panels";
|
|
4
|
+
|
|
5
|
+
type ResizablePanelGroupProps = Omit<
|
|
6
|
+
ResizablePrimitive.GroupProps,
|
|
7
|
+
"className"
|
|
8
|
+
>;
|
|
9
|
+
|
|
10
|
+
function ResizablePanelGroup({
|
|
11
|
+
orientation = "horizontal",
|
|
12
|
+
...props
|
|
13
|
+
}: ResizablePanelGroupProps) {
|
|
14
|
+
return (
|
|
15
|
+
<ResizablePrimitive.Group
|
|
16
|
+
data-slot="resizable-panel-group"
|
|
17
|
+
data-orientation={orientation}
|
|
18
|
+
orientation={orientation}
|
|
19
|
+
className="flex h-full w-full data-[orientation=vertical]:flex-col"
|
|
20
|
+
{...props}
|
|
21
|
+
/>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type ResizablePanelProps = Omit<ResizablePrimitive.PanelProps, "className">;
|
|
26
|
+
|
|
27
|
+
function ResizablePanel({ ...props }: ResizablePanelProps) {
|
|
28
|
+
return <ResizablePrimitive.Panel data-slot="resizable-panel" {...props} />;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
type ResizableHandleProps = Omit<
|
|
32
|
+
ResizablePrimitive.SeparatorProps,
|
|
33
|
+
"className"
|
|
34
|
+
> & {
|
|
35
|
+
withHandle?: boolean;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
function ResizableHandle({ withHandle, ...props }: ResizableHandleProps) {
|
|
39
|
+
return (
|
|
40
|
+
<ResizablePrimitive.Separator
|
|
41
|
+
data-slot="resizable-handle"
|
|
42
|
+
className="bg-border hover:bg-muted-foreground/20 focus-visible:ring-ring relative flex w-px items-center justify-center transition-colors after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-offset-1 focus-visible:outline-hidden [&[data-orientation=vertical]]:h-px [&[data-orientation=vertical]]:w-full [&[data-orientation=vertical]]:after:left-0 [&[data-orientation=vertical]]:after:h-1 [&[data-orientation=vertical]]:after:w-full [&[data-orientation=vertical]]:after:translate-x-0 [&[data-orientation=vertical]]:after:-translate-y-1/2 [&[data-orientation=vertical]>div]:rotate-90"
|
|
43
|
+
{...props}
|
|
44
|
+
>
|
|
45
|
+
{withHandle && (
|
|
46
|
+
<div className="bg-border z-10 flex h-4 w-1 shrink-0 rounded-full" />
|
|
47
|
+
)}
|
|
48
|
+
</ResizablePrimitive.Separator>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { ResizableHandle, ResizablePanel, ResizablePanelGroup };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ScrollArea as ScrollAreaPrimitive } from "@base-ui/react/scroll-area";
|
|
2
|
+
|
|
3
|
+
function ScrollArea({
|
|
4
|
+
children,
|
|
5
|
+
...props
|
|
6
|
+
}: Omit<ScrollAreaPrimitive.Root.Props, "className">) {
|
|
7
|
+
return (
|
|
8
|
+
<ScrollAreaPrimitive.Root
|
|
9
|
+
data-slot="scroll-area"
|
|
10
|
+
className="relative overflow-hidden size-full"
|
|
11
|
+
{...props}
|
|
12
|
+
>
|
|
13
|
+
<ScrollAreaPrimitive.Viewport
|
|
14
|
+
data-slot="scroll-area-viewport"
|
|
15
|
+
className="focus-visible:ring-ring/50 size-full overflow-auto rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1"
|
|
16
|
+
>
|
|
17
|
+
{children}
|
|
18
|
+
</ScrollAreaPrimitive.Viewport>
|
|
19
|
+
<ScrollBar />
|
|
20
|
+
<ScrollAreaPrimitive.Corner />
|
|
21
|
+
</ScrollAreaPrimitive.Root>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function ScrollBar({
|
|
26
|
+
orientation = "vertical",
|
|
27
|
+
...props
|
|
28
|
+
}: Omit<ScrollAreaPrimitive.Scrollbar.Props, "className">) {
|
|
29
|
+
return (
|
|
30
|
+
<ScrollAreaPrimitive.Scrollbar
|
|
31
|
+
data-slot="scroll-area-scrollbar"
|
|
32
|
+
data-orientation={orientation}
|
|
33
|
+
orientation={orientation}
|
|
34
|
+
className="data-horizontal:h-2.5 data-horizontal:flex-col data-horizontal:border-t data-horizontal:border-t-transparent data-vertical:h-full data-vertical:w-2.5 data-vertical:border-l data-vertical:border-l-transparent flex touch-none p-px transition-colors select-none"
|
|
35
|
+
{...props}
|
|
36
|
+
>
|
|
37
|
+
<ScrollAreaPrimitive.Thumb
|
|
38
|
+
data-slot="scroll-area-thumb"
|
|
39
|
+
className="rounded-full bg-border relative flex-1"
|
|
40
|
+
/>
|
|
41
|
+
</ScrollAreaPrimitive.Scrollbar>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { ScrollArea, ScrollBar };
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
import { Heading } from "../atoms/heading";
|
|
4
|
+
import { Text } from "../atoms/text";
|
|
5
|
+
import { Stack } from "../atoms/stack";
|
|
6
|
+
|
|
7
|
+
interface SectionProps extends Omit<
|
|
8
|
+
React.ComponentProps<"section">,
|
|
9
|
+
"className"
|
|
10
|
+
> {
|
|
11
|
+
title?: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
actions?: React.ReactNode;
|
|
14
|
+
/** Gap between header and content. Default is "4" */
|
|
15
|
+
gap?: "2" | "3" | "4" | "6" | "8";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function Section({
|
|
19
|
+
title,
|
|
20
|
+
description,
|
|
21
|
+
actions,
|
|
22
|
+
gap = "4",
|
|
23
|
+
children,
|
|
24
|
+
...props
|
|
25
|
+
}: SectionProps) {
|
|
26
|
+
const hasHeader = title || description || actions;
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<section data-slot="section" className="w-full" {...props}>
|
|
30
|
+
<Stack gap={gap}>
|
|
31
|
+
{hasHeader && (
|
|
32
|
+
<div className="flex items-start justify-between gap-4">
|
|
33
|
+
<Stack gap="1">
|
|
34
|
+
{title && <Heading level="3">{title}</Heading>}
|
|
35
|
+
{description && (
|
|
36
|
+
<Text size="sm" variant="muted">
|
|
37
|
+
{description}
|
|
38
|
+
</Text>
|
|
39
|
+
)}
|
|
40
|
+
</Stack>
|
|
41
|
+
{actions && (
|
|
42
|
+
<div className="flex shrink-0 items-center gap-2">{actions}</div>
|
|
43
|
+
)}
|
|
44
|
+
</div>
|
|
45
|
+
)}
|
|
46
|
+
{children}
|
|
47
|
+
</Stack>
|
|
48
|
+
</section>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function SectionHeader({
|
|
53
|
+
...props
|
|
54
|
+
}: Omit<React.ComponentProps<"div">, "className">) {
|
|
55
|
+
return (
|
|
56
|
+
<div
|
|
57
|
+
data-slot="section-header"
|
|
58
|
+
className="flex items-start justify-between gap-4"
|
|
59
|
+
{...props}
|
|
60
|
+
/>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function SectionTitle({
|
|
65
|
+
...props
|
|
66
|
+
}: Omit<React.ComponentProps<typeof Heading>, "className">) {
|
|
67
|
+
return <Heading data-slot="section-title" level="3" {...props} />;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function SectionDescription({
|
|
71
|
+
...props
|
|
72
|
+
}: Omit<React.ComponentProps<typeof Text>, "className">) {
|
|
73
|
+
return (
|
|
74
|
+
<Text
|
|
75
|
+
data-slot="section-description"
|
|
76
|
+
size="sm"
|
|
77
|
+
variant="muted"
|
|
78
|
+
{...props}
|
|
79
|
+
/>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function SectionActions({
|
|
84
|
+
...props
|
|
85
|
+
}: Omit<React.ComponentProps<"div">, "className">) {
|
|
86
|
+
return (
|
|
87
|
+
<div
|
|
88
|
+
data-slot="section-actions"
|
|
89
|
+
className="flex shrink-0 items-center gap-2"
|
|
90
|
+
{...props}
|
|
91
|
+
/>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function SectionContent({
|
|
96
|
+
...props
|
|
97
|
+
}: Omit<React.ComponentProps<"div">, "className">) {
|
|
98
|
+
return <div data-slot="section-content" className="w-full" {...props} />;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export {
|
|
102
|
+
Section,
|
|
103
|
+
SectionActions,
|
|
104
|
+
SectionContent,
|
|
105
|
+
SectionDescription,
|
|
106
|
+
SectionHeader,
|
|
107
|
+
SectionTitle,
|
|
108
|
+
};
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Select as SelectPrimitive } from "@base-ui/react/select";
|
|
4
|
+
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
|
|
7
|
+
const Select = SelectPrimitive.Root;
|
|
8
|
+
|
|
9
|
+
function SelectGroup({
|
|
10
|
+
...props
|
|
11
|
+
}: Omit<SelectPrimitive.Group.Props, "className">) {
|
|
12
|
+
return (
|
|
13
|
+
<SelectPrimitive.Group
|
|
14
|
+
data-slot="select-group"
|
|
15
|
+
className="scroll-my-1 p-1"
|
|
16
|
+
{...props}
|
|
17
|
+
/>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function SelectValue({
|
|
22
|
+
placeholder,
|
|
23
|
+
...props
|
|
24
|
+
}: Omit<SelectPrimitive.Value.Props, "className"> & {
|
|
25
|
+
/** Text to show when no value is selected */
|
|
26
|
+
placeholder?: string;
|
|
27
|
+
}) {
|
|
28
|
+
return (
|
|
29
|
+
<>
|
|
30
|
+
<SelectPrimitive.Value
|
|
31
|
+
data-slot="select-value"
|
|
32
|
+
className="flex-1 text-left data-[placeholder]:hidden"
|
|
33
|
+
{...props}
|
|
34
|
+
/>
|
|
35
|
+
{placeholder && (
|
|
36
|
+
<span
|
|
37
|
+
data-slot="select-placeholder"
|
|
38
|
+
className="text-muted-foreground [[data-slot=select-value]:not([data-placeholder])~&]:hidden"
|
|
39
|
+
>
|
|
40
|
+
{placeholder}
|
|
41
|
+
</span>
|
|
42
|
+
)}
|
|
43
|
+
</>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function SelectTrigger({
|
|
48
|
+
size = "default",
|
|
49
|
+
children,
|
|
50
|
+
...props
|
|
51
|
+
}: Omit<SelectPrimitive.Trigger.Props, "className"> & {
|
|
52
|
+
size?: "sm" | "default";
|
|
53
|
+
}) {
|
|
54
|
+
return (
|
|
55
|
+
<SelectPrimitive.Trigger
|
|
56
|
+
data-slot="select-trigger"
|
|
57
|
+
data-size={size}
|
|
58
|
+
className="border-input data-[placeholder]:text-muted-foreground dark:bg-input/30 dark:hover:bg-input/50 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 gap-1.5 rounded-lg border bg-transparent py-2 pr-2 pl-2.5 text-sm transition-colors select-none focus-visible:ring-[3px] aria-invalid:ring-[3px] data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] *:data-[slot=select-value]:flex *:data-[slot=select-value]:data-[placeholder]:absolute *:data-[slot=select-value]:data-[placeholder]:w-0 *:data-[slot=select-value]:data-[placeholder]:overflow-hidden *:data-[slot=select-value]:gap-1.5 [&_svg:not([class*='size-'])]:size-4 flex w-full items-center justify-between whitespace-nowrap outline-none disabled:cursor-not-allowed disabled:opacity-50 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:items-center [&_svg]:pointer-events-none [&_svg]:shrink-0"
|
|
59
|
+
{...props}
|
|
60
|
+
>
|
|
61
|
+
{children}
|
|
62
|
+
<SelectPrimitive.Icon
|
|
63
|
+
render={
|
|
64
|
+
<ChevronDownIcon className="text-muted-foreground size-4 pointer-events-none" />
|
|
65
|
+
}
|
|
66
|
+
/>
|
|
67
|
+
</SelectPrimitive.Trigger>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function SelectContent({
|
|
72
|
+
children,
|
|
73
|
+
side = "bottom",
|
|
74
|
+
sideOffset = 4,
|
|
75
|
+
align = "center",
|
|
76
|
+
alignOffset = 0,
|
|
77
|
+
alignItemWithTrigger = true,
|
|
78
|
+
...props
|
|
79
|
+
}: Omit<SelectPrimitive.Popup.Props, "className"> &
|
|
80
|
+
Pick<
|
|
81
|
+
SelectPrimitive.Positioner.Props,
|
|
82
|
+
"align" | "alignOffset" | "side" | "sideOffset" | "alignItemWithTrigger"
|
|
83
|
+
>) {
|
|
84
|
+
return (
|
|
85
|
+
<SelectPrimitive.Portal>
|
|
86
|
+
<SelectPrimitive.Positioner
|
|
87
|
+
side={side}
|
|
88
|
+
sideOffset={sideOffset}
|
|
89
|
+
align={align}
|
|
90
|
+
alignOffset={alignOffset}
|
|
91
|
+
alignItemWithTrigger={alignItemWithTrigger}
|
|
92
|
+
className="isolate z-50"
|
|
93
|
+
>
|
|
94
|
+
<SelectPrimitive.Popup
|
|
95
|
+
data-slot="select-content"
|
|
96
|
+
className="bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 min-w-(--anchor-width) max-w-80 rounded-lg p-1 shadow-md ring-1 duration-100 relative isolate z-50 max-h-(--available-height) origin-(--transform-origin) overflow-x-hidden overflow-y-auto"
|
|
97
|
+
{...props}
|
|
98
|
+
>
|
|
99
|
+
<SelectScrollUpButton />
|
|
100
|
+
<SelectPrimitive.List>{children}</SelectPrimitive.List>
|
|
101
|
+
<SelectScrollDownButton />
|
|
102
|
+
</SelectPrimitive.Popup>
|
|
103
|
+
</SelectPrimitive.Positioner>
|
|
104
|
+
</SelectPrimitive.Portal>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function SelectLabel({
|
|
109
|
+
...props
|
|
110
|
+
}: Omit<SelectPrimitive.GroupLabel.Props, "className">) {
|
|
111
|
+
return (
|
|
112
|
+
<SelectPrimitive.GroupLabel
|
|
113
|
+
data-slot="select-label"
|
|
114
|
+
className="text-muted-foreground px-1.5 py-1 text-xs"
|
|
115
|
+
{...props}
|
|
116
|
+
/>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function SelectItem({
|
|
121
|
+
children,
|
|
122
|
+
...props
|
|
123
|
+
}: Omit<SelectPrimitive.Item.Props, "className">) {
|
|
124
|
+
return (
|
|
125
|
+
<SelectPrimitive.Item
|
|
126
|
+
data-slot="select-item"
|
|
127
|
+
className="focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2 relative flex w-full cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0"
|
|
128
|
+
{...props}
|
|
129
|
+
>
|
|
130
|
+
<SelectPrimitive.ItemText className="flex flex-1 gap-2 shrink-0 whitespace-nowrap">
|
|
131
|
+
{children}
|
|
132
|
+
</SelectPrimitive.ItemText>
|
|
133
|
+
<SelectPrimitive.ItemIndicator
|
|
134
|
+
render={
|
|
135
|
+
<span className="pointer-events-none absolute right-2 flex size-4 items-center justify-center" />
|
|
136
|
+
}
|
|
137
|
+
>
|
|
138
|
+
<CheckIcon className="pointer-events-none" />
|
|
139
|
+
</SelectPrimitive.ItemIndicator>
|
|
140
|
+
</SelectPrimitive.Item>
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function SelectSeparator({
|
|
145
|
+
...props
|
|
146
|
+
}: Omit<SelectPrimitive.Separator.Props, "className">) {
|
|
147
|
+
return (
|
|
148
|
+
<SelectPrimitive.Separator
|
|
149
|
+
data-slot="select-separator"
|
|
150
|
+
className="bg-border -mx-1 my-1 h-px pointer-events-none"
|
|
151
|
+
{...props}
|
|
152
|
+
/>
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function SelectScrollUpButton({
|
|
157
|
+
...props
|
|
158
|
+
}: Omit<
|
|
159
|
+
React.ComponentProps<typeof SelectPrimitive.ScrollUpArrow>,
|
|
160
|
+
"className"
|
|
161
|
+
>) {
|
|
162
|
+
return (
|
|
163
|
+
<SelectPrimitive.ScrollUpArrow
|
|
164
|
+
data-slot="select-scroll-up-button"
|
|
165
|
+
className="bg-popover z-10 flex cursor-default items-center justify-center py-1 [&_svg:not([class*='size-'])]:size-4 top-0 w-full"
|
|
166
|
+
{...props}
|
|
167
|
+
>
|
|
168
|
+
<ChevronUpIcon />
|
|
169
|
+
</SelectPrimitive.ScrollUpArrow>
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function SelectScrollDownButton({
|
|
174
|
+
...props
|
|
175
|
+
}: Omit<
|
|
176
|
+
React.ComponentProps<typeof SelectPrimitive.ScrollDownArrow>,
|
|
177
|
+
"className"
|
|
178
|
+
>) {
|
|
179
|
+
return (
|
|
180
|
+
<SelectPrimitive.ScrollDownArrow
|
|
181
|
+
data-slot="select-scroll-down-button"
|
|
182
|
+
className="bg-popover z-10 flex cursor-default items-center justify-center py-1 [&_svg:not([class*='size-'])]:size-4 bottom-0 w-full"
|
|
183
|
+
{...props}
|
|
184
|
+
>
|
|
185
|
+
<ChevronDownIcon />
|
|
186
|
+
</SelectPrimitive.ScrollDownArrow>
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export {
|
|
191
|
+
Select,
|
|
192
|
+
SelectContent,
|
|
193
|
+
SelectGroup,
|
|
194
|
+
SelectItem,
|
|
195
|
+
SelectLabel,
|
|
196
|
+
SelectScrollDownButton,
|
|
197
|
+
SelectScrollUpButton,
|
|
198
|
+
SelectSeparator,
|
|
199
|
+
SelectTrigger,
|
|
200
|
+
SelectValue,
|
|
201
|
+
};
|