@brightweblabs/ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@brightweblabs/ui",
3
+ "private": false,
4
+ "version": "0.1.0",
5
+ "main": "./src/index.ts",
6
+ "types": "./src/index.ts",
7
+ "files": [
8
+ "src"
9
+ ],
10
+ "license": "MIT",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/BWLeoRibeiro/brightweb-platform.git"
14
+ },
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
18
+ "exports": {
19
+ ".": "./src/index.ts"
20
+ },
21
+ "dependencies": {
22
+ "@radix-ui/react-dialog": "^1.1.15",
23
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
24
+ "@radix-ui/react-label": "^2.1.8",
25
+ "@radix-ui/react-popover": "^1.1.15",
26
+ "@radix-ui/react-separator": "^1.1.8",
27
+ "@radix-ui/react-slot": "^1.2.4",
28
+ "class-variance-authority": "^0.7.1",
29
+ "clsx": "^2.1.1",
30
+ "date-fns": "^4.1.0",
31
+ "lucide-react": "^0.562.0",
32
+ "next": "16.1.1",
33
+ "next-themes": "^0.4.6",
34
+ "radix-ui": "^1.4.3",
35
+ "react": "19.2.3",
36
+ "react-day-picker": "^9.13.2",
37
+ "react-dom": "19.2.3",
38
+ "recharts": "^2.15.4",
39
+ "sonner": "^2.0.7",
40
+ "tailwind-merge": "^3.4.0"
41
+ }
42
+ }
@@ -0,0 +1,144 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { AlertDialog as AlertDialogPrimitive } from "radix-ui"
5
+
6
+ import { cn } from "../lib/utils"
7
+ import { buttonVariants } from "./button"
8
+
9
+ function AlertDialog({ ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {
10
+ return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />
11
+ }
12
+
13
+ function AlertDialogTrigger({
14
+ ...props
15
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {
16
+ return <AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
17
+ }
18
+
19
+ function AlertDialogPortal({
20
+ ...props
21
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {
22
+ return <AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
23
+ }
24
+
25
+ function AlertDialogOverlay({
26
+ className,
27
+ ...props
28
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {
29
+ return (
30
+ <AlertDialogPrimitive.Overlay
31
+ data-slot="alert-dialog-overlay"
32
+ className={cn(
33
+ "fixed inset-0 z-50 bg-black/55 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
34
+ className
35
+ )}
36
+ {...props}
37
+ />
38
+ )
39
+ }
40
+
41
+ function AlertDialogContent({
42
+ className,
43
+ ...props
44
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Content>) {
45
+ return (
46
+ <AlertDialogPortal>
47
+ <AlertDialogOverlay />
48
+ <AlertDialogPrimitive.Content
49
+ data-slot="alert-dialog-content"
50
+ className={cn(
51
+ "bg-background fixed top-1/2 left-1/2 z-50 grid w-full max-w-md -translate-x-1/2 -translate-y-1/2 gap-4 rounded-2xl border border-black/10 p-6 shadow-[0_24px_64px_rgba(8,24,16,0.25)] duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 dark:border-white/12",
52
+ className
53
+ )}
54
+ {...props}
55
+ />
56
+ </AlertDialogPortal>
57
+ )
58
+ }
59
+
60
+ function AlertDialogHeader({ className, ...props }: React.ComponentProps<"div">) {
61
+ return (
62
+ <div
63
+ data-slot="alert-dialog-header"
64
+ className={cn("flex flex-col gap-1.5 text-left", className)}
65
+ {...props}
66
+ />
67
+ )
68
+ }
69
+
70
+ function AlertDialogFooter({ className, ...props }: React.ComponentProps<"div">) {
71
+ return (
72
+ <div
73
+ data-slot="alert-dialog-footer"
74
+ className={cn("mt-2 flex items-center justify-end gap-2", className)}
75
+ {...props}
76
+ />
77
+ )
78
+ }
79
+
80
+ function AlertDialogTitle({
81
+ className,
82
+ ...props
83
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
84
+ return (
85
+ <AlertDialogPrimitive.Title
86
+ data-slot="alert-dialog-title"
87
+ className={cn("text-base font-semibold text-foreground", className)}
88
+ {...props}
89
+ />
90
+ )
91
+ }
92
+
93
+ function AlertDialogDescription({
94
+ className,
95
+ ...props
96
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {
97
+ return (
98
+ <AlertDialogPrimitive.Description
99
+ data-slot="alert-dialog-description"
100
+ className={cn("text-sm text-foreground/70", className)}
101
+ {...props}
102
+ />
103
+ )
104
+ }
105
+
106
+ function AlertDialogAction({
107
+ className,
108
+ ...props
109
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Action>) {
110
+ return (
111
+ <AlertDialogPrimitive.Action
112
+ data-slot="alert-dialog-action"
113
+ className={cn(buttonVariants(), className)}
114
+ {...props}
115
+ />
116
+ )
117
+ }
118
+
119
+ function AlertDialogCancel({
120
+ className,
121
+ ...props
122
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Cancel>) {
123
+ return (
124
+ <AlertDialogPrimitive.Cancel
125
+ data-slot="alert-dialog-cancel"
126
+ className={cn(buttonVariants({ variant: "outline" }), className)}
127
+ {...props}
128
+ />
129
+ )
130
+ }
131
+
132
+ export {
133
+ AlertDialog,
134
+ AlertDialogAction,
135
+ AlertDialogCancel,
136
+ AlertDialogContent,
137
+ AlertDialogDescription,
138
+ AlertDialogFooter,
139
+ AlertDialogHeader,
140
+ AlertDialogOverlay,
141
+ AlertDialogPortal,
142
+ AlertDialogTitle,
143
+ AlertDialogTrigger,
144
+ }
@@ -0,0 +1,48 @@
1
+ import * as React from "react"
2
+ import { cva, type VariantProps } from "class-variance-authority"
3
+ import { Slot } from "radix-ui"
4
+
5
+ import { cn } from "../lib/utils"
6
+
7
+ const badgeVariants = cva(
8
+ "inline-flex items-center justify-center rounded-full border border-transparent px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: "bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
13
+ secondary:
14
+ "bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
15
+ destructive:
16
+ "bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
17
+ outline:
18
+ "border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
19
+ ghost: "[a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
20
+ link: "text-primary underline-offset-4 [a&]:hover:underline",
21
+ },
22
+ },
23
+ defaultVariants: {
24
+ variant: "default",
25
+ },
26
+ }
27
+ )
28
+
29
+ function Badge({
30
+ className,
31
+ variant = "default",
32
+ asChild = false,
33
+ ...props
34
+ }: React.ComponentProps<"span"> &
35
+ VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
36
+ const Comp = asChild ? Slot.Root : "span"
37
+
38
+ return (
39
+ <Comp
40
+ data-slot="badge"
41
+ data-variant={variant}
42
+ className={cn(badgeVariants({ variant }), className)}
43
+ {...props}
44
+ />
45
+ )
46
+ }
47
+
48
+ export { Badge, badgeVariants }
@@ -0,0 +1,109 @@
1
+ import * as React from "react"
2
+ import { ChevronRight, MoreHorizontal } from "lucide-react"
3
+ import { Slot } from "radix-ui"
4
+
5
+ import { cn } from "../lib/utils"
6
+
7
+ function Breadcrumb({ ...props }: React.ComponentProps<"nav">) {
8
+ return <nav aria-label="breadcrumb" data-slot="breadcrumb" {...props} />
9
+ }
10
+
11
+ function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
12
+ return (
13
+ <ol
14
+ data-slot="breadcrumb-list"
15
+ className={cn(
16
+ "text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words sm:gap-2.5",
17
+ className
18
+ )}
19
+ {...props}
20
+ />
21
+ )
22
+ }
23
+
24
+ function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
25
+ return (
26
+ <li
27
+ data-slot="breadcrumb-item"
28
+ className={cn("inline-flex items-center gap-1.5", className)}
29
+ {...props}
30
+ />
31
+ )
32
+ }
33
+
34
+ function BreadcrumbLink({
35
+ asChild,
36
+ className,
37
+ ...props
38
+ }: React.ComponentProps<"a"> & {
39
+ asChild?: boolean
40
+ }) {
41
+ const Comp = asChild ? Slot.Root : "a"
42
+
43
+ return (
44
+ <Comp
45
+ data-slot="breadcrumb-link"
46
+ className={cn("hover:text-foreground transition-colors", className)}
47
+ {...props}
48
+ />
49
+ )
50
+ }
51
+
52
+ function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
53
+ return (
54
+ <span
55
+ data-slot="breadcrumb-page"
56
+ role="link"
57
+ aria-disabled="true"
58
+ aria-current="page"
59
+ className={cn("text-foreground font-normal", className)}
60
+ {...props}
61
+ />
62
+ )
63
+ }
64
+
65
+ function BreadcrumbSeparator({
66
+ children,
67
+ className,
68
+ ...props
69
+ }: React.ComponentProps<"li">) {
70
+ return (
71
+ <li
72
+ data-slot="breadcrumb-separator"
73
+ role="presentation"
74
+ aria-hidden="true"
75
+ className={cn("[&>svg]:size-3.5", className)}
76
+ {...props}
77
+ >
78
+ {children ?? <ChevronRight />}
79
+ </li>
80
+ )
81
+ }
82
+
83
+ function BreadcrumbEllipsis({
84
+ className,
85
+ ...props
86
+ }: React.ComponentProps<"span">) {
87
+ return (
88
+ <span
89
+ data-slot="breadcrumb-ellipsis"
90
+ role="presentation"
91
+ aria-hidden="true"
92
+ className={cn("flex size-9 items-center justify-center", className)}
93
+ {...props}
94
+ >
95
+ <MoreHorizontal className="size-4" />
96
+ <span className="sr-only">More</span>
97
+ </span>
98
+ )
99
+ }
100
+
101
+ export {
102
+ Breadcrumb,
103
+ BreadcrumbList,
104
+ BreadcrumbItem,
105
+ BreadcrumbLink,
106
+ BreadcrumbPage,
107
+ BreadcrumbSeparator,
108
+ BreadcrumbEllipsis,
109
+ }
@@ -0,0 +1,64 @@
1
+ import * as React from "react";
2
+ import { Slot } from "@radix-ui/react-slot";
3
+ import { cva, type VariantProps } from "class-variance-authority";
4
+
5
+ import { cn } from "../lib/utils";
6
+
7
+ const buttonVariants = cva(
8
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md paragraph-small font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
13
+ destructive:
14
+ "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
15
+ outline:
16
+ "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
17
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
18
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
19
+ link: "text-foreground underline-offset-4 transition-colors hover:text-primary hover:underline",
20
+
21
+ },
22
+ size: {
23
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
24
+ xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
25
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
26
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
27
+ icon: "size-9",
28
+ "icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
29
+ "icon-sm": "size-8",
30
+ "icon-lg": "size-10",
31
+ link: "h-auto min-h-0 px-0 py-0",
32
+ },
33
+ },
34
+ defaultVariants: {
35
+ variant: "default",
36
+ size: "default",
37
+ },
38
+ },
39
+ );
40
+
41
+ function Button({
42
+ className,
43
+ variant = "default",
44
+ size = "default",
45
+ asChild = false,
46
+ ...props
47
+ }: React.ComponentProps<"button"> &
48
+ VariantProps<typeof buttonVariants> & {
49
+ asChild?: boolean;
50
+ }) {
51
+ const Comp = asChild ? Slot : "button";
52
+
53
+ return (
54
+ <Comp
55
+ data-slot="button"
56
+ data-variant={variant}
57
+ data-size={size}
58
+ className={cn(buttonVariants({ variant, size, className }))}
59
+ {...props}
60
+ />
61
+ );
62
+ }
63
+
64
+ export { Button, buttonVariants };
@@ -0,0 +1,220 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import {
5
+ ChevronDownIcon,
6
+ ChevronLeftIcon,
7
+ ChevronRightIcon,
8
+ } from "lucide-react"
9
+ import {
10
+ DayPicker,
11
+ getDefaultClassNames,
12
+ type DayButton,
13
+ } from "react-day-picker"
14
+
15
+ import { cn } from "../lib/utils"
16
+ import { Button, buttonVariants } from "./button"
17
+
18
+ function Calendar({
19
+ className,
20
+ classNames,
21
+ showOutsideDays = true,
22
+ captionLayout = "label",
23
+ buttonVariant = "ghost",
24
+ formatters,
25
+ components,
26
+ ...props
27
+ }: React.ComponentProps<typeof DayPicker> & {
28
+ buttonVariant?: React.ComponentProps<typeof Button>["variant"]
29
+ }) {
30
+ const defaultClassNames = getDefaultClassNames()
31
+
32
+ return (
33
+ <DayPicker
34
+ showOutsideDays={showOutsideDays}
35
+ className={cn(
36
+ "bg-background group/calendar p-3 [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
37
+ String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
38
+ String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
39
+ className
40
+ )}
41
+ captionLayout={captionLayout}
42
+ formatters={{
43
+ formatMonthDropdown: (date) =>
44
+ date.toLocaleString("default", { month: "short" }),
45
+ ...formatters,
46
+ }}
47
+ classNames={{
48
+ root: cn("w-fit", defaultClassNames.root),
49
+ months: cn(
50
+ "flex gap-4 flex-col md:flex-row relative",
51
+ defaultClassNames.months
52
+ ),
53
+ month: cn("flex flex-col w-full gap-4", defaultClassNames.month),
54
+ nav: cn(
55
+ "flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between",
56
+ defaultClassNames.nav
57
+ ),
58
+ button_previous: cn(
59
+ buttonVariants({ variant: buttonVariant }),
60
+ "size-(--cell-size) aria-disabled:opacity-50 p-0 select-none",
61
+ defaultClassNames.button_previous
62
+ ),
63
+ button_next: cn(
64
+ buttonVariants({ variant: buttonVariant }),
65
+ "size-(--cell-size) aria-disabled:opacity-50 p-0 select-none",
66
+ defaultClassNames.button_next
67
+ ),
68
+ month_caption: cn(
69
+ "flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)",
70
+ defaultClassNames.month_caption
71
+ ),
72
+ dropdowns: cn(
73
+ "w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5",
74
+ defaultClassNames.dropdowns
75
+ ),
76
+ dropdown_root: cn(
77
+ "relative has-focus:border-ring border border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] rounded-md",
78
+ defaultClassNames.dropdown_root
79
+ ),
80
+ dropdown: cn(
81
+ "absolute bg-popover inset-0 opacity-0",
82
+ defaultClassNames.dropdown
83
+ ),
84
+ caption_label: cn(
85
+ "select-none font-medium",
86
+ captionLayout === "label"
87
+ ? "text-sm"
88
+ : "rounded-md pl-2 pr-1 flex items-center gap-1 text-sm h-8 [&>svg]:text-muted-foreground [&>svg]:size-3.5",
89
+ defaultClassNames.caption_label
90
+ ),
91
+ table: "w-full border-collapse",
92
+ weekdays: cn("flex", defaultClassNames.weekdays),
93
+ weekday: cn(
94
+ "text-muted-foreground rounded-md flex-1 font-normal text-[0.8rem] select-none",
95
+ defaultClassNames.weekday
96
+ ),
97
+ week: cn("flex w-full mt-2", defaultClassNames.week),
98
+ week_number_header: cn(
99
+ "select-none w-(--cell-size)",
100
+ defaultClassNames.week_number_header
101
+ ),
102
+ week_number: cn(
103
+ "text-[0.8rem] select-none text-muted-foreground",
104
+ defaultClassNames.week_number
105
+ ),
106
+ day: cn(
107
+ "relative w-full h-full p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none",
108
+ props.showWeekNumber
109
+ ? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-md"
110
+ : "[&:first-child[data-selected=true]_button]:rounded-l-md",
111
+ defaultClassNames.day
112
+ ),
113
+ range_start: cn(
114
+ "rounded-l-md bg-accent",
115
+ defaultClassNames.range_start
116
+ ),
117
+ range_middle: cn("rounded-none", defaultClassNames.range_middle),
118
+ range_end: cn("rounded-r-md bg-accent", defaultClassNames.range_end),
119
+ today: cn(
120
+ "bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none",
121
+ defaultClassNames.today
122
+ ),
123
+ outside: cn(
124
+ "text-muted-foreground aria-selected:text-muted-foreground",
125
+ defaultClassNames.outside
126
+ ),
127
+ disabled: cn(
128
+ "text-muted-foreground opacity-50",
129
+ defaultClassNames.disabled
130
+ ),
131
+ hidden: cn("invisible", defaultClassNames.hidden),
132
+ ...classNames,
133
+ }}
134
+ components={{
135
+ Root: ({ className, rootRef, ...props }) => {
136
+ return (
137
+ <div
138
+ data-slot="calendar"
139
+ ref={rootRef}
140
+ className={cn(className)}
141
+ {...props}
142
+ />
143
+ )
144
+ },
145
+ Chevron: ({ className, orientation, ...props }) => {
146
+ if (orientation === "left") {
147
+ return (
148
+ <ChevronLeftIcon className={cn("size-4", className)} {...props} />
149
+ )
150
+ }
151
+
152
+ if (orientation === "right") {
153
+ return (
154
+ <ChevronRightIcon
155
+ className={cn("size-4", className)}
156
+ {...props}
157
+ />
158
+ )
159
+ }
160
+
161
+ return (
162
+ <ChevronDownIcon className={cn("size-4", className)} {...props} />
163
+ )
164
+ },
165
+ DayButton: CalendarDayButton,
166
+ WeekNumber: ({ children, ...props }) => {
167
+ return (
168
+ <td {...props}>
169
+ <div className="flex size-(--cell-size) items-center justify-center text-center">
170
+ {children}
171
+ </div>
172
+ </td>
173
+ )
174
+ },
175
+ ...components,
176
+ }}
177
+ {...props}
178
+ />
179
+ )
180
+ }
181
+
182
+ function CalendarDayButton({
183
+ className,
184
+ day,
185
+ modifiers,
186
+ ...props
187
+ }: React.ComponentProps<typeof DayButton>) {
188
+ const defaultClassNames = getDefaultClassNames()
189
+
190
+ const ref = React.useRef<HTMLButtonElement>(null)
191
+ React.useEffect(() => {
192
+ if (modifiers.focused) ref.current?.focus()
193
+ }, [modifiers.focused])
194
+
195
+ return (
196
+ <Button
197
+ ref={ref}
198
+ variant="ghost"
199
+ size="icon"
200
+ data-day={day.date.toLocaleDateString()}
201
+ data-selected-single={
202
+ modifiers.selected &&
203
+ !modifiers.range_start &&
204
+ !modifiers.range_end &&
205
+ !modifiers.range_middle
206
+ }
207
+ data-range-start={modifiers.range_start}
208
+ data-range-end={modifiers.range_end}
209
+ data-range-middle={modifiers.range_middle}
210
+ className={cn(
211
+ "data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 dark:hover:text-accent-foreground flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md [&>span]:text-xs [&>span]:opacity-70",
212
+ defaultClassNames.day,
213
+ className
214
+ )}
215
+ {...props}
216
+ />
217
+ )
218
+ }
219
+
220
+ export { Calendar, CalendarDayButton }
@@ -0,0 +1,68 @@
1
+ import * as React from "react";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+
4
+ import { cn } from "../lib/utils";
5
+
6
+ const cardVariants = cva("bg-card text-card-foreground flex flex-col rounded-xl shadow-sm", {
7
+ variants: {
8
+ variant: {
9
+ default: "border border-border",
10
+ /** Insight/blog card: borderless, overflow-hidden; hover lift handled by motion on parent */
11
+ insight: "!border-0 border-transparent shadow-none overflow-hidden bg-card rounded-xl",
12
+ },
13
+ },
14
+ defaultVariants: {
15
+ variant: "default",
16
+ },
17
+ });
18
+
19
+ function Card({
20
+ className,
21
+ variant = "default",
22
+ ...props
23
+ }: React.ComponentProps<"div"> & VariantProps<typeof cardVariants>) {
24
+ return (
25
+ <div data-slot="card" data-variant={variant} className={cn(cardVariants({ variant, className }))} {...props} />
26
+ );
27
+ }
28
+
29
+ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
30
+ return (
31
+ <div
32
+ data-slot="card-header"
33
+ className={cn(
34
+ "@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
35
+ className,
36
+ )}
37
+ {...props}
38
+ />
39
+ );
40
+ }
41
+
42
+ function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
43
+ return <div data-slot="card-title" className={cn("leading-none font-semibold", className)} {...props} />;
44
+ }
45
+
46
+ function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
47
+ return <div data-slot="card-description" className={cn("text-muted-foreground text-sm", className)} {...props} />;
48
+ }
49
+
50
+ function CardAction({ className, ...props }: React.ComponentProps<"div">) {
51
+ return (
52
+ <div
53
+ data-slot="card-action"
54
+ className={cn("col-start-2 row-span-2 row-start-1 self-start justify-self-end", className)}
55
+ {...props}
56
+ />
57
+ );
58
+ }
59
+
60
+ function CardContent({ className, ...props }: React.ComponentProps<"div">) {
61
+ return <div data-slot="card-content" className={cn(className)} {...props} />;
62
+ }
63
+
64
+ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
65
+ return <div data-slot="card-footer" className={cn("flex items-center [.border-t]:pt-6", className)} {...props} />;
66
+ }
67
+
68
+ export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent };