tr]:last:border-b-0",
46 | className
47 | )}
48 | {...props}
49 | />
50 | )
51 | }
52 |
53 | function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
54 | return (
55 |
63 | )
64 | }
65 |
66 | function TableHead({ className, ...props }: React.ComponentProps<"th">) {
67 | return (
68 | [role=checkbox]]:translate-y-[2px]",
72 | className
73 | )}
74 | {...props}
75 | />
76 | )
77 | }
78 |
79 | function TableCell({ className, ...props }: React.ComponentProps<"td">) {
80 | return (
81 | | [role=checkbox]]:translate-y-[2px]",
85 | className
86 | )}
87 | {...props}
88 | />
89 | )
90 | }
91 |
92 | function TableCaption({
93 | className,
94 | ...props
95 | }: React.ComponentProps<"caption">) {
96 | return (
97 |
102 | )
103 | }
104 |
105 | export {
106 | Table,
107 | TableHeader,
108 | TableBody,
109 | TableFooter,
110 | TableHead,
111 | TableRow,
112 | TableCell,
113 | TableCaption,
114 | }
115 |
--------------------------------------------------------------------------------
/src/components/ui/calendar.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import { ChevronLeft, ChevronRight } from "lucide-react"
3 | import { DayPicker } from "react-day-picker"
4 |
5 | import { cn } from "@/lib/utils"
6 | import { buttonVariants } from "@/components/ui/button"
7 |
8 | function Calendar({
9 | className,
10 | classNames,
11 | showOutsideDays = true,
12 | ...props
13 | }: React.ComponentProps) {
14 | return (
15 | .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"
39 | : "[&:has([aria-selected])]:rounded-md"
40 | ),
41 | day: cn(
42 | buttonVariants({ variant: "ghost" }),
43 | "size-8 p-0 font-normal aria-selected:opacity-100"
44 | ),
45 | day_range_start:
46 | "day-range-start aria-selected:bg-primary aria-selected:text-primary-foreground",
47 | day_range_end:
48 | "day-range-end aria-selected:bg-primary aria-selected:text-primary-foreground",
49 | day_selected:
50 | "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
51 | day_today: "bg-accent text-accent-foreground",
52 | day_outside:
53 | "day-outside text-muted-foreground aria-selected:text-muted-foreground",
54 | day_disabled: "text-muted-foreground opacity-50",
55 | day_range_middle:
56 | "aria-selected:bg-accent aria-selected:text-accent-foreground",
57 | day_hidden: "invisible",
58 | ...classNames,
59 | }}
60 | components={{
61 | IconLeft: ({ className, ...props }) => (
62 |
63 | ),
64 | IconRight: ({ className, ...props }) => (
65 |
66 | ),
67 | }}
68 | {...props}
69 | />
70 | )
71 | }
72 |
73 | export { Calendar }
74 |
--------------------------------------------------------------------------------
/src/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 |
--------------------------------------------------------------------------------
/src/components/ui/dialog.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import * as DialogPrimitive from "@radix-ui/react-dialog"
3 | import { XIcon } from "lucide-react"
4 |
5 | import { cn } from "@/lib/utils"
6 |
7 | function Dialog({
8 | ...props
9 | }: React.ComponentProps) {
10 | return
11 | }
12 |
13 | function DialogTrigger({
14 | ...props
15 | }: React.ComponentProps) {
16 | return
17 | }
18 |
19 | function DialogPortal({
20 | ...props
21 | }: React.ComponentProps) {
22 | return
23 | }
24 |
25 | function DialogClose({
26 | ...props
27 | }: React.ComponentProps) {
28 | return
29 | }
30 |
31 | function DialogOverlay({
32 | className,
33 | ...props
34 | }: React.ComponentProps) {
35 | return (
36 |
44 | )
45 | }
46 |
47 | function DialogContent({
48 | className,
49 | children,
50 | ...props
51 | }: React.ComponentProps) {
52 | return (
53 |
54 |
55 |
63 | {children}
64 |
65 |
66 | Close
67 |
68 |
69 |
70 | )
71 | }
72 |
73 | function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
74 | return (
75 |
80 | )
81 | }
82 |
83 | function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
84 | return (
85 |
93 | )
94 | }
95 |
96 | function DialogTitle({
97 | className,
98 | ...props
99 | }: React.ComponentProps) {
100 | return (
101 |
106 | )
107 | }
108 |
109 | function DialogDescription({
110 | className,
111 | ...props
112 | }: React.ComponentProps) {
113 | return (
114 |
119 | )
120 | }
121 |
122 | export {
123 | Dialog,
124 | DialogClose,
125 | DialogContent,
126 | DialogDescription,
127 | DialogFooter,
128 | DialogHeader,
129 | DialogOverlay,
130 | DialogPortal,
131 | DialogTitle,
132 | DialogTrigger,
133 | }
134 |
--------------------------------------------------------------------------------
/src/components/ui/form.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import * as LabelPrimitive from "@radix-ui/react-label"
3 | import { Slot } from "@radix-ui/react-slot"
4 | import {
5 | Controller,
6 | FormProvider,
7 | useFormContext,
8 | useFormState,
9 | type ControllerProps,
10 | type FieldPath,
11 | type FieldValues,
12 | } from "react-hook-form"
13 |
14 | import { cn } from "@/lib/utils"
15 | import { Label } from "@/components/ui/label"
16 |
17 | const Form = FormProvider
18 |
19 | type FormFieldContextValue<
20 | TFieldValues extends FieldValues = FieldValues,
21 | TName extends FieldPath = FieldPath,
22 | > = {
23 | name: TName
24 | }
25 |
26 | const FormFieldContext = React.createContext(
27 | {} as FormFieldContextValue
28 | )
29 |
30 | const FormField = <
31 | TFieldValues extends FieldValues = FieldValues,
32 | TName extends FieldPath = FieldPath,
33 | >({
34 | ...props
35 | }: ControllerProps) => {
36 | return (
37 |
38 |
39 |
40 | )
41 | }
42 |
43 | const useFormField = () => {
44 | const fieldContext = React.useContext(FormFieldContext)
45 | const itemContext = React.useContext(FormItemContext)
46 | const { getFieldState } = useFormContext()
47 | const formState = useFormState({ name: fieldContext.name })
48 | const fieldState = getFieldState(fieldContext.name, formState)
49 |
50 | if (!fieldContext) {
51 | throw new Error("useFormField should be used within ")
52 | }
53 |
54 | const { id } = itemContext
55 |
56 | return {
57 | id,
58 | name: fieldContext.name,
59 | formItemId: `${id}-form-item`,
60 | formDescriptionId: `${id}-form-item-description`,
61 | formMessageId: `${id}-form-item-message`,
62 | ...fieldState,
63 | }
64 | }
65 |
66 | type FormItemContextValue = {
67 | id: string
68 | }
69 |
70 | const FormItemContext = React.createContext(
71 | {} as FormItemContextValue
72 | )
73 |
74 | function FormItem({ className, ...props }: React.ComponentProps<"div">) {
75 | const id = React.useId()
76 |
77 | return (
78 |
79 |
84 |
85 | )
86 | }
87 |
88 | function FormLabel({
89 | className,
90 | ...props
91 | }: React.ComponentProps) {
92 | const { error, formItemId } = useFormField()
93 |
94 | return (
95 |
102 | )
103 | }
104 |
105 | function FormControl({ ...props }: React.ComponentProps) {
106 | const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
107 |
108 | return (
109 |
120 | )
121 | }
122 |
123 | function FormDescription({ className, ...props }: React.ComponentProps<"p">) {
124 | const { formDescriptionId } = useFormField()
125 |
126 | return (
127 |
133 | )
134 | }
135 |
136 | function FormMessage({ className, ...props }: React.ComponentProps<"p">) {
137 | const { error, formMessageId } = useFormField()
138 | const body = error ? String(error?.message ?? "") : props.children
139 |
140 | if (!body) {
141 | return null
142 | }
143 |
144 | return (
145 |
151 | {body}
152 |
153 | )
154 | }
155 |
156 | export {
157 | useFormField,
158 | Form,
159 | FormItem,
160 | FormLabel,
161 | FormControl,
162 | FormDescription,
163 | FormMessage,
164 | FormField,
165 | }
166 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | @import "tailwindcss";
2 | @import "tw-animate-css";
3 |
4 | @custom-variant dark (&:is(.dark *));
5 |
6 | @theme inline {
7 | --radius-sm: calc(var(--radius) - 4px);
8 | --radius-md: calc(var(--radius) - 2px);
9 | --radius-lg: var(--radius);
10 | --radius-xl: calc(var(--radius) + 4px);
11 | --color-background: var(--background);
12 | --color-foreground: var(--foreground);
13 | --color-card: var(--card);
14 | --color-card-foreground: var(--card-foreground);
15 | --color-popover: var(--popover);
16 | --color-popover-foreground: var(--popover-foreground);
17 | --color-primary: var(--primary);
18 | --color-primary-foreground: var(--primary-foreground);
19 | --color-secondary: var(--secondary);
20 | --color-secondary-foreground: var(--secondary-foreground);
21 | --color-muted: var(--muted);
22 | --color-muted-foreground: var(--muted-foreground);
23 | --color-accent: var(--accent);
24 | --color-accent-foreground: var(--accent-foreground);
25 | --color-destructive: var(--destructive);
26 | --color-border: var(--border);
27 | --color-input: var(--input);
28 | --color-ring: var(--ring);
29 | --color-chart-1: var(--chart-1);
30 | --color-chart-2: var(--chart-2);
31 | --color-chart-3: var(--chart-3);
32 | --color-chart-4: var(--chart-4);
33 | --color-chart-5: var(--chart-5);
34 | --color-sidebar: var(--sidebar);
35 | --color-sidebar-foreground: var(--sidebar-foreground);
36 | --color-sidebar-primary: var(--sidebar-primary);
37 | --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
38 | --color-sidebar-accent: var(--sidebar-accent);
39 | --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
40 | --color-sidebar-border: var(--sidebar-border);
41 | --color-sidebar-ring: var(--sidebar-ring);
42 | }
43 |
44 | :root {
45 | --radius: 0.625rem;
46 | --background: oklch(1 0 0);
47 | --foreground: oklch(0.145 0 0);
48 | --card: oklch(1 0 0);
49 | --card-foreground: oklch(0.145 0 0);
50 | --popover: oklch(1 0 0);
51 | --popover-foreground: oklch(0.145 0 0);
52 | --primary: oklch(0.205 0 0);
53 | --primary-foreground: oklch(0.985 0 0);
54 | --secondary: oklch(0.97 0 0);
55 | --secondary-foreground: oklch(0.205 0 0);
56 | --muted: oklch(0.97 0 0);
57 | --muted-foreground: oklch(0.556 0 0);
58 | --accent: oklch(0.97 0 0);
59 | --accent-foreground: oklch(0.205 0 0);
60 | --destructive: oklch(0.577 0.245 27.325);
61 | --border: oklch(0.922 0 0);
62 | --input: oklch(0.922 0 0);
63 | --ring: oklch(0.708 0 0);
64 | --chart-1: oklch(0.646 0.222 41.116);
65 | --chart-2: oklch(0.6 0.118 184.704);
66 | --chart-3: oklch(0.398 0.07 227.392);
67 | --chart-4: oklch(0.828 0.189 84.429);
68 | --chart-5: oklch(0.769 0.188 70.08);
69 | --sidebar: oklch(0.985 0 0);
70 | --sidebar-foreground: oklch(0.145 0 0);
71 | --sidebar-primary: oklch(0.205 0 0);
72 | --sidebar-primary-foreground: oklch(0.985 0 0);
73 | --sidebar-accent: oklch(0.97 0 0);
74 | --sidebar-accent-foreground: oklch(0.205 0 0);
75 | --sidebar-border: oklch(0.922 0 0);
76 | --sidebar-ring: oklch(0.708 0 0);
77 | }
78 |
79 | .dark {
80 | --background: oklch(0.145 0 0);
81 | --foreground: oklch(0.985 0 0);
82 | --card: oklch(0.205 0 0);
83 | --card-foreground: oklch(0.985 0 0);
84 | --popover: oklch(0.205 0 0);
85 | --popover-foreground: oklch(0.985 0 0);
86 | --primary: oklch(0.922 0 0);
87 | --primary-foreground: oklch(0.205 0 0);
88 | --secondary: oklch(0.269 0 0);
89 | --secondary-foreground: oklch(0.985 0 0);
90 | --muted: oklch(0.269 0 0);
91 | --muted-foreground: oklch(0.708 0 0);
92 | --accent: oklch(0.269 0 0);
93 | --accent-foreground: oklch(0.985 0 0);
94 | --destructive: oklch(0.704 0.191 22.216);
95 | --border: oklch(1 0 0 / 10%);
96 | --input: oklch(1 0 0 / 15%);
97 | --ring: oklch(0.556 0 0);
98 | --chart-1: oklch(0.488 0.243 264.376);
99 | --chart-2: oklch(0.696 0.17 162.48);
100 | --chart-3: oklch(0.769 0.188 70.08);
101 | --chart-4: oklch(0.627 0.265 303.9);
102 | --chart-5: oklch(0.645 0.246 16.439);
103 | --sidebar: oklch(0.205 0 0);
104 | --sidebar-foreground: oklch(0.985 0 0);
105 | --sidebar-primary: oklch(0.488 0.243 264.376);
106 | --sidebar-primary-foreground: oklch(0.985 0 0);
107 | --sidebar-accent: oklch(0.269 0 0);
108 | --sidebar-accent-foreground: oklch(0.985 0 0);
109 | --sidebar-border: oklch(1 0 0 / 10%);
110 | --sidebar-ring: oklch(0.556 0 0);
111 | }
112 |
113 | @layer base {
114 | * {
115 | @apply border-border outline-ring/50;
116 | }
117 | body {
118 | @apply bg-background text-foreground;
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/src/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 |
--------------------------------------------------------------------------------
/src/components/ui/drawer.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import { Drawer as DrawerPrimitive } from "vaul"
3 |
4 | import { cn } from "@/lib/utils"
5 |
6 | function Drawer({
7 | ...props
8 | }: React.ComponentProps) {
9 | return
10 | }
11 |
12 | function DrawerTrigger({
13 | ...props
14 | }: React.ComponentProps) {
15 | return
16 | }
17 |
18 | function DrawerPortal({
19 | ...props
20 | }: React.ComponentProps) {
21 | return
22 | }
23 |
24 | function DrawerClose({
25 | ...props
26 | }: React.ComponentProps) {
27 | return
28 | }
29 |
30 | function DrawerOverlay({
31 | className,
32 | ...props
33 | }: React.ComponentProps) {
34 | return (
35 |
43 | )
44 | }
45 |
46 | function DrawerContent({
47 | className,
48 | children,
49 | ...props
50 | }: React.ComponentProps) {
51 | return (
52 |
53 |
54 |
66 |
67 | {children}
68 |
69 |
70 | )
71 | }
72 |
73 | function DrawerHeader({ className, ...props }: React.ComponentProps<"div">) {
74 | return (
75 |
80 | )
81 | }
82 |
83 | function DrawerFooter({ className, ...props }: React.ComponentProps<"div">) {
84 | return (
85 |
90 | )
91 | }
92 |
93 | function DrawerTitle({
94 | className,
95 | ...props
96 | }: React.ComponentProps) {
97 | return (
98 |
103 | )
104 | }
105 |
106 | function DrawerDescription({
107 | className,
108 | ...props
109 | }: React.ComponentProps) {
110 | return (
111 |
116 | )
117 | }
118 |
119 | export {
120 | Drawer,
121 | DrawerPortal,
122 | DrawerOverlay,
123 | DrawerTrigger,
124 | DrawerClose,
125 | DrawerContent,
126 | DrawerHeader,
127 | DrawerFooter,
128 | DrawerTitle,
129 | DrawerDescription,
130 | }
131 |
--------------------------------------------------------------------------------
/src/components/ui/sheet.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import * as SheetPrimitive from "@radix-ui/react-dialog"
3 | import { XIcon } from "lucide-react"
4 |
5 | import { cn } from "@/lib/utils"
6 |
7 | function Sheet({ ...props }: React.ComponentProps) {
8 | return
9 | }
10 |
11 | function SheetTrigger({
12 | ...props
13 | }: React.ComponentProps) {
14 | return
15 | }
16 |
17 | function SheetClose({
18 | ...props
19 | }: React.ComponentProps) {
20 | return
21 | }
22 |
23 | function SheetPortal({
24 | ...props
25 | }: React.ComponentProps) {
26 | return
27 | }
28 |
29 | function SheetOverlay({
30 | className,
31 | ...props
32 | }: React.ComponentProps) {
33 | return (
34 |
42 | )
43 | }
44 |
45 | function SheetContent({
46 | className,
47 | children,
48 | side = "right",
49 | ...props
50 | }: React.ComponentProps & {
51 | side?: "top" | "right" | "bottom" | "left"
52 | }) {
53 | return (
54 |
55 |
56 |
72 | {children}
73 |
74 |
75 | Close
76 |
77 |
78 |
79 | )
80 | }
81 |
82 | function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
83 | return (
84 |
89 | )
90 | }
91 |
92 | function SheetFooter({ className, ...props }: React.ComponentProps<"div">) {
93 | return (
94 |
99 | )
100 | }
101 |
102 | function SheetTitle({
103 | className,
104 | ...props
105 | }: React.ComponentProps) {
106 | return (
107 |
112 | )
113 | }
114 |
115 | function SheetDescription({
116 | className,
117 | ...props
118 | }: React.ComponentProps) {
119 | return (
120 |
125 | )
126 | }
127 |
128 | export {
129 | Sheet,
130 | SheetTrigger,
131 | SheetClose,
132 | SheetContent,
133 | SheetHeader,
134 | SheetFooter,
135 | SheetTitle,
136 | SheetDescription,
137 | }
138 |
--------------------------------------------------------------------------------
/src/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 |
--------------------------------------------------------------------------------
/src/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 |
--------------------------------------------------------------------------------
/src/components/ui/select.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import * as SelectPrimitive from "@radix-ui/react-select"
3 | import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react"
4 |
5 | import { cn } from "@/lib/utils"
6 |
7 | function Select({
8 | ...props
9 | }: React.ComponentProps) {
10 | return
11 | }
12 |
13 | function SelectGroup({
14 | ...props
15 | }: React.ComponentProps) {
16 | return
17 | }
18 |
19 | function SelectValue({
20 | ...props
21 | }: React.ComponentProps) {
22 | return
23 | }
24 |
25 | function SelectTrigger({
26 | className,
27 | size = "default",
28 | children,
29 | ...props
30 | }: React.ComponentProps & {
31 | size?: "sm" | "default"
32 | }) {
33 | return (
34 |
43 | {children}
44 |
45 |
46 |
47 |
48 | )
49 | }
50 |
51 | function SelectContent({
52 | className,
53 | children,
54 | position = "popper",
55 | ...props
56 | }: React.ComponentProps) {
57 | return (
58 |
59 |
70 |
71 |
78 | {children}
79 |
80 |
81 |
82 |
83 | )
84 | }
85 |
86 | function SelectLabel({
87 | className,
88 | ...props
89 | }: React.ComponentProps) {
90 | return (
91 |
96 | )
97 | }
98 |
99 | function SelectItem({
100 | className,
101 | children,
102 | ...props
103 | }: React.ComponentProps) {
104 | return (
105 |
113 |
114 |
115 |
116 |
117 |
118 | {children}
119 |
120 | )
121 | }
122 |
123 | function SelectSeparator({
124 | className,
125 | ...props
126 | }: React.ComponentProps) {
127 | return (
128 |
133 | )
134 | }
135 |
136 | function SelectScrollUpButton({
137 | className,
138 | ...props
139 | }: React.ComponentProps) {
140 | return (
141 |
149 |
150 |
151 | )
152 | }
153 |
154 | function SelectScrollDownButton({
155 | className,
156 | ...props
157 | }: React.ComponentProps) {
158 | return (
159 |
167 |
168 |
169 | )
170 | }
171 |
172 | export {
173 | Select,
174 | SelectContent,
175 | SelectGroup,
176 | SelectItem,
177 | SelectLabel,
178 | SelectScrollDownButton,
179 | SelectScrollUpButton,
180 | SelectSeparator,
181 | SelectTrigger,
182 | SelectValue,
183 | }
184 |
--------------------------------------------------------------------------------
/src/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 focus-visible:ring-ring/50 outline-none transition-[color,box-shadow] focus-visible:ring-[3px] 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 |
--------------------------------------------------------------------------------
/src/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 |
--------------------------------------------------------------------------------
/src/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 |
--------------------------------------------------------------------------------
/src/components/ui/menubar.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import * as MenubarPrimitive from "@radix-ui/react-menubar"
3 | import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
4 |
5 | import { cn } from "@/lib/utils"
6 |
7 | function Menubar({
8 | className,
9 | ...props
10 | }: React.ComponentProps) {
11 | return (
12 |
20 | )
21 | }
22 |
23 | function MenubarMenu({
24 | ...props
25 | }: React.ComponentProps) {
26 | return
27 | }
28 |
29 | function MenubarGroup({
30 | ...props
31 | }: React.ComponentProps) {
32 | return
33 | }
34 |
35 | function MenubarPortal({
36 | ...props
37 | }: React.ComponentProps) {
38 | return
39 | }
40 |
41 | function MenubarRadioGroup({
42 | ...props
43 | }: React.ComponentProps) {
44 | return (
45 |
46 | )
47 | }
48 |
49 | function MenubarTrigger({
50 | className,
51 | ...props
52 | }: React.ComponentProps) {
53 | return (
54 |
62 | )
63 | }
64 |
65 | function MenubarContent({
66 | className,
67 | align = "start",
68 | alignOffset = -4,
69 | sideOffset = 8,
70 | ...props
71 | }: React.ComponentProps) {
72 | return (
73 |
74 |
85 |
86 | )
87 | }
88 |
89 | function MenubarItem({
90 | className,
91 | inset,
92 | variant = "default",
93 | ...props
94 | }: React.ComponentProps & {
95 | inset?: boolean
96 | variant?: "default" | "destructive"
97 | }) {
98 | return (
99 |
109 | )
110 | }
111 |
112 | function MenubarCheckboxItem({
113 | className,
114 | children,
115 | checked,
116 | ...props
117 | }: React.ComponentProps) {
118 | return (
119 |
128 |
129 |
130 |
131 |
132 |
133 | {children}
134 |
135 | )
136 | }
137 |
138 | function MenubarRadioItem({
139 | className,
140 | children,
141 | ...props
142 | }: React.ComponentProps) {
143 | return (
144 |
152 |
153 |
154 |
155 |
156 |
157 | {children}
158 |
159 | )
160 | }
161 |
162 | function MenubarLabel({
163 | className,
164 | inset,
165 | ...props
166 | }: React.ComponentProps & {
167 | inset?: boolean
168 | }) {
169 | return (
170 |
179 | )
180 | }
181 |
182 | function MenubarSeparator({
183 | className,
184 | ...props
185 | }: React.ComponentProps) {
186 | return (
187 |
192 | )
193 | }
194 |
195 | function MenubarShortcut({
196 | className,
197 | ...props
198 | }: React.ComponentProps<"span">) {
199 | return (
200 |
208 | )
209 | }
210 |
211 | function MenubarSub({
212 | ...props
213 | }: React.ComponentProps) {
214 | return
215 | }
216 |
217 | function MenubarSubTrigger({
218 | className,
219 | inset,
220 | children,
221 | ...props
222 | }: React.ComponentProps & {
223 | inset?: boolean
224 | }) {
225 | return (
226 |
235 | {children}
236 |
237 |
238 | )
239 | }
240 |
241 | function MenubarSubContent({
242 | className,
243 | ...props
244 | }: React.ComponentProps) {
245 | return (
246 |
254 | )
255 | }
256 |
257 | export {
258 | Menubar,
259 | MenubarPortal,
260 | MenubarMenu,
261 | MenubarTrigger,
262 | MenubarContent,
263 | MenubarGroup,
264 | MenubarSeparator,
265 | MenubarLabel,
266 | MenubarItem,
267 | MenubarShortcut,
268 | MenubarCheckboxItem,
269 | MenubarRadioGroup,
270 | MenubarRadioItem,
271 | MenubarSub,
272 | MenubarSubTrigger,
273 | MenubarSubContent,
274 | }
275 |
--------------------------------------------------------------------------------
/src/components/ui/chart.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import * as RechartsPrimitive from "recharts"
3 |
4 | import { cn } from "@/lib/utils"
5 |
6 | // Format: { THEME_NAME: CSS_SELECTOR }
7 | const THEMES = { light: "", dark: ".dark" } as const
8 |
9 | export type ChartConfig = {
10 | [k in string]: {
11 | label?: React.ReactNode
12 | icon?: React.ComponentType
13 | } & (
14 | | { color?: string; theme?: never }
15 | | { color?: never; theme: Record }
16 | )
17 | }
18 |
19 | type ChartContextProps = {
20 | config: ChartConfig
21 | }
22 |
23 | const ChartContext = React.createContext(null)
24 |
25 | function useChart() {
26 | const context = React.useContext(ChartContext)
27 |
28 | if (!context) {
29 | throw new Error("useChart must be used within a ")
30 | }
31 |
32 | return context
33 | }
34 |
35 | function ChartContainer({
36 | id,
37 | className,
38 | children,
39 | config,
40 | ...props
41 | }: React.ComponentProps<"div"> & {
42 | config: ChartConfig
43 | children: React.ComponentProps<
44 | typeof RechartsPrimitive.ResponsiveContainer
45 | >["children"]
46 | }) {
47 | const uniqueId = React.useId()
48 | const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`
49 |
50 | return (
51 |
52 |
61 |
62 |
63 | {children}
64 |
65 |
66 |
67 | )
68 | }
69 |
70 | const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
71 | const colorConfig = Object.entries(config).filter(
72 | ([, config]) => config.theme || config.color
73 | )
74 |
75 | if (!colorConfig.length) {
76 | return null
77 | }
78 |
79 | return (
80 | |