tr]:last:border-b-0",
48 | className
49 | )}
50 | {...props}
51 | />
52 | )
53 | }
54 |
55 | function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
56 | return (
57 |
65 | )
66 | }
67 |
68 | function TableHead({ className, ...props }: React.ComponentProps<"th">) {
69 | return (
70 | [role=checkbox]]:translate-y-[2px]",
74 | className
75 | )}
76 | {...props}
77 | />
78 | )
79 | }
80 |
81 | function TableCell({ className, ...props }: React.ComponentProps<"td">) {
82 | return (
83 | | [role=checkbox]]:translate-y-[2px]",
87 | className
88 | )}
89 | {...props}
90 | />
91 | )
92 | }
93 |
94 | function TableCaption({
95 | className,
96 | ...props
97 | }: React.ComponentProps<"caption">) {
98 | return (
99 |
104 | )
105 | }
106 |
107 | export {
108 | Table,
109 | TableHeader,
110 | TableBody,
111 | TableFooter,
112 | TableHead,
113 | TableRow,
114 | TableCell,
115 | TableCaption,
116 | }
117 |
--------------------------------------------------------------------------------
/components/ui/calendar.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import { ChevronLeft, ChevronRight } from "lucide-react"
5 | import { DayPicker } from "react-day-picker"
6 |
7 | import { cn } from "@/lib/utils"
8 | import { buttonVariants } from "@/components/ui/button"
9 |
10 | function Calendar({
11 | className,
12 | classNames,
13 | showOutsideDays = true,
14 | ...props
15 | }: React.ComponentProps) {
16 | return (
17 | .day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md"
41 | : "[&:has([aria-selected])]:rounded-md"
42 | ),
43 | day: cn(
44 | buttonVariants({ variant: "ghost" }),
45 | "size-8 p-0 font-normal aria-selected:opacity-100"
46 | ),
47 | day_range_start:
48 | "day-range-start aria-selected:bg-primary aria-selected:text-primary-foreground",
49 | day_range_end:
50 | "day-range-end aria-selected:bg-primary aria-selected:text-primary-foreground",
51 | day_selected:
52 | "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
53 | day_today: "bg-accent text-accent-foreground",
54 | day_outside:
55 | "day-outside text-muted-foreground aria-selected:text-muted-foreground",
56 | day_disabled: "text-muted-foreground opacity-50",
57 | day_range_middle:
58 | "aria-selected:bg-accent aria-selected:text-accent-foreground",
59 | day_hidden: "invisible",
60 | ...classNames,
61 | }}
62 | components={{
63 | IconLeft: ({ className, ...props }) => (
64 |
65 | ),
66 | IconRight: ({ className, ...props }) => (
67 |
68 | ),
69 | }}
70 | {...props}
71 | />
72 | )
73 | }
74 |
75 | export { Calendar }
76 |
--------------------------------------------------------------------------------
/components/ui/pagination.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import {
3 | ChevronLeftIcon,
4 | ChevronRightIcon,
5 | MoreHorizontalIcon,
6 | } from "lucide-react"
7 |
8 | import { cn } from "@/lib/utils"
9 | import { Button, buttonVariants } from "@/components/ui/button"
10 |
11 | function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
12 | return (
13 |
20 | )
21 | }
22 |
23 | function PaginationContent({
24 | className,
25 | ...props
26 | }: React.ComponentProps<"ul">) {
27 | return (
28 |
33 | )
34 | }
35 |
36 | function PaginationItem({ ...props }: React.ComponentProps<"li">) {
37 | return
38 | }
39 |
40 | type PaginationLinkProps = {
41 | isActive?: boolean
42 | } & Pick, "size"> &
43 | React.ComponentProps<"a">
44 |
45 | function PaginationLink({
46 | className,
47 | isActive,
48 | size = "icon",
49 | ...props
50 | }: PaginationLinkProps) {
51 | return (
52 |
65 | )
66 | }
67 |
68 | function PaginationPrevious({
69 | className,
70 | ...props
71 | }: React.ComponentProps) {
72 | return (
73 |
79 |
80 | Previous
81 |
82 | )
83 | }
84 |
85 | function PaginationNext({
86 | className,
87 | ...props
88 | }: React.ComponentProps) {
89 | return (
90 |
96 | Next
97 |
98 |
99 | )
100 | }
101 |
102 | function PaginationEllipsis({
103 | className,
104 | ...props
105 | }: React.ComponentProps<"span">) {
106 | return (
107 |
113 |
114 | More pages
115 |
116 | )
117 | }
118 |
119 | export {
120 | Pagination,
121 | PaginationContent,
122 | PaginationLink,
123 | PaginationItem,
124 | PaginationPrevious,
125 | PaginationNext,
126 | PaginationEllipsis,
127 | }
128 |
--------------------------------------------------------------------------------
/components/ui/dialog.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as DialogPrimitive from "@radix-ui/react-dialog"
5 | import { XIcon } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | function Dialog({
10 | ...props
11 | }: React.ComponentProps) {
12 | return
13 | }
14 |
15 | function DialogTrigger({
16 | ...props
17 | }: React.ComponentProps) {
18 | return
19 | }
20 |
21 | function DialogPortal({
22 | ...props
23 | }: React.ComponentProps) {
24 | return
25 | }
26 |
27 | function DialogClose({
28 | ...props
29 | }: React.ComponentProps) {
30 | return
31 | }
32 |
33 | function DialogOverlay({
34 | className,
35 | ...props
36 | }: React.ComponentProps) {
37 | return (
38 |
46 | )
47 | }
48 |
49 | function DialogContent({
50 | className,
51 | children,
52 | ...props
53 | }: React.ComponentProps) {
54 | return (
55 |
56 |
57 |
65 | {children}
66 |
67 |
68 | Close
69 |
70 |
71 |
72 | )
73 | }
74 |
75 | function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
76 | return (
77 |
82 | )
83 | }
84 |
85 | function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
86 | return (
87 |
95 | )
96 | }
97 |
98 | function DialogTitle({
99 | className,
100 | ...props
101 | }: React.ComponentProps) {
102 | return (
103 |
108 | )
109 | }
110 |
111 | function DialogDescription({
112 | className,
113 | ...props
114 | }: React.ComponentProps) {
115 | return (
116 |
121 | )
122 | }
123 |
124 | export {
125 | Dialog,
126 | DialogClose,
127 | DialogContent,
128 | DialogDescription,
129 | DialogFooter,
130 | DialogHeader,
131 | DialogOverlay,
132 | DialogPortal,
133 | DialogTitle,
134 | DialogTrigger,
135 | }
136 |
--------------------------------------------------------------------------------
/components/ui/form.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as LabelPrimitive from "@radix-ui/react-label"
5 | import { Slot } from "@radix-ui/react-slot"
6 | import {
7 | Controller,
8 | FormProvider,
9 | useFormContext,
10 | useFormState,
11 | type ControllerProps,
12 | type FieldPath,
13 | type FieldValues,
14 | } from "react-hook-form"
15 |
16 | import { cn } from "@/lib/utils"
17 | import { Label } from "@/components/ui/label"
18 |
19 | const Form = FormProvider
20 |
21 | type FormFieldContextValue<
22 | TFieldValues extends FieldValues = FieldValues,
23 | TName extends FieldPath = FieldPath,
24 | > = {
25 | name: TName
26 | }
27 |
28 | const FormFieldContext = React.createContext(
29 | {} as FormFieldContextValue
30 | )
31 |
32 | const FormField = <
33 | TFieldValues extends FieldValues = FieldValues,
34 | TName extends FieldPath = FieldPath,
35 | >({
36 | ...props
37 | }: ControllerProps) => {
38 | return (
39 |
40 |
41 |
42 | )
43 | }
44 |
45 | const useFormField = () => {
46 | const fieldContext = React.useContext(FormFieldContext)
47 | const itemContext = React.useContext(FormItemContext)
48 | const { getFieldState } = useFormContext()
49 | const formState = useFormState({ name: fieldContext.name })
50 | const fieldState = getFieldState(fieldContext.name, formState)
51 |
52 | if (!fieldContext) {
53 | throw new Error("useFormField should be used within ")
54 | }
55 |
56 | const { id } = itemContext
57 |
58 | return {
59 | id,
60 | name: fieldContext.name,
61 | formItemId: `${id}-form-item`,
62 | formDescriptionId: `${id}-form-item-description`,
63 | formMessageId: `${id}-form-item-message`,
64 | ...fieldState,
65 | }
66 | }
67 |
68 | type FormItemContextValue = {
69 | id: string
70 | }
71 |
72 | const FormItemContext = React.createContext(
73 | {} as FormItemContextValue
74 | )
75 |
76 | function FormItem({ className, ...props }: React.ComponentProps<"div">) {
77 | const id = React.useId()
78 |
79 | return (
80 |
81 |
86 |
87 | )
88 | }
89 |
90 | function FormLabel({
91 | className,
92 | ...props
93 | }: React.ComponentProps) {
94 | const { error, formItemId } = useFormField()
95 |
96 | return (
97 |
104 | )
105 | }
106 |
107 | function FormControl({ ...props }: React.ComponentProps) {
108 | const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
109 |
110 | return (
111 |
122 | )
123 | }
124 |
125 | function FormDescription({ className, ...props }: React.ComponentProps<"p">) {
126 | const { formDescriptionId } = useFormField()
127 |
128 | return (
129 |
135 | )
136 | }
137 |
138 | function FormMessage({ className, ...props }: React.ComponentProps<"p">) {
139 | const { error, formMessageId } = useFormField()
140 | const body = error ? String(error?.message ?? "") : props.children
141 |
142 | if (!body) {
143 | return null
144 | }
145 |
146 | return (
147 |
153 | {body}
154 |
155 | )
156 | }
157 |
158 | export {
159 | useFormField,
160 | Form,
161 | FormItem,
162 | FormLabel,
163 | FormControl,
164 | FormDescription,
165 | FormMessage,
166 | FormField,
167 | }
168 |
--------------------------------------------------------------------------------
/components/ui/alert-dialog.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
5 |
6 | import { cn } from "@/lib/utils"
7 | import { buttonVariants } from "@/components/ui/button"
8 |
9 | function AlertDialog({
10 | ...props
11 | }: React.ComponentProps) {
12 | return
13 | }
14 |
15 | function AlertDialogTrigger({
16 | ...props
17 | }: React.ComponentProps) {
18 | return (
19 |
20 | )
21 | }
22 |
23 | function AlertDialogPortal({
24 | ...props
25 | }: React.ComponentProps) {
26 | return (
27 |
28 | )
29 | }
30 |
31 | function AlertDialogOverlay({
32 | className,
33 | ...props
34 | }: React.ComponentProps) {
35 | return (
36 |
44 | )
45 | }
46 |
47 | function AlertDialogContent({
48 | className,
49 | ...props
50 | }: React.ComponentProps) {
51 | return (
52 |
53 |
54 |
62 |
63 | )
64 | }
65 |
66 | function AlertDialogHeader({
67 | className,
68 | ...props
69 | }: React.ComponentProps<"div">) {
70 | return (
71 |
76 | )
77 | }
78 |
79 | function AlertDialogFooter({
80 | className,
81 | ...props
82 | }: React.ComponentProps<"div">) {
83 | return (
84 |
92 | )
93 | }
94 |
95 | function AlertDialogTitle({
96 | className,
97 | ...props
98 | }: React.ComponentProps) {
99 | return (
100 |
105 | )
106 | }
107 |
108 | function AlertDialogDescription({
109 | className,
110 | ...props
111 | }: React.ComponentProps) {
112 | return (
113 |
118 | )
119 | }
120 |
121 | function AlertDialogAction({
122 | className,
123 | ...props
124 | }: React.ComponentProps) {
125 | return (
126 |
130 | )
131 | }
132 |
133 | function AlertDialogCancel({
134 | className,
135 | ...props
136 | }: React.ComponentProps) {
137 | return (
138 |
142 | )
143 | }
144 |
145 | export {
146 | AlertDialog,
147 | AlertDialogPortal,
148 | AlertDialogOverlay,
149 | AlertDialogTrigger,
150 | AlertDialogContent,
151 | AlertDialogHeader,
152 | AlertDialogFooter,
153 | AlertDialogTitle,
154 | AlertDialogDescription,
155 | AlertDialogAction,
156 | AlertDialogCancel,
157 | }
158 |
--------------------------------------------------------------------------------
/components/ui/drawer.tsx:
--------------------------------------------------------------------------------
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 | function Drawer({
9 | ...props
10 | }: React.ComponentProps) {
11 | return
12 | }
13 |
14 | function DrawerTrigger({
15 | ...props
16 | }: React.ComponentProps) {
17 | return
18 | }
19 |
20 | function DrawerPortal({
21 | ...props
22 | }: React.ComponentProps) {
23 | return
24 | }
25 |
26 | function DrawerClose({
27 | ...props
28 | }: React.ComponentProps) {
29 | return
30 | }
31 |
32 | function DrawerOverlay({
33 | className,
34 | ...props
35 | }: React.ComponentProps) {
36 | return (
37 |
45 | )
46 | }
47 |
48 | function DrawerContent({
49 | className,
50 | children,
51 | ...props
52 | }: React.ComponentProps) {
53 | return (
54 |
55 |
56 |
68 |
69 | {children}
70 |
71 |
72 | )
73 | }
74 |
75 | function DrawerHeader({ className, ...props }: React.ComponentProps<"div">) {
76 | return (
77 |
82 | )
83 | }
84 |
85 | function DrawerFooter({ className, ...props }: React.ComponentProps<"div">) {
86 | return (
87 |
92 | )
93 | }
94 |
95 | function DrawerTitle({
96 | className,
97 | ...props
98 | }: React.ComponentProps) {
99 | return (
100 |
105 | )
106 | }
107 |
108 | function DrawerDescription({
109 | className,
110 | ...props
111 | }: React.ComponentProps) {
112 | return (
113 |
118 | )
119 | }
120 |
121 | export {
122 | Drawer,
123 | DrawerPortal,
124 | DrawerOverlay,
125 | DrawerTrigger,
126 | DrawerClose,
127 | DrawerContent,
128 | DrawerHeader,
129 | DrawerFooter,
130 | DrawerTitle,
131 | DrawerDescription,
132 | }
133 |
--------------------------------------------------------------------------------
/components/ui/sheet.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as SheetPrimitive from "@radix-ui/react-dialog"
5 | import { XIcon } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | function Sheet({ ...props }: React.ComponentProps) {
10 | return
11 | }
12 |
13 | function SheetTrigger({
14 | ...props
15 | }: React.ComponentProps) {
16 | return
17 | }
18 |
19 | function SheetClose({
20 | ...props
21 | }: React.ComponentProps) {
22 | return
23 | }
24 |
25 | function SheetPortal({
26 | ...props
27 | }: React.ComponentProps) {
28 | return
29 | }
30 |
31 | function SheetOverlay({
32 | className,
33 | ...props
34 | }: React.ComponentProps) {
35 | return (
36 |
44 | )
45 | }
46 |
47 | function SheetContent({
48 | className,
49 | children,
50 | side = "right",
51 | ...props
52 | }: React.ComponentProps & {
53 | side?: "top" | "right" | "bottom" | "left"
54 | }) {
55 | return (
56 |
57 |
58 |
74 | {children}
75 |
76 |
77 | Close
78 |
79 |
80 |
81 | )
82 | }
83 |
84 | function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
85 | return (
86 |
91 | )
92 | }
93 |
94 | function SheetFooter({ className, ...props }: React.ComponentProps<"div">) {
95 | return (
96 |
101 | )
102 | }
103 |
104 | function SheetTitle({
105 | className,
106 | ...props
107 | }: React.ComponentProps) {
108 | return (
109 |
114 | )
115 | }
116 |
117 | function SheetDescription({
118 | className,
119 | ...props
120 | }: React.ComponentProps) {
121 | return (
122 |
127 | )
128 | }
129 |
130 | export {
131 | Sheet,
132 | SheetTrigger,
133 | SheetClose,
134 | SheetContent,
135 | SheetHeader,
136 | SheetFooter,
137 | SheetTitle,
138 | SheetDescription,
139 | }
140 |
--------------------------------------------------------------------------------
/app/globals.css:
--------------------------------------------------------------------------------
1 | @import "tailwindcss";
2 |
3 | @plugin "tailwindcss-animate";
4 |
5 | @custom-variant dark (&:is(.dark *));
6 |
7 | @theme inline {
8 | --color-background: var(--background);
9 | --color-foreground: var(--foreground);
10 | --font-sans: var(--font-geist-sans);
11 | --font-mono: var(--font-geist-mono);
12 | --color-sidebar-ring: var(--sidebar-ring);
13 | --color-sidebar-border: var(--sidebar-border);
14 | --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
15 | --color-sidebar-accent: var(--sidebar-accent);
16 | --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
17 | --color-sidebar-primary: var(--sidebar-primary);
18 | --color-sidebar-foreground: var(--sidebar-foreground);
19 | --color-sidebar: var(--sidebar);
20 | --color-chart-5: var(--chart-5);
21 | --color-chart-4: var(--chart-4);
22 | --color-chart-3: var(--chart-3);
23 | --color-chart-2: var(--chart-2);
24 | --color-chart-1: var(--chart-1);
25 | --color-ring: var(--ring);
26 | --color-input: var(--input);
27 | --color-border: var(--border);
28 | --color-destructive: var(--destructive);
29 | --color-accent-foreground: var(--accent-foreground);
30 | --color-accent: var(--accent);
31 | --color-muted-foreground: var(--muted-foreground);
32 | --color-muted: var(--muted);
33 | --color-secondary-foreground: var(--secondary-foreground);
34 | --color-secondary: var(--secondary);
35 | --color-primary-foreground: var(--primary-foreground);
36 | --color-primary: var(--primary);
37 | --color-popover-foreground: var(--popover-foreground);
38 | --color-popover: var(--popover);
39 | --color-card-foreground: var(--card-foreground);
40 | --color-card: var(--card);
41 | --radius-sm: calc(var(--radius) - 4px);
42 | --radius-md: calc(var(--radius) - 2px);
43 | --radius-lg: var(--radius);
44 | --radius-xl: calc(var(--radius) + 4px);
45 | --animate-accordion-down: accordion-down 0.2s ease-out;
46 | --animate-accordion-up: accordion-up 0.2s ease-out;
47 |
48 | @keyframes accordion-down {
49 | from {
50 | height: 0;
51 | }
52 | to {
53 | height: var(--radix-accordion-content-height);
54 | }
55 | }
56 |
57 | @keyframes accordion-up {
58 | from {
59 | height: var(--radix-accordion-content-height);
60 | }
61 | to {
62 | height: 0;
63 | }
64 | }
65 | }
66 |
67 | :root {
68 | --radius: 0.625rem;
69 | --background: oklch(1 0 0);
70 | --foreground: oklch(0.145 0 0);
71 | --card: oklch(1 0 0);
72 | --card-foreground: oklch(0.145 0 0);
73 | --popover: oklch(1 0 0);
74 | --popover-foreground: oklch(0.145 0 0);
75 | --primary: oklch(0.205 0 0);
76 | --primary-foreground: oklch(0.985 0 0);
77 | --secondary: oklch(0.97 0 0);
78 | --secondary-foreground: oklch(0.205 0 0);
79 | --muted: oklch(0.97 0 0);
80 | --muted-foreground: oklch(0.556 0 0);
81 | --accent: oklch(0.97 0 0);
82 | --accent-foreground: oklch(0.205 0 0);
83 | --destructive: oklch(0.577 0.245 27.325);
84 | --border: oklch(0.922 0 0);
85 | --input: oklch(0.922 0 0);
86 | --ring: oklch(0.708 0 0);
87 | --chart-1: oklch(0.646 0.222 41.116);
88 | --chart-2: oklch(0.6 0.118 184.704);
89 | --chart-3: oklch(0.398 0.07 227.392);
90 | --chart-4: oklch(0.828 0.189 84.429);
91 | --chart-5: oklch(0.769 0.188 70.08);
92 | --sidebar: oklch(0.985 0 0);
93 | --sidebar-foreground: oklch(0.145 0 0);
94 | --sidebar-primary: oklch(0.205 0 0);
95 | --sidebar-primary-foreground: oklch(0.985 0 0);
96 | --sidebar-accent: oklch(0.97 0 0);
97 | --sidebar-accent-foreground: oklch(0.205 0 0);
98 | --sidebar-border: oklch(0.922 0 0);
99 | --sidebar-ring: oklch(0.708 0 0);
100 | }
101 |
102 | .dark {
103 | --background: oklch(0.145 0 0);
104 | --foreground: oklch(0.985 0 0);
105 | --card: oklch(0.205 0 0);
106 | --card-foreground: oklch(0.985 0 0);
107 | --popover: oklch(0.205 0 0);
108 | --popover-foreground: oklch(0.985 0 0);
109 | --primary: oklch(0.922 0 0);
110 | --primary-foreground: oklch(0.205 0 0);
111 | --secondary: oklch(0.269 0 0);
112 | --secondary-foreground: oklch(0.985 0 0);
113 | --muted: oklch(0.269 0 0);
114 | --muted-foreground: oklch(0.708 0 0);
115 | --accent: oklch(0.269 0 0);
116 | --accent-foreground: oklch(0.985 0 0);
117 | --destructive: oklch(0.704 0.191 22.216);
118 | --border: oklch(1 0 0 / 10%);
119 | --input: oklch(1 0 0 / 15%);
120 | --ring: oklch(0.556 0 0);
121 | --chart-1: oklch(0.488 0.243 264.376);
122 | --chart-2: oklch(0.696 0.17 162.48);
123 | --chart-3: oklch(0.769 0.188 70.08);
124 | --chart-4: oklch(0.627 0.265 303.9);
125 | --chart-5: oklch(0.645 0.246 16.439);
126 | --sidebar: oklch(0.205 0 0);
127 | --sidebar-foreground: oklch(0.985 0 0);
128 | --sidebar-primary: oklch(0.488 0.243 264.376);
129 | --sidebar-primary-foreground: oklch(0.985 0 0);
130 | --sidebar-accent: oklch(0.269 0 0);
131 | --sidebar-accent-foreground: oklch(0.985 0 0);
132 | --sidebar-border: oklch(1 0 0 / 10%);
133 | --sidebar-ring: oklch(0.556 0 0);
134 | }
135 |
136 | @layer base {
137 | * {
138 | @apply border-border outline-ring/50;
139 | }
140 | body {
141 | @apply bg-background text-foreground;
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/components/ui/command.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import { Command as CommandPrimitive } from "cmdk"
5 | import { SearchIcon } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 | import {
9 | Dialog,
10 | DialogContent,
11 | DialogDescription,
12 | DialogHeader,
13 | DialogTitle,
14 | } from "@/components/ui/dialog"
15 |
16 | function Command({
17 | className,
18 | ...props
19 | }: React.ComponentProps) {
20 | return (
21 |
29 | )
30 | }
31 |
32 | function CommandDialog({
33 | title = "Command Palette",
34 | description = "Search for a command to run...",
35 | children,
36 | ...props
37 | }: React.ComponentProps & {
38 | title?: string
39 | description?: string
40 | }) {
41 | return (
42 |
53 | )
54 | }
55 |
56 | function CommandInput({
57 | className,
58 | ...props
59 | }: React.ComponentProps) {
60 | return (
61 |
65 |
66 |
74 |
75 | )
76 | }
77 |
78 | function CommandList({
79 | className,
80 | ...props
81 | }: React.ComponentProps) {
82 | return (
83 |
91 | )
92 | }
93 |
94 | function CommandEmpty({
95 | ...props
96 | }: React.ComponentProps) {
97 | return (
98 |
103 | )
104 | }
105 |
106 | function CommandGroup({
107 | className,
108 | ...props
109 | }: React.ComponentProps) {
110 | return (
111 |
119 | )
120 | }
121 |
122 | function CommandSeparator({
123 | className,
124 | ...props
125 | }: React.ComponentProps) {
126 | return (
127 |
132 | )
133 | }
134 |
135 | function CommandItem({
136 | className,
137 | ...props
138 | }: React.ComponentProps) {
139 | return (
140 |
148 | )
149 | }
150 |
151 | function CommandShortcut({
152 | className,
153 | ...props
154 | }: React.ComponentProps<"span">) {
155 | return (
156 |
164 | )
165 | }
166 |
167 | export {
168 | Command,
169 | CommandDialog,
170 | CommandInput,
171 | CommandList,
172 | CommandEmpty,
173 | CommandGroup,
174 | CommandItem,
175 | CommandShortcut,
176 | CommandSeparator,
177 | }
178 |
--------------------------------------------------------------------------------
/components/ui/carousel.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import useEmblaCarousel, {
5 | type UseEmblaCarouselType,
6 | } from "embla-carousel-react"
7 | import { ArrowLeft, ArrowRight } from "lucide-react"
8 |
9 | import { cn } from "@/lib/utils"
10 | import { Button } from "@/components/ui/button"
11 |
12 | type CarouselApi = UseEmblaCarouselType[1]
13 | type UseCarouselParameters = Parameters
14 | type CarouselOptions = UseCarouselParameters[0]
15 | type CarouselPlugin = UseCarouselParameters[1]
16 |
17 | type CarouselProps = {
18 | opts?: CarouselOptions
19 | plugins?: CarouselPlugin
20 | orientation?: "horizontal" | "vertical"
21 | setApi?: (api: CarouselApi) => void
22 | }
23 |
24 | type CarouselContextProps = {
25 | carouselRef: ReturnType[0]
26 | api: ReturnType[1]
27 | scrollPrev: () => void
28 | scrollNext: () => void
29 | canScrollPrev: boolean
30 | canScrollNext: boolean
31 | } & CarouselProps
32 |
33 | const CarouselContext = React.createContext(null)
34 |
35 | function useCarousel() {
36 | const context = React.useContext(CarouselContext)
37 |
38 | if (!context) {
39 | throw new Error("useCarousel must be used within a ")
40 | }
41 |
42 | return context
43 | }
44 |
45 | function Carousel({
46 | orientation = "horizontal",
47 | opts,
48 | setApi,
49 | plugins,
50 | className,
51 | children,
52 | ...props
53 | }: React.ComponentProps<"div"> & CarouselProps) {
54 | const [carouselRef, api] = useEmblaCarousel(
55 | {
56 | ...opts,
57 | axis: orientation === "horizontal" ? "x" : "y",
58 | },
59 | plugins
60 | )
61 | const [canScrollPrev, setCanScrollPrev] = React.useState(false)
62 | const [canScrollNext, setCanScrollNext] = React.useState(false)
63 |
64 | const onSelect = React.useCallback((api: CarouselApi) => {
65 | if (!api) return
66 | setCanScrollPrev(api.canScrollPrev())
67 | setCanScrollNext(api.canScrollNext())
68 | }, [])
69 |
70 | const scrollPrev = React.useCallback(() => {
71 | api?.scrollPrev()
72 | }, [api])
73 |
74 | const scrollNext = React.useCallback(() => {
75 | api?.scrollNext()
76 | }, [api])
77 |
78 | const handleKeyDown = React.useCallback(
79 | (event: React.KeyboardEvent) => {
80 | if (event.key === "ArrowLeft") {
81 | event.preventDefault()
82 | scrollPrev()
83 | } else if (event.key === "ArrowRight") {
84 | event.preventDefault()
85 | scrollNext()
86 | }
87 | },
88 | [scrollPrev, scrollNext]
89 | )
90 |
91 | React.useEffect(() => {
92 | if (!api || !setApi) return
93 | setApi(api)
94 | }, [api, setApi])
95 |
96 | React.useEffect(() => {
97 | if (!api) return
98 | onSelect(api)
99 | api.on("reInit", onSelect)
100 | api.on("select", onSelect)
101 |
102 | return () => {
103 | api?.off("select", onSelect)
104 | }
105 | }, [api, onSelect])
106 |
107 | return (
108 |
121 |
129 | {children}
130 |
131 |
132 | )
133 | }
134 |
135 | function CarouselContent({ className, ...props }: React.ComponentProps<"div">) {
136 | const { carouselRef, orientation } = useCarousel()
137 |
138 | return (
139 |
153 | )
154 | }
155 |
156 | function CarouselItem({ className, ...props }: React.ComponentProps<"div">) {
157 | const { orientation } = useCarousel()
158 |
159 | return (
160 |
171 | )
172 | }
173 |
174 | function CarouselPrevious({
175 | className,
176 | variant = "outline",
177 | size = "icon",
178 | ...props
179 | }: React.ComponentProps) {
180 | const { orientation, scrollPrev, canScrollPrev } = useCarousel()
181 |
182 | return (
183 |
201 | )
202 | }
203 |
204 | function CarouselNext({
205 | className,
206 | variant = "outline",
207 | size = "icon",
208 | ...props
209 | }: React.ComponentProps) {
210 | const { orientation, scrollNext, canScrollNext } = useCarousel()
211 |
212 | return (
213 |
231 | )
232 | }
233 |
234 | export {
235 | type CarouselApi,
236 | Carousel,
237 | CarouselContent,
238 | CarouselItem,
239 | CarouselPrevious,
240 | CarouselNext,
241 | }
242 |
--------------------------------------------------------------------------------
/components/ui/select.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as SelectPrimitive from "@radix-ui/react-select"
5 | import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | function Select({
10 | ...props
11 | }: React.ComponentProps) {
12 | return
13 | }
14 |
15 | function SelectGroup({
16 | ...props
17 | }: React.ComponentProps) {
18 | return
19 | }
20 |
21 | function SelectValue({
22 | ...props
23 | }: React.ComponentProps) {
24 | return
25 | }
26 |
27 | function SelectTrigger({
28 | className,
29 | size = "default",
30 | children,
31 | ...props
32 | }: React.ComponentProps & {
33 | size?: "sm" | "default"
34 | }) {
35 | return (
36 |
45 | {children}
46 |
47 |
48 |
49 |
50 | )
51 | }
52 |
53 | function SelectContent({
54 | className,
55 | children,
56 | position = "popper",
57 | ...props
58 | }: React.ComponentProps) {
59 | return (
60 |
61 |
72 |
73 |
80 | {children}
81 |
82 |
83 |
84 |
85 | )
86 | }
87 |
88 | function SelectLabel({
89 | className,
90 | ...props
91 | }: React.ComponentProps) {
92 | return (
93 |
98 | )
99 | }
100 |
101 | function SelectItem({
102 | className,
103 | children,
104 | ...props
105 | }: React.ComponentProps) {
106 | return (
107 |
115 |
116 |
117 |
118 |
119 |
120 | {children}
121 |
122 | )
123 | }
124 |
125 | function SelectSeparator({
126 | className,
127 | ...props
128 | }: React.ComponentProps) {
129 | return (
130 |
135 | )
136 | }
137 |
138 | function SelectScrollUpButton({
139 | className,
140 | ...props
141 | }: React.ComponentProps) {
142 | return (
143 |
151 |
152 |
153 | )
154 | }
155 |
156 | function SelectScrollDownButton({
157 | className,
158 | ...props
159 | }: React.ComponentProps) {
160 | return (
161 |
169 |
170 |
171 | )
172 | }
173 |
174 | export {
175 | Select,
176 | SelectContent,
177 | SelectGroup,
178 | SelectItem,
179 | SelectLabel,
180 | SelectScrollDownButton,
181 | SelectScrollUpButton,
182 | SelectSeparator,
183 | SelectTrigger,
184 | SelectValue,
185 | }
186 |
--------------------------------------------------------------------------------
/components/ui/navigation-menu.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"
3 | import { cva } from "class-variance-authority"
4 | import { ChevronDownIcon } from "lucide-react"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | function NavigationMenu({
9 | className,
10 | children,
11 | viewport = true,
12 | ...props
13 | }: React.ComponentProps & {
14 | viewport?: boolean
15 | }) {
16 | return (
17 |
26 | {children}
27 | {viewport && }
28 |
29 | )
30 | }
31 |
32 | function NavigationMenuList({
33 | className,
34 | ...props
35 | }: React.ComponentProps) {
36 | return (
37 |
45 | )
46 | }
47 |
48 | function NavigationMenuItem({
49 | className,
50 | ...props
51 | }: React.ComponentProps) {
52 | return (
53 |
58 | )
59 | }
60 |
61 | const navigationMenuTriggerStyle = cva(
62 | "group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=open]:hover:bg-accent data-[state=open]:text-accent-foreground data-[state=open]:focus:bg-accent data-[state=open]:bg-accent/50 ring-ring/10 dark:ring-ring/20 dark:outline-ring/40 outline-ring/50 transition-[color,box-shadow] focus-visible:ring-4 focus-visible:outline-1"
63 | )
64 |
65 | function NavigationMenuTrigger({
66 | className,
67 | children,
68 | ...props
69 | }: React.ComponentProps) {
70 | return (
71 |
76 | {children}{" "}
77 |
81 |
82 | )
83 | }
84 |
85 | function NavigationMenuContent({
86 | className,
87 | ...props
88 | }: React.ComponentProps) {
89 | return (
90 |
99 | )
100 | }
101 |
102 | function NavigationMenuViewport({
103 | className,
104 | ...props
105 | }: React.ComponentProps) {
106 | return (
107 |
112 |
120 |
121 | )
122 | }
123 |
124 | function NavigationMenuLink({
125 | className,
126 | ...props
127 | }: React.ComponentProps) {
128 | return (
129 |
137 | )
138 | }
139 |
140 | function NavigationMenuIndicator({
141 | className,
142 | ...props
143 | }: React.ComponentProps) {
144 | return (
145 |
153 |
154 |
155 | )
156 | }
157 |
158 | export {
159 | NavigationMenu,
160 | NavigationMenuList,
161 | NavigationMenuItem,
162 | NavigationMenuContent,
163 | NavigationMenuTrigger,
164 | NavigationMenuLink,
165 | NavigationMenuIndicator,
166 | NavigationMenuViewport,
167 | navigationMenuTriggerStyle,
168 | }
169 |
--------------------------------------------------------------------------------
/components/ProductGrid.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 | import { navbarData } from '@/lib/data'
3 | import { Minus, MoreVertical, Plus, ShoppingCart, X } from 'lucide-react'
4 | import Link from 'next/link'
5 | import React, { useState } from 'react'
6 | import {
7 | Sheet,
8 | SheetContent,
9 | SheetHeader,
10 | SheetTitle,
11 | SheetTrigger,
12 | } from './ui/sheet'
13 | import { useCart } from '@/hooks/use-cart'
14 | import Image from 'next/image'
15 | import Checkout from './checkout'
16 |
17 | type Props = {
18 | products: any[]
19 | }
20 |
21 | const ProductGrid = ({ products }: Props) => {
22 | const [toggle, setToggle] = useState(false)
23 |
24 | const {
25 | isOpen,
26 | setIsOpen,
27 | items: cartItems,
28 | updateQuantity,
29 | removeItem: removeFromCart,
30 | cartTotal,
31 | } = useCart()
32 |
33 | //Buy now button - Amazon!
34 | //success
35 |
36 | return (
37 |
38 |
161 |
162 |
163 |
164 | {products.map((product, index) => (
165 |
170 |
171 |
178 |
179 |
180 |
181 |
182 | {product.name}
183 |
184 |
185 |
186 | ${product.price}
187 |
188 |
189 |
190 |
191 | ))}
192 |
193 |
194 |
195 | )
196 | }
197 |
198 | export default ProductGrid
199 |
--------------------------------------------------------------------------------
/components/ui/context-menu.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as ContextMenuPrimitive from "@radix-ui/react-context-menu"
5 | import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | function ContextMenu({
10 | ...props
11 | }: React.ComponentProps) {
12 | return
13 | }
14 |
15 | function ContextMenuTrigger({
16 | ...props
17 | }: React.ComponentProps) {
18 | return (
19 |
20 | )
21 | }
22 |
23 | function ContextMenuGroup({
24 | ...props
25 | }: React.ComponentProps) {
26 | return (
27 |
28 | )
29 | }
30 |
31 | function ContextMenuPortal({
32 | ...props
33 | }: React.ComponentProps) {
34 | return (
35 |
36 | )
37 | }
38 |
39 | function ContextMenuSub({
40 | ...props
41 | }: React.ComponentProps) {
42 | return
43 | }
44 |
45 | function ContextMenuRadioGroup({
46 | ...props
47 | }: React.ComponentProps) {
48 | return (
49 |
53 | )
54 | }
55 |
56 | function ContextMenuSubTrigger({
57 | className,
58 | inset,
59 | children,
60 | ...props
61 | }: React.ComponentProps & {
62 | inset?: boolean
63 | }) {
64 | return (
65 |
74 | {children}
75 |
76 |
77 | )
78 | }
79 |
80 | function ContextMenuSubContent({
81 | className,
82 | ...props
83 | }: React.ComponentProps) {
84 | return (
85 |
93 | )
94 | }
95 |
96 | function ContextMenuContent({
97 | className,
98 | ...props
99 | }: React.ComponentProps) {
100 | return (
101 |
102 |
110 |
111 | )
112 | }
113 |
114 | function ContextMenuItem({
115 | className,
116 | inset,
117 | variant = "default",
118 | ...props
119 | }: React.ComponentProps & {
120 | inset?: boolean
121 | variant?: "default" | "destructive"
122 | }) {
123 | return (
124 |
134 | )
135 | }
136 |
137 | function ContextMenuCheckboxItem({
138 | className,
139 | children,
140 | checked,
141 | ...props
142 | }: React.ComponentProps) {
143 | return (
144 |
153 |
154 |
155 |
156 |
157 |
158 | {children}
159 |
160 | )
161 | }
162 |
163 | function ContextMenuRadioItem({
164 | className,
165 | children,
166 | ...props
167 | }: React.ComponentProps) {
168 | return (
169 |
177 |
178 |
179 |
180 |
181 |
182 | {children}
183 |
184 | )
185 | }
186 |
187 | function ContextMenuLabel({
188 | className,
189 | inset,
190 | ...props
191 | }: React.ComponentProps & {
192 | inset?: boolean
193 | }) {
194 | return (
195 |
204 | )
205 | }
206 |
207 | function ContextMenuSeparator({
208 | className,
209 | ...props
210 | }: React.ComponentProps) {
211 | return (
212 |
217 | )
218 | }
219 |
220 | function ContextMenuShortcut({
221 | className,
222 | ...props
223 | }: React.ComponentProps<"span">) {
224 | return (
225 |
233 | )
234 | }
235 |
236 | export {
237 | ContextMenu,
238 | ContextMenuTrigger,
239 | ContextMenuContent,
240 | ContextMenuItem,
241 | ContextMenuCheckboxItem,
242 | ContextMenuRadioItem,
243 | ContextMenuLabel,
244 | ContextMenuSeparator,
245 | ContextMenuShortcut,
246 | ContextMenuGroup,
247 | ContextMenuPortal,
248 | ContextMenuSub,
249 | ContextMenuSubContent,
250 | ContextMenuSubTrigger,
251 | ContextMenuRadioGroup,
252 | }
253 |
--------------------------------------------------------------------------------
/components/ui/dropdown-menu.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
5 | import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | function DropdownMenu({
10 | ...props
11 | }: React.ComponentProps) {
12 | return
13 | }
14 |
15 | function DropdownMenuPortal({
16 | ...props
17 | }: React.ComponentProps) {
18 | return (
19 |
20 | )
21 | }
22 |
23 | function DropdownMenuTrigger({
24 | ...props
25 | }: React.ComponentProps) {
26 | return (
27 |
31 | )
32 | }
33 |
34 | function DropdownMenuContent({
35 | className,
36 | sideOffset = 4,
37 | ...props
38 | }: React.ComponentProps) {
39 | return (
40 |
41 |
50 |
51 | )
52 | }
53 |
54 | function DropdownMenuGroup({
55 | ...props
56 | }: React.ComponentProps) {
57 | return (
58 |
59 | )
60 | }
61 |
62 | function DropdownMenuItem({
63 | className,
64 | inset,
65 | variant = "default",
66 | ...props
67 | }: React.ComponentProps & {
68 | inset?: boolean
69 | variant?: "default" | "destructive"
70 | }) {
71 | return (
72 |
82 | )
83 | }
84 |
85 | function DropdownMenuCheckboxItem({
86 | className,
87 | children,
88 | checked,
89 | ...props
90 | }: React.ComponentProps) {
91 | return (
92 |
101 |
102 |
103 |
104 |
105 |
106 | {children}
107 |
108 | )
109 | }
110 |
111 | function DropdownMenuRadioGroup({
112 | ...props
113 | }: React.ComponentProps) {
114 | return (
115 |
119 | )
120 | }
121 |
122 | function DropdownMenuRadioItem({
123 | className,
124 | children,
125 | ...props
126 | }: React.ComponentProps) {
127 | return (
128 |
136 |
137 |
138 |
139 |
140 |
141 | {children}
142 |
143 | )
144 | }
145 |
146 | function DropdownMenuLabel({
147 | className,
148 | inset,
149 | ...props
150 | }: React.ComponentProps & {
151 | inset?: boolean
152 | }) {
153 | return (
154 |
163 | )
164 | }
165 |
166 | function DropdownMenuSeparator({
167 | className,
168 | ...props
169 | }: React.ComponentProps) {
170 | return (
171 |
176 | )
177 | }
178 |
179 | function DropdownMenuShortcut({
180 | className,
181 | ...props
182 | }: React.ComponentProps<"span">) {
183 | return (
184 |
192 | )
193 | }
194 |
195 | function DropdownMenuSub({
196 | ...props
197 | }: React.ComponentProps) {
198 | return
199 | }
200 |
201 | function DropdownMenuSubTrigger({
202 | className,
203 | inset,
204 | children,
205 | ...props
206 | }: React.ComponentProps & {
207 | inset?: boolean
208 | }) {
209 | return (
210 |
219 | {children}
220 |
221 |
222 | )
223 | }
224 |
225 | function DropdownMenuSubContent({
226 | className,
227 | ...props
228 | }: React.ComponentProps) {
229 | return (
230 |
238 | )
239 | }
240 |
241 | export {
242 | DropdownMenu,
243 | DropdownMenuPortal,
244 | DropdownMenuTrigger,
245 | DropdownMenuContent,
246 | DropdownMenuGroup,
247 | DropdownMenuLabel,
248 | DropdownMenuItem,
249 | DropdownMenuCheckboxItem,
250 | DropdownMenuRadioGroup,
251 | DropdownMenuRadioItem,
252 | DropdownMenuSeparator,
253 | DropdownMenuShortcut,
254 | DropdownMenuSub,
255 | DropdownMenuSubTrigger,
256 | DropdownMenuSubContent,
257 | }
258 |
--------------------------------------------------------------------------------
/components/ui/menubar.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as MenubarPrimitive from "@radix-ui/react-menubar"
5 | import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | function Menubar({
10 | className,
11 | ...props
12 | }: React.ComponentProps) {
13 | return (
14 |
22 | )
23 | }
24 |
25 | function MenubarMenu({
26 | ...props
27 | }: React.ComponentProps) {
28 | return
29 | }
30 |
31 | function MenubarGroup({
32 | ...props
33 | }: React.ComponentProps) {
34 | return
35 | }
36 |
37 | function MenubarPortal({
38 | ...props
39 | }: React.ComponentProps) {
40 | return
41 | }
42 |
43 | function MenubarRadioGroup({
44 | ...props
45 | }: React.ComponentProps) {
46 | return (
47 |
48 | )
49 | }
50 |
51 | function MenubarTrigger({
52 | className,
53 | ...props
54 | }: React.ComponentProps) {
55 | return (
56 |
64 | )
65 | }
66 |
67 | function MenubarContent({
68 | className,
69 | align = "start",
70 | alignOffset = -4,
71 | sideOffset = 8,
72 | ...props
73 | }: React.ComponentProps) {
74 | return (
75 |
76 |
87 |
88 | )
89 | }
90 |
91 | function MenubarItem({
92 | className,
93 | inset,
94 | variant = "default",
95 | ...props
96 | }: React.ComponentProps & {
97 | inset?: boolean
98 | variant?: "default" | "destructive"
99 | }) {
100 | return (
101 |
111 | )
112 | }
113 |
114 | function MenubarCheckboxItem({
115 | className,
116 | children,
117 | checked,
118 | ...props
119 | }: React.ComponentProps) {
120 | return (
121 |
130 |
131 |
132 |
133 |
134 |
135 | {children}
136 |
137 | )
138 | }
139 |
140 | function MenubarRadioItem({
141 | className,
142 | children,
143 | ...props
144 | }: React.ComponentProps) {
145 | return (
146 |
154 |
155 |
156 |
157 |
158 |
159 | {children}
160 |
161 | )
162 | }
163 |
164 | function MenubarLabel({
165 | className,
166 | inset,
167 | ...props
168 | }: React.ComponentProps & {
169 | inset?: boolean
170 | }) {
171 | return (
172 |
181 | )
182 | }
183 |
184 | function MenubarSeparator({
185 | className,
186 | ...props
187 | }: React.ComponentProps) {
188 | return (
189 |
194 | )
195 | }
196 |
197 | function MenubarShortcut({
198 | className,
199 | ...props
200 | }: React.ComponentProps<"span">) {
201 | return (
202 |
210 | )
211 | }
212 |
213 | function MenubarSub({
214 | ...props
215 | }: React.ComponentProps) {
216 | return
217 | }
218 |
219 | function MenubarSubTrigger({
220 | className,
221 | inset,
222 | children,
223 | ...props
224 | }: React.ComponentProps & {
225 | inset?: boolean
226 | }) {
227 | return (
228 |
237 | {children}
238 |
239 |
240 | )
241 | }
242 |
243 | function MenubarSubContent({
244 | className,
245 | ...props
246 | }: React.ComponentProps) {
247 | return (
248 |
256 | )
257 | }
258 |
259 | export {
260 | Menubar,
261 | MenubarPortal,
262 | MenubarMenu,
263 | MenubarTrigger,
264 | MenubarContent,
265 | MenubarGroup,
266 | MenubarSeparator,
267 | MenubarLabel,
268 | MenubarItem,
269 | MenubarShortcut,
270 | MenubarCheckboxItem,
271 | MenubarRadioGroup,
272 | MenubarRadioItem,
273 | MenubarSub,
274 | MenubarSubTrigger,
275 | MenubarSubContent,
276 | }
277 |
--------------------------------------------------------------------------------
/components/ui/chart.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as RechartsPrimitive from "recharts"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | // Format: { THEME_NAME: CSS_SELECTOR }
9 | const THEMES = { light: "", dark: ".dark" } as const
10 |
11 | export type ChartConfig = {
12 | [k in string]: {
13 | label?: React.ReactNode
14 | icon?: React.ComponentType
15 | } & (
16 | | { color?: string; theme?: never }
17 | | { color?: never; theme: Record }
18 | )
19 | }
20 |
21 | type ChartContextProps = {
22 | config: ChartConfig
23 | }
24 |
25 | const ChartContext = React.createContext(null)
26 |
27 | function useChart() {
28 | const context = React.useContext(ChartContext)
29 |
30 | if (!context) {
31 | throw new Error("useChart must be used within a ")
32 | }
33 |
34 | return context
35 | }
36 |
37 | function ChartContainer({
38 | id,
39 | className,
40 | children,
41 | config,
42 | ...props
43 | }: React.ComponentProps<"div"> & {
44 | config: ChartConfig
45 | children: React.ComponentProps<
46 | typeof RechartsPrimitive.ResponsiveContainer
47 | >["children"]
48 | }) {
49 | const uniqueId = React.useId()
50 | const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`
51 |
52 | return (
53 |
54 |
63 |
64 |
65 | {children}
66 |
67 |
68 |
69 | )
70 | }
71 |
72 | const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
73 | const colorConfig = Object.entries(config).filter(
74 | ([, config]) => config.theme || config.color
75 | )
76 |
77 | if (!colorConfig.length) {
78 | return null
79 | }
80 |
81 | return (
82 | |