Skip to content

Commit dd5e93b

Browse files
committed
First
1 parent 18aa62d commit dd5e93b

27 files changed

+11885
-0
lines changed

.gitignore

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
# Editor directories and files
16+
.vscode/*
17+
!.vscode/extensions.json
18+
.idea
19+
.DS_Store
20+
*.suo
21+
*.ntvs*
22+
*.njsproj
23+
*.sln
24+
*.sw?
25+
26+
.env

components.json

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"$schema": "https://ui.shadcn.com/schema.json",
3+
"style": "new-york",
4+
"rsc": false,
5+
"tsx": false,
6+
"tailwind": {
7+
"config": "tailwind.config.js",
8+
"css": "src/index.css",
9+
"baseColor": "slate",
10+
"cssVariables": false,
11+
"prefix": ""
12+
},
13+
"aliases": {
14+
"components": "@/components",
15+
"utils": "@/lib/utils"
16+
}
17+
}

components/ui/button.jsx

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import * as React from "react"
2+
import { Slot } from "@radix-ui/react-slot"
3+
import { cva } from "class-variance-authority";
4+
5+
import { cn } from "@/lib/utils"
6+
7+
const buttonVariants = cva(
8+
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-950 disabled:pointer-events-none disabled:opacity-50 dark:focus-visible:ring-slate-300",
9+
{
10+
variants: {
11+
variant: {
12+
default:
13+
"bg-slate-900 text-slate-50 shadow hover:bg-slate-900/90 dark:bg-slate-50 dark:text-slate-900 dark:hover:bg-slate-50/90",
14+
destructive:
15+
"bg-red-500 text-slate-50 shadow-sm hover:bg-red-500/90 dark:bg-red-900 dark:text-slate-50 dark:hover:bg-red-900/90",
16+
outline:
17+
"border border-slate-200 bg-white shadow-sm hover:bg-slate-100 hover:text-slate-900 dark:border-slate-800 dark:bg-slate-950 dark:hover:bg-slate-800 dark:hover:text-slate-50",
18+
secondary:
19+
"bg-slate-100 text-slate-900 shadow-sm hover:bg-slate-100/80 dark:bg-slate-800 dark:text-slate-50 dark:hover:bg-slate-800/80",
20+
ghost: "hover:bg-slate-100 hover:text-slate-900 dark:hover:bg-slate-800 dark:hover:text-slate-50",
21+
link: "text-slate-900 underline-offset-4 hover:underline dark:text-slate-50",
22+
},
23+
size: {
24+
default: "h-9 px-4 py-2",
25+
sm: "h-8 rounded-md px-3 text-xs",
26+
lg: "h-10 rounded-md px-8",
27+
icon: "h-9 w-9",
28+
},
29+
},
30+
defaultVariants: {
31+
variant: "default",
32+
size: "default",
33+
},
34+
}
35+
)
36+
37+
const Button = React.forwardRef(({ className, variant, size, asChild = false, ...props }, ref) => {
38+
const Comp = asChild ? Slot : "button"
39+
return (
40+
(<Comp
41+
className={cn(buttonVariants({ variant, size, className }))}
42+
ref={ref}
43+
{...props} />)
44+
);
45+
})
46+
Button.displayName = "Button"
47+
48+
export { Button, buttonVariants }

components/ui/form.jsx

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import * as React from "react"
2+
import { Slot } from "@radix-ui/react-slot"
3+
import { Controller, FormProvider, useFormContext } from "react-hook-form";
4+
5+
import { cn } from "@/lib/utils"
6+
import { Label } from "@/components/ui/label"
7+
8+
const Form = FormProvider
9+
10+
const FormFieldContext = React.createContext({})
11+
12+
const FormField = (
13+
{
14+
...props
15+
}
16+
) => {
17+
return (
18+
(<FormFieldContext.Provider value={{ name: props.name }}>
19+
<Controller {...props} />
20+
</FormFieldContext.Provider>)
21+
);
22+
}
23+
24+
const useFormField = () => {
25+
const fieldContext = React.useContext(FormFieldContext)
26+
const itemContext = React.useContext(FormItemContext)
27+
const { getFieldState, formState } = useFormContext()
28+
29+
const fieldState = getFieldState(fieldContext.name, formState)
30+
31+
if (!fieldContext) {
32+
throw new Error("useFormField should be used within <FormField>")
33+
}
34+
35+
const { id } = itemContext
36+
37+
return {
38+
id,
39+
name: fieldContext.name,
40+
formItemId: `${id}-form-item`,
41+
formDescriptionId: `${id}-form-item-description`,
42+
formMessageId: `${id}-form-item-message`,
43+
...fieldState,
44+
}
45+
}
46+
47+
const FormItemContext = React.createContext({})
48+
49+
const FormItem = React.forwardRef(({ className, ...props }, ref) => {
50+
const id = React.useId()
51+
52+
return (
53+
(<FormItemContext.Provider value={{ id }}>
54+
<div ref={ref} className={cn("space-y-2", className)} {...props} />
55+
</FormItemContext.Provider>)
56+
);
57+
})
58+
FormItem.displayName = "FormItem"
59+
60+
const FormLabel = React.forwardRef(({ className, ...props }, ref) => {
61+
const { error, formItemId } = useFormField()
62+
63+
return (
64+
(<Label
65+
ref={ref}
66+
className={cn(error && "text-red-500 dark:text-red-900", className)}
67+
htmlFor={formItemId}
68+
{...props} />)
69+
);
70+
})
71+
FormLabel.displayName = "FormLabel"
72+
73+
const FormControl = React.forwardRef(({ ...props }, ref) => {
74+
const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
75+
76+
return (
77+
(<Slot
78+
ref={ref}
79+
id={formItemId}
80+
aria-describedby={
81+
!error
82+
? `${formDescriptionId}`
83+
: `${formDescriptionId} ${formMessageId}`
84+
}
85+
aria-invalid={!!error}
86+
{...props} />)
87+
);
88+
})
89+
FormControl.displayName = "FormControl"
90+
91+
const FormDescription = React.forwardRef(({ className, ...props }, ref) => {
92+
const { formDescriptionId } = useFormField()
93+
94+
return (
95+
(<p
96+
ref={ref}
97+
id={formDescriptionId}
98+
className={cn("text-[0.8rem] text-slate-500 dark:text-slate-400", className)}
99+
{...props} />)
100+
);
101+
})
102+
FormDescription.displayName = "FormDescription"
103+
104+
const FormMessage = React.forwardRef(({ className, children, ...props }, ref) => {
105+
const { error, formMessageId } = useFormField()
106+
const body = error ? String(error?.message) : children
107+
108+
if (!body) {
109+
return null
110+
}
111+
112+
return (
113+
(<p
114+
ref={ref}
115+
id={formMessageId}
116+
className={cn("text-[0.8rem] font-medium text-red-500 dark:text-red-900", className)}
117+
{...props}>
118+
{body}
119+
</p>)
120+
);
121+
})
122+
FormMessage.displayName = "FormMessage"
123+
124+
export {
125+
useFormField,
126+
Form,
127+
FormItem,
128+
FormLabel,
129+
FormControl,
130+
FormDescription,
131+
FormMessage,
132+
FormField,
133+
}

components/ui/input.jsx

+19
Original file line numberDiff line numberDiff line change
@@ -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-9 w-full rounded-md border border-slate-200 bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-slate-500 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-950 disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-800 dark:placeholder:text-slate-400 dark:focus-visible:ring-slate-300",
11+
className
12+
)}
13+
ref={ref}
14+
{...props} />)
15+
);
16+
})
17+
Input.displayName = "Input"
18+
19+
export { Input }

components/ui/label.jsx

+16
Original file line numberDiff line numberDiff line change
@@ -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 }

components/ui/toast.jsx

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import * as React from "react"
2+
import { Cross2Icon } from "@radix-ui/react-icons"
3+
import * as ToastPrimitives from "@radix-ui/react-toast"
4+
import { cva } from "class-variance-authority";
5+
6+
import { cn } from "@/lib/utils"
7+
8+
const ToastProvider = ToastPrimitives.Provider
9+
10+
const ToastViewport = React.forwardRef(({ className, ...props }, ref) => (
11+
<ToastPrimitives.Viewport
12+
ref={ref}
13+
className={cn(
14+
"fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]",
15+
className
16+
)}
17+
{...props} />
18+
))
19+
ToastViewport.displayName = ToastPrimitives.Viewport.displayName
20+
21+
const toastVariants = cva(
22+
"group pointer-events-auto relative flex w-full items-center justify-between space-x-2 overflow-hidden rounded-md border border-slate-200 p-4 pr-6 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full dark:border-slate-800",
23+
{
24+
variants: {
25+
variant: {
26+
default: "border bg-white text-slate-950 dark:bg-slate-950 dark:text-slate-50",
27+
destructive:
28+
"destructive group border-red-500 bg-red-500 text-slate-50 dark:border-red-900 dark:bg-red-900 dark:text-slate-50",
29+
},
30+
},
31+
defaultVariants: {
32+
variant: "default",
33+
},
34+
}
35+
)
36+
37+
const Toast = React.forwardRef(({ className, variant, ...props }, ref) => {
38+
return (
39+
(<ToastPrimitives.Root
40+
ref={ref}
41+
className={cn(toastVariants({ variant }), className)}
42+
{...props} />)
43+
);
44+
})
45+
Toast.displayName = ToastPrimitives.Root.displayName
46+
47+
const ToastAction = React.forwardRef(({ className, ...props }, ref) => (
48+
<ToastPrimitives.Action
49+
ref={ref}
50+
className={cn(
51+
"inline-flex h-8 shrink-0 items-center justify-center rounded-md border border-slate-200 bg-transparent px-3 text-sm font-medium transition-colors hover:bg-slate-100 focus:outline-none focus:ring-1 focus:ring-slate-950 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-slate-100/40 group-[.destructive]:hover:border-red-500/30 group-[.destructive]:hover:bg-red-500 group-[.destructive]:hover:text-slate-50 group-[.destructive]:focus:ring-red-500 dark:border-slate-800 dark:hover:bg-slate-800 dark:focus:ring-slate-300 dark:group-[.destructive]:border-slate-800/40 dark:group-[.destructive]:hover:border-red-900/30 dark:group-[.destructive]:hover:bg-red-900 dark:group-[.destructive]:hover:text-slate-50 dark:group-[.destructive]:focus:ring-red-900",
52+
className
53+
)}
54+
{...props} />
55+
))
56+
ToastAction.displayName = ToastPrimitives.Action.displayName
57+
58+
const ToastClose = React.forwardRef(({ className, ...props }, ref) => (
59+
<ToastPrimitives.Close
60+
ref={ref}
61+
className={cn(
62+
"absolute right-1 top-1 rounded-md p-1 text-slate-950/50 opacity-0 transition-opacity hover:text-slate-950 focus:opacity-100 focus:outline-none focus:ring-1 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600 dark:text-slate-50/50 dark:hover:text-slate-50",
63+
className
64+
)}
65+
toast-close=""
66+
{...props}>
67+
<Cross2Icon className="h-4 w-4" />
68+
</ToastPrimitives.Close>
69+
))
70+
ToastClose.displayName = ToastPrimitives.Close.displayName
71+
72+
const ToastTitle = React.forwardRef(({ className, ...props }, ref) => (
73+
<ToastPrimitives.Title
74+
ref={ref}
75+
className={cn("text-sm font-semibold [&+div]:text-xs", className)}
76+
{...props} />
77+
))
78+
ToastTitle.displayName = ToastPrimitives.Title.displayName
79+
80+
const ToastDescription = React.forwardRef(({ className, ...props }, ref) => (
81+
<ToastPrimitives.Description ref={ref} className={cn("text-sm opacity-90", className)} {...props} />
82+
))
83+
ToastDescription.displayName = ToastPrimitives.Description.displayName
84+
85+
export { ToastProvider, ToastViewport, Toast, ToastTitle, ToastDescription, ToastClose, ToastAction };

components/ui/toaster.jsx

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import {
2+
Toast,
3+
ToastClose,
4+
ToastDescription,
5+
ToastProvider,
6+
ToastTitle,
7+
ToastViewport,
8+
} from "@/components/ui/toast"
9+
import { useToast } from "@/components/ui/use-toast"
10+
11+
export function Toaster() {
12+
const { toasts } = useToast()
13+
14+
return (
15+
(<ToastProvider>
16+
{toasts.map(function ({ id, title, description, action, ...props }) {
17+
return (
18+
(<Toast key={id} {...props}>
19+
<div className="grid gap-1">
20+
{title && <ToastTitle>{title}</ToastTitle>}
21+
{description && (
22+
<ToastDescription>{description}</ToastDescription>
23+
)}
24+
</div>
25+
{action}
26+
<ToastClose />
27+
</Toast>)
28+
);
29+
})}
30+
<ToastViewport />
31+
</ToastProvider>)
32+
);
33+
}

0 commit comments

Comments
 (0)