@windrun-huaiin/base-ui 3.2.4 → 3.4.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 (81) hide show
  1. package/dist/components/client/index.d.mts +46 -0
  2. package/dist/components/client/index.d.ts +46 -0
  3. package/dist/components/client/index.js +1822 -0
  4. package/dist/components/client/index.js.map +1 -0
  5. package/dist/components/client/index.mjs +1866 -0
  6. package/dist/components/client/index.mjs.map +1 -0
  7. package/dist/components/index.d.mts +1 -44
  8. package/dist/components/index.d.ts +1 -44
  9. package/dist/components/index.js +4 -571
  10. package/dist/components/index.js.map +1 -1
  11. package/dist/components/index.mjs +3 -564
  12. package/dist/components/index.mjs.map +1 -1
  13. package/dist/index.d.mts +3 -39
  14. package/dist/index.d.ts +3 -39
  15. package/dist/index.js +189 -4581
  16. package/dist/index.js.map +1 -1
  17. package/dist/index.mjs +191 -4354
  18. package/dist/index.mjs.map +1 -1
  19. package/dist/lib/index.js +0 -1
  20. package/dist/lib/index.js.map +1 -1
  21. package/dist/lib/index.mjs +0 -1
  22. package/dist/lib/index.mjs.map +1 -1
  23. package/dist/ui/index.d.mts +37 -711
  24. package/dist/ui/index.d.ts +37 -711
  25. package/dist/ui/index.js +172 -4249
  26. package/dist/ui/index.js.map +1 -1
  27. package/dist/ui/index.mjs +171 -4025
  28. package/dist/ui/index.mjs.map +1 -1
  29. package/package.json +11 -37
  30. package/src/components/404-page.tsx +1 -1
  31. package/src/components/client/index.ts +15 -0
  32. package/src/components/global-icon.tsx +1 -1
  33. package/src/components/index.ts +15 -8
  34. package/src/index.ts +4 -1
  35. package/src/ui/index.ts +2 -48
  36. package/src/ui/accordion.tsx +0 -58
  37. package/src/ui/alert.tsx +0 -59
  38. package/src/ui/aspect-ratio.tsx +0 -7
  39. package/src/ui/avatar.tsx +0 -50
  40. package/src/ui/badge.tsx +0 -36
  41. package/src/ui/breadcrumb.tsx +0 -115
  42. package/src/ui/calendar.tsx +0 -66
  43. package/src/ui/card.tsx +0 -79
  44. package/src/ui/carousel.tsx +0 -262
  45. package/src/ui/chart.tsx +0 -365
  46. package/src/ui/checkbox.tsx +0 -30
  47. package/src/ui/collapsible.tsx +0 -11
  48. package/src/ui/command.tsx +0 -153
  49. package/src/ui/context-menu.tsx +0 -200
  50. package/src/ui/dialog.tsx +0 -122
  51. package/src/ui/drawer.tsx +0 -118
  52. package/src/ui/form.tsx +0 -178
  53. package/src/ui/hover-card.tsx +0 -29
  54. package/src/ui/input-otp.tsx +0 -71
  55. package/src/ui/input.tsx +0 -22
  56. package/src/ui/menubar.tsx +0 -236
  57. package/src/ui/navigation-menu.tsx +0 -128
  58. package/src/ui/pagination.tsx +0 -117
  59. package/src/ui/popover.tsx +0 -31
  60. package/src/ui/progress.tsx +0 -28
  61. package/src/ui/radio-group.tsx +0 -44
  62. package/src/ui/resizable.tsx +0 -45
  63. package/src/ui/scroll-area.tsx +0 -48
  64. package/src/ui/select.tsx +0 -160
  65. package/src/ui/separator.tsx +0 -31
  66. package/src/ui/sheet.tsx +0 -140
  67. package/src/ui/sidebar.tsx +0 -763
  68. package/src/ui/skeleton.tsx +0 -15
  69. package/src/ui/slider.tsx +0 -28
  70. package/src/ui/sonner.tsx +0 -31
  71. package/src/ui/switch.tsx +0 -29
  72. package/src/ui/table.tsx +0 -117
  73. package/src/ui/tabs.tsx +0 -55
  74. package/src/ui/textarea.tsx +0 -22
  75. package/src/ui/toast.tsx +0 -129
  76. package/src/ui/toaster.tsx +0 -35
  77. package/src/ui/toggle-group.tsx +0 -61
  78. package/src/ui/toggle.tsx +0 -45
  79. package/src/ui/tooltip.tsx +0 -30
  80. package/src/ui/use-mobile.tsx +0 -19
  81. package/src/ui/use-toast.ts +0 -194
package/src/ui/card.tsx DELETED
@@ -1,79 +0,0 @@
1
- import * as React from "react"
2
-
3
- import { cn } from "@lib/utils"
4
-
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-lg border bg-card text-card-foreground shadow-xs",
13
- className
14
- )}
15
- {...props}
16
- />
17
- ))
18
- Card.displayName = "Card"
19
-
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"
31
-
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"
46
-
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
-
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"
66
-
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"
78
-
79
- export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
@@ -1,262 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import useEmblaCarousel, {
5
- type UseEmblaCarouselType,
6
- } from "embla-carousel-react"
7
- import { globalLucideIcons as icons } from "@base-ui/components/global-icon"
8
-
9
- import { cn } from "@lib/utils"
10
- import { Button } from "@base-ui/ui/button"
11
-
12
- type CarouselApi = UseEmblaCarouselType[1]
13
- type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
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<typeof useEmblaCarousel>[0]
26
- api: ReturnType<typeof useEmblaCarousel>[1]
27
- scrollPrev: () => void
28
- scrollNext: () => void
29
- canScrollPrev: boolean
30
- canScrollNext: boolean
31
- } & CarouselProps
32
-
33
- const CarouselContext = React.createContext<CarouselContextProps | null>(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 <Carousel />")
40
- }
41
-
42
- return context
43
- }
44
-
45
- const Carousel = React.forwardRef<
46
- HTMLDivElement,
47
- React.HTMLAttributes<HTMLDivElement> & CarouselProps
48
- >(
49
- (
50
- {
51
- orientation = "horizontal",
52
- opts,
53
- setApi,
54
- plugins,
55
- className,
56
- children,
57
- ...props
58
- },
59
- ref
60
- ) => {
61
- const [carouselRef, api] = useEmblaCarousel(
62
- {
63
- ...opts,
64
- axis: orientation === "horizontal" ? "x" : "y",
65
- },
66
- plugins
67
- )
68
- const [canScrollPrev, setCanScrollPrev] = React.useState(false)
69
- const [canScrollNext, setCanScrollNext] = React.useState(false)
70
-
71
- const onSelect = React.useCallback((api: CarouselApi) => {
72
- if (!api) {
73
- return
74
- }
75
-
76
- setCanScrollPrev(api.canScrollPrev())
77
- setCanScrollNext(api.canScrollNext())
78
- }, [])
79
-
80
- const scrollPrev = React.useCallback(() => {
81
- api?.scrollPrev()
82
- }, [api])
83
-
84
- const scrollNext = React.useCallback(() => {
85
- api?.scrollNext()
86
- }, [api])
87
-
88
- const handleKeyDown = React.useCallback(
89
- (event: React.KeyboardEvent<HTMLDivElement>) => {
90
- if (event.key === "ArrowLeft") {
91
- event.preventDefault()
92
- scrollPrev()
93
- } else if (event.key === "ArrowRight") {
94
- event.preventDefault()
95
- scrollNext()
96
- }
97
- },
98
- [scrollPrev, scrollNext]
99
- )
100
-
101
- React.useEffect(() => {
102
- if (!api || !setApi) {
103
- return
104
- }
105
-
106
- setApi(api)
107
- }, [api, setApi])
108
-
109
- React.useEffect(() => {
110
- if (!api) {
111
- return
112
- }
113
-
114
- onSelect(api)
115
- api.on("reInit", onSelect)
116
- api.on("select", onSelect)
117
-
118
- return () => {
119
- api?.off("select", onSelect)
120
- }
121
- }, [api, onSelect])
122
-
123
- return (
124
- <CarouselContext.Provider
125
- value={{
126
- carouselRef,
127
- api: api,
128
- opts,
129
- orientation:
130
- orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
131
- scrollPrev,
132
- scrollNext,
133
- canScrollPrev,
134
- canScrollNext,
135
- }}
136
- >
137
- <div
138
- ref={ref}
139
- onKeyDownCapture={handleKeyDown}
140
- className={cn("relative", className)}
141
- role="region"
142
- aria-roledescription="carousel"
143
- {...props}
144
- >
145
- {children}
146
- </div>
147
- </CarouselContext.Provider>
148
- )
149
- }
150
- )
151
- Carousel.displayName = "Carousel"
152
-
153
- const CarouselContent = React.forwardRef<
154
- HTMLDivElement,
155
- React.HTMLAttributes<HTMLDivElement>
156
- >(({ className, ...props }, ref) => {
157
- const { carouselRef, orientation } = useCarousel()
158
-
159
- return (
160
- <div ref={carouselRef} className="overflow-hidden">
161
- <div
162
- ref={ref}
163
- className={cn(
164
- "flex",
165
- orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
166
- className
167
- )}
168
- {...props}
169
- />
170
- </div>
171
- )
172
- })
173
- CarouselContent.displayName = "CarouselContent"
174
-
175
- const CarouselItem = React.forwardRef<
176
- HTMLDivElement,
177
- React.HTMLAttributes<HTMLDivElement>
178
- >(({ className, ...props }, ref) => {
179
- const { orientation } = useCarousel()
180
-
181
- return (
182
- <div
183
- ref={ref}
184
- role="group"
185
- aria-roledescription="slide"
186
- className={cn(
187
- "min-w-0 shrink-0 grow-0 basis-full",
188
- orientation === "horizontal" ? "pl-4" : "pt-4",
189
- className
190
- )}
191
- {...props}
192
- />
193
- )
194
- })
195
- CarouselItem.displayName = "CarouselItem"
196
-
197
- const CarouselPrevious = React.forwardRef<
198
- HTMLButtonElement,
199
- React.ComponentProps<typeof Button>
200
- >(({ className, variant = "outline", size = "icon", ...props }, ref) => {
201
- const { orientation, scrollPrev, canScrollPrev } = useCarousel()
202
-
203
- return (
204
- <Button
205
- ref={ref}
206
- variant={variant}
207
- size={size}
208
- className={cn(
209
- "absolute h-8 w-8 rounded-full",
210
- orientation === "horizontal"
211
- ? "-left-12 top-1/2 -translate-y-1/2"
212
- : "-top-12 left-1/2 -translate-x-1/2 rotate-90",
213
- className
214
- )}
215
- disabled={!canScrollPrev}
216
- onClick={scrollPrev}
217
- {...props}
218
- >
219
- <icons.ArrowLeft className="h-4 w-4" />
220
- <span className="sr-only">Previous slide</span>
221
- </Button>
222
- )
223
- })
224
- CarouselPrevious.displayName = "CarouselPrevious"
225
-
226
- const CarouselNext = React.forwardRef<
227
- HTMLButtonElement,
228
- React.ComponentProps<typeof Button>
229
- >(({ className, variant = "outline", size = "icon", ...props }, ref) => {
230
- const { orientation, scrollNext, canScrollNext } = useCarousel()
231
-
232
- return (
233
- <Button
234
- ref={ref}
235
- variant={variant}
236
- size={size}
237
- className={cn(
238
- "absolute h-8 w-8 rounded-full",
239
- orientation === "horizontal"
240
- ? "-right-12 top-1/2 -translate-y-1/2"
241
- : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
242
- className
243
- )}
244
- disabled={!canScrollNext}
245
- onClick={scrollNext}
246
- {...props}
247
- >
248
- <icons.ArrowRight className="h-4 w-4" />
249
- <span className="sr-only">Next slide</span>
250
- </Button>
251
- )
252
- })
253
- CarouselNext.displayName = "CarouselNext"
254
-
255
- export {
256
- type CarouselApi,
257
- Carousel,
258
- CarouselContent,
259
- CarouselItem,
260
- CarouselPrevious,
261
- CarouselNext,
262
- }
package/src/ui/chart.tsx DELETED
@@ -1,365 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import * as RechartsPrimitive from "recharts"
5
-
6
- import { cn } from "@lib/utils"
7
-
8
- // Format: { THEME_NAME: CSS_SELECTOR }
9
- const THEMES = { light: "", dark: ".dark" } as const
10
-
11
- export type ChartConfig = {
12
- [k in string]: {
13
- label?: React.ReactNode
14
- icon?: React.ComponentType
15
- } & (
16
- | { color?: string; theme?: never }
17
- | { color?: never; theme: Record<keyof typeof THEMES, string> }
18
- )
19
- }
20
-
21
- type ChartContextProps = {
22
- config: ChartConfig
23
- }
24
-
25
- const ChartContext = React.createContext<ChartContextProps | null>(null)
26
-
27
- function useChart() {
28
- const context = React.useContext(ChartContext)
29
-
30
- if (!context) {
31
- throw new Error("useChart must be used within a <ChartContainer />")
32
- }
33
-
34
- return context
35
- }
36
-
37
- const ChartContainer = React.forwardRef<
38
- HTMLDivElement,
39
- React.ComponentProps<"div"> & {
40
- config: ChartConfig
41
- children: React.ComponentProps<
42
- typeof RechartsPrimitive.ResponsiveContainer
43
- >["children"]
44
- }
45
- >(({ id, className, children, config, ...props }, ref) => {
46
- const uniqueId = React.useId()
47
- const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`
48
-
49
- return (
50
- <ChartContext.Provider value={{ config }}>
51
- <div
52
- data-chart={chartId}
53
- ref={ref}
54
- className={cn(
55
- "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[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-hidden [&_.recharts-surface]:outline-hidden",
56
- className
57
- )}
58
- {...props}
59
- >
60
- <ChartStyle id={chartId} config={config} />
61
- <RechartsPrimitive.ResponsiveContainer>
62
- {children}
63
- </RechartsPrimitive.ResponsiveContainer>
64
- </div>
65
- </ChartContext.Provider>
66
- )
67
- })
68
- ChartContainer.displayName = "Chart"
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
- <style
81
- dangerouslySetInnerHTML={{
82
- __html: Object.entries(THEMES)
83
- .map(
84
- ([theme, prefix]) => `
85
- ${prefix} [data-chart=${id}] {
86
- ${colorConfig
87
- .map(([key, itemConfig]) => {
88
- const color =
89
- itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||
90
- itemConfig.color
91
- return color ? ` --color-${key}: ${color};` : null
92
- })
93
- .join("\n")}
94
- }
95
- `
96
- )
97
- .join("\n"),
98
- }}
99
- />
100
- )
101
- }
102
-
103
- const ChartTooltip = RechartsPrimitive.Tooltip
104
-
105
- const ChartTooltipContent = React.forwardRef<
106
- HTMLDivElement,
107
- React.ComponentProps<typeof RechartsPrimitive.Tooltip> &
108
- React.ComponentProps<"div"> & {
109
- hideLabel?: boolean
110
- hideIndicator?: boolean
111
- indicator?: "line" | "dot" | "dashed"
112
- nameKey?: string
113
- labelKey?: string
114
- }
115
- >(
116
- (
117
- {
118
- active,
119
- payload,
120
- className,
121
- indicator = "dot",
122
- hideLabel = false,
123
- hideIndicator = false,
124
- label,
125
- labelFormatter,
126
- labelClassName,
127
- formatter,
128
- color,
129
- nameKey,
130
- labelKey,
131
- },
132
- ref
133
- ) => {
134
- const { config } = useChart()
135
-
136
- const tooltipLabel = React.useMemo(() => {
137
- if (hideLabel || !payload?.length) {
138
- return null
139
- }
140
-
141
- const [item] = payload
142
- const key = `${labelKey || item.dataKey || item.name || "value"}`
143
- const itemConfig = getPayloadConfigFromPayload(config, item, key)
144
- const value =
145
- !labelKey && typeof label === "string"
146
- ? config[label as keyof typeof config]?.label || label
147
- : itemConfig?.label
148
-
149
- if (labelFormatter) {
150
- return (
151
- <div className={cn("font-medium", labelClassName)}>
152
- {labelFormatter(value, payload)}
153
- </div>
154
- )
155
- }
156
-
157
- if (!value) {
158
- return null
159
- }
160
-
161
- return <div className={cn("font-medium", labelClassName)}>{value}</div>
162
- }, [
163
- label,
164
- labelFormatter,
165
- payload,
166
- hideLabel,
167
- labelClassName,
168
- config,
169
- labelKey,
170
- ])
171
-
172
- if (!active || !payload?.length) {
173
- return null
174
- }
175
-
176
- const nestLabel = payload.length === 1 && indicator !== "dot"
177
-
178
- return (
179
- <div
180
- ref={ref}
181
- className={cn(
182
- "grid min-w-[8rem] items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl",
183
- className
184
- )}
185
- >
186
- {!nestLabel ? tooltipLabel : null}
187
- <div className="grid gap-1.5">
188
- {payload.map((item, index) => {
189
- const key = `${nameKey || item.name || item.dataKey || "value"}`
190
- const itemConfig = getPayloadConfigFromPayload(config, item, key)
191
- const indicatorColor = color || item.payload.fill || item.color
192
-
193
- return (
194
- <div
195
- key={item.dataKey}
196
- className={cn(
197
- "flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground",
198
- indicator === "dot" && "items-center"
199
- )}
200
- >
201
- {formatter && item?.value !== undefined && item.name ? (
202
- formatter(item.value, item.name, item, index, item.payload)
203
- ) : (
204
- <>
205
- {itemConfig?.icon ? (
206
- <itemConfig.icon />
207
- ) : (
208
- !hideIndicator && (
209
- <div
210
- className={cn(
211
- "shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)",
212
- {
213
- "h-2.5 w-2.5": indicator === "dot",
214
- "w-1": indicator === "line",
215
- "w-0 border-[1.5px] border-dashed bg-transparent":
216
- indicator === "dashed",
217
- "my-0.5": nestLabel && indicator === "dashed",
218
- }
219
- )}
220
- style={
221
- {
222
- "--color-bg": indicatorColor,
223
- "--color-border": indicatorColor,
224
- } as React.CSSProperties
225
- }
226
- />
227
- )
228
- )}
229
- <div
230
- className={cn(
231
- "flex flex-1 justify-between leading-none",
232
- nestLabel ? "items-end" : "items-center"
233
- )}
234
- >
235
- <div className="grid gap-1.5">
236
- {nestLabel ? tooltipLabel : null}
237
- <span className="text-muted-foreground">
238
- {itemConfig?.label || item.name}
239
- </span>
240
- </div>
241
- {item.value && (
242
- <span className="font-mono font-medium tabular-nums text-foreground">
243
- {item.value.toLocaleString()}
244
- </span>
245
- )}
246
- </div>
247
- </>
248
- )}
249
- </div>
250
- )
251
- })}
252
- </div>
253
- </div>
254
- )
255
- }
256
- )
257
- ChartTooltipContent.displayName = "ChartTooltip"
258
-
259
- const ChartLegend = RechartsPrimitive.Legend
260
-
261
- const ChartLegendContent = React.forwardRef<
262
- HTMLDivElement,
263
- React.ComponentProps<"div"> &
264
- Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & {
265
- hideIcon?: boolean
266
- nameKey?: string
267
- }
268
- >(
269
- (
270
- { className, hideIcon = false, payload, verticalAlign = "bottom", nameKey },
271
- ref
272
- ) => {
273
- const { config } = useChart()
274
-
275
- if (!payload?.length) {
276
- return null
277
- }
278
-
279
- return (
280
- <div
281
- ref={ref}
282
- className={cn(
283
- "flex items-center justify-center gap-4",
284
- verticalAlign === "top" ? "pb-3" : "pt-3",
285
- className
286
- )}
287
- >
288
- {payload.map((item) => {
289
- const key = `${nameKey || item.dataKey || "value"}`
290
- const itemConfig = getPayloadConfigFromPayload(config, item, key)
291
-
292
- return (
293
- <div
294
- key={item.value}
295
- className={cn(
296
- "flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground"
297
- )}
298
- >
299
- {itemConfig?.icon && !hideIcon ? (
300
- <itemConfig.icon />
301
- ) : (
302
- <div
303
- className="h-2 w-2 shrink-0 rounded-[2px]"
304
- style={{
305
- backgroundColor: item.color,
306
- }}
307
- />
308
- )}
309
- {itemConfig?.label}
310
- </div>
311
- )
312
- })}
313
- </div>
314
- )
315
- }
316
- )
317
- ChartLegendContent.displayName = "ChartLegend"
318
-
319
- // Helper to extract item config from a payload.
320
- function getPayloadConfigFromPayload(
321
- config: ChartConfig,
322
- payload: unknown,
323
- key: string
324
- ) {
325
- if (typeof payload !== "object" || payload === null) {
326
- return undefined
327
- }
328
-
329
- const payloadPayload =
330
- "payload" in payload &&
331
- typeof payload.payload === "object" &&
332
- payload.payload !== null
333
- ? payload.payload
334
- : undefined
335
-
336
- let configLabelKey: string = key
337
-
338
- if (
339
- key in payload &&
340
- typeof payload[key as keyof typeof payload] === "string"
341
- ) {
342
- configLabelKey = payload[key as keyof typeof payload] as string
343
- } else if (
344
- payloadPayload &&
345
- key in payloadPayload &&
346
- typeof payloadPayload[key as keyof typeof payloadPayload] === "string"
347
- ) {
348
- configLabelKey = payloadPayload[
349
- key as keyof typeof payloadPayload
350
- ] as string
351
- }
352
-
353
- return configLabelKey in config
354
- ? config[configLabelKey]
355
- : config[key as keyof typeof config]
356
- }
357
-
358
- export {
359
- ChartContainer,
360
- ChartTooltip,
361
- ChartTooltipContent,
362
- ChartLegend,
363
- ChartLegendContent,
364
- ChartStyle,
365
- }