@lark-apaas/coding-templates 0.1.4 → 0.1.6

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 (85) hide show
  1. package/package.json +1 -1
  2. package/template-vite-react/README.md +175 -0
  3. package/template-vite-react/client/index.html +2 -1
  4. package/template-vite-react/client/src/app.tsx +3 -1
  5. package/template-vite-react/client/src/components/layout.tsx +0 -2
  6. package/template-vite-react/client/src/components/ui/README.md +134 -0
  7. package/template-vite-react/client/src/components/ui/accordion.tsx +22 -28
  8. package/template-vite-react/client/src/components/ui/alert-dialog.tsx +34 -64
  9. package/template-vite-react/client/src/components/ui/alert.tsx +10 -15
  10. package/template-vite-react/client/src/components/ui/aspect-ratio.tsx +5 -16
  11. package/template-vite-react/client/src/components/ui/avatar.tsx +11 -67
  12. package/template-vite-react/client/src/components/ui/badge.tsx +21 -31
  13. package/template-vite-react/client/src/components/ui/breadcrumb.tsx +23 -39
  14. package/template-vite-react/client/src/components/ui/button.tsx +36 -25
  15. package/template-vite-react/client/src/components/ui/calendar.tsx +37 -43
  16. package/template-vite-react/client/src/components/ui/card.tsx +73 -94
  17. package/template-vite-react/client/src/components/ui/carousel.tsx +7 -8
  18. package/template-vite-react/client/src/components/ui/chart.tsx +35 -49
  19. package/template-vite-react/client/src/components/ui/checkbox.tsx +10 -7
  20. package/template-vite-react/client/src/components/ui/collapsible.tsx +20 -6
  21. package/template-vite-react/client/src/components/ui/command.tsx +52 -40
  22. package/template-vite-react/client/src/components/ui/context-menu.tsx +170 -117
  23. package/template-vite-react/client/src/components/ui/dialog.tsx +37 -52
  24. package/template-vite-react/client/src/components/ui/drawer.tsx +12 -9
  25. package/template-vite-react/client/src/components/ui/dropdown-menu.tsx +194 -133
  26. package/template-vite-react/client/src/components/ui/hover-card.tsx +24 -29
  27. package/template-vite-react/client/src/components/ui/input-group.tsx +39 -29
  28. package/template-vite-react/client/src/components/ui/input-otp.tsx +7 -17
  29. package/template-vite-react/client/src/components/ui/input.tsx +4 -3
  30. package/template-vite-react/client/src/components/ui/label.tsx +9 -3
  31. package/template-vite-react/client/src/components/ui/menubar.tsx +160 -92
  32. package/template-vite-react/client/src/components/ui/navigation-menu.tsx +45 -45
  33. package/template-vite-react/client/src/components/ui/pagination.tsx +32 -35
  34. package/template-vite-react/client/src/components/ui/popover.tsx +20 -62
  35. package/template-vite-react/client/src/components/ui/progress.tsx +14 -64
  36. package/template-vite-react/client/src/components/ui/radio-group.tsx +20 -13
  37. package/template-vite-react/client/src/components/ui/resizable.tsx +18 -10
  38. package/template-vite-react/client/src/components/ui/scroll-area.tsx +13 -10
  39. package/template-vite-react/client/src/components/ui/select.tsx +122 -78
  40. package/template-vite-react/client/src/components/ui/separator.tsx +7 -4
  41. package/template-vite-react/client/src/components/ui/sheet.tsx +42 -41
  42. package/template-vite-react/client/src/components/ui/sidebar.tsx +162 -156
  43. package/template-vite-react/client/src/components/ui/skeleton.tsx +1 -1
  44. package/template-vite-react/client/src/components/ui/slider.tsx +52 -22
  45. package/template-vite-react/client/src/components/ui/sonner.tsx +44 -26
  46. package/template-vite-react/client/src/components/ui/switch.tsx +9 -8
  47. package/template-vite-react/client/src/components/ui/table.tsx +5 -5
  48. package/template-vite-react/client/src/components/ui/tabs.tsx +24 -38
  49. package/template-vite-react/client/src/components/ui/textarea.tsx +1 -1
  50. package/template-vite-react/client/src/components/ui/toggle-group.tsx +14 -20
  51. package/template-vite-react/client/src/components/ui/toggle.tsx +13 -10
  52. package/template-vite-react/client/src/components/ui/tooltip.tsx +30 -33
  53. package/template-vite-react/client/src/index.css +130 -0
  54. package/template-vite-react/client/src/main.tsx +1 -4
  55. package/template-vite-react/client/src/pages/home/index.tsx +5 -5
  56. package/template-vite-react/components.json +2 -6
  57. package/template-vite-react/eslint.config.js +11 -0
  58. package/template-vite-react/package.json +27 -2
  59. package/template-vite-react/vite.config.ts +5 -0
  60. package/template-vite-react/client/src/components/header.tsx +0 -22
  61. package/template-vite-react/client/src/components/theme-provider.tsx +0 -45
  62. package/template-vite-react/client/src/components/ui/icons/file-ae-colorful-icon.tsx +0 -21
  63. package/template-vite-react/client/src/components/ui/icons/file-ai-colorful-icon.tsx +0 -36
  64. package/template-vite-react/client/src/components/ui/icons/file-android-colorful-icon.tsx +0 -33
  65. package/template-vite-react/client/src/components/ui/icons/file-audio-colorful-icon.tsx +0 -21
  66. package/template-vite-react/client/src/components/ui/icons/file-code-colorful-icon.tsx +0 -28
  67. package/template-vite-react/client/src/components/ui/icons/file-csv-colorful-icon.tsx +0 -21
  68. package/template-vite-react/client/src/components/ui/icons/file-eml-colorful-icon.tsx +0 -29
  69. package/template-vite-react/client/src/components/ui/icons/file-ios-colorful-icon.tsx +0 -25
  70. package/template-vite-react/client/src/components/ui/icons/file-keynote-colorful-icon.tsx +0 -29
  71. package/template-vite-react/client/src/components/ui/icons/file-pages-colorful-icon.tsx +0 -29
  72. package/template-vite-react/client/src/components/ui/icons/file-ps-colorful-icon.tsx +0 -21
  73. package/template-vite-react/client/src/components/ui/icons/file-sketch-colorful-icon.tsx +0 -21
  74. package/template-vite-react/client/src/components/ui/icons/file-slide-colorful-icon.tsx +0 -21
  75. package/template-vite-react/client/src/components/ui/icons/file-vcf-colorful-icon.tsx +0 -29
  76. package/template-vite-react/client/src/components/ui/icons/file-wiki-excel-colorful-icon.tsx +0 -23
  77. package/template-vite-react/client/src/components/ui/icons/file-wiki-image-colorful-icon.tsx +0 -27
  78. package/template-vite-react/client/src/components/ui/icons/file-wiki-pdf-colorful-icon.tsx +0 -20
  79. package/template-vite-react/client/src/components/ui/icons/file-wiki-ppt-colorful-icon.tsx +0 -21
  80. package/template-vite-react/client/src/components/ui/icons/file-wiki-text-colorful-icon.tsx +0 -12
  81. package/template-vite-react/client/src/components/ui/icons/file-wiki-unknown-colorful-icon.tsx +0 -14
  82. package/template-vite-react/client/src/components/ui/icons/file-wiki-video-colorful-icon.tsx +0 -23
  83. package/template-vite-react/client/src/components/ui/icons/file-wiki-word-colorful-icon.tsx +0 -38
  84. package/template-vite-react/client/src/components/ui/icons/file-wiki-zip-colorful-icon.tsx +0 -21
  85. package/template-vite-react/client/src/types/index.ts +0 -1
@@ -1,14 +1,15 @@
1
+ "use client"
2
+
1
3
  import * as React from "react"
2
4
  import {
3
- DayPicker,
4
- getDefaultClassNames,
5
- type DayButton,
6
- type Locale,
7
- } from "react-day-picker"
5
+ ChevronDownIcon,
6
+ ChevronLeftIcon,
7
+ ChevronRightIcon,
8
+ } from "lucide-react"
9
+ import { DayButton, DayPicker, getDefaultClassNames } from "react-day-picker"
8
10
 
9
11
  import { cn } from "@/lib/utils"
10
12
  import { Button, buttonVariants } from "@/components/ui/button"
11
- import { ChevronLeftIcon, ChevronRightIcon, ChevronDownIcon } from "lucide-react"
12
13
 
13
14
  function Calendar({
14
15
  className,
@@ -16,7 +17,6 @@ function Calendar({
16
17
  showOutsideDays = true,
17
18
  captionLayout = "label",
18
19
  buttonVariant = "ghost",
19
- locale,
20
20
  formatters,
21
21
  components,
22
22
  ...props
@@ -29,95 +29,88 @@ function Calendar({
29
29
  <DayPicker
30
30
  showOutsideDays={showOutsideDays}
31
31
  className={cn(
32
- "group/calendar bg-background p-2 [--cell-radius:var(--radius-md)] [--cell-size:--spacing(7)] in-data-[slot=card-content]:bg-transparent in-data-[slot=popover-content]:bg-transparent",
32
+ "bg-background group/calendar p-3 [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
33
33
  String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
34
34
  String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
35
35
  className
36
36
  )}
37
37
  captionLayout={captionLayout}
38
- locale={locale}
39
38
  formatters={{
40
39
  formatMonthDropdown: (date) =>
41
- date.toLocaleString(locale?.code, { month: "short" }),
40
+ date.toLocaleString("default", { month: "short" }),
42
41
  ...formatters,
43
42
  }}
44
43
  classNames={{
45
44
  root: cn("w-fit", defaultClassNames.root),
46
45
  months: cn(
47
- "relative flex flex-col gap-4 md:flex-row",
46
+ "flex gap-4 flex-col md:flex-row relative",
48
47
  defaultClassNames.months
49
48
  ),
50
- month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
49
+ month: cn("flex flex-col w-full gap-4", defaultClassNames.month),
51
50
  nav: cn(
52
- "absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1",
51
+ "flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between",
53
52
  defaultClassNames.nav
54
53
  ),
55
54
  button_previous: cn(
56
55
  buttonVariants({ variant: buttonVariant }),
57
- "size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
56
+ "size-(--cell-size) aria-disabled:opacity-50 p-0 select-none",
58
57
  defaultClassNames.button_previous
59
58
  ),
60
59
  button_next: cn(
61
60
  buttonVariants({ variant: buttonVariant }),
62
- "size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
61
+ "size-(--cell-size) aria-disabled:opacity-50 p-0 select-none",
63
62
  defaultClassNames.button_next
64
63
  ),
65
64
  month_caption: cn(
66
- "flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)",
65
+ "flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)",
67
66
  defaultClassNames.month_caption
68
67
  ),
69
68
  dropdowns: cn(
70
- "flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium",
69
+ "w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5",
71
70
  defaultClassNames.dropdowns
72
71
  ),
73
72
  dropdown_root: cn(
74
- "relative rounded-(--cell-radius)",
73
+ "relative has-focus:border-ring border border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] rounded-md",
75
74
  defaultClassNames.dropdown_root
76
75
  ),
77
76
  dropdown: cn(
78
- "absolute inset-0 bg-popover opacity-0",
77
+ "absolute bg-popover inset-0 opacity-0",
79
78
  defaultClassNames.dropdown
80
79
  ),
81
80
  caption_label: cn(
82
- "font-medium select-none",
81
+ "select-none font-medium",
83
82
  captionLayout === "label"
84
83
  ? "text-sm"
85
- : "flex items-center gap-1 rounded-(--cell-radius) text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground",
84
+ : "rounded-md pl-2 pr-1 flex items-center gap-1 text-sm h-8 [&>svg]:text-muted-foreground [&>svg]:size-3.5",
86
85
  defaultClassNames.caption_label
87
86
  ),
88
87
  table: "w-full border-collapse",
89
88
  weekdays: cn("flex", defaultClassNames.weekdays),
90
89
  weekday: cn(
91
- "flex-1 rounded-(--cell-radius) text-[0.8rem] font-normal text-muted-foreground select-none",
90
+ "text-muted-foreground rounded-md flex-1 font-normal text-[0.8rem] select-none",
92
91
  defaultClassNames.weekday
93
92
  ),
94
- week: cn("mt-2 flex w-full", defaultClassNames.week),
93
+ week: cn("flex w-full mt-2", defaultClassNames.week),
95
94
  week_number_header: cn(
96
- "w-(--cell-size) select-none",
95
+ "select-none w-(--cell-size)",
97
96
  defaultClassNames.week_number_header
98
97
  ),
99
98
  week_number: cn(
100
- "text-[0.8rem] text-muted-foreground select-none",
99
+ "text-[0.8rem] select-none text-muted-foreground",
101
100
  defaultClassNames.week_number
102
101
  ),
103
102
  day: cn(
104
- "group/day relative aspect-square h-full w-full rounded-(--cell-radius) p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-r-(--cell-radius)",
105
- props.showWeekNumber
106
- ? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-(--cell-radius)"
107
- : "[&:first-child[data-selected=true]_button]:rounded-l-(--cell-radius)",
103
+ "relative w-full h-full p-0 text-center [&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none",
108
104
  defaultClassNames.day
109
105
  ),
110
106
  range_start: cn(
111
- "relative isolate z-0 rounded-l-(--cell-radius) bg-muted after:absolute after:inset-y-0 after:right-0 after:w-4 after:bg-muted",
107
+ "rounded-l-md bg-accent",
112
108
  defaultClassNames.range_start
113
109
  ),
114
110
  range_middle: cn("rounded-none", defaultClassNames.range_middle),
115
- range_end: cn(
116
- "relative isolate z-0 rounded-r-(--cell-radius) bg-muted after:absolute after:inset-y-0 after:left-0 after:w-4 after:bg-muted",
117
- defaultClassNames.range_end
118
- ),
111
+ range_end: cn("rounded-r-md bg-accent", defaultClassNames.range_end),
119
112
  today: cn(
120
- "rounded-(--cell-radius) bg-muted text-foreground data-[selected=true]:rounded-none",
113
+ "bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none",
121
114
  defaultClassNames.today
122
115
  ),
123
116
  outside: cn(
@@ -151,7 +144,10 @@ function Calendar({
151
144
 
152
145
  if (orientation === "right") {
153
146
  return (
154
- <ChevronRightIcon className={cn("size-4", className)} {...props} />
147
+ <ChevronRightIcon
148
+ className={cn("size-4", className)}
149
+ {...props}
150
+ />
155
151
  )
156
152
  }
157
153
 
@@ -159,9 +155,7 @@ function Calendar({
159
155
  <ChevronDownIcon className={cn("size-4", className)} {...props} />
160
156
  )
161
157
  },
162
- DayButton: ({ ...props }) => (
163
- <CalendarDayButton locale={locale} {...props} />
164
- ),
158
+ DayButton: CalendarDayButton,
165
159
  WeekNumber: ({ children, ...props }) => {
166
160
  return (
167
161
  <td {...props}>
@@ -182,9 +176,8 @@ function CalendarDayButton({
182
176
  className,
183
177
  day,
184
178
  modifiers,
185
- locale,
186
179
  ...props
187
- }: React.ComponentProps<typeof DayButton> & { locale?: Partial<Locale> }) {
180
+ }: React.ComponentProps<typeof DayButton>) {
188
181
  const defaultClassNames = getDefaultClassNames()
189
182
 
190
183
  const ref = React.useRef<HTMLButtonElement>(null)
@@ -194,9 +187,10 @@ function CalendarDayButton({
194
187
 
195
188
  return (
196
189
  <Button
190
+ ref={ref}
197
191
  variant="ghost"
198
192
  size="icon"
199
- data-day={day.date.toLocaleDateString(locale?.code)}
193
+ data-day={day.date.toLocaleDateString()}
200
194
  data-selected-single={
201
195
  modifiers.selected &&
202
196
  !modifiers.range_start &&
@@ -207,7 +201,7 @@ function CalendarDayButton({
207
201
  data-range-end={modifiers.range_end}
208
202
  data-range-middle={modifiers.range_middle}
209
203
  className={cn(
210
- "relative isolate z-10 flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 border-0 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-[3px] group-data-[focused=true]/day:ring-ring/50 data-[range-end=true]:rounded-(--cell-radius) data-[range-end=true]:rounded-r-(--cell-radius) data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground data-[range-middle=true]:rounded-none data-[range-middle=true]:bg-muted data-[range-middle=true]:text-foreground data-[range-start=true]:rounded-(--cell-radius) data-[range-start=true]:rounded-l-(--cell-radius) data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground dark:hover:text-foreground [&>span]:text-xs [&>span]:opacity-70",
204
+ "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",
211
205
  defaultClassNames.day,
212
206
  className
213
207
  )}
@@ -1,103 +1,82 @@
1
- import * as React from "react"
1
+ import * as React from "react";
2
2
 
3
- import { cn } from "@/lib/utils"
3
+ import { cn } from "@/lib/utils";
4
4
 
5
- function Card({
6
- className,
7
- size = "default",
8
- ...props
9
- }: React.ComponentProps<"div"> & { size?: "default" | "sm" }) {
10
- return (
11
- <div
12
- data-slot="card"
13
- data-size={size}
14
- className={cn(
15
- "group/card flex flex-col gap-4 overflow-hidden rounded-xl bg-card py-4 text-sm text-card-foreground ring-1 ring-foreground/10 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
16
- className
17
- )}
18
- {...props}
19
- />
20
- )
21
- }
5
+ const Card = React.forwardRef<
6
+ HTMLDivElement,
7
+ React.HTMLAttributes<HTMLDivElement>
8
+ >(({ className, ...props }, ref) => (
9
+ <div
10
+ ref={ref}
11
+ className={cn(
12
+ "rounded-xl border bg-card border-card-border text-card-foreground shadow-sm",
13
+ className
14
+ )}
15
+ {...props}
16
+ />
17
+ ));
18
+ Card.displayName = "Card"
22
19
 
23
- function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
24
- return (
25
- <div
26
- data-slot="card-header"
27
- className={cn(
28
- "group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3",
29
- className
30
- )}
31
- {...props}
32
- />
33
- )
34
- }
20
+ const CardHeader = React.forwardRef<
21
+ HTMLDivElement,
22
+ React.HTMLAttributes<HTMLDivElement>
23
+ >(({ className, ...props }, ref) => (
24
+ <div
25
+ ref={ref}
26
+ className={cn("flex flex-col space-y-1.5 p-6", className)}
27
+ {...props}
28
+ />
29
+ ));
30
+ CardHeader.displayName = "CardHeader"
35
31
 
36
- function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
37
- return (
38
- <div
39
- data-slot="card-title"
40
- className={cn(
41
- "text-base leading-snug font-medium group-data-[size=sm]/card:text-sm",
42
- className
43
- )}
44
- {...props}
45
- />
46
- )
47
- }
32
+ const CardTitle = React.forwardRef<
33
+ HTMLDivElement,
34
+ React.HTMLAttributes<HTMLDivElement>
35
+ >(({ className, ...props }, ref) => (
36
+ <div
37
+ ref={ref}
38
+ className={cn(
39
+ "text-2xl font-semibold leading-none tracking-tight",
40
+ className
41
+ )}
42
+ {...props}
43
+ />
44
+ ))
45
+ CardTitle.displayName = "CardTitle"
48
46
 
49
- function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
50
- return (
51
- <div
52
- data-slot="card-description"
53
- className={cn("text-sm text-muted-foreground", className)}
54
- {...props}
55
- />
56
- )
57
- }
47
+ const CardDescription = React.forwardRef<
48
+ HTMLDivElement,
49
+ React.HTMLAttributes<HTMLDivElement>
50
+ >(({ className, ...props }, ref) => (
51
+ <div
52
+ ref={ref}
53
+ className={cn("text-sm text-muted-foreground", className)}
54
+ {...props}
55
+ />
56
+ ));
57
+ CardDescription.displayName = "CardDescription"
58
58
 
59
- function CardAction({ className, ...props }: React.ComponentProps<"div">) {
60
- return (
61
- <div
62
- data-slot="card-action"
63
- className={cn(
64
- "col-start-2 row-span-2 row-start-1 self-start justify-self-end",
65
- className
66
- )}
67
- {...props}
68
- />
69
- )
70
- }
59
+ const CardContent = React.forwardRef<
60
+ HTMLDivElement,
61
+ React.HTMLAttributes<HTMLDivElement>
62
+ >(({ className, ...props }, ref) => (
63
+ <div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
64
+ ))
65
+ CardContent.displayName = "CardContent"
71
66
 
72
- function CardContent({ className, ...props }: React.ComponentProps<"div">) {
73
- return (
74
- <div
75
- data-slot="card-content"
76
- className={cn("px-4 group-data-[size=sm]/card:px-3", className)}
77
- {...props}
78
- />
79
- )
80
- }
81
-
82
- function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
83
- return (
84
- <div
85
- data-slot="card-footer"
86
- className={cn(
87
- "flex items-center rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/card:p-3",
88
- className
89
- )}
90
- {...props}
91
- />
92
- )
93
- }
67
+ const CardFooter = React.forwardRef<
68
+ HTMLDivElement,
69
+ React.HTMLAttributes<HTMLDivElement>
70
+ >(({ className, ...props }, ref) => (
71
+ <div
72
+ ref={ref}
73
+ className={cn("flex items-center p-6 pt-0", className)}
74
+ {...props}
75
+ />
76
+ ))
77
+ CardFooter.displayName = "CardFooter"
94
78
 
95
79
  export {
96
- Card,
97
- CardHeader,
98
- CardFooter,
99
- CardTitle,
100
- CardAction,
101
- CardDescription,
102
- CardContent,
103
- }
80
+ Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle
81
+ };
82
+
@@ -4,10 +4,10 @@ import * as React from "react"
4
4
  import useEmblaCarousel, {
5
5
  type UseEmblaCarouselType,
6
6
  } from "embla-carousel-react"
7
+ import { ArrowLeft, ArrowRight } from "lucide-react"
7
8
 
8
9
  import { cn } from "@/lib/utils"
9
10
  import { Button } from "@/components/ui/button"
10
- import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react"
11
11
 
12
12
  type CarouselApi = UseEmblaCarouselType[1]
13
13
  type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
@@ -174,7 +174,7 @@ function CarouselItem({ className, ...props }: React.ComponentProps<"div">) {
174
174
  function CarouselPrevious({
175
175
  className,
176
176
  variant = "outline",
177
- size = "icon-sm",
177
+ size = "icon",
178
178
  ...props
179
179
  }: React.ComponentProps<typeof Button>) {
180
180
  const { orientation, scrollPrev, canScrollPrev } = useCarousel()
@@ -185,7 +185,7 @@ function CarouselPrevious({
185
185
  variant={variant}
186
186
  size={size}
187
187
  className={cn(
188
- "absolute touch-manipulation rounded-full",
188
+ "absolute size-8 rounded-full",
189
189
  orientation === "horizontal"
190
190
  ? "top-1/2 -left-12 -translate-y-1/2"
191
191
  : "-top-12 left-1/2 -translate-x-1/2 rotate-90",
@@ -195,7 +195,7 @@ function CarouselPrevious({
195
195
  onClick={scrollPrev}
196
196
  {...props}
197
197
  >
198
- <ChevronLeftIcon />
198
+ <ArrowLeft />
199
199
  <span className="sr-only">Previous slide</span>
200
200
  </Button>
201
201
  )
@@ -204,7 +204,7 @@ function CarouselPrevious({
204
204
  function CarouselNext({
205
205
  className,
206
206
  variant = "outline",
207
- size = "icon-sm",
207
+ size = "icon",
208
208
  ...props
209
209
  }: React.ComponentProps<typeof Button>) {
210
210
  const { orientation, scrollNext, canScrollNext } = useCarousel()
@@ -215,7 +215,7 @@ function CarouselNext({
215
215
  variant={variant}
216
216
  size={size}
217
217
  className={cn(
218
- "absolute touch-manipulation rounded-full",
218
+ "absolute size-8 rounded-full",
219
219
  orientation === "horizontal"
220
220
  ? "top-1/2 -right-12 -translate-y-1/2"
221
221
  : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
@@ -225,7 +225,7 @@ function CarouselNext({
225
225
  onClick={scrollNext}
226
226
  {...props}
227
227
  >
228
- <ChevronRightIcon />
228
+ <ArrowRight />
229
229
  <span className="sr-only">Next slide</span>
230
230
  </Button>
231
231
  )
@@ -238,5 +238,4 @@ export {
238
238
  CarouselItem,
239
239
  CarouselPrevious,
240
240
  CarouselNext,
241
- useCarousel,
242
241
  }
@@ -1,25 +1,22 @@
1
+ "use client"
2
+
1
3
  import * as React from "react"
2
4
  import * as RechartsPrimitive from "recharts"
3
- import type { TooltipValueType } from "recharts"
4
5
 
5
6
  import { cn } from "@/lib/utils"
6
7
 
7
8
  // Format: { THEME_NAME: CSS_SELECTOR }
8
9
  const THEMES = { light: "", dark: ".dark" } as const
9
10
 
10
- const INITIAL_DIMENSION = { width: 320, height: 200 } as const
11
- type TooltipNameType = number | string
12
-
13
- export type ChartConfig = Record<
14
- string,
15
- {
11
+ export type ChartConfig = {
12
+ [k in string]: {
16
13
  label?: React.ReactNode
17
14
  icon?: React.ComponentType
18
15
  } & (
19
16
  | { color?: string; theme?: never }
20
17
  | { color?: never; theme: Record<keyof typeof THEMES, string> }
21
18
  )
22
- >
19
+ }
23
20
 
24
21
  type ChartContextProps = {
25
22
  config: ChartConfig
@@ -42,20 +39,15 @@ function ChartContainer({
42
39
  className,
43
40
  children,
44
41
  config,
45
- initialDimension = INITIAL_DIMENSION,
46
42
  ...props
47
43
  }: React.ComponentProps<"div"> & {
48
44
  config: ChartConfig
49
45
  children: React.ComponentProps<
50
46
  typeof RechartsPrimitive.ResponsiveContainer
51
47
  >["children"]
52
- initialDimension?: {
53
- width: number
54
- height: number
55
- }
56
48
  }) {
57
49
  const uniqueId = React.useId()
58
- const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}`
50
+ const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`
59
51
 
60
52
  return (
61
53
  <ChartContext.Provider value={{ config }}>
@@ -63,15 +55,13 @@ function ChartContainer({
63
55
  data-slot="chart"
64
56
  data-chart={chartId}
65
57
  className={cn(
66
- "flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden",
58
+ "[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border flex aspect-video justify-center text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden",
67
59
  className
68
60
  )}
69
61
  {...props}
70
62
  >
71
63
  <ChartStyle id={chartId} config={config} />
72
- <RechartsPrimitive.ResponsiveContainer
73
- initialDimension={initialDimension}
74
- >
64
+ <RechartsPrimitive.ResponsiveContainer>
75
65
  {children}
76
66
  </RechartsPrimitive.ResponsiveContainer>
77
67
  </div>
@@ -81,7 +71,7 @@ function ChartContainer({
81
71
 
82
72
  const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
83
73
  const colorConfig = Object.entries(config).filter(
84
- ([, config]) => config.theme ?? config.color
74
+ ([, config]) => config.theme || config.color
85
75
  )
86
76
 
87
77
  if (!colorConfig.length) {
@@ -98,7 +88,7 @@ ${prefix} [data-chart=${id}] {
98
88
  ${colorConfig
99
89
  .map(([key, itemConfig]) => {
100
90
  const color =
101
- itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??
91
+ itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||
102
92
  itemConfig.color
103
93
  return color ? ` --color-${key}: ${color};` : null
104
94
  })
@@ -135,13 +125,7 @@ function ChartTooltipContent({
135
125
  indicator?: "line" | "dot" | "dashed"
136
126
  nameKey?: string
137
127
  labelKey?: string
138
- } & Omit<
139
- RechartsPrimitive.DefaultTooltipContentProps<
140
- TooltipValueType,
141
- TooltipNameType
142
- >,
143
- "accessibilityLayer"
144
- >) {
128
+ }) {
145
129
  const { config } = useChart()
146
130
 
147
131
  const tooltipLabel = React.useMemo(() => {
@@ -150,11 +134,11 @@ function ChartTooltipContent({
150
134
  }
151
135
 
152
136
  const [item] = payload
153
- const key = `${labelKey ?? item?.dataKey ?? item?.name ?? "value"}`
137
+ const key = `${labelKey || item?.dataKey || item?.name || "value"}`
154
138
  const itemConfig = getPayloadConfigFromPayload(config, item, key)
155
139
  const value =
156
140
  !labelKey && typeof label === "string"
157
- ? (config[label]?.label ?? label)
141
+ ? config[label as keyof typeof config]?.label || label
158
142
  : itemConfig?.label
159
143
 
160
144
  if (labelFormatter) {
@@ -189,7 +173,7 @@ function ChartTooltipContent({
189
173
  return (
190
174
  <div
191
175
  className={cn(
192
- "grid min-w-32 items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl",
176
+ "border-border/50 bg-background grid min-w-[8rem] items-start gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl",
193
177
  className
194
178
  )}
195
179
  >
@@ -198,15 +182,15 @@ function ChartTooltipContent({
198
182
  {payload
199
183
  .filter((item) => item.type !== "none")
200
184
  .map((item, index) => {
201
- const key = `${nameKey ?? item.name ?? item.dataKey ?? "value"}`
185
+ const key = `${nameKey || item.name || item.dataKey || "value"}`
202
186
  const itemConfig = getPayloadConfigFromPayload(config, item, key)
203
- const indicatorColor = color ?? item.payload?.fill ?? item.color
187
+ const indicatorColor = color || item.payload.fill || item.color
204
188
 
205
189
  return (
206
190
  <div
207
- key={index}
191
+ key={item.dataKey}
208
192
  className={cn(
209
- "flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground",
193
+ "[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5",
210
194
  indicator === "dot" && "items-center"
211
195
  )}
212
196
  >
@@ -247,14 +231,12 @@ function ChartTooltipContent({
247
231
  <div className="grid gap-1.5">
248
232
  {nestLabel ? tooltipLabel : null}
249
233
  <span className="text-muted-foreground">
250
- {itemConfig?.label ?? item.name}
234
+ {itemConfig?.label || item.name}
251
235
  </span>
252
236
  </div>
253
- {item.value != null && (
254
- <span className="font-mono font-medium text-foreground tabular-nums">
255
- {typeof item.value === "number"
256
- ? item.value.toLocaleString()
257
- : String(item.value)}
237
+ {item.value && (
238
+ <span className="text-foreground font-mono font-medium tabular-nums">
239
+ {item.value.toLocaleString()}
258
240
  </span>
259
241
  )}
260
242
  </div>
@@ -276,10 +258,11 @@ function ChartLegendContent({
276
258
  payload,
277
259
  verticalAlign = "bottom",
278
260
  nameKey,
279
- }: React.ComponentProps<"div"> & {
280
- hideIcon?: boolean
281
- nameKey?: string
282
- } & RechartsPrimitive.DefaultLegendContentProps) {
261
+ }: React.ComponentProps<"div"> &
262
+ Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & {
263
+ hideIcon?: boolean
264
+ nameKey?: string
265
+ }) {
283
266
  const { config } = useChart()
284
267
 
285
268
  if (!payload?.length) {
@@ -296,15 +279,15 @@ function ChartLegendContent({
296
279
  >
297
280
  {payload
298
281
  .filter((item) => item.type !== "none")
299
- .map((item, index) => {
300
- const key = `${nameKey ?? item.dataKey ?? "value"}`
282
+ .map((item) => {
283
+ const key = `${nameKey || item.dataKey || "value"}`
301
284
  const itemConfig = getPayloadConfigFromPayload(config, item, key)
302
285
 
303
286
  return (
304
287
  <div
305
- key={index}
288
+ key={item.value}
306
289
  className={cn(
307
- "flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground"
290
+ "[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3"
308
291
  )}
309
292
  >
310
293
  {itemConfig?.icon && !hideIcon ? (
@@ -325,6 +308,7 @@ function ChartLegendContent({
325
308
  )
326
309
  }
327
310
 
311
+ // Helper to extract item config from a payload.
328
312
  function getPayloadConfigFromPayload(
329
313
  config: ChartConfig,
330
314
  payload: unknown,
@@ -358,7 +342,9 @@ function getPayloadConfigFromPayload(
358
342
  ] as string
359
343
  }
360
344
 
361
- return configLabelKey in config ? config[configLabelKey] : config[key]
345
+ return configLabelKey in config
346
+ ? config[configLabelKey]
347
+ : config[key as keyof typeof config]
362
348
  }
363
349
 
364
350
  export {