xertica-ui 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/App.tsx +182 -0
  2. package/README.md +330 -0
  3. package/assets/xertica-logo.svg +38 -0
  4. package/assets/xertica-x-logo.svg +21 -0
  5. package/bin/cli.ts +193 -0
  6. package/components/AssistenteXertica.tsx +2003 -0
  7. package/components/AudioPlayer.tsx +203 -0
  8. package/components/CodeBlock.tsx +242 -0
  9. package/components/DocumentEditor.tsx +504 -0
  10. package/components/ForgotPasswordPage.tsx +170 -0
  11. package/components/FormattedDocument.tsx +87 -0
  12. package/components/HomeContent.tsx +123 -0
  13. package/components/HomePage.tsx +70 -0
  14. package/components/LanguageSelector.tsx +54 -0
  15. package/components/LoginPage.tsx +199 -0
  16. package/components/MarkdownMessage.tsx +62 -0
  17. package/components/ModernChatInput.tsx +502 -0
  18. package/components/PodcastPlayer.tsx +409 -0
  19. package/components/ResetPasswordPage.tsx +234 -0
  20. package/components/Sidebar.tsx +489 -0
  21. package/components/TemplateContent.tsx +629 -0
  22. package/components/TemplatePage.tsx +70 -0
  23. package/components/ThemeToggle.tsx +65 -0
  24. package/components/VerifyEmailPage.tsx +187 -0
  25. package/components/XerticaLogo.tsx +69 -0
  26. package/components/XerticaOrbe.tsx +1339 -0
  27. package/components/XerticaXLogo.tsx +53 -0
  28. package/components/examples/DrawingMapExample.tsx +530 -0
  29. package/components/examples/FilterableMapExample.tsx +380 -0
  30. package/components/examples/LocationPickerExample.tsx +330 -0
  31. package/components/examples/MapExamples.tsx +280 -0
  32. package/components/examples/MapShowcase.tsx +446 -0
  33. package/components/examples/RouteMapExamples.tsx +329 -0
  34. package/components/examples/SimpleFilterableMap.tsx +192 -0
  35. package/components/examples/index.ts +52 -0
  36. package/components/figma/ImageWithFallback.tsx +27 -0
  37. package/components/index.ts +44 -0
  38. package/components/media/AudioPlayer.tsx +278 -0
  39. package/components/media/FloatingMediaWrapper.tsx +166 -0
  40. package/components/media/VideoPlayer.tsx +285 -0
  41. package/components/ui/accordion.tsx +66 -0
  42. package/components/ui/alert-dialog.tsx +159 -0
  43. package/components/ui/alert.tsx +91 -0
  44. package/components/ui/aspect-ratio.tsx +11 -0
  45. package/components/ui/avatar.tsx +65 -0
  46. package/components/ui/badge.tsx +55 -0
  47. package/components/ui/breadcrumb.tsx +109 -0
  48. package/components/ui/button.tsx +78 -0
  49. package/components/ui/calendar.tsx +235 -0
  50. package/components/ui/card.tsx +92 -0
  51. package/components/ui/carousel.tsx +241 -0
  52. package/components/ui/chart.tsx +353 -0
  53. package/components/ui/checkbox.tsx +32 -0
  54. package/components/ui/collapsible.tsx +33 -0
  55. package/components/ui/command.tsx +177 -0
  56. package/components/ui/context-menu.tsx +252 -0
  57. package/components/ui/dialog.tsx +138 -0
  58. package/components/ui/drawer.tsx +134 -0
  59. package/components/ui/dropdown-menu.tsx +257 -0
  60. package/components/ui/empty.tsx +90 -0
  61. package/components/ui/file-upload.tsx +152 -0
  62. package/components/ui/form.tsx +195 -0
  63. package/components/ui/google-maps-loader.tsx +379 -0
  64. package/components/ui/hover-card.tsx +44 -0
  65. package/components/ui/index.ts +242 -0
  66. package/components/ui/input-otp.tsx +77 -0
  67. package/components/ui/input.tsx +38 -0
  68. package/components/ui/label.tsx +24 -0
  69. package/components/ui/map-config.ts +12 -0
  70. package/components/ui/map-layers.tsx +129 -0
  71. package/components/ui/map.exports.ts +31 -0
  72. package/components/ui/map.tsx +412 -0
  73. package/components/ui/menubar.tsx +276 -0
  74. package/components/ui/navigation-menu.tsx +162 -0
  75. package/components/ui/notification-badge.tsx +61 -0
  76. package/components/ui/page-header.tsx +229 -0
  77. package/components/ui/pagination.tsx +127 -0
  78. package/components/ui/popover.tsx +48 -0
  79. package/components/ui/progress.tsx +31 -0
  80. package/components/ui/radio-group.tsx +56 -0
  81. package/components/ui/rating.tsx +102 -0
  82. package/components/ui/resizable.tsx +405 -0
  83. package/components/ui/route-map.tsx +246 -0
  84. package/components/ui/scroll-area.tsx +58 -0
  85. package/components/ui/search.tsx +70 -0
  86. package/components/ui/select.tsx +176 -0
  87. package/components/ui/separator.tsx +28 -0
  88. package/components/ui/sheet.tsx +138 -0
  89. package/components/ui/sidebar.tsx +726 -0
  90. package/components/ui/simple-map.tsx +92 -0
  91. package/components/ui/skeleton.tsx +13 -0
  92. package/components/ui/slider.tsx +58 -0
  93. package/components/ui/sonner.tsx +77 -0
  94. package/components/ui/stats-card.tsx +84 -0
  95. package/components/ui/stepper.tsx +126 -0
  96. package/components/ui/switch.tsx +34 -0
  97. package/components/ui/table.tsx +116 -0
  98. package/components/ui/tabs.tsx +66 -0
  99. package/components/ui/textarea.tsx +26 -0
  100. package/components/ui/timeline.tsx +140 -0
  101. package/components/ui/toggle-group.tsx +71 -0
  102. package/components/ui/toggle.tsx +46 -0
  103. package/components/ui/tooltip.tsx +61 -0
  104. package/components/ui/tree-view.tsx +123 -0
  105. package/components/ui/use-mobile.ts +24 -0
  106. package/components/ui/utils.ts +6 -0
  107. package/components/ui/xertica-assistant.tsx +1420 -0
  108. package/contexts/ApiKeyContext.tsx +123 -0
  109. package/contexts/AssistenteContext.tsx +118 -0
  110. package/contexts/BrandColorsContext.tsx +551 -0
  111. package/contexts/LanguageContext.tsx +36 -0
  112. package/contexts/ThemeContext.tsx +85 -0
  113. package/dist/cli.js +20922 -0
  114. package/eslint.config.js +41 -0
  115. package/guidelines/Guidelines.md +61 -0
  116. package/hooks/useTheme.ts +4 -0
  117. package/imports/Podcast.tsx +389 -0
  118. package/imports/XerticaAi.tsx +46 -0
  119. package/imports/XerticaX.tsx +20 -0
  120. package/imports/svg-aueiaqngck.ts +11 -0
  121. package/imports/svg-v9krss1ozd.ts +16 -0
  122. package/imports/svg-vhrdofe3qe.ts +5 -0
  123. package/index.css +4448 -0
  124. package/index.html +14 -0
  125. package/main.tsx +10 -0
  126. package/package.json +119 -0
  127. package/postcss.config.js +6 -0
  128. package/routes.tsx +33 -0
  129. package/styles/globals.css +15 -0
  130. package/styles/xertica/app-overrides/chat.css +61 -0
  131. package/styles/xertica/app-overrides/scrollbar.css +33 -0
  132. package/styles/xertica/base.css +70 -0
  133. package/styles/xertica/integrations/google-maps.css +76 -0
  134. package/styles/xertica/integrations/sonner.css +73 -0
  135. package/styles/xertica/theme-map.css +88 -0
  136. package/styles/xertica/tokens.css +190 -0
  137. package/tsconfig.json +31 -0
  138. package/tsconfig.node.json +10 -0
  139. package/utils/gemini.ts +140 -0
  140. package/vite-env.d.ts +12 -0
  141. package/vite.config.ts +36 -0
@@ -0,0 +1,55 @@
1
+ import * as React from "react";
2
+ import { Slot, Slottable } from "@radix-ui/react-slot";
3
+ import { cva, type VariantProps } from "class-variance-authority";
4
+
5
+ import { cn } from "./utils";
6
+
7
+ const badgeVariants = cva(
8
+ "inline-flex items-center justify-center rounded-md border 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:
13
+ "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
14
+ secondary:
15
+ "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
16
+ destructive:
17
+ "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
18
+ outline:
19
+ "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
20
+ success:
21
+ "border-transparent bg-[var(--toast-success-bg)] text-[var(--toast-success-icon)]",
22
+ warning:
23
+ "border-transparent bg-[var(--toast-warning-bg)] text-[var(--toast-warning-icon)]",
24
+ info:
25
+ "border-transparent bg-[var(--toast-info-bg)] text-[var(--toast-info-icon)]",
26
+ },
27
+ },
28
+ defaultVariants: {
29
+ variant: "default",
30
+ },
31
+ },
32
+ );
33
+
34
+ export function Badge({
35
+ className,
36
+ variant,
37
+ asChild = false,
38
+ children,
39
+ ...props
40
+ }: React.ComponentProps<"span"> &
41
+ VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
42
+ const Comp = asChild ? Slot : "span";
43
+
44
+ return (
45
+ <Comp
46
+ data-slot="badge"
47
+ className={cn(badgeVariants({ variant }), className)}
48
+ {...props}
49
+ >
50
+ <Slottable>{children}</Slottable>
51
+ </Comp>
52
+ );
53
+ }
54
+
55
+ export { badgeVariants };
@@ -0,0 +1,109 @@
1
+ import * as React from "react";
2
+ import { Slot } from "@radix-ui/react-slot";
3
+ import { ChevronRight, MoreHorizontal } from "lucide-react";
4
+
5
+ import { cn } from "./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 : "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,78 @@
1
+ import * as React from "react";
2
+ import { Slot, Slottable } from "@radix-ui/react-slot";
3
+ import { cva, type VariantProps } from "class-variance-authority";
4
+ import { Loader2 } from "lucide-react";
5
+
6
+ import { cn } from "./utils";
7
+
8
+ const buttonVariants = cva(
9
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-[var(--radius)] text-sm font-medium transition-colors 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",
10
+ {
11
+ variants: {
12
+ variant: {
13
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
14
+ destructive:
15
+ "bg-destructive text-destructive-foreground hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
16
+ outline:
17
+ "border border-border bg-background hover:bg-accent hover:text-accent-foreground",
18
+ secondary:
19
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80",
20
+ ghost:
21
+ "hover:bg-accent hover:text-accent-foreground",
22
+ link: "text-primary underline-offset-4 hover:underline",
23
+ },
24
+ size: {
25
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
26
+ sm: "h-8 rounded-[var(--radius)] gap-1.5 px-3 has-[>svg]:px-2.5",
27
+ lg: "h-10 rounded-[var(--radius)] px-6 has-[>svg]:px-4",
28
+ icon: "size-9 rounded-[var(--radius)]",
29
+ },
30
+ },
31
+ defaultVariants: {
32
+ variant: "default",
33
+ size: "default",
34
+ },
35
+ },
36
+ );
37
+
38
+ const Button = React.forwardRef<
39
+ HTMLButtonElement,
40
+ React.ComponentProps<"button"> &
41
+ VariantProps<typeof buttonVariants> & {
42
+ asChild?: boolean;
43
+ loading?: boolean;
44
+ }
45
+ >(({
46
+ className,
47
+ variant,
48
+ size,
49
+ asChild = false,
50
+ loading = false,
51
+ children,
52
+ ...props
53
+ }, ref) => {
54
+ const Comp = asChild ? Slot : "button";
55
+
56
+ return (
57
+ <Comp
58
+ data-slot="button"
59
+ className={cn(buttonVariants({ variant, size, className }))}
60
+ disabled={loading || props.disabled}
61
+ ref={ref}
62
+ {...props}
63
+ >
64
+ {loading ? (
65
+ <>
66
+ <Loader2 className="animate-spin" />
67
+ <Slottable>{children}</Slottable>
68
+ </>
69
+ ) : (
70
+ <Slottable>{children}</Slottable>
71
+ )}
72
+ </Comp>
73
+ );
74
+ });
75
+
76
+ Button.displayName = "Button";
77
+
78
+ export { Button, buttonVariants };
@@ -0,0 +1,235 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { ChevronLeft, ChevronRight, ChevronDown } from "lucide-react"
5
+ import {
6
+ DayPicker,
7
+ getDefaultClassNames,
8
+ type DayButton,
9
+ } from "react-day-picker"
10
+
11
+ import { cn } from "./utils"
12
+ import { Button, buttonVariants } from "./button"
13
+
14
+ function Calendar({
15
+ className,
16
+ classNames,
17
+ showOutsideDays = true,
18
+ captionLayout = "label",
19
+ buttonVariant = "ghost",
20
+ formatters,
21
+ components,
22
+ ...props
23
+ }: React.ComponentProps<typeof DayPicker> & {
24
+ buttonVariant?: React.ComponentProps<typeof Button>["variant"]
25
+ }) {
26
+ const defaultClassNames = getDefaultClassNames()
27
+
28
+ return (
29
+ <DayPicker
30
+ showOutsideDays={showOutsideDays}
31
+ className={cn(
32
+ "bg-background group/calendar p-4 [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent font-sans",
33
+ String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
34
+ String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
35
+ className
36
+ )}
37
+ captionLayout={captionLayout}
38
+ formatters={formatters}
39
+ classNames={{
40
+ root: cn("w-fit", defaultClassNames.root),
41
+ months: cn(
42
+ "flex gap-6 flex-col md:flex-row relative",
43
+ defaultClassNames.months
44
+ ),
45
+ month: cn("flex flex-col w-full gap-5", defaultClassNames.month),
46
+ nav: cn(
47
+ "flex items-center gap-2 w-full absolute top-0 inset-x-0 justify-between",
48
+ defaultClassNames.nav
49
+ ),
50
+ button_previous: cn(
51
+ buttonVariants({ variant: buttonVariant }),
52
+ "size-(--cell-size) aria-disabled:opacity-40 p-0 select-none hover:bg-accent/50 transition-colors duration-200",
53
+ defaultClassNames.button_previous
54
+ ),
55
+ button_next: cn(
56
+ buttonVariants({ variant: buttonVariant }),
57
+ "size-(--cell-size) aria-disabled:opacity-40 p-0 select-none hover:bg-accent/50 transition-colors duration-200",
58
+ defaultClassNames.button_next
59
+ ),
60
+ month_caption: cn(
61
+ "flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)",
62
+ defaultClassNames.month_caption
63
+ ),
64
+ dropdowns: cn(
65
+ "w-full flex items-center justify-center h-(--cell-size) gap-2",
66
+ defaultClassNames.dropdowns
67
+ ),
68
+ dropdown_root: cn(
69
+ "relative rounded-[var(--radius)] hover:bg-accent transition-colors",
70
+ defaultClassNames.dropdown_root
71
+ ),
72
+ dropdown: cn(
73
+ "absolute bg-popover inset-0 opacity-0 cursor-pointer",
74
+ defaultClassNames.dropdown
75
+ ),
76
+ caption_label: cn(
77
+ "select-none font-[family-name:var(--font-family,Roboto)] tracking-tight hover:bg-accent hover:text-accent-foreground transition-all duration-200 rounded-[var(--radius)] px-2 py-1",
78
+ captionLayout === "label"
79
+ ? "text-[length:var(--calendar-caption-size)] font-[number:var(--font-weight-semibold)]"
80
+ : "flex items-center gap-1.5 text-[length:var(--calendar-caption-size)] font-[number:var(--font-weight-semibold)] [&>svg]:text-muted-foreground [&>svg]:size-4",
81
+ defaultClassNames.caption_label
82
+ ),
83
+ table: "w-full border-collapse mt-1",
84
+ weekdays: cn("flex gap-1", defaultClassNames.weekdays),
85
+ weekday: cn(
86
+ "text-muted-foreground rounded-(--cell-radius) flex-1 select-none text-[length:var(--calendar-weekday-size)] font-[number:var(--font-weight-medium)] uppercase tracking-wider",
87
+ defaultClassNames.weekday
88
+ ),
89
+ week: cn("flex w-full gap-1", defaultClassNames.week),
90
+ week_number_header: cn(
91
+ "select-none w-(--cell-size)",
92
+ defaultClassNames.week_number_header
93
+ ),
94
+ week_number: cn(
95
+ "select-none text-muted-foreground text-[length:var(--calendar-weekday-size)]",
96
+ defaultClassNames.week_number
97
+ ),
98
+ day: cn(
99
+ "relative w-full rounded-(--cell-radius) h-full p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-(--cell-radius) group/day aspect-square select-none",
100
+ props.showWeekNumber
101
+ ? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-(--cell-radius)"
102
+ : "[&:first-child[data-selected=true]_button]:rounded-l-(--cell-radius)",
103
+ defaultClassNames.day
104
+ ),
105
+ range_start: cn(
106
+ "rounded-l-(--cell-radius) bg-accent/50 relative after:bg-accent/50 after:absolute after:inset-y-0 after:w-2 after:right-0 -z-0 isolate",
107
+ defaultClassNames.range_start
108
+ ),
109
+ range_middle: cn(
110
+ "rounded-none bg-accent/30",
111
+ defaultClassNames.range_middle
112
+ ),
113
+ range_end: cn(
114
+ "rounded-r-(--cell-radius) bg-accent/50 relative after:bg-accent/50 after:absolute after:inset-y-0 after:w-2 after:left-0 -z-0 isolate",
115
+ defaultClassNames.range_end
116
+ ),
117
+ today: cn(
118
+ "bg-accent/60 text-accent-foreground rounded-(--cell-radius) data-[selected=true]:rounded-none font-[number:var(--font-weight-semibold)]",
119
+ defaultClassNames.today
120
+ ),
121
+ outside: cn(
122
+ "text-muted-foreground/40 aria-selected:text-muted-foreground/40",
123
+ defaultClassNames.outside
124
+ ),
125
+ disabled: cn(
126
+ "text-muted-foreground/30 opacity-40",
127
+ defaultClassNames.disabled
128
+ ),
129
+ hidden: cn("invisible", defaultClassNames.hidden),
130
+ ...classNames,
131
+ }}
132
+ components={{
133
+ Root: ({ className, rootRef, ...props }) => {
134
+ return (
135
+ <div
136
+ data-slot="calendar"
137
+ ref={rootRef}
138
+ className={cn(className)}
139
+ {...props}
140
+ />
141
+ )
142
+ },
143
+ Chevron: ({ className, orientation, ...props }) => {
144
+ if (orientation === "left") {
145
+ return (
146
+ <ChevronLeft
147
+ className={cn("size-5 transition-transform group-hover:scale-110", className)}
148
+ {...props}
149
+ />
150
+ )
151
+ }
152
+
153
+ if (orientation === "right") {
154
+ return (
155
+ <ChevronRight
156
+ className={cn("size-5 transition-transform group-hover:scale-110", className)}
157
+ {...props}
158
+ />
159
+ )
160
+ }
161
+
162
+ return (
163
+ <ChevronDown
164
+ className={cn("size-4", className)}
165
+ {...props}
166
+ />
167
+ )
168
+ },
169
+ DayButton: CalendarDayButton,
170
+ WeekNumber: ({ children, ...props }) => {
171
+ return (
172
+ <td {...props}>
173
+ <div className="flex size-(--cell-size) items-center justify-center text-center font-[number:var(--font-weight-medium)]">
174
+ {children}
175
+ </div>
176
+ </td>
177
+ )
178
+ },
179
+ ...components,
180
+ }}
181
+ {...props}
182
+ />
183
+ )
184
+ }
185
+
186
+ function CalendarDayButton({
187
+ className,
188
+ day,
189
+ modifiers,
190
+ ...props
191
+ }: React.ComponentProps<typeof DayButton>) {
192
+ const defaultClassNames = getDefaultClassNames()
193
+
194
+ const ref = React.useRef<HTMLButtonElement>(null)
195
+ React.useEffect(() => {
196
+ if (modifiers.focused) ref.current?.focus()
197
+ }, [modifiers.focused])
198
+
199
+ return (
200
+ <Button
201
+ ref={ref}
202
+ variant="ghost"
203
+ size="icon"
204
+ data-day={day.date.toLocaleDateString()}
205
+ data-selected-single={
206
+ modifiers.selected &&
207
+ !modifiers.range_start &&
208
+ !modifiers.range_end &&
209
+ !modifiers.range_middle
210
+ }
211
+ data-range-start={modifiers.range_start}
212
+ data-range-end={modifiers.range_end}
213
+ data-range-middle={modifiers.range_middle}
214
+ className={cn(
215
+ "relative isolate z-10 flex aspect-square size-auto w-full min-w-(--cell-size) flex-col items-center justify-center gap-1 border-0 leading-none transition-all duration-200 cursor-pointer disabled:cursor-not-allowed",
216
+ "text-[length:var(--calendar-day-size)] font-[number:var(--font-weight-regular)]",
217
+ "hover:bg-accent/70 hover:text-accent-foreground hover:scale-105",
218
+ "data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[selected-single=true]:font-[number:var(--font-weight-semibold)] data-[selected-single=true]:shadow-sm",
219
+ "data-[range-middle=true]:bg-accent/50 data-[range-middle=true]:text-foreground",
220
+ "data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-start=true]:font-[number:var(--font-weight-semibold)] data-[range-start=true]:shadow-sm",
221
+ "data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground data-[range-end=true]:font-[number:var(--font-weight-semibold)] data-[range-end=true]:shadow-sm",
222
+ "group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 group-data-[focused=true]/day:ring-2 group-data-[focused=true]/day:ring-offset-2 group-data-[focused=true]/day:ring-offset-background",
223
+ "data-[range-end=true]:rounded-(--cell-radius) data-[range-end=true]:rounded-r-(--cell-radius)",
224
+ "data-[range-middle=true]:rounded-none",
225
+ "data-[range-start=true]:rounded-(--cell-radius) data-[range-start=true]:rounded-l-(--cell-radius)",
226
+ "[&>span]:opacity-80",
227
+ defaultClassNames.day,
228
+ className
229
+ )}
230
+ {...props}
231
+ />
232
+ )
233
+ }
234
+
235
+ export { Calendar, CalendarDayButton }
@@ -0,0 +1,92 @@
1
+ import * as React from "react";
2
+
3
+ import { cn } from "./utils";
4
+
5
+ function Card({ className, ...props }: React.ComponentProps<"div">) {
6
+ return (
7
+ <div
8
+ data-slot="card"
9
+ className={cn(
10
+ "bg-card text-card-foreground flex flex-col gap-6 rounded-xl",
11
+ className,
12
+ )}
13
+ {...props}
14
+ />
15
+ );
16
+ }
17
+
18
+ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
19
+ return (
20
+ <div
21
+ data-slot="card-header"
22
+ className={cn(
23
+ "@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 pt-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
24
+ className,
25
+ )}
26
+ {...props}
27
+ />
28
+ );
29
+ }
30
+
31
+ function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
32
+ return (
33
+ <h4
34
+ data-slot="card-title"
35
+ className={cn("leading-none", className)}
36
+ {...props}
37
+ />
38
+ );
39
+ }
40
+
41
+ function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
42
+ return (
43
+ <p
44
+ data-slot="card-description"
45
+ className={cn("text-muted-foreground", className)}
46
+ {...props}
47
+ />
48
+ );
49
+ }
50
+
51
+ function CardAction({ className, ...props }: React.ComponentProps<"div">) {
52
+ return (
53
+ <div
54
+ data-slot="card-action"
55
+ className={cn(
56
+ "col-start-2 row-span-2 row-start-1 self-start justify-self-end",
57
+ className,
58
+ )}
59
+ {...props}
60
+ />
61
+ );
62
+ }
63
+
64
+ function CardContent({ className, ...props }: React.ComponentProps<"div">) {
65
+ return (
66
+ <div
67
+ data-slot="card-content"
68
+ className={cn("px-6 [&:last-child]:pb-6", className)}
69
+ {...props}
70
+ />
71
+ );
72
+ }
73
+
74
+ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
75
+ return (
76
+ <div
77
+ data-slot="card-footer"
78
+ className={cn("flex items-center px-6 pb-6 [.border-t]:pt-6", className)}
79
+ {...props}
80
+ />
81
+ );
82
+ }
83
+
84
+ export {
85
+ Card,
86
+ CardHeader,
87
+ CardFooter,
88
+ CardTitle,
89
+ CardAction,
90
+ CardDescription,
91
+ CardContent,
92
+ };