create-bdpamke-react-scaffold 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/LICENSE +21 -0
- package/README.md +62 -0
- package/bin/create-bdpamke-react-scaffold.js +101 -0
- package/package.json +39 -0
- package/template/.env.example +6 -0
- package/template/FUNCTIONS_EXAMPLES.md +480 -0
- package/template/HOWTOadd a page.md +166 -0
- package/template/REACT_PROPS_USEEFFECT.md +210 -0
- package/template/REGISTRATION_FLOW.md +268 -0
- package/template/USESTATE_EXAMPLES.md +451 -0
- package/template/components.json +20 -0
- package/template/index.html +13 -0
- package/template/jsconfig.json +19 -0
- package/template/package-lock.json +5988 -0
- package/template/package.json +73 -0
- package/template/postcss.config.cjs +6 -0
- package/template/public/images/BDPA_edited.png +0 -0
- package/template/server/server.js +86 -0
- package/template/server/utils/apiClient.js +59 -0
- package/template/server/utils/password.js +60 -0
- package/template/src/App.jsx +10 -0
- package/template/src/components/layout/Container.jsx +7 -0
- package/template/src/components/layout/Section.jsx +7 -0
- package/template/src/components/ui/accordion.jsx +41 -0
- package/template/src/components/ui/alert-dialog.jsx +99 -0
- package/template/src/components/ui/alert.jsx +47 -0
- package/template/src/components/ui/aspect-ratio.jsx +5 -0
- package/template/src/components/ui/avatar.jsx +35 -0
- package/template/src/components/ui/badge.jsx +34 -0
- package/template/src/components/ui/button.jsx +47 -0
- package/template/src/components/ui/calendar.jsx +173 -0
- package/template/src/components/ui/card.jsx +50 -0
- package/template/src/components/ui/carousel.jsx +194 -0
- package/template/src/components/ui/checkbox.jsx +22 -0
- package/template/src/components/ui/collapsible.jsx +11 -0
- package/template/src/components/ui/command.jsx +116 -0
- package/template/src/components/ui/dialog.jsx +94 -0
- package/template/src/components/ui/drawer.jsx +92 -0
- package/template/src/components/ui/dropdown-menu.jsx +155 -0
- package/template/src/components/ui/form.jsx +138 -0
- package/template/src/components/ui/hover-card.jsx +25 -0
- package/template/src/components/ui/icons.jsx +81 -0
- package/template/src/components/ui/input.jsx +19 -0
- package/template/src/components/ui/label.jsx +16 -0
- package/template/src/components/ui/menubar.jsx +200 -0
- package/template/src/components/ui/navigation-menu.jsx +104 -0
- package/template/src/components/ui/popover.jsx +25 -0
- package/template/src/components/ui/progress.jsx +20 -0
- package/template/src/components/ui/radio-group.jsx +29 -0
- package/template/src/components/ui/scroll-area.jsx +40 -0
- package/template/src/components/ui/select.jsx +120 -0
- package/template/src/components/ui/separator.jsx +25 -0
- package/template/src/components/ui/sheet.jsx +108 -0
- package/template/src/components/ui/skeleton.jsx +10 -0
- package/template/src/components/ui/slider.jsx +23 -0
- package/template/src/components/ui/sonner.jsx +42 -0
- package/template/src/components/ui/switch.jsx +24 -0
- package/template/src/components/ui/table.jsx +83 -0
- package/template/src/components/ui/tabs.jsx +41 -0
- package/template/src/components/ui/textarea.jsx +18 -0
- package/template/src/components/ui/toast.jsx +82 -0
- package/template/src/components/ui/toaster.jsx +33 -0
- package/template/src/components/ui/toggle.jsx +40 -0
- package/template/src/components/ui/tooltip.jsx +24 -0
- package/template/src/hooks/use-toast.js +155 -0
- package/template/src/index.css +61 -0
- package/template/src/index.js +6 -0
- package/template/src/lib/utils.js +11 -0
- package/template/src/main.jsx +15 -0
- package/template/src/pages/Home.jsx +26 -0
- package/template/tailwind.config.cjs +76 -0
- package/template/vite.config.mts +22 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import {
|
|
3
|
+
ChevronDownIcon,
|
|
4
|
+
ChevronLeftIcon,
|
|
5
|
+
ChevronRightIcon,
|
|
6
|
+
} from "lucide-react"
|
|
7
|
+
import { DayPicker, getDefaultClassNames } from "react-day-picker";
|
|
8
|
+
|
|
9
|
+
import { cn } from "@/lib/utils"
|
|
10
|
+
import { Button, buttonVariants } from "@/components/ui/button"
|
|
11
|
+
|
|
12
|
+
function Calendar({
|
|
13
|
+
className,
|
|
14
|
+
classNames,
|
|
15
|
+
showOutsideDays = true,
|
|
16
|
+
captionLayout = "label",
|
|
17
|
+
buttonVariant = "ghost",
|
|
18
|
+
formatters,
|
|
19
|
+
components,
|
|
20
|
+
...props
|
|
21
|
+
}) {
|
|
22
|
+
const defaultClassNames = getDefaultClassNames()
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<DayPicker
|
|
26
|
+
showOutsideDays={showOutsideDays}
|
|
27
|
+
className={cn(
|
|
28
|
+
"bg-background group/calendar p-3 [--cell-size:2rem] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
|
|
29
|
+
String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
|
|
30
|
+
String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
|
|
31
|
+
className
|
|
32
|
+
)}
|
|
33
|
+
captionLayout={captionLayout}
|
|
34
|
+
formatters={{
|
|
35
|
+
formatMonthDropdown: (date) =>
|
|
36
|
+
date.toLocaleString("default", { month: "short" }),
|
|
37
|
+
...formatters,
|
|
38
|
+
}}
|
|
39
|
+
classNames={{
|
|
40
|
+
root: cn("w-fit", defaultClassNames.root),
|
|
41
|
+
months: cn("relative flex flex-col gap-4 md:flex-row", defaultClassNames.months),
|
|
42
|
+
month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
|
|
43
|
+
nav: cn(
|
|
44
|
+
"absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1",
|
|
45
|
+
defaultClassNames.nav
|
|
46
|
+
),
|
|
47
|
+
button_previous: cn(
|
|
48
|
+
buttonVariants({ variant: buttonVariant }),
|
|
49
|
+
"h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50",
|
|
50
|
+
defaultClassNames.button_previous
|
|
51
|
+
),
|
|
52
|
+
button_next: cn(
|
|
53
|
+
buttonVariants({ variant: buttonVariant }),
|
|
54
|
+
"h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50",
|
|
55
|
+
defaultClassNames.button_next
|
|
56
|
+
),
|
|
57
|
+
month_caption: cn(
|
|
58
|
+
"flex h-[--cell-size] w-full items-center justify-center px-[--cell-size]",
|
|
59
|
+
defaultClassNames.month_caption
|
|
60
|
+
),
|
|
61
|
+
dropdowns: cn(
|
|
62
|
+
"flex h-[--cell-size] w-full items-center justify-center gap-1.5 text-sm font-medium",
|
|
63
|
+
defaultClassNames.dropdowns
|
|
64
|
+
),
|
|
65
|
+
dropdown_root: cn(
|
|
66
|
+
"has-focus:border-ring border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] relative rounded-md border",
|
|
67
|
+
defaultClassNames.dropdown_root
|
|
68
|
+
),
|
|
69
|
+
dropdown: cn("bg-popover absolute inset-0 opacity-0", defaultClassNames.dropdown),
|
|
70
|
+
caption_label: cn("select-none font-medium", captionLayout === "label"
|
|
71
|
+
? "text-sm"
|
|
72
|
+
: "[&>svg]:text-muted-foreground flex h-8 items-center gap-1 rounded-md pl-2 pr-1 text-sm [&>svg]:size-3.5", defaultClassNames.caption_label),
|
|
73
|
+
table: "w-full border-collapse",
|
|
74
|
+
weekdays: cn("flex", defaultClassNames.weekdays),
|
|
75
|
+
weekday: cn(
|
|
76
|
+
"text-muted-foreground flex-1 select-none rounded-md text-[0.8rem] font-normal",
|
|
77
|
+
defaultClassNames.weekday
|
|
78
|
+
),
|
|
79
|
+
week: cn("mt-2 flex w-full", defaultClassNames.week),
|
|
80
|
+
week_number_header: cn("w-[--cell-size] select-none", defaultClassNames.week_number_header),
|
|
81
|
+
week_number: cn(
|
|
82
|
+
"text-muted-foreground select-none text-[0.8rem]",
|
|
83
|
+
defaultClassNames.week_number
|
|
84
|
+
),
|
|
85
|
+
day: cn(
|
|
86
|
+
"group/day relative aspect-square h-full w-full select-none p-0 text-center [&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md",
|
|
87
|
+
defaultClassNames.day
|
|
88
|
+
),
|
|
89
|
+
range_start: cn("bg-accent rounded-l-md", defaultClassNames.range_start),
|
|
90
|
+
range_middle: cn("rounded-none", defaultClassNames.range_middle),
|
|
91
|
+
range_end: cn("bg-accent rounded-r-md", defaultClassNames.range_end),
|
|
92
|
+
today: cn(
|
|
93
|
+
"bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none",
|
|
94
|
+
defaultClassNames.today
|
|
95
|
+
),
|
|
96
|
+
outside: cn(
|
|
97
|
+
"text-muted-foreground aria-selected:text-muted-foreground",
|
|
98
|
+
defaultClassNames.outside
|
|
99
|
+
),
|
|
100
|
+
disabled: cn("text-muted-foreground opacity-50", defaultClassNames.disabled),
|
|
101
|
+
hidden: cn("invisible", defaultClassNames.hidden),
|
|
102
|
+
...classNames,
|
|
103
|
+
}}
|
|
104
|
+
components={{
|
|
105
|
+
Root: ({ className, rootRef, ...props }) => {
|
|
106
|
+
return (<div data-slot="calendar" ref={rootRef} className={cn(className)} {...props} />);
|
|
107
|
+
},
|
|
108
|
+
Chevron: ({ className, orientation, ...props }) => {
|
|
109
|
+
if (orientation === "left") {
|
|
110
|
+
return (<ChevronLeftIcon className={cn("size-4", className)} {...props} />);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (orientation === "right") {
|
|
114
|
+
return (<ChevronRightIcon className={cn("size-4", className)} {...props} />);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return (<ChevronDownIcon className={cn("size-4", className)} {...props} />);
|
|
118
|
+
},
|
|
119
|
+
DayButton: CalendarDayButton,
|
|
120
|
+
WeekNumber: ({ children, ...props }) => {
|
|
121
|
+
return (
|
|
122
|
+
<td {...props}>
|
|
123
|
+
<div
|
|
124
|
+
className="flex size-[--cell-size] items-center justify-center text-center">
|
|
125
|
+
{children}
|
|
126
|
+
</div>
|
|
127
|
+
</td>
|
|
128
|
+
);
|
|
129
|
+
},
|
|
130
|
+
...components,
|
|
131
|
+
}}
|
|
132
|
+
{...props} />
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function CalendarDayButton({
|
|
137
|
+
className,
|
|
138
|
+
day,
|
|
139
|
+
modifiers,
|
|
140
|
+
...props
|
|
141
|
+
}) {
|
|
142
|
+
const defaultClassNames = getDefaultClassNames()
|
|
143
|
+
|
|
144
|
+
const ref = React.useRef(null)
|
|
145
|
+
React.useEffect(() => {
|
|
146
|
+
if (modifiers.focused) ref.current?.focus()
|
|
147
|
+
}, [modifiers.focused])
|
|
148
|
+
|
|
149
|
+
return (
|
|
150
|
+
<Button
|
|
151
|
+
ref={ref}
|
|
152
|
+
variant="ghost"
|
|
153
|
+
size="icon"
|
|
154
|
+
data-day={day.date.toLocaleDateString()}
|
|
155
|
+
data-selected-single={
|
|
156
|
+
modifiers.selected &&
|
|
157
|
+
!modifiers.range_start &&
|
|
158
|
+
!modifiers.range_end &&
|
|
159
|
+
!modifiers.range_middle
|
|
160
|
+
}
|
|
161
|
+
data-range-start={modifiers.range_start}
|
|
162
|
+
data-range-end={modifiers.range_end}
|
|
163
|
+
data-range-middle={modifiers.range_middle}
|
|
164
|
+
className={cn(
|
|
165
|
+
"data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 flex aspect-square h-auto w-full min-w-[--cell-size] flex-col gap-1 font-normal leading-none data-[range-end=true]:rounded-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] [&>span]:text-xs [&>span]:opacity-70",
|
|
166
|
+
defaultClassNames.day,
|
|
167
|
+
className
|
|
168
|
+
)}
|
|
169
|
+
{...props} />
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export { Calendar, CalendarDayButton }
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/lib/utils"
|
|
4
|
+
|
|
5
|
+
const Card = React.forwardRef(({ className, ...props }, ref) => (
|
|
6
|
+
<div
|
|
7
|
+
ref={ref}
|
|
8
|
+
className={cn("rounded-lg border bg-card text-card-foreground shadow-sm", className)}
|
|
9
|
+
{...props} />
|
|
10
|
+
))
|
|
11
|
+
Card.displayName = "Card"
|
|
12
|
+
|
|
13
|
+
const CardHeader = React.forwardRef(({ className, ...props }, ref) => (
|
|
14
|
+
<div
|
|
15
|
+
ref={ref}
|
|
16
|
+
className={cn("flex flex-col space-y-1.5 p-6", className)}
|
|
17
|
+
{...props} />
|
|
18
|
+
))
|
|
19
|
+
CardHeader.displayName = "CardHeader"
|
|
20
|
+
|
|
21
|
+
const CardTitle = React.forwardRef(({ className, ...props }, ref) => (
|
|
22
|
+
<div
|
|
23
|
+
ref={ref}
|
|
24
|
+
className={cn("text-2xl font-semibold leading-none tracking-tight", className)}
|
|
25
|
+
{...props} />
|
|
26
|
+
))
|
|
27
|
+
CardTitle.displayName = "CardTitle"
|
|
28
|
+
|
|
29
|
+
const CardDescription = React.forwardRef(({ className, ...props }, ref) => (
|
|
30
|
+
<div
|
|
31
|
+
ref={ref}
|
|
32
|
+
className={cn("text-sm text-muted-foreground", className)}
|
|
33
|
+
{...props} />
|
|
34
|
+
))
|
|
35
|
+
CardDescription.displayName = "CardDescription"
|
|
36
|
+
|
|
37
|
+
const CardContent = React.forwardRef(({ className, ...props }, ref) => (
|
|
38
|
+
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
|
|
39
|
+
))
|
|
40
|
+
CardContent.displayName = "CardContent"
|
|
41
|
+
|
|
42
|
+
const CardFooter = React.forwardRef(({ className, ...props }, ref) => (
|
|
43
|
+
<div
|
|
44
|
+
ref={ref}
|
|
45
|
+
className={cn("flex items-center p-6 pt-0", className)}
|
|
46
|
+
{...props} />
|
|
47
|
+
))
|
|
48
|
+
CardFooter.displayName = "CardFooter"
|
|
49
|
+
|
|
50
|
+
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import * as React from "react"
|
|
3
|
+
import useEmblaCarousel from "embla-carousel-react";
|
|
4
|
+
import { ArrowLeft, ArrowRight } from "lucide-react"
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
import { Button } from "@/components/ui/button"
|
|
8
|
+
|
|
9
|
+
const CarouselContext = React.createContext(null)
|
|
10
|
+
|
|
11
|
+
function useCarousel() {
|
|
12
|
+
const context = React.useContext(CarouselContext)
|
|
13
|
+
|
|
14
|
+
if (!context) {
|
|
15
|
+
throw new Error("useCarousel must be used within a <Carousel />")
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return context
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const Carousel = React.forwardRef((
|
|
22
|
+
{
|
|
23
|
+
orientation = "horizontal",
|
|
24
|
+
opts,
|
|
25
|
+
setApi,
|
|
26
|
+
plugins,
|
|
27
|
+
className,
|
|
28
|
+
children,
|
|
29
|
+
...props
|
|
30
|
+
},
|
|
31
|
+
ref
|
|
32
|
+
) => {
|
|
33
|
+
const [carouselRef, api] = useEmblaCarousel({
|
|
34
|
+
...opts,
|
|
35
|
+
axis: orientation === "horizontal" ? "x" : "y",
|
|
36
|
+
}, plugins)
|
|
37
|
+
const [canScrollPrev, setCanScrollPrev] = React.useState(false)
|
|
38
|
+
const [canScrollNext, setCanScrollNext] = React.useState(false)
|
|
39
|
+
|
|
40
|
+
const onSelect = React.useCallback((api) => {
|
|
41
|
+
if (!api) {
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
setCanScrollPrev(api.canScrollPrev())
|
|
46
|
+
setCanScrollNext(api.canScrollNext())
|
|
47
|
+
}, [])
|
|
48
|
+
|
|
49
|
+
const scrollPrev = React.useCallback(() => {
|
|
50
|
+
api?.scrollPrev()
|
|
51
|
+
}, [api])
|
|
52
|
+
|
|
53
|
+
const scrollNext = React.useCallback(() => {
|
|
54
|
+
api?.scrollNext()
|
|
55
|
+
}, [api])
|
|
56
|
+
|
|
57
|
+
const handleKeyDown = React.useCallback((event) => {
|
|
58
|
+
if (event.key === "ArrowLeft") {
|
|
59
|
+
event.preventDefault()
|
|
60
|
+
scrollPrev()
|
|
61
|
+
} else if (event.key === "ArrowRight") {
|
|
62
|
+
event.preventDefault()
|
|
63
|
+
scrollNext()
|
|
64
|
+
}
|
|
65
|
+
}, [scrollPrev, scrollNext])
|
|
66
|
+
|
|
67
|
+
React.useEffect(() => {
|
|
68
|
+
if (!api || !setApi) {
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
setApi(api)
|
|
73
|
+
}, [api, setApi])
|
|
74
|
+
|
|
75
|
+
React.useEffect(() => {
|
|
76
|
+
if (!api) {
|
|
77
|
+
return
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
onSelect(api)
|
|
81
|
+
api.on("reInit", onSelect)
|
|
82
|
+
api.on("select", onSelect)
|
|
83
|
+
|
|
84
|
+
return () => {
|
|
85
|
+
api?.off("select", onSelect)
|
|
86
|
+
};
|
|
87
|
+
}, [api, onSelect])
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<CarouselContext.Provider
|
|
91
|
+
value={{
|
|
92
|
+
carouselRef,
|
|
93
|
+
api: api,
|
|
94
|
+
opts,
|
|
95
|
+
orientation:
|
|
96
|
+
orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
|
|
97
|
+
scrollPrev,
|
|
98
|
+
scrollNext,
|
|
99
|
+
canScrollPrev,
|
|
100
|
+
canScrollNext,
|
|
101
|
+
}}>
|
|
102
|
+
<div
|
|
103
|
+
ref={ref}
|
|
104
|
+
onKeyDownCapture={handleKeyDown}
|
|
105
|
+
className={cn("relative", className)}
|
|
106
|
+
role="region"
|
|
107
|
+
aria-roledescription="carousel"
|
|
108
|
+
{...props}>
|
|
109
|
+
{children}
|
|
110
|
+
</div>
|
|
111
|
+
</CarouselContext.Provider>
|
|
112
|
+
);
|
|
113
|
+
})
|
|
114
|
+
Carousel.displayName = "Carousel"
|
|
115
|
+
|
|
116
|
+
const CarouselContent = React.forwardRef(({ className, ...props }, ref) => {
|
|
117
|
+
const { carouselRef, orientation } = useCarousel()
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<div ref={carouselRef} className="overflow-hidden">
|
|
121
|
+
<div
|
|
122
|
+
ref={ref}
|
|
123
|
+
className={cn(
|
|
124
|
+
"flex",
|
|
125
|
+
orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
|
|
126
|
+
className
|
|
127
|
+
)}
|
|
128
|
+
{...props} />
|
|
129
|
+
</div>
|
|
130
|
+
);
|
|
131
|
+
})
|
|
132
|
+
CarouselContent.displayName = "CarouselContent"
|
|
133
|
+
|
|
134
|
+
const CarouselItem = React.forwardRef(({ className, ...props }, ref) => {
|
|
135
|
+
const { orientation } = useCarousel()
|
|
136
|
+
|
|
137
|
+
return (
|
|
138
|
+
<div
|
|
139
|
+
ref={ref}
|
|
140
|
+
role="group"
|
|
141
|
+
aria-roledescription="slide"
|
|
142
|
+
className={cn(
|
|
143
|
+
"min-w-0 shrink-0 grow-0 basis-full",
|
|
144
|
+
orientation === "horizontal" ? "pl-4" : "pt-4",
|
|
145
|
+
className
|
|
146
|
+
)}
|
|
147
|
+
{...props} />
|
|
148
|
+
);
|
|
149
|
+
})
|
|
150
|
+
CarouselItem.displayName = "CarouselItem"
|
|
151
|
+
|
|
152
|
+
const CarouselPrevious = React.forwardRef(({ className, variant = "outline", size = "icon", ...props }, ref) => {
|
|
153
|
+
const { orientation, scrollPrev, canScrollPrev } = useCarousel()
|
|
154
|
+
|
|
155
|
+
return (
|
|
156
|
+
<Button
|
|
157
|
+
ref={ref}
|
|
158
|
+
variant={variant}
|
|
159
|
+
size={size}
|
|
160
|
+
className={cn("absolute h-8 w-8 rounded-full", orientation === "horizontal"
|
|
161
|
+
? "-left-12 top-1/2 -translate-y-1/2"
|
|
162
|
+
: "-top-12 left-1/2 -translate-x-1/2 rotate-90", className)}
|
|
163
|
+
disabled={!canScrollPrev}
|
|
164
|
+
onClick={scrollPrev}
|
|
165
|
+
{...props}>
|
|
166
|
+
<ArrowLeft className="h-4 w-4" />
|
|
167
|
+
<span className="sr-only">Previous slide</span>
|
|
168
|
+
</Button>
|
|
169
|
+
);
|
|
170
|
+
})
|
|
171
|
+
CarouselPrevious.displayName = "CarouselPrevious"
|
|
172
|
+
|
|
173
|
+
const CarouselNext = React.forwardRef(({ className, variant = "outline", size = "icon", ...props }, ref) => {
|
|
174
|
+
const { orientation, scrollNext, canScrollNext } = useCarousel()
|
|
175
|
+
|
|
176
|
+
return (
|
|
177
|
+
<Button
|
|
178
|
+
ref={ref}
|
|
179
|
+
variant={variant}
|
|
180
|
+
size={size}
|
|
181
|
+
className={cn("absolute h-8 w-8 rounded-full", orientation === "horizontal"
|
|
182
|
+
? "-right-12 top-1/2 -translate-y-1/2"
|
|
183
|
+
: "-bottom-12 left-1/2 -translate-x-1/2 rotate-90", className)}
|
|
184
|
+
disabled={!canScrollNext}
|
|
185
|
+
onClick={scrollNext}
|
|
186
|
+
{...props}>
|
|
187
|
+
<ArrowRight className="h-4 w-4" />
|
|
188
|
+
<span className="sr-only">Next slide</span>
|
|
189
|
+
</Button>
|
|
190
|
+
);
|
|
191
|
+
})
|
|
192
|
+
CarouselNext.displayName = "CarouselNext"
|
|
193
|
+
|
|
194
|
+
export { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
|
|
3
|
+
import { Check } from "lucide-react"
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils"
|
|
6
|
+
|
|
7
|
+
const Checkbox = React.forwardRef(({ className, ...props }, ref) => (
|
|
8
|
+
<CheckboxPrimitive.Root
|
|
9
|
+
ref={ref}
|
|
10
|
+
className={cn(
|
|
11
|
+
"grid place-content-center peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
|
|
12
|
+
className
|
|
13
|
+
)}
|
|
14
|
+
{...props}>
|
|
15
|
+
<CheckboxPrimitive.Indicator className={cn("grid place-content-center text-current")}>
|
|
16
|
+
<Check className="h-4 w-4" />
|
|
17
|
+
</CheckboxPrimitive.Indicator>
|
|
18
|
+
</CheckboxPrimitive.Root>
|
|
19
|
+
))
|
|
20
|
+
Checkbox.displayName = CheckboxPrimitive.Root.displayName
|
|
21
|
+
|
|
22
|
+
export { Checkbox }
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"
|
|
4
|
+
|
|
5
|
+
const Collapsible = CollapsiblePrimitive.Root
|
|
6
|
+
|
|
7
|
+
const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger
|
|
8
|
+
|
|
9
|
+
const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent
|
|
10
|
+
|
|
11
|
+
export { Collapsible, CollapsibleTrigger, CollapsibleContent }
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { Command as CommandPrimitive } from "cmdk"
|
|
3
|
+
import { Search } from "lucide-react"
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils"
|
|
6
|
+
import { Dialog, DialogContent } from "@/components/ui/dialog"
|
|
7
|
+
|
|
8
|
+
const Command = React.forwardRef(({ className, ...props }, ref) => (
|
|
9
|
+
<CommandPrimitive
|
|
10
|
+
ref={ref}
|
|
11
|
+
className={cn(
|
|
12
|
+
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
|
|
13
|
+
className
|
|
14
|
+
)}
|
|
15
|
+
{...props} />
|
|
16
|
+
))
|
|
17
|
+
Command.displayName = CommandPrimitive.displayName
|
|
18
|
+
|
|
19
|
+
const CommandDialog = ({
|
|
20
|
+
children,
|
|
21
|
+
...props
|
|
22
|
+
}) => {
|
|
23
|
+
return (
|
|
24
|
+
<Dialog {...props}>
|
|
25
|
+
<DialogContent className="overflow-hidden p-0 shadow-lg">
|
|
26
|
+
<Command
|
|
27
|
+
className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
|
|
28
|
+
{children}
|
|
29
|
+
</Command>
|
|
30
|
+
</DialogContent>
|
|
31
|
+
</Dialog>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const CommandInput = React.forwardRef(({ className, ...props }, ref) => (
|
|
36
|
+
<div className="flex items-center border-b px-3" cmdk-input-wrapper="">
|
|
37
|
+
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
|
|
38
|
+
<CommandPrimitive.Input
|
|
39
|
+
ref={ref}
|
|
40
|
+
className={cn(
|
|
41
|
+
"flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
42
|
+
className
|
|
43
|
+
)}
|
|
44
|
+
{...props} />
|
|
45
|
+
</div>
|
|
46
|
+
))
|
|
47
|
+
|
|
48
|
+
CommandInput.displayName = CommandPrimitive.Input.displayName
|
|
49
|
+
|
|
50
|
+
const CommandList = React.forwardRef(({ className, ...props }, ref) => (
|
|
51
|
+
<CommandPrimitive.List
|
|
52
|
+
ref={ref}
|
|
53
|
+
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
|
|
54
|
+
{...props} />
|
|
55
|
+
))
|
|
56
|
+
|
|
57
|
+
CommandList.displayName = CommandPrimitive.List.displayName
|
|
58
|
+
|
|
59
|
+
const CommandEmpty = React.forwardRef((props, ref) => (
|
|
60
|
+
<CommandPrimitive.Empty ref={ref} className="py-6 text-center text-sm" {...props} />
|
|
61
|
+
))
|
|
62
|
+
|
|
63
|
+
CommandEmpty.displayName = CommandPrimitive.Empty.displayName
|
|
64
|
+
|
|
65
|
+
const CommandGroup = React.forwardRef(({ className, ...props }, ref) => (
|
|
66
|
+
<CommandPrimitive.Group
|
|
67
|
+
ref={ref}
|
|
68
|
+
className={cn(
|
|
69
|
+
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
|
|
70
|
+
className
|
|
71
|
+
)}
|
|
72
|
+
{...props} />
|
|
73
|
+
))
|
|
74
|
+
|
|
75
|
+
CommandGroup.displayName = CommandPrimitive.Group.displayName
|
|
76
|
+
|
|
77
|
+
const CommandSeparator = React.forwardRef(({ className, ...props }, ref) => (
|
|
78
|
+
<CommandPrimitive.Separator ref={ref} className={cn("-mx-1 h-px bg-border", className)} {...props} />
|
|
79
|
+
))
|
|
80
|
+
CommandSeparator.displayName = CommandPrimitive.Separator.displayName
|
|
81
|
+
|
|
82
|
+
const CommandItem = React.forwardRef(({ className, ...props }, ref) => (
|
|
83
|
+
<CommandPrimitive.Item
|
|
84
|
+
ref={ref}
|
|
85
|
+
className={cn(
|
|
86
|
+
"relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected='true']:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
87
|
+
className
|
|
88
|
+
)}
|
|
89
|
+
{...props} />
|
|
90
|
+
))
|
|
91
|
+
|
|
92
|
+
CommandItem.displayName = CommandPrimitive.Item.displayName
|
|
93
|
+
|
|
94
|
+
const CommandShortcut = ({
|
|
95
|
+
className,
|
|
96
|
+
...props
|
|
97
|
+
}) => {
|
|
98
|
+
return (
|
|
99
|
+
<span
|
|
100
|
+
className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)}
|
|
101
|
+
{...props} />
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
CommandShortcut.displayName = "CommandShortcut"
|
|
105
|
+
|
|
106
|
+
export {
|
|
107
|
+
Command,
|
|
108
|
+
CommandDialog,
|
|
109
|
+
CommandInput,
|
|
110
|
+
CommandList,
|
|
111
|
+
CommandEmpty,
|
|
112
|
+
CommandGroup,
|
|
113
|
+
CommandItem,
|
|
114
|
+
CommandShortcut,
|
|
115
|
+
CommandSeparator,
|
|
116
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as DialogPrimitive from "@radix-ui/react-dialog"
|
|
3
|
+
import { X } from "lucide-react"
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils"
|
|
6
|
+
|
|
7
|
+
const Dialog = DialogPrimitive.Root
|
|
8
|
+
|
|
9
|
+
const DialogTrigger = DialogPrimitive.Trigger
|
|
10
|
+
|
|
11
|
+
const DialogPortal = DialogPrimitive.Portal
|
|
12
|
+
|
|
13
|
+
const DialogClose = DialogPrimitive.Close
|
|
14
|
+
|
|
15
|
+
const DialogOverlay = React.forwardRef(({ className, ...props }, ref) => (
|
|
16
|
+
<DialogPrimitive.Overlay
|
|
17
|
+
ref={ref}
|
|
18
|
+
className={cn(
|
|
19
|
+
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
20
|
+
className
|
|
21
|
+
)}
|
|
22
|
+
{...props} />
|
|
23
|
+
))
|
|
24
|
+
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
|
|
25
|
+
|
|
26
|
+
const DialogContent = React.forwardRef(({ className, children, ...props }, ref) => (
|
|
27
|
+
<DialogPortal>
|
|
28
|
+
<DialogOverlay />
|
|
29
|
+
<DialogPrimitive.Content
|
|
30
|
+
ref={ref}
|
|
31
|
+
className={cn(
|
|
32
|
+
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
|
|
33
|
+
className
|
|
34
|
+
)}
|
|
35
|
+
{...props}>
|
|
36
|
+
{children}
|
|
37
|
+
<DialogPrimitive.Close
|
|
38
|
+
className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
|
|
39
|
+
<X className="h-4 w-4" />
|
|
40
|
+
<span className="sr-only">Close</span>
|
|
41
|
+
</DialogPrimitive.Close>
|
|
42
|
+
</DialogPrimitive.Content>
|
|
43
|
+
</DialogPortal>
|
|
44
|
+
))
|
|
45
|
+
DialogContent.displayName = DialogPrimitive.Content.displayName
|
|
46
|
+
|
|
47
|
+
const DialogHeader = ({
|
|
48
|
+
className,
|
|
49
|
+
...props
|
|
50
|
+
}) => (
|
|
51
|
+
<div
|
|
52
|
+
className={cn("flex flex-col space-y-1.5 text-center sm:text-left", className)}
|
|
53
|
+
{...props} />
|
|
54
|
+
)
|
|
55
|
+
DialogHeader.displayName = "DialogHeader"
|
|
56
|
+
|
|
57
|
+
const DialogFooter = ({
|
|
58
|
+
className,
|
|
59
|
+
...props
|
|
60
|
+
}) => (
|
|
61
|
+
<div
|
|
62
|
+
className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)}
|
|
63
|
+
{...props} />
|
|
64
|
+
)
|
|
65
|
+
DialogFooter.displayName = "DialogFooter"
|
|
66
|
+
|
|
67
|
+
const DialogTitle = React.forwardRef(({ className, ...props }, ref) => (
|
|
68
|
+
<DialogPrimitive.Title
|
|
69
|
+
ref={ref}
|
|
70
|
+
className={cn("text-lg font-semibold leading-none tracking-tight", className)}
|
|
71
|
+
{...props} />
|
|
72
|
+
))
|
|
73
|
+
DialogTitle.displayName = DialogPrimitive.Title.displayName
|
|
74
|
+
|
|
75
|
+
const DialogDescription = React.forwardRef(({ className, ...props }, ref) => (
|
|
76
|
+
<DialogPrimitive.Description
|
|
77
|
+
ref={ref}
|
|
78
|
+
className={cn("text-sm text-muted-foreground", className)}
|
|
79
|
+
{...props} />
|
|
80
|
+
))
|
|
81
|
+
DialogDescription.displayName = DialogPrimitive.Description.displayName
|
|
82
|
+
|
|
83
|
+
export {
|
|
84
|
+
Dialog,
|
|
85
|
+
DialogPortal,
|
|
86
|
+
DialogOverlay,
|
|
87
|
+
DialogClose,
|
|
88
|
+
DialogTrigger,
|
|
89
|
+
DialogContent,
|
|
90
|
+
DialogHeader,
|
|
91
|
+
DialogFooter,
|
|
92
|
+
DialogTitle,
|
|
93
|
+
DialogDescription,
|
|
94
|
+
}
|