create-strayl-web-app 1.0.0
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 +59 -0
- package/dist/index.js.map +1 -0
- package/package.json +39 -0
- package/template/README.md +290 -0
- package/template/components.json +24 -0
- package/template/package.json +56 -0
- package/template/public/favicon.ico +0 -0
- package/template/public/google-logo.svg +6 -0
- package/template/public/logo-dark.ico +0 -0
- package/template/public/logo-dark.webp +0 -0
- package/template/public/logo-light.ico +0 -0
- package/template/public/logo-light.webp +0 -0
- package/template/public/manifest.json +16 -0
- package/template/public/robots.txt +3 -0
- package/template/src/components/Header.tsx +76 -0
- package/template/src/components/language-switcher.tsx +38 -0
- package/template/src/components/theme-provider.tsx +14 -0
- package/template/src/components/themed-logo.tsx +44 -0
- package/template/src/components/ui/accordion.tsx +69 -0
- package/template/src/components/ui/alert-dialog.tsx +169 -0
- package/template/src/components/ui/alert.tsx +80 -0
- package/template/src/components/ui/autocomplete.tsx +301 -0
- package/template/src/components/ui/avatar.tsx +46 -0
- package/template/src/components/ui/badge.tsx +60 -0
- package/template/src/components/ui/breadcrumb.tsx +112 -0
- package/template/src/components/ui/button.tsx +73 -0
- package/template/src/components/ui/card.tsx +244 -0
- package/template/src/components/ui/checkbox-group.tsx +16 -0
- package/template/src/components/ui/checkbox.tsx +60 -0
- package/template/src/components/ui/collapsible.tsx +45 -0
- package/template/src/components/ui/combobox.tsx +415 -0
- package/template/src/components/ui/command.tsx +264 -0
- package/template/src/components/ui/dialog.tsx +196 -0
- package/template/src/components/ui/empty.tsx +127 -0
- package/template/src/components/ui/field.tsx +74 -0
- package/template/src/components/ui/fieldset.tsx +29 -0
- package/template/src/components/ui/form.tsx +17 -0
- package/template/src/components/ui/frame.tsx +82 -0
- package/template/src/components/ui/group.tsx +97 -0
- package/template/src/components/ui/input-group.tsx +101 -0
- package/template/src/components/ui/input.tsx +66 -0
- package/template/src/components/ui/kbd.tsx +28 -0
- package/template/src/components/ui/label.tsx +28 -0
- package/template/src/components/ui/menu.tsx +310 -0
- package/template/src/components/ui/meter.tsx +67 -0
- package/template/src/components/ui/number-field.tsx +160 -0
- package/template/src/components/ui/pagination.tsx +136 -0
- package/template/src/components/ui/popover.tsx +104 -0
- package/template/src/components/ui/preview-card.tsx +55 -0
- package/template/src/components/ui/progress.tsx +81 -0
- package/template/src/components/ui/radio-group.tsx +36 -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 +203 -0
- package/template/src/components/ui/sidebar.tsx +743 -0
- package/template/src/components/ui/skeleton.tsx +16 -0
- package/template/src/components/ui/slider.tsx +74 -0
- package/template/src/components/ui/spinner.tsx +18 -0
- package/template/src/components/ui/switch.tsx +27 -0
- package/template/src/components/ui/table.tsx +126 -0
- package/template/src/components/ui/tabs.tsx +87 -0
- package/template/src/components/ui/textarea.tsx +51 -0
- package/template/src/components/ui/toast.tsx +269 -0
- package/template/src/components/ui/toggle-group.tsx +102 -0
- package/template/src/components/ui/toggle.tsx +45 -0
- package/template/src/components/ui/toolbar.tsx +83 -0
- package/template/src/components/ui/tooltip.tsx +65 -0
- package/template/src/hooks/use-mobile.ts +21 -0
- package/template/src/lib/i18n.ts +70 -0
- package/template/src/lib/utils.ts +6 -0
- package/template/src/routeTree.gen.ts +68 -0
- package/template/src/router.tsx +17 -0
- package/template/src/routes/__root.tsx +62 -0
- package/template/src/routes/index.tsx +71 -0
- package/template/src/styles.css +121 -0
- package/template/tsconfig.json +28 -0
- package/template/vite.config.ts +30 -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 backdrop-blur-sm 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_3fr] 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,127 @@
|
|
|
1
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/lib/utils";
|
|
4
|
+
|
|
5
|
+
function Empty({ className, ...props }: React.ComponentProps<"div">) {
|
|
6
|
+
return (
|
|
7
|
+
<div
|
|
8
|
+
className={cn(
|
|
9
|
+
"flex min-w-0 flex-1 flex-col items-center justify-center gap-6 text-balance p-6 text-center md:p-12",
|
|
10
|
+
className,
|
|
11
|
+
)}
|
|
12
|
+
data-slot="empty"
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function EmptyHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
19
|
+
return (
|
|
20
|
+
<div
|
|
21
|
+
className={cn(
|
|
22
|
+
"flex max-w-sm flex-col items-center text-center",
|
|
23
|
+
className,
|
|
24
|
+
)}
|
|
25
|
+
data-slot="empty-header"
|
|
26
|
+
{...props}
|
|
27
|
+
/>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const emptyMediaVariants = cva(
|
|
32
|
+
"flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
33
|
+
{
|
|
34
|
+
defaultVariants: {
|
|
35
|
+
variant: "default",
|
|
36
|
+
},
|
|
37
|
+
variants: {
|
|
38
|
+
variant: {
|
|
39
|
+
default: "bg-transparent",
|
|
40
|
+
icon: "relative flex size-9 shrink-0 items-center justify-center rounded-md border bg-card text-foreground shadow-sm/5 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-md)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)] [&_svg:not([class*='size-'])]:size-4.5",
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
function EmptyMedia({
|
|
47
|
+
className,
|
|
48
|
+
variant = "default",
|
|
49
|
+
...props
|
|
50
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof emptyMediaVariants>) {
|
|
51
|
+
return (
|
|
52
|
+
<div
|
|
53
|
+
className={cn("relative mb-6", className)}
|
|
54
|
+
data-slot="empty-media"
|
|
55
|
+
data-variant={variant}
|
|
56
|
+
{...props}
|
|
57
|
+
>
|
|
58
|
+
{variant === "icon" && (
|
|
59
|
+
<>
|
|
60
|
+
<div
|
|
61
|
+
aria-hidden="true"
|
|
62
|
+
className={cn(
|
|
63
|
+
emptyMediaVariants({ className, variant }),
|
|
64
|
+
"-translate-x-0.5 -rotate-10 pointer-events-none absolute bottom-px origin-bottom-left scale-84 shadow-none",
|
|
65
|
+
)}
|
|
66
|
+
/>
|
|
67
|
+
<div
|
|
68
|
+
aria-hidden="true"
|
|
69
|
+
className={cn(
|
|
70
|
+
emptyMediaVariants({ className, variant }),
|
|
71
|
+
"pointer-events-none absolute bottom-px origin-bottom-right translate-x-0.5 rotate-10 scale-84 shadow-none",
|
|
72
|
+
)}
|
|
73
|
+
/>
|
|
74
|
+
</>
|
|
75
|
+
)}
|
|
76
|
+
<div
|
|
77
|
+
className={cn(emptyMediaVariants({ className, variant }))}
|
|
78
|
+
{...props}
|
|
79
|
+
/>
|
|
80
|
+
</div>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function EmptyTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
85
|
+
return (
|
|
86
|
+
<div
|
|
87
|
+
className={cn("font-heading font-semibold text-xl", className)}
|
|
88
|
+
data-slot="empty-title"
|
|
89
|
+
{...props}
|
|
90
|
+
/>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function EmptyDescription({ className, ...props }: React.ComponentProps<"p">) {
|
|
95
|
+
return (
|
|
96
|
+
<div
|
|
97
|
+
className={cn(
|
|
98
|
+
"text-muted-foreground text-sm [&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4 [[data-slot=empty-title]+&]:mt-1",
|
|
99
|
+
className,
|
|
100
|
+
)}
|
|
101
|
+
data-slot="empty-description"
|
|
102
|
+
{...props}
|
|
103
|
+
/>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function EmptyContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
108
|
+
return (
|
|
109
|
+
<div
|
|
110
|
+
className={cn(
|
|
111
|
+
"flex w-full min-w-0 max-w-sm flex-col items-center gap-4 text-balance text-sm",
|
|
112
|
+
className,
|
|
113
|
+
)}
|
|
114
|
+
data-slot="empty-content"
|
|
115
|
+
{...props}
|
|
116
|
+
/>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export {
|
|
121
|
+
Empty,
|
|
122
|
+
EmptyHeader,
|
|
123
|
+
EmptyTitle,
|
|
124
|
+
EmptyDescription,
|
|
125
|
+
EmptyContent,
|
|
126
|
+
EmptyMedia,
|
|
127
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Field as FieldPrimitive } from "@base-ui/react/field";
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
|
|
7
|
+
function Field({ className, ...props }: FieldPrimitive.Root.Props) {
|
|
8
|
+
return (
|
|
9
|
+
<FieldPrimitive.Root
|
|
10
|
+
className={cn("flex flex-col items-start gap-2", className)}
|
|
11
|
+
data-slot="field"
|
|
12
|
+
{...props}
|
|
13
|
+
/>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function FieldLabel({ className, ...props }: FieldPrimitive.Label.Props) {
|
|
18
|
+
return (
|
|
19
|
+
<FieldPrimitive.Label
|
|
20
|
+
className={cn(
|
|
21
|
+
"inline-flex items-center gap-2 font-medium text-base/4.5 text-foreground sm:text-sm/4",
|
|
22
|
+
className,
|
|
23
|
+
)}
|
|
24
|
+
data-slot="field-label"
|
|
25
|
+
{...props}
|
|
26
|
+
/>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function FieldItem({ className, ...props }: FieldPrimitive.Item.Props) {
|
|
31
|
+
return (
|
|
32
|
+
<FieldPrimitive.Item
|
|
33
|
+
className={cn("flex", className)}
|
|
34
|
+
data-slot="field-item"
|
|
35
|
+
{...props}
|
|
36
|
+
/>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function FieldDescription({
|
|
41
|
+
className,
|
|
42
|
+
...props
|
|
43
|
+
}: FieldPrimitive.Description.Props) {
|
|
44
|
+
return (
|
|
45
|
+
<FieldPrimitive.Description
|
|
46
|
+
className={cn("text-muted-foreground text-xs", className)}
|
|
47
|
+
data-slot="field-description"
|
|
48
|
+
{...props}
|
|
49
|
+
/>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function FieldError({ className, ...props }: FieldPrimitive.Error.Props) {
|
|
54
|
+
return (
|
|
55
|
+
<FieldPrimitive.Error
|
|
56
|
+
className={cn("text-destructive-foreground text-xs", className)}
|
|
57
|
+
data-slot="field-error"
|
|
58
|
+
{...props}
|
|
59
|
+
/>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const FieldControl = FieldPrimitive.Control;
|
|
64
|
+
const FieldValidity = FieldPrimitive.Validity;
|
|
65
|
+
|
|
66
|
+
export {
|
|
67
|
+
Field,
|
|
68
|
+
FieldLabel,
|
|
69
|
+
FieldDescription,
|
|
70
|
+
FieldError,
|
|
71
|
+
FieldControl,
|
|
72
|
+
FieldItem,
|
|
73
|
+
FieldValidity,
|
|
74
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Fieldset as FieldsetPrimitive } from "@base-ui/react/fieldset";
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
|
|
7
|
+
function Fieldset({ className, ...props }: FieldsetPrimitive.Root.Props) {
|
|
8
|
+
return (
|
|
9
|
+
<FieldsetPrimitive.Root
|
|
10
|
+
className={cn("flex w-full max-w-64 flex-col gap-6", className)}
|
|
11
|
+
data-slot="fieldset"
|
|
12
|
+
{...props}
|
|
13
|
+
/>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
function FieldsetLegend({
|
|
17
|
+
className,
|
|
18
|
+
...props
|
|
19
|
+
}: FieldsetPrimitive.Legend.Props) {
|
|
20
|
+
return (
|
|
21
|
+
<FieldsetPrimitive.Legend
|
|
22
|
+
className={cn("font-semibold text-foreground", className)}
|
|
23
|
+
data-slot="fieldset-legend"
|
|
24
|
+
{...props}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { Fieldset, FieldsetLegend };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Form as FormPrimitive } from "@base-ui/react/form";
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
|
|
7
|
+
function Form({ className, ...props }: FormPrimitive.Props) {
|
|
8
|
+
return (
|
|
9
|
+
<FormPrimitive
|
|
10
|
+
className={cn("flex w-full flex-col gap-4", className)}
|
|
11
|
+
data-slot="form"
|
|
12
|
+
{...props}
|
|
13
|
+
/>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { Form };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/lib/utils";
|
|
4
|
+
|
|
5
|
+
function Frame({ className, ...props }: React.ComponentProps<"div">) {
|
|
6
|
+
return (
|
|
7
|
+
<div
|
|
8
|
+
className={cn(
|
|
9
|
+
"relative flex flex-col rounded-2xl bg-muted/72 p-1",
|
|
10
|
+
"*:[[data-slot=frame-panel]+[data-slot=frame-panel]]:mt-1",
|
|
11
|
+
className,
|
|
12
|
+
)}
|
|
13
|
+
data-slot="frame"
|
|
14
|
+
{...props}
|
|
15
|
+
/>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function FramePanel({ className, ...props }: React.ComponentProps<"div">) {
|
|
20
|
+
return (
|
|
21
|
+
<div
|
|
22
|
+
className={cn(
|
|
23
|
+
"relative rounded-xl border bg-background bg-clip-padding p-5 shadow-xs/5 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-xl)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
|
|
24
|
+
className,
|
|
25
|
+
)}
|
|
26
|
+
data-slot="frame-panel"
|
|
27
|
+
{...props}
|
|
28
|
+
/>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function FrameHeader({ className, ...props }: React.ComponentProps<"header">) {
|
|
33
|
+
return (
|
|
34
|
+
<header
|
|
35
|
+
className={cn("flex flex-col px-5 py-4", className)}
|
|
36
|
+
data-slot="frame-panel-header"
|
|
37
|
+
{...props}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function FrameTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
43
|
+
return (
|
|
44
|
+
<div
|
|
45
|
+
className={cn("font-semibold text-sm", className)}
|
|
46
|
+
data-slot="frame-panel-title"
|
|
47
|
+
{...props}
|
|
48
|
+
/>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function FrameDescription({
|
|
53
|
+
className,
|
|
54
|
+
...props
|
|
55
|
+
}: React.ComponentProps<"div">) {
|
|
56
|
+
return (
|
|
57
|
+
<div
|
|
58
|
+
className={cn("text-muted-foreground text-sm", className)}
|
|
59
|
+
data-slot="frame-panel-description"
|
|
60
|
+
{...props}
|
|
61
|
+
/>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function FrameFooter({ className, ...props }: React.ComponentProps<"footer">) {
|
|
66
|
+
return (
|
|
67
|
+
<footer
|
|
68
|
+
className={cn("px-5 py-4", className)}
|
|
69
|
+
data-slot="frame-panel-footer"
|
|
70
|
+
{...props}
|
|
71
|
+
/>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export {
|
|
76
|
+
Frame,
|
|
77
|
+
FramePanel,
|
|
78
|
+
FrameHeader,
|
|
79
|
+
FrameTitle,
|
|
80
|
+
FrameDescription,
|
|
81
|
+
FrameFooter,
|
|
82
|
+
};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { mergeProps } from "@base-ui/react/merge-props";
|
|
4
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
5
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
6
|
+
import type * as React from "react";
|
|
7
|
+
|
|
8
|
+
import { cn } from "@/lib/utils";
|
|
9
|
+
import { Separator } from "@/components/ui/separator";
|
|
10
|
+
|
|
11
|
+
const groupVariants = cva(
|
|
12
|
+
"flex w-fit *:focus-visible:z-1 has-[>[data-slot=group]]:gap-2 *:has-focus-visible:z-1 dark:*:[[data-slot=button]:hover~[data-slot=separator]:not([data-slot]:hover~[data-slot=separator]~[data-slot=separator]),[data-slot][data-pressed]~[data-slot=separator]:not([data-slot][data-pressed]~[data-slot=separator]~[data-slot=separator])]:before:bg-input/64 dark:*:[[data-slot=separator]:has(~[data-slot=button]:hover):not(:has(~[data-slot=separator]~[data-slot]:hover)),[data-slot=separator]:has(~[data-slot][data-pressed]):not(:has(~[data-slot=separator]~[data-slot][data-pressed]))]:before:bg-input/64",
|
|
13
|
+
{
|
|
14
|
+
defaultVariants: {
|
|
15
|
+
orientation: "horizontal",
|
|
16
|
+
},
|
|
17
|
+
variants: {
|
|
18
|
+
orientation: {
|
|
19
|
+
horizontal:
|
|
20
|
+
"*:[[data-slot]~[data-slot]:not([data-slot=separator])]:before:-start-[0.5px] *:data-slot:not-data-[slot=separator]:has-[~[data-slot]]:before:-end-[0.5px] *:pointer-coarse:after:min-w-auto *:data-slot:has-[~[data-slot]]:rounded-e-none *:data-slot:has-[~[data-slot]]:border-e-0 *:data-slot:has-[~[data-slot]]:before:rounded-e-none *:[[data-slot]~[data-slot]]:rounded-s-none *:[[data-slot]~[data-slot]]:border-s-0 *:[[data-slot]~[data-slot]]:before:rounded-s-none",
|
|
21
|
+
vertical:
|
|
22
|
+
"*:[[data-slot]~[data-slot]:not([data-slot=separator])]:before:-top-[0.5px] *:data-slot:not-data-[slot=separator]:has-[~[data-slot]]:before:-bottom-[0.5px] flex-col *:pointer-coarse:after:min-h-auto *:data-slot:has-[~[data-slot]]:rounded-b-none *:data-slot:has-[~[data-slot]]:border-b-0 *:data-slot:not-data-[slot=separator]:has-[~[data-slot]]:before:hidden *:data-slot:has-[~[data-slot]]:before:rounded-b-none dark:*:last:before:hidden dark:*:first:before:block *:[[data-slot]~[data-slot]]:rounded-t-none *:[[data-slot]~[data-slot]]:border-t-0 *:[[data-slot]~[data-slot]]:before:rounded-t-none",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
function Group({
|
|
29
|
+
className,
|
|
30
|
+
orientation,
|
|
31
|
+
children,
|
|
32
|
+
...props
|
|
33
|
+
}: {
|
|
34
|
+
className?: string;
|
|
35
|
+
orientation?: VariantProps<typeof groupVariants>["orientation"];
|
|
36
|
+
children: React.ReactNode;
|
|
37
|
+
} & React.ComponentProps<"div">) {
|
|
38
|
+
return (
|
|
39
|
+
<div
|
|
40
|
+
className={cn(groupVariants({ orientation }), className)}
|
|
41
|
+
data-orientation={orientation}
|
|
42
|
+
data-slot="group"
|
|
43
|
+
role="group"
|
|
44
|
+
{...props}
|
|
45
|
+
>
|
|
46
|
+
{children}
|
|
47
|
+
</div>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function GroupText({
|
|
52
|
+
className,
|
|
53
|
+
render,
|
|
54
|
+
...props
|
|
55
|
+
}: useRender.ComponentProps<"div">) {
|
|
56
|
+
const defaultProps = {
|
|
57
|
+
className: cn(
|
|
58
|
+
"relative inline-flex items-center whitespace-nowrap rounded-lg border border-input bg-muted not-dark:bg-clip-padding px-[calc(--spacing(3)-1px)] text-muted-foreground text-base sm:text-sm shadow-xs/5 outline-none transition-shadow 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:bg-input/64 dark:before:shadow-[0_-1px_--theme(--color-white/6%)] [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 [&_svg]:-mx-0.5",
|
|
59
|
+
className,
|
|
60
|
+
),
|
|
61
|
+
"data-slot": "group-text",
|
|
62
|
+
};
|
|
63
|
+
return useRender({
|
|
64
|
+
defaultTagName: "div",
|
|
65
|
+
props: mergeProps(defaultProps, props),
|
|
66
|
+
render,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function GroupSeparator({
|
|
71
|
+
className,
|
|
72
|
+
orientation = "vertical",
|
|
73
|
+
...props
|
|
74
|
+
}: {
|
|
75
|
+
className?: string;
|
|
76
|
+
} & React.ComponentProps<typeof Separator>) {
|
|
77
|
+
return (
|
|
78
|
+
<Separator
|
|
79
|
+
className={cn(
|
|
80
|
+
"[[data-slot=input-control]:focus-within+&,[data-slot=input-group]:focus-within+&,[data-slot=select-trigger]:focus-visible+*+&,[data-slot=number-field]:focus-within+input+&]:-translate-x-px pointer-events-none relative z-2 bg-input before:absolute before:inset-0 has-[+[data-slot=input-control]:focus-within,+[data-slot=input-group]:focus-within,+[data-slot=select-trigger]:focus-visible+*,+[data-slot=number-field]:focus-within]:translate-x-px has-[+[data-slot=input-control]:focus-within,+[data-slot=input-group]:focus-within,+[data-slot=select-trigger]:focus-visible+*,+[data-slot=number-field]:focus-within]:bg-ring dark:before:bg-input/32 [[data-slot=input-control]:focus-within+&,[data-slot=input-group]:focus-within+&,[data-slot=select-trigger]:focus-visible+*+&,[data-slot=number-field]:focus-within+&,[data-slot=number-field]:focus-within+input+&]:bg-ring",
|
|
81
|
+
className,
|
|
82
|
+
)}
|
|
83
|
+
orientation={orientation}
|
|
84
|
+
{...props}
|
|
85
|
+
/>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export {
|
|
90
|
+
Group,
|
|
91
|
+
Group as ButtonGroup,
|
|
92
|
+
GroupText,
|
|
93
|
+
GroupText as ButtonGroupText,
|
|
94
|
+
GroupSeparator,
|
|
95
|
+
GroupSeparator as ButtonGroupSeparator,
|
|
96
|
+
groupVariants,
|
|
97
|
+
};
|