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,92 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { Drawer as DrawerPrimitive } from "vaul"
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
|
|
8
|
+
const Drawer = ({
|
|
9
|
+
shouldScaleBackground = true,
|
|
10
|
+
...props
|
|
11
|
+
}) => (
|
|
12
|
+
<DrawerPrimitive.Root shouldScaleBackground={shouldScaleBackground} {...props} />
|
|
13
|
+
)
|
|
14
|
+
Drawer.displayName = "Drawer"
|
|
15
|
+
|
|
16
|
+
const DrawerTrigger = DrawerPrimitive.Trigger
|
|
17
|
+
|
|
18
|
+
const DrawerPortal = DrawerPrimitive.Portal
|
|
19
|
+
|
|
20
|
+
const DrawerClose = DrawerPrimitive.Close
|
|
21
|
+
|
|
22
|
+
const DrawerOverlay = React.forwardRef(({ className, ...props }, ref) => (
|
|
23
|
+
<DrawerPrimitive.Overlay
|
|
24
|
+
ref={ref}
|
|
25
|
+
className={cn("fixed inset-0 z-50 bg-black/80", className)}
|
|
26
|
+
{...props} />
|
|
27
|
+
))
|
|
28
|
+
DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName
|
|
29
|
+
|
|
30
|
+
const DrawerContent = React.forwardRef(({ className, children, ...props }, ref) => (
|
|
31
|
+
<DrawerPortal>
|
|
32
|
+
<DrawerOverlay />
|
|
33
|
+
<DrawerPrimitive.Content
|
|
34
|
+
ref={ref}
|
|
35
|
+
className={cn(
|
|
36
|
+
"fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background",
|
|
37
|
+
className
|
|
38
|
+
)}
|
|
39
|
+
{...props}>
|
|
40
|
+
<div className="mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted" />
|
|
41
|
+
{children}
|
|
42
|
+
</DrawerPrimitive.Content>
|
|
43
|
+
</DrawerPortal>
|
|
44
|
+
))
|
|
45
|
+
DrawerContent.displayName = "DrawerContent"
|
|
46
|
+
|
|
47
|
+
const DrawerHeader = ({
|
|
48
|
+
className,
|
|
49
|
+
...props
|
|
50
|
+
}) => (
|
|
51
|
+
<div
|
|
52
|
+
className={cn("grid gap-1.5 p-4 text-center sm:text-left", className)}
|
|
53
|
+
{...props} />
|
|
54
|
+
)
|
|
55
|
+
DrawerHeader.displayName = "DrawerHeader"
|
|
56
|
+
|
|
57
|
+
const DrawerFooter = ({
|
|
58
|
+
className,
|
|
59
|
+
...props
|
|
60
|
+
}) => (
|
|
61
|
+
<div className={cn("mt-auto flex flex-col gap-2 p-4", className)} {...props} />
|
|
62
|
+
)
|
|
63
|
+
DrawerFooter.displayName = "DrawerFooter"
|
|
64
|
+
|
|
65
|
+
const DrawerTitle = React.forwardRef(({ className, ...props }, ref) => (
|
|
66
|
+
<DrawerPrimitive.Title
|
|
67
|
+
ref={ref}
|
|
68
|
+
className={cn("text-lg font-semibold leading-none tracking-tight", className)}
|
|
69
|
+
{...props} />
|
|
70
|
+
))
|
|
71
|
+
DrawerTitle.displayName = DrawerPrimitive.Title.displayName
|
|
72
|
+
|
|
73
|
+
const DrawerDescription = React.forwardRef(({ className, ...props }, ref) => (
|
|
74
|
+
<DrawerPrimitive.Description
|
|
75
|
+
ref={ref}
|
|
76
|
+
className={cn("text-sm text-muted-foreground", className)}
|
|
77
|
+
{...props} />
|
|
78
|
+
))
|
|
79
|
+
DrawerDescription.displayName = DrawerPrimitive.Description.displayName
|
|
80
|
+
|
|
81
|
+
export {
|
|
82
|
+
Drawer,
|
|
83
|
+
DrawerPortal,
|
|
84
|
+
DrawerOverlay,
|
|
85
|
+
DrawerTrigger,
|
|
86
|
+
DrawerClose,
|
|
87
|
+
DrawerContent,
|
|
88
|
+
DrawerHeader,
|
|
89
|
+
DrawerFooter,
|
|
90
|
+
DrawerTitle,
|
|
91
|
+
DrawerDescription,
|
|
92
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
|
|
3
|
+
import { Check, ChevronRight, Circle } from "lucide-react"
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils"
|
|
6
|
+
|
|
7
|
+
const DropdownMenu = DropdownMenuPrimitive.Root
|
|
8
|
+
|
|
9
|
+
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
|
|
10
|
+
|
|
11
|
+
const DropdownMenuGroup = DropdownMenuPrimitive.Group
|
|
12
|
+
|
|
13
|
+
const DropdownMenuPortal = DropdownMenuPrimitive.Portal
|
|
14
|
+
|
|
15
|
+
const DropdownMenuSub = DropdownMenuPrimitive.Sub
|
|
16
|
+
|
|
17
|
+
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
|
|
18
|
+
|
|
19
|
+
const DropdownMenuSubTrigger = React.forwardRef(({ className, inset, children, ...props }, ref) => (
|
|
20
|
+
<DropdownMenuPrimitive.SubTrigger
|
|
21
|
+
ref={ref}
|
|
22
|
+
className={cn(
|
|
23
|
+
"flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
24
|
+
inset && "pl-8",
|
|
25
|
+
className
|
|
26
|
+
)}
|
|
27
|
+
{...props}>
|
|
28
|
+
{children}
|
|
29
|
+
<ChevronRight className="ml-auto" />
|
|
30
|
+
</DropdownMenuPrimitive.SubTrigger>
|
|
31
|
+
))
|
|
32
|
+
DropdownMenuSubTrigger.displayName =
|
|
33
|
+
DropdownMenuPrimitive.SubTrigger.displayName
|
|
34
|
+
|
|
35
|
+
const DropdownMenuSubContent = React.forwardRef(({ className, ...props }, ref) => (
|
|
36
|
+
<DropdownMenuPrimitive.SubContent
|
|
37
|
+
ref={ref}
|
|
38
|
+
className={cn(
|
|
39
|
+
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg 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-[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 origin-[--radix-dropdown-menu-content-transform-origin]",
|
|
40
|
+
className
|
|
41
|
+
)}
|
|
42
|
+
{...props} />
|
|
43
|
+
))
|
|
44
|
+
DropdownMenuSubContent.displayName =
|
|
45
|
+
DropdownMenuPrimitive.SubContent.displayName
|
|
46
|
+
|
|
47
|
+
const DropdownMenuContent = React.forwardRef(({ className, sideOffset = 4, ...props }, ref) => (
|
|
48
|
+
<DropdownMenuPrimitive.Portal>
|
|
49
|
+
<DropdownMenuPrimitive.Content
|
|
50
|
+
ref={ref}
|
|
51
|
+
sideOffset={sideOffset}
|
|
52
|
+
className={cn(
|
|
53
|
+
"z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md 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-[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 origin-[--radix-dropdown-menu-content-transform-origin]",
|
|
54
|
+
className
|
|
55
|
+
)}
|
|
56
|
+
{...props} />
|
|
57
|
+
</DropdownMenuPrimitive.Portal>
|
|
58
|
+
))
|
|
59
|
+
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
|
|
60
|
+
|
|
61
|
+
const DropdownMenuItem = React.forwardRef(({ className, inset, ...props }, ref) => (
|
|
62
|
+
<DropdownMenuPrimitive.Item
|
|
63
|
+
ref={ref}
|
|
64
|
+
className={cn(
|
|
65
|
+
"relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
66
|
+
inset && "pl-8",
|
|
67
|
+
className
|
|
68
|
+
)}
|
|
69
|
+
{...props} />
|
|
70
|
+
))
|
|
71
|
+
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
|
|
72
|
+
|
|
73
|
+
const DropdownMenuCheckboxItem = React.forwardRef(({ className, children, checked, ...props }, ref) => (
|
|
74
|
+
<DropdownMenuPrimitive.CheckboxItem
|
|
75
|
+
ref={ref}
|
|
76
|
+
className={cn(
|
|
77
|
+
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
78
|
+
className
|
|
79
|
+
)}
|
|
80
|
+
checked={checked}
|
|
81
|
+
{...props}>
|
|
82
|
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
83
|
+
<DropdownMenuPrimitive.ItemIndicator>
|
|
84
|
+
<Check className="h-4 w-4" />
|
|
85
|
+
</DropdownMenuPrimitive.ItemIndicator>
|
|
86
|
+
</span>
|
|
87
|
+
{children}
|
|
88
|
+
</DropdownMenuPrimitive.CheckboxItem>
|
|
89
|
+
))
|
|
90
|
+
DropdownMenuCheckboxItem.displayName =
|
|
91
|
+
DropdownMenuPrimitive.CheckboxItem.displayName
|
|
92
|
+
|
|
93
|
+
const DropdownMenuRadioItem = React.forwardRef(({ className, children, ...props }, ref) => (
|
|
94
|
+
<DropdownMenuPrimitive.RadioItem
|
|
95
|
+
ref={ref}
|
|
96
|
+
className={cn(
|
|
97
|
+
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
98
|
+
className
|
|
99
|
+
)}
|
|
100
|
+
{...props}>
|
|
101
|
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
102
|
+
<DropdownMenuPrimitive.ItemIndicator>
|
|
103
|
+
<Circle className="h-2 w-2 fill-current" />
|
|
104
|
+
</DropdownMenuPrimitive.ItemIndicator>
|
|
105
|
+
</span>
|
|
106
|
+
{children}
|
|
107
|
+
</DropdownMenuPrimitive.RadioItem>
|
|
108
|
+
))
|
|
109
|
+
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
|
|
110
|
+
|
|
111
|
+
const DropdownMenuLabel = React.forwardRef(({ className, inset, ...props }, ref) => (
|
|
112
|
+
<DropdownMenuPrimitive.Label
|
|
113
|
+
ref={ref}
|
|
114
|
+
className={cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className)}
|
|
115
|
+
{...props} />
|
|
116
|
+
))
|
|
117
|
+
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
|
|
118
|
+
|
|
119
|
+
const DropdownMenuSeparator = React.forwardRef(({ className, ...props }, ref) => (
|
|
120
|
+
<DropdownMenuPrimitive.Separator
|
|
121
|
+
ref={ref}
|
|
122
|
+
className={cn("-mx-1 my-1 h-px bg-muted", className)}
|
|
123
|
+
{...props} />
|
|
124
|
+
))
|
|
125
|
+
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
|
|
126
|
+
|
|
127
|
+
const DropdownMenuShortcut = ({
|
|
128
|
+
className,
|
|
129
|
+
...props
|
|
130
|
+
}) => {
|
|
131
|
+
return (
|
|
132
|
+
<span
|
|
133
|
+
className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
|
|
134
|
+
{...props} />
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
|
|
138
|
+
|
|
139
|
+
export {
|
|
140
|
+
DropdownMenu,
|
|
141
|
+
DropdownMenuTrigger,
|
|
142
|
+
DropdownMenuContent,
|
|
143
|
+
DropdownMenuItem,
|
|
144
|
+
DropdownMenuCheckboxItem,
|
|
145
|
+
DropdownMenuRadioItem,
|
|
146
|
+
DropdownMenuLabel,
|
|
147
|
+
DropdownMenuSeparator,
|
|
148
|
+
DropdownMenuShortcut,
|
|
149
|
+
DropdownMenuGroup,
|
|
150
|
+
DropdownMenuPortal,
|
|
151
|
+
DropdownMenuSub,
|
|
152
|
+
DropdownMenuSubContent,
|
|
153
|
+
DropdownMenuSubTrigger,
|
|
154
|
+
DropdownMenuRadioGroup,
|
|
155
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import * as React from "react"
|
|
3
|
+
import { Slot } from "@radix-ui/react-slot"
|
|
4
|
+
import { Controller, FormProvider, useFormContext } from "react-hook-form";
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
import { Label } from "@/components/ui/label"
|
|
8
|
+
|
|
9
|
+
const Form = FormProvider
|
|
10
|
+
|
|
11
|
+
const FormFieldContext = React.createContext(null)
|
|
12
|
+
|
|
13
|
+
const FormField = (
|
|
14
|
+
{
|
|
15
|
+
...props
|
|
16
|
+
}
|
|
17
|
+
) => {
|
|
18
|
+
return (
|
|
19
|
+
<FormFieldContext.Provider value={{ name: props.name }}>
|
|
20
|
+
<Controller {...props} />
|
|
21
|
+
</FormFieldContext.Provider>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const useFormField = () => {
|
|
26
|
+
const fieldContext = React.useContext(FormFieldContext)
|
|
27
|
+
const itemContext = React.useContext(FormItemContext)
|
|
28
|
+
const { getFieldState, formState } = useFormContext()
|
|
29
|
+
|
|
30
|
+
if (!fieldContext) {
|
|
31
|
+
throw new Error("useFormField should be used within <FormField>")
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (!itemContext) {
|
|
35
|
+
throw new Error("useFormField should be used within <FormItem>")
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const fieldState = getFieldState(fieldContext.name, formState)
|
|
39
|
+
|
|
40
|
+
const { id } = itemContext
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
id,
|
|
44
|
+
name: fieldContext.name,
|
|
45
|
+
formItemId: `${id}-form-item`,
|
|
46
|
+
formDescriptionId: `${id}-form-item-description`,
|
|
47
|
+
formMessageId: `${id}-form-item-message`,
|
|
48
|
+
...fieldState,
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const FormItemContext = React.createContext(null)
|
|
53
|
+
|
|
54
|
+
const FormItem = React.forwardRef(({ className, ...props }, ref) => {
|
|
55
|
+
const id = React.useId()
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<FormItemContext.Provider value={{ id }}>
|
|
59
|
+
<div ref={ref} className={cn("space-y-2", className)} {...props} />
|
|
60
|
+
</FormItemContext.Provider>
|
|
61
|
+
);
|
|
62
|
+
})
|
|
63
|
+
FormItem.displayName = "FormItem"
|
|
64
|
+
|
|
65
|
+
const FormLabel = React.forwardRef(({ className, ...props }, ref) => {
|
|
66
|
+
const { error, formItemId } = useFormField()
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<Label
|
|
70
|
+
ref={ref}
|
|
71
|
+
className={cn(error && "text-destructive", className)}
|
|
72
|
+
htmlFor={formItemId}
|
|
73
|
+
{...props} />
|
|
74
|
+
);
|
|
75
|
+
})
|
|
76
|
+
FormLabel.displayName = "FormLabel"
|
|
77
|
+
|
|
78
|
+
const FormControl = React.forwardRef(({ ...props }, ref) => {
|
|
79
|
+
const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<Slot
|
|
83
|
+
ref={ref}
|
|
84
|
+
id={formItemId}
|
|
85
|
+
aria-describedby={
|
|
86
|
+
!error
|
|
87
|
+
? `${formDescriptionId}`
|
|
88
|
+
: `${formDescriptionId} ${formMessageId}`
|
|
89
|
+
}
|
|
90
|
+
aria-invalid={!!error}
|
|
91
|
+
{...props} />
|
|
92
|
+
);
|
|
93
|
+
})
|
|
94
|
+
FormControl.displayName = "FormControl"
|
|
95
|
+
|
|
96
|
+
const FormDescription = React.forwardRef(({ className, ...props }, ref) => {
|
|
97
|
+
const { formDescriptionId } = useFormField()
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<p
|
|
101
|
+
ref={ref}
|
|
102
|
+
id={formDescriptionId}
|
|
103
|
+
className={cn("text-sm text-muted-foreground", className)}
|
|
104
|
+
{...props} />
|
|
105
|
+
);
|
|
106
|
+
})
|
|
107
|
+
FormDescription.displayName = "FormDescription"
|
|
108
|
+
|
|
109
|
+
const FormMessage = React.forwardRef(({ className, children, ...props }, ref) => {
|
|
110
|
+
const { error, formMessageId } = useFormField()
|
|
111
|
+
const body = error ? String(error?.message ?? "") : children
|
|
112
|
+
|
|
113
|
+
if (!body) {
|
|
114
|
+
return null
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
<p
|
|
119
|
+
ref={ref}
|
|
120
|
+
id={formMessageId}
|
|
121
|
+
className={cn("text-sm font-medium text-destructive", className)}
|
|
122
|
+
{...props}>
|
|
123
|
+
{body}
|
|
124
|
+
</p>
|
|
125
|
+
);
|
|
126
|
+
})
|
|
127
|
+
FormMessage.displayName = "FormMessage"
|
|
128
|
+
|
|
129
|
+
export {
|
|
130
|
+
useFormField,
|
|
131
|
+
Form,
|
|
132
|
+
FormItem,
|
|
133
|
+
FormLabel,
|
|
134
|
+
FormControl,
|
|
135
|
+
FormDescription,
|
|
136
|
+
FormMessage,
|
|
137
|
+
FormField,
|
|
138
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as HoverCardPrimitive from "@radix-ui/react-hover-card"
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
|
|
8
|
+
const HoverCard = HoverCardPrimitive.Root
|
|
9
|
+
|
|
10
|
+
const HoverCardTrigger = HoverCardPrimitive.Trigger
|
|
11
|
+
|
|
12
|
+
const HoverCardContent = React.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
|
|
13
|
+
<HoverCardPrimitive.Content
|
|
14
|
+
ref={ref}
|
|
15
|
+
align={align}
|
|
16
|
+
sideOffset={sideOffset}
|
|
17
|
+
className={cn(
|
|
18
|
+
"z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none 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-[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 origin-[--radix-hover-card-content-transform-origin]",
|
|
19
|
+
className
|
|
20
|
+
)}
|
|
21
|
+
{...props} />
|
|
22
|
+
))
|
|
23
|
+
HoverCardContent.displayName = HoverCardPrimitive.Content.displayName
|
|
24
|
+
|
|
25
|
+
export { HoverCard, HoverCardTrigger, HoverCardContent }
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// Local SVG icon module — inline icon components, no external icon library needed.
|
|
2
|
+
// All icons accept className and other SVG props.
|
|
3
|
+
|
|
4
|
+
function SvgIcon({ className = "h-4 w-4", children, ...props }) {
|
|
5
|
+
return (
|
|
6
|
+
<svg
|
|
7
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
8
|
+
viewBox="0 0 24 24"
|
|
9
|
+
fill="none"
|
|
10
|
+
stroke="currentColor"
|
|
11
|
+
strokeWidth="2"
|
|
12
|
+
strokeLinecap="round"
|
|
13
|
+
strokeLinejoin="round"
|
|
14
|
+
className={className}
|
|
15
|
+
{...props}
|
|
16
|
+
>
|
|
17
|
+
{children}
|
|
18
|
+
</svg>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function Check({ className, ...p }) {
|
|
23
|
+
return <SvgIcon className={className} {...p}><path d="M20 6 9 17l-5-5" /></SvgIcon>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function X({ className, ...p }) {
|
|
27
|
+
return <SvgIcon className={className} {...p}><path d="M18 6 6 18" /><path d="m6 6 12 12" /></SvgIcon>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function Circle({ className, ...p }) {
|
|
31
|
+
return <SvgIcon className={className} {...p}><circle cx="12" cy="12" r="10" /></SvgIcon>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function CheckCircle({ className, ...p }) {
|
|
35
|
+
return <SvgIcon className={className} {...p}><circle cx="12" cy="12" r="10" /><path d="m9 12 2 2 4-4" /></SvgIcon>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function AlertCircle({ className, ...p }) {
|
|
39
|
+
return <SvgIcon className={className} {...p}><circle cx="12" cy="12" r="10" /><line x1="12" y1="8" x2="12" y2="12" /><line x1="12" y1="16" x2="12.01" y2="16" /></SvgIcon>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function Info({ className, ...p }) {
|
|
43
|
+
return <SvgIcon className={className} {...p}><circle cx="12" cy="12" r="10" /><path d="M12 16v-4" /><path d="M12 8h.01" /></SvgIcon>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function Menu({ className, ...p }) {
|
|
47
|
+
return <SvgIcon className={className} {...p}><line x1="4" x2="20" y1="6" y2="6" /><line x1="4" x2="20" y1="12" y2="12" /><line x1="4" x2="20" y1="18" y2="18" /></SvgIcon>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function Search({ className, ...p }) {
|
|
51
|
+
return <SvgIcon className={className} {...p}><circle cx="11" cy="11" r="8" /><path d="m21 21-4.3-4.3" /></SvgIcon>;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function ChevronDown({ className, ...p }) {
|
|
55
|
+
return <SvgIcon className={className} {...p}><path d="m6 9 6 6 6-6" /></SvgIcon>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function ChevronUp({ className, ...p }) {
|
|
59
|
+
return <SvgIcon className={className} {...p}><path d="m18 15-6-6-6 6" /></SvgIcon>;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function ChevronRight({ className, ...p }) {
|
|
63
|
+
return <SvgIcon className={className} {...p}><path d="m9 18 6-6-6-6" /></SvgIcon>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function ChevronLeft({ className, ...p }) {
|
|
67
|
+
return <SvgIcon className={className} {...p}><path d="m15 18-6-6 6-6" /></SvgIcon>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function ArrowRight({ className, ...p }) {
|
|
71
|
+
return <SvgIcon className={className} {...p}><path d="M5 12h14" /><path d="m12 5 7 7-7 7" /></SvgIcon>;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function ArrowLeft({ className, ...p }) {
|
|
75
|
+
return <SvgIcon className={className} {...p}><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></SvgIcon>;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Aliases
|
|
79
|
+
export const ChevronDownIcon = ChevronDown;
|
|
80
|
+
export const ChevronLeftIcon = ChevronLeft;
|
|
81
|
+
export const ChevronRightIcon = ChevronRight;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/lib/utils"
|
|
4
|
+
|
|
5
|
+
const Input = React.forwardRef(({ className, type, ...props }, ref) => {
|
|
6
|
+
return (
|
|
7
|
+
<input
|
|
8
|
+
type={type}
|
|
9
|
+
className={cn(
|
|
10
|
+
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
11
|
+
className
|
|
12
|
+
)}
|
|
13
|
+
ref={ref}
|
|
14
|
+
{...props} />
|
|
15
|
+
);
|
|
16
|
+
})
|
|
17
|
+
Input.displayName = "Input"
|
|
18
|
+
|
|
19
|
+
export { Input }
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as LabelPrimitive from "@radix-ui/react-label"
|
|
3
|
+
import { cva } from "class-variance-authority";
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils"
|
|
6
|
+
|
|
7
|
+
const labelVariants = cva(
|
|
8
|
+
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
const Label = React.forwardRef(({ className, ...props }, ref) => (
|
|
12
|
+
<LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} />
|
|
13
|
+
))
|
|
14
|
+
Label.displayName = LabelPrimitive.Root.displayName
|
|
15
|
+
|
|
16
|
+
export { Label }
|