create-strayl-app 1.0.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/dist/index.js +62 -0
- package/dist/index.js.map +1 -0
- package/package.json +39 -0
- package/template/components.json +21 -0
- package/template/gitignore +10 -0
- package/template/package.json +37 -0
- package/template/public/favicon.ico +1 -0
- package/template/src/components/theme-provider.tsx +21 -0
- package/template/src/components/ui/badge.tsx +60 -0
- package/template/src/components/ui/button.tsx +73 -0
- package/template/src/components/ui/card.tsx +244 -0
- package/template/src/components/ui/dialog.tsx +196 -0
- package/template/src/components/ui/input.tsx +66 -0
- package/template/src/components/ui/label.tsx +28 -0
- package/template/src/components/ui/scroll-area.tsx +64 -0
- package/template/src/components/ui/select.tsx +180 -0
- package/template/src/components/ui/separator.tsx +23 -0
- package/template/src/components/ui/sheet.tsx +204 -0
- package/template/src/components/ui/textarea.tsx +51 -0
- package/template/src/hooks/use-mobile.ts +21 -0
- package/template/src/lib/utils.ts +6 -0
- package/template/src/routeTree.gen.ts +76 -0
- package/template/src/router.tsx +18 -0
- package/template/src/routes/__root.tsx +33 -0
- package/template/src/routes/index.tsx +30 -0
- package/template/src/styles.css +156 -0
- package/template/tsconfig.json +19 -0
- package/template/vite.config.ts +16 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
|
|
4
|
+
import { XIcon } from "lucide-react";
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
import { Button } from "@/components/ui/button";
|
|
7
|
+
import { ScrollArea } from "@/components/ui/scroll-area";
|
|
8
|
+
|
|
9
|
+
const DialogCreateHandle = DialogPrimitive.createHandle;
|
|
10
|
+
|
|
11
|
+
const Dialog = DialogPrimitive.Root;
|
|
12
|
+
|
|
13
|
+
const DialogPortal = DialogPrimitive.Portal;
|
|
14
|
+
|
|
15
|
+
function DialogTrigger(props: DialogPrimitive.Trigger.Props) {
|
|
16
|
+
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function DialogClose(props: DialogPrimitive.Close.Props) {
|
|
20
|
+
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function DialogBackdrop({
|
|
24
|
+
className,
|
|
25
|
+
...props
|
|
26
|
+
}: DialogPrimitive.Backdrop.Props) {
|
|
27
|
+
return (
|
|
28
|
+
<DialogPrimitive.Backdrop
|
|
29
|
+
className={cn(
|
|
30
|
+
"fixed inset-0 z-50 bg-black/32 transition-all duration-200 data-ending-style:opacity-0 data-starting-style:opacity-0",
|
|
31
|
+
className,
|
|
32
|
+
)}
|
|
33
|
+
data-slot="dialog-backdrop"
|
|
34
|
+
{...props}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function DialogViewport({
|
|
40
|
+
className,
|
|
41
|
+
...props
|
|
42
|
+
}: DialogPrimitive.Viewport.Props) {
|
|
43
|
+
return (
|
|
44
|
+
<DialogPrimitive.Viewport
|
|
45
|
+
className={cn(
|
|
46
|
+
"fixed inset-0 z-50 grid grid-rows-[1fr_auto_1fr] justify-items-center p-4",
|
|
47
|
+
className,
|
|
48
|
+
)}
|
|
49
|
+
data-slot="dialog-viewport"
|
|
50
|
+
{...props}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function DialogPopup({
|
|
56
|
+
className,
|
|
57
|
+
children,
|
|
58
|
+
showCloseButton = true,
|
|
59
|
+
bottomStickOnMobile = true,
|
|
60
|
+
...props
|
|
61
|
+
}: DialogPrimitive.Popup.Props & {
|
|
62
|
+
showCloseButton?: boolean;
|
|
63
|
+
bottomStickOnMobile?: boolean;
|
|
64
|
+
}) {
|
|
65
|
+
return (
|
|
66
|
+
<DialogPortal>
|
|
67
|
+
<DialogBackdrop />
|
|
68
|
+
<DialogViewport
|
|
69
|
+
className={cn(
|
|
70
|
+
bottomStickOnMobile &&
|
|
71
|
+
"max-sm:grid-rows-[1fr_auto] max-sm:p-0 max-sm:pt-12",
|
|
72
|
+
)}
|
|
73
|
+
>
|
|
74
|
+
<DialogPrimitive.Popup
|
|
75
|
+
className={cn(
|
|
76
|
+
"-translate-y-[calc(1.25rem*var(--nested-dialogs))] relative row-start-2 flex max-h-full min-h-0 w-full min-w-0 max-w-lg scale-[calc(1-0.1*var(--nested-dialogs))] flex-col rounded-2xl border bg-popover not-dark:bg-clip-padding text-popover-foreground opacity-[calc(1-0.1*var(--nested-dialogs))] shadow-lg/5 transition-[scale,opacity,translate] duration-200 ease-in-out will-change-transform before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-2xl)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] data-nested:data-ending-style:translate-y-8 data-nested:data-starting-style:translate-y-8 data-nested-dialog-open:origin-top data-ending-style:scale-98 data-starting-style:scale-98 data-ending-style:opacity-0 data-starting-style:opacity-0 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
|
77
|
+
bottomStickOnMobile &&
|
|
78
|
+
"max-sm:max-w-none max-sm:rounded-none max-sm:border-x-0 max-sm:border-t max-sm:border-b-0 max-sm:opacity-[calc(1-min(var(--nested-dialogs),1))] max-sm:data-ending-style:translate-y-4 max-sm:data-starting-style:translate-y-4 max-sm:before:hidden max-sm:before:rounded-none",
|
|
79
|
+
className,
|
|
80
|
+
)}
|
|
81
|
+
data-slot="dialog-popup"
|
|
82
|
+
{...props}
|
|
83
|
+
>
|
|
84
|
+
{children}
|
|
85
|
+
{showCloseButton && (
|
|
86
|
+
<DialogPrimitive.Close
|
|
87
|
+
aria-label="Close"
|
|
88
|
+
className="absolute end-2 top-2"
|
|
89
|
+
render={<Button size="icon" variant="ghost" />}
|
|
90
|
+
>
|
|
91
|
+
<XIcon />
|
|
92
|
+
</DialogPrimitive.Close>
|
|
93
|
+
)}
|
|
94
|
+
</DialogPrimitive.Popup>
|
|
95
|
+
</DialogViewport>
|
|
96
|
+
</DialogPortal>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
101
|
+
return (
|
|
102
|
+
<div
|
|
103
|
+
className={cn(
|
|
104
|
+
"flex flex-col gap-2 p-6 in-[[data-slot=dialog-popup]:has([data-slot=dialog-panel])]:pb-3 max-sm:pb-4",
|
|
105
|
+
className,
|
|
106
|
+
)}
|
|
107
|
+
data-slot="dialog-header"
|
|
108
|
+
{...props}
|
|
109
|
+
/>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function DialogFooter({
|
|
114
|
+
className,
|
|
115
|
+
variant = "default",
|
|
116
|
+
...props
|
|
117
|
+
}: React.ComponentProps<"div"> & {
|
|
118
|
+
variant?: "default" | "bare";
|
|
119
|
+
}) {
|
|
120
|
+
return (
|
|
121
|
+
<div
|
|
122
|
+
className={cn(
|
|
123
|
+
"flex flex-col-reverse gap-2 px-6 sm:flex-row sm:justify-end sm:rounded-b-[calc(var(--radius-2xl)-1px)]",
|
|
124
|
+
variant === "default" && "border-t bg-muted/72 py-4",
|
|
125
|
+
variant === "bare" &&
|
|
126
|
+
"in-[[data-slot=dialog-popup]:has([data-slot=dialog-panel])]:pt-3 pt-4 pb-6",
|
|
127
|
+
className,
|
|
128
|
+
)}
|
|
129
|
+
data-slot="dialog-footer"
|
|
130
|
+
{...props}
|
|
131
|
+
/>
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {
|
|
136
|
+
return (
|
|
137
|
+
<DialogPrimitive.Title
|
|
138
|
+
className={cn(
|
|
139
|
+
"font-heading font-semibold text-xl leading-none",
|
|
140
|
+
className,
|
|
141
|
+
)}
|
|
142
|
+
data-slot="dialog-title"
|
|
143
|
+
{...props}
|
|
144
|
+
/>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function DialogDescription({
|
|
149
|
+
className,
|
|
150
|
+
...props
|
|
151
|
+
}: DialogPrimitive.Description.Props) {
|
|
152
|
+
return (
|
|
153
|
+
<DialogPrimitive.Description
|
|
154
|
+
className={cn("text-muted-foreground text-sm", className)}
|
|
155
|
+
data-slot="dialog-description"
|
|
156
|
+
{...props}
|
|
157
|
+
/>
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function DialogPanel({
|
|
162
|
+
className,
|
|
163
|
+
scrollFade = true,
|
|
164
|
+
...props
|
|
165
|
+
}: React.ComponentProps<"div"> & { scrollFade?: boolean }) {
|
|
166
|
+
return (
|
|
167
|
+
<ScrollArea scrollFade={scrollFade}>
|
|
168
|
+
<div
|
|
169
|
+
className={cn(
|
|
170
|
+
"p-6 in-[[data-slot=dialog-popup]:has([data-slot=dialog-header])]:pt-1 in-[[data-slot=dialog-popup]:has([data-slot=dialog-footer]:not(.border-t))]:pb-1",
|
|
171
|
+
className,
|
|
172
|
+
)}
|
|
173
|
+
data-slot="dialog-panel"
|
|
174
|
+
{...props}
|
|
175
|
+
/>
|
|
176
|
+
</ScrollArea>
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export {
|
|
181
|
+
DialogCreateHandle,
|
|
182
|
+
Dialog,
|
|
183
|
+
DialogTrigger,
|
|
184
|
+
DialogPortal,
|
|
185
|
+
DialogClose,
|
|
186
|
+
DialogBackdrop,
|
|
187
|
+
DialogBackdrop as DialogOverlay,
|
|
188
|
+
DialogPopup,
|
|
189
|
+
DialogPopup as DialogContent,
|
|
190
|
+
DialogHeader,
|
|
191
|
+
DialogFooter,
|
|
192
|
+
DialogTitle,
|
|
193
|
+
DialogDescription,
|
|
194
|
+
DialogPanel,
|
|
195
|
+
DialogViewport,
|
|
196
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Input as InputPrimitive } from "@base-ui/react/input";
|
|
4
|
+
import type * as React from "react";
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils";
|
|
7
|
+
|
|
8
|
+
type InputProps = Omit<
|
|
9
|
+
InputPrimitive.Props & React.RefAttributes<HTMLInputElement>,
|
|
10
|
+
"size"
|
|
11
|
+
> & {
|
|
12
|
+
size?: "sm" | "default" | "lg" | number;
|
|
13
|
+
unstyled?: boolean;
|
|
14
|
+
nativeInput?: boolean;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function Input({
|
|
18
|
+
className,
|
|
19
|
+
size = "default",
|
|
20
|
+
unstyled = false,
|
|
21
|
+
nativeInput = false,
|
|
22
|
+
...props
|
|
23
|
+
}: InputProps) {
|
|
24
|
+
const inputClassName = cn(
|
|
25
|
+
"h-8.5 w-full min-w-0 rounded-[inherit] px-[calc(--spacing(3)-1px)] leading-8.5 outline-none placeholder:text-muted-foreground/72 sm:h-7.5 sm:leading-7.5",
|
|
26
|
+
size === "sm" &&
|
|
27
|
+
"h-7.5 px-[calc(--spacing(2.5)-1px)] leading-7.5 sm:h-6.5 sm:leading-6.5",
|
|
28
|
+
size === "lg" && "h-9.5 leading-9.5 sm:h-8.5 sm:leading-8.5",
|
|
29
|
+
props.type === "search" &&
|
|
30
|
+
"[&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none [&::-webkit-search-results-button]:appearance-none [&::-webkit-search-results-decoration]:appearance-none",
|
|
31
|
+
props.type === "file" &&
|
|
32
|
+
"text-muted-foreground file:me-3 file:bg-transparent file:font-medium file:text-foreground file:text-sm",
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<span
|
|
37
|
+
className={
|
|
38
|
+
cn(
|
|
39
|
+
!unstyled &&
|
|
40
|
+
"relative inline-flex w-full rounded-lg border border-input bg-background not-dark:bg-clip-padding text-base text-foreground shadow-xs/5 ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-has-disabled:not-has-focus-visible:not-has-aria-invalid:before:shadow-[0_1px_--theme(--color-black/6%)] has-focus-visible:has-aria-invalid:border-destructive/64 has-focus-visible:has-aria-invalid:ring-destructive/16 has-aria-invalid:border-destructive/36 has-focus-visible:border-ring has-disabled:opacity-64 has-[:disabled,:focus-visible,[aria-invalid]]:shadow-none has-focus-visible:ring-[3px] sm:text-sm dark:bg-input/32 dark:has-aria-invalid:ring-destructive/24 dark:not-has-disabled:not-has-focus-visible:not-has-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
|
41
|
+
className,
|
|
42
|
+
) || undefined
|
|
43
|
+
}
|
|
44
|
+
data-size={size}
|
|
45
|
+
data-slot="input-control"
|
|
46
|
+
>
|
|
47
|
+
{nativeInput ? (
|
|
48
|
+
<input
|
|
49
|
+
className={inputClassName}
|
|
50
|
+
data-slot="input"
|
|
51
|
+
size={typeof size === "number" ? size : undefined}
|
|
52
|
+
{...props}
|
|
53
|
+
/>
|
|
54
|
+
) : (
|
|
55
|
+
<InputPrimitive
|
|
56
|
+
className={inputClassName}
|
|
57
|
+
data-slot="input"
|
|
58
|
+
size={typeof size === "number" ? size : undefined}
|
|
59
|
+
{...props}
|
|
60
|
+
/>
|
|
61
|
+
)}
|
|
62
|
+
</span>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { Input, type InputProps };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { mergeProps } from "@base-ui/react/merge-props";
|
|
4
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils";
|
|
7
|
+
|
|
8
|
+
function Label({
|
|
9
|
+
className,
|
|
10
|
+
render,
|
|
11
|
+
...props
|
|
12
|
+
}: useRender.ComponentProps<"label">) {
|
|
13
|
+
const defaultProps = {
|
|
14
|
+
className: cn(
|
|
15
|
+
"inline-flex items-center gap-2 text-base/4.5 sm:text-sm/4 font-medium text-foreground",
|
|
16
|
+
className,
|
|
17
|
+
),
|
|
18
|
+
"data-slot": "label",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
return useRender({
|
|
22
|
+
defaultTagName: "label",
|
|
23
|
+
props: mergeProps<"label">(defaultProps, props),
|
|
24
|
+
render,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { Label };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { ScrollArea as ScrollAreaPrimitive } from "@base-ui/react/scroll-area";
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
|
|
7
|
+
function ScrollArea({
|
|
8
|
+
className,
|
|
9
|
+
children,
|
|
10
|
+
scrollFade = false,
|
|
11
|
+
scrollbarGutter = false,
|
|
12
|
+
...props
|
|
13
|
+
}: ScrollAreaPrimitive.Root.Props & {
|
|
14
|
+
scrollFade?: boolean;
|
|
15
|
+
scrollbarGutter?: boolean;
|
|
16
|
+
}) {
|
|
17
|
+
return (
|
|
18
|
+
<ScrollAreaPrimitive.Root
|
|
19
|
+
className={cn("size-full min-h-0", className)}
|
|
20
|
+
{...props}
|
|
21
|
+
>
|
|
22
|
+
<ScrollAreaPrimitive.Viewport
|
|
23
|
+
className={cn(
|
|
24
|
+
"h-full rounded-[inherit] outline-none transition-shadows focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background data-has-overflow-x:overscroll-x-contain",
|
|
25
|
+
scrollFade &&
|
|
26
|
+
"mask-t-from-[calc(100%-min(var(--fade-size),var(--scroll-area-overflow-y-start)))] mask-b-from-[calc(100%-min(var(--fade-size),var(--scroll-area-overflow-y-end)))] mask-l-from-[calc(100%-min(var(--fade-size),var(--scroll-area-overflow-x-start)))] mask-r-from-[calc(100%-min(var(--fade-size),var(--scroll-area-overflow-x-end)))] [--fade-size:1.5rem]",
|
|
27
|
+
scrollbarGutter &&
|
|
28
|
+
"data-has-overflow-y:pe-2.5 data-has-overflow-x:pb-2.5",
|
|
29
|
+
)}
|
|
30
|
+
data-slot="scroll-area-viewport"
|
|
31
|
+
>
|
|
32
|
+
{children}
|
|
33
|
+
</ScrollAreaPrimitive.Viewport>
|
|
34
|
+
<ScrollBar orientation="vertical" />
|
|
35
|
+
<ScrollBar orientation="horizontal" />
|
|
36
|
+
<ScrollAreaPrimitive.Corner data-slot="scroll-area-corner" />
|
|
37
|
+
</ScrollAreaPrimitive.Root>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function ScrollBar({
|
|
42
|
+
className,
|
|
43
|
+
orientation = "vertical",
|
|
44
|
+
...props
|
|
45
|
+
}: ScrollAreaPrimitive.Scrollbar.Props) {
|
|
46
|
+
return (
|
|
47
|
+
<ScrollAreaPrimitive.Scrollbar
|
|
48
|
+
className={cn(
|
|
49
|
+
"m-1 flex opacity-0 transition-opacity delay-300 data-[orientation=horizontal]:h-1.5 data-[orientation=vertical]:w-1.5 data-[orientation=horizontal]:flex-col data-hovering:opacity-100 data-scrolling:opacity-100 data-hovering:delay-0 data-scrolling:delay-0 data-hovering:duration-100 data-scrolling:duration-100",
|
|
50
|
+
className,
|
|
51
|
+
)}
|
|
52
|
+
data-slot="scroll-area-scrollbar"
|
|
53
|
+
orientation={orientation}
|
|
54
|
+
{...props}
|
|
55
|
+
>
|
|
56
|
+
<ScrollAreaPrimitive.Thumb
|
|
57
|
+
className="relative flex-1 rounded-full bg-foreground/20"
|
|
58
|
+
data-slot="scroll-area-thumb"
|
|
59
|
+
/>
|
|
60
|
+
</ScrollAreaPrimitive.Scrollbar>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { ScrollArea, ScrollBar };
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Select as SelectPrimitive } from "@base-ui/react/select";
|
|
4
|
+
import {
|
|
5
|
+
ChevronDownIcon,
|
|
6
|
+
ChevronsUpDownIcon,
|
|
7
|
+
ChevronUpIcon,
|
|
8
|
+
} from "lucide-react";
|
|
9
|
+
|
|
10
|
+
import { cn } from "@/lib/utils";
|
|
11
|
+
|
|
12
|
+
const Select = SelectPrimitive.Root;
|
|
13
|
+
|
|
14
|
+
function SelectTrigger({
|
|
15
|
+
className,
|
|
16
|
+
size = "default",
|
|
17
|
+
children,
|
|
18
|
+
...props
|
|
19
|
+
}: SelectPrimitive.Trigger.Props & {
|
|
20
|
+
size?: "sm" | "default" | "lg";
|
|
21
|
+
}) {
|
|
22
|
+
return (
|
|
23
|
+
<SelectPrimitive.Trigger
|
|
24
|
+
className={cn(
|
|
25
|
+
"relative inline-flex min-h-9 w-full min-w-36 select-none items-center justify-center gap-2 rounded-lg border border-input bg-background not-dark:bg-clip-padding px-[calc(--spacing(3)-1px)] text-left text-base text-foreground shadow-xs/5 outline-none ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-data-disabled:not-focus-visible:not-aria-invalid:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 focus-visible:border-ring focus-visible:ring-[3px] aria-invalid:border-destructive/36 focus-visible:aria-invalid:border-destructive/64 focus-visible:aria-invalid:ring-destructive/16 data-disabled:pointer-events-none data-disabled:opacity-64 sm:min-h-8 sm:text-sm dark:bg-input/32 dark:aria-invalid:ring-destructive/24 dark:not-data-disabled:not-focus-visible:not-aria-invalid:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [&_svg:not([class*='opacity-'])]:opacity-80 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0 [[data-disabled],:focus-visible,[aria-invalid],[data-pressed]]:shadow-none",
|
|
26
|
+
size === "sm" &&
|
|
27
|
+
"min-h-8 gap-1.5 px-[calc(--spacing(2.5)-1px)] sm:min-h-7",
|
|
28
|
+
size === "lg" && "min-h-10 sm:min-h-9",
|
|
29
|
+
className,
|
|
30
|
+
)}
|
|
31
|
+
data-slot="select-trigger"
|
|
32
|
+
{...props}
|
|
33
|
+
>
|
|
34
|
+
{children}
|
|
35
|
+
<SelectPrimitive.Icon data-slot="select-icon">
|
|
36
|
+
<ChevronsUpDownIcon className="-me-1 size-4.5 opacity-80 sm:size-4" />
|
|
37
|
+
</SelectPrimitive.Icon>
|
|
38
|
+
</SelectPrimitive.Trigger>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function SelectValue({ className, ...props }: SelectPrimitive.Value.Props) {
|
|
43
|
+
return (
|
|
44
|
+
<SelectPrimitive.Value
|
|
45
|
+
className={cn(
|
|
46
|
+
"flex-1 truncate data-placeholder:text-muted-foreground",
|
|
47
|
+
className,
|
|
48
|
+
)}
|
|
49
|
+
data-slot="select-value"
|
|
50
|
+
{...props}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function SelectPopup({
|
|
56
|
+
className,
|
|
57
|
+
children,
|
|
58
|
+
sideOffset = 4,
|
|
59
|
+
alignItemWithTrigger = true,
|
|
60
|
+
...props
|
|
61
|
+
}: SelectPrimitive.Popup.Props & {
|
|
62
|
+
sideOffset?: SelectPrimitive.Positioner.Props["sideOffset"];
|
|
63
|
+
alignItemWithTrigger?: SelectPrimitive.Positioner.Props["alignItemWithTrigger"];
|
|
64
|
+
}) {
|
|
65
|
+
return (
|
|
66
|
+
<SelectPrimitive.Portal>
|
|
67
|
+
<SelectPrimitive.Positioner
|
|
68
|
+
alignItemWithTrigger={alignItemWithTrigger}
|
|
69
|
+
className="z-50 select-none"
|
|
70
|
+
data-slot="select-positioner"
|
|
71
|
+
sideOffset={sideOffset}
|
|
72
|
+
>
|
|
73
|
+
<SelectPrimitive.Popup
|
|
74
|
+
className="origin-(--transform-origin) text-foreground"
|
|
75
|
+
data-slot="select-popup"
|
|
76
|
+
{...props}
|
|
77
|
+
>
|
|
78
|
+
<SelectPrimitive.ScrollUpArrow
|
|
79
|
+
className="top-0 z-50 flex h-6 w-full cursor-default items-center justify-center before:pointer-events-none before:absolute before:inset-x-px before:top-px before:h-[200%] before:rounded-t-[calc(var(--radius-lg)-1px)] before:bg-linear-to-b before:from-50% before:from-popover"
|
|
80
|
+
data-slot="select-scroll-up-arrow"
|
|
81
|
+
>
|
|
82
|
+
<ChevronUpIcon className="relative size-4.5 sm:size-4" />
|
|
83
|
+
</SelectPrimitive.ScrollUpArrow>
|
|
84
|
+
<div className="relative h-full rounded-lg border bg-popover not-dark:bg-clip-padding shadow-lg/5 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)]">
|
|
85
|
+
<SelectPrimitive.List
|
|
86
|
+
className={cn(
|
|
87
|
+
"max-h-(--available-height) min-w-(--anchor-width) overflow-y-auto p-1",
|
|
88
|
+
className,
|
|
89
|
+
)}
|
|
90
|
+
data-slot="select-list"
|
|
91
|
+
>
|
|
92
|
+
{children}
|
|
93
|
+
</SelectPrimitive.List>
|
|
94
|
+
</div>
|
|
95
|
+
<SelectPrimitive.ScrollDownArrow
|
|
96
|
+
className="bottom-0 z-50 flex h-6 w-full cursor-default items-center justify-center before:pointer-events-none before:absolute before:inset-x-px before:bottom-px before:h-[200%] before:rounded-b-[calc(var(--radius-lg)-1px)] before:bg-linear-to-t before:from-50% before:from-popover"
|
|
97
|
+
data-slot="select-scroll-down-arrow"
|
|
98
|
+
>
|
|
99
|
+
<ChevronDownIcon className="relative size-4.5 sm:size-4" />
|
|
100
|
+
</SelectPrimitive.ScrollDownArrow>
|
|
101
|
+
</SelectPrimitive.Popup>
|
|
102
|
+
</SelectPrimitive.Positioner>
|
|
103
|
+
</SelectPrimitive.Portal>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function SelectItem({
|
|
108
|
+
className,
|
|
109
|
+
children,
|
|
110
|
+
...props
|
|
111
|
+
}: SelectPrimitive.Item.Props) {
|
|
112
|
+
return (
|
|
113
|
+
<SelectPrimitive.Item
|
|
114
|
+
className={cn(
|
|
115
|
+
"grid min-h-8 in-data-[side=none]:min-w-[calc(var(--anchor-width)+1.25rem)] cursor-default grid-cols-[1rem_1fr] items-center gap-2 rounded-sm py-1 ps-2 pe-4 text-base outline-none data-disabled:pointer-events-none data-highlighted:bg-accent data-highlighted:text-accent-foreground data-disabled:opacity-64 sm:min-h-7 sm:text-sm [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
116
|
+
className,
|
|
117
|
+
)}
|
|
118
|
+
data-slot="select-item"
|
|
119
|
+
{...props}
|
|
120
|
+
>
|
|
121
|
+
<SelectPrimitive.ItemIndicator className="col-start-1">
|
|
122
|
+
<svg
|
|
123
|
+
fill="none"
|
|
124
|
+
height="24"
|
|
125
|
+
stroke="currentColor"
|
|
126
|
+
strokeLinecap="round"
|
|
127
|
+
strokeLinejoin="round"
|
|
128
|
+
strokeWidth="2"
|
|
129
|
+
viewBox="0 0 24 24"
|
|
130
|
+
width="24"
|
|
131
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
132
|
+
>
|
|
133
|
+
<path d="M5.252 12.7 10.2 18.63 18.748 5.37" />
|
|
134
|
+
</svg>
|
|
135
|
+
</SelectPrimitive.ItemIndicator>
|
|
136
|
+
<SelectPrimitive.ItemText className="col-start-2 min-w-0">
|
|
137
|
+
{children}
|
|
138
|
+
</SelectPrimitive.ItemText>
|
|
139
|
+
</SelectPrimitive.Item>
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function SelectSeparator({
|
|
144
|
+
className,
|
|
145
|
+
...props
|
|
146
|
+
}: SelectPrimitive.Separator.Props) {
|
|
147
|
+
return (
|
|
148
|
+
<SelectPrimitive.Separator
|
|
149
|
+
className={cn("mx-2 my-1 h-px bg-border", className)}
|
|
150
|
+
data-slot="select-separator"
|
|
151
|
+
{...props}
|
|
152
|
+
/>
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function SelectGroup(props: SelectPrimitive.Group.Props) {
|
|
157
|
+
return <SelectPrimitive.Group data-slot="select-group" {...props} />;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function SelectGroupLabel(props: SelectPrimitive.GroupLabel.Props) {
|
|
161
|
+
return (
|
|
162
|
+
<SelectPrimitive.GroupLabel
|
|
163
|
+
className="px-2 py-1.5 font-medium text-muted-foreground text-xs"
|
|
164
|
+
data-slot="select-group-label"
|
|
165
|
+
{...props}
|
|
166
|
+
/>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export {
|
|
171
|
+
Select,
|
|
172
|
+
SelectTrigger,
|
|
173
|
+
SelectValue,
|
|
174
|
+
SelectPopup,
|
|
175
|
+
SelectPopup as SelectContent,
|
|
176
|
+
SelectItem,
|
|
177
|
+
SelectSeparator,
|
|
178
|
+
SelectGroup,
|
|
179
|
+
SelectGroupLabel,
|
|
180
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Separator as SeparatorPrimitive } from "@base-ui/react/separator";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/lib/utils";
|
|
4
|
+
|
|
5
|
+
function Separator({
|
|
6
|
+
className,
|
|
7
|
+
orientation = "horizontal",
|
|
8
|
+
...props
|
|
9
|
+
}: SeparatorPrimitive.Props) {
|
|
10
|
+
return (
|
|
11
|
+
<SeparatorPrimitive
|
|
12
|
+
className={cn(
|
|
13
|
+
"shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px data-[orientation=vertical]:not-[[class^='h-']]:not-[[class*='_h-']]:self-stretch",
|
|
14
|
+
className,
|
|
15
|
+
)}
|
|
16
|
+
data-slot="separator"
|
|
17
|
+
orientation={orientation}
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { Separator };
|