@gentleduck/registry-ui 0.2.5 → 0.2.8
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/.turbo/turbo-check-types.log +1 -0
- package/.turbo/turbo-test.log +23 -0
- package/CHANGELOG.md +21 -0
- package/package.json +9 -8
- package/src/_old/_table/index.ts +9 -0
- package/src/_old/_table/table.tsx +7 -7
- package/src/_old/_upload/index.ts +13 -0
- package/src/_old/_upload/upload-sonner.tsx +1 -1
- package/src/alert-dialog/alert-dialog.tsx +11 -4
- package/src/aspect-ratio/aspect-ratio.tsx +9 -11
- package/src/audio/audio-visualizer.tsx +28 -2
- package/src/audio/audio.types.ts +1 -2
- package/src/button/__test__/button.test.tsx +80 -0
- package/src/button/button.tsx +1 -1
- package/src/button-group/button-group.tsx +1 -0
- package/src/calendar/calendar.tsx +161 -141
- package/src/carousel/carousel.tsx +1 -0
- package/src/chart/__test__/chart.test.tsx +40 -0
- package/src/chart/chart.tsx +16 -7
- package/src/checkbox/checkbox.tsx +1 -0
- package/src/collapsible/collapsible.tsx +2 -1
- package/src/combobox/combobox.tsx +96 -69
- package/src/command/command.tsx +34 -37
- package/src/context-menu/context-menu.tsx +11 -3
- package/src/dialog/dialog-responsive.tsx +12 -1
- package/src/dialog/dialog.tsx +12 -4
- package/src/dropdown-menu/dropdown-menu.tsx +11 -3
- package/src/empty/empty.tsx +30 -17
- package/src/field/field.tsx +138 -109
- package/src/input-group/input-group.tsx +3 -0
- package/src/item/item.tsx +1 -0
- package/src/json-editor/json-editor.tsx +59 -60
- package/src/json-editor/json-editor.view.tsx +1 -0
- package/src/label/label.tsx +1 -0
- package/src/menubar/menubar.tsx +10 -3
- package/src/popover/popover.tsx +4 -0
- package/src/preview-panel/preview-panel-dialog.tsx +86 -80
- package/src/preview-panel/preview-panel.tsx +280 -273
- package/src/resizable/resizable.tsx +17 -15
- package/src/select/select.tsx +3 -0
- package/src/separator/separator.tsx +0 -1
- package/src/sheet/sheet.tsx +16 -4
- package/src/sidebar/sidebar.tsx +436 -378
- package/src/slider/slider.tsx +8 -10
- package/src/sonner/sonner.chunks.tsx +3 -0
- package/src/sonner/sonner.tsx +23 -20
- package/src/switch/switch.tsx +1 -0
- package/src/tabs/tabs.tsx +2 -2
- package/src/toggle/toggle.constants.ts +2 -2
- package/src/tooltip/tooltip.tsx +3 -0
- package/tsconfig.json +10 -1
|
@@ -7,154 +7,174 @@ import * as React from 'react'
|
|
|
7
7
|
import { type DayButton, DayPicker, getDefaultClassNames } from 'react-day-picker'
|
|
8
8
|
import { Button, buttonVariants } from '../button'
|
|
9
9
|
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
buttonVariant?: React.ComponentProps<typeof Button>['variant']
|
|
22
|
-
}) {
|
|
23
|
-
const direction = useDirection(dir as Direction)
|
|
24
|
-
const defaultClassNames = getDefaultClassNames()
|
|
25
|
-
const localeTag = React.useMemo(() => {
|
|
26
|
-
const code = props.locale?.code
|
|
27
|
-
if (!code) return undefined
|
|
28
|
-
return code.startsWith('ar') ? `${code}-u-nu-arab` : code
|
|
29
|
-
}, [props.locale])
|
|
10
|
+
function mergeRefs<T>(...refs: (React.Ref<T> | undefined)[]): React.RefCallback<T> {
|
|
11
|
+
return (node) => {
|
|
12
|
+
for (const ref of refs) {
|
|
13
|
+
if (typeof ref === 'function') {
|
|
14
|
+
ref(node)
|
|
15
|
+
} else if (ref != null) {
|
|
16
|
+
;(ref as React.MutableRefObject<T | null>).current = node
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
30
21
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
22
|
+
const Calendar = React.forwardRef<
|
|
23
|
+
HTMLDivElement,
|
|
24
|
+
React.ComponentProps<typeof DayPicker> & {
|
|
25
|
+
buttonVariant?: React.ComponentProps<typeof Button>['variant']
|
|
26
|
+
}
|
|
27
|
+
>(
|
|
28
|
+
(
|
|
29
|
+
{
|
|
30
|
+
className,
|
|
31
|
+
classNames,
|
|
32
|
+
showOutsideDays = true,
|
|
33
|
+
captionLayout = 'label',
|
|
34
|
+
buttonVariant = 'ghost',
|
|
35
|
+
formatters,
|
|
36
|
+
components,
|
|
37
|
+
dir,
|
|
38
|
+
...props
|
|
39
|
+
},
|
|
40
|
+
ref,
|
|
41
|
+
) => {
|
|
42
|
+
const direction = useDirection(dir as Direction)
|
|
43
|
+
const defaultClassNames = getDefaultClassNames()
|
|
44
|
+
const localeTag = React.useMemo(() => {
|
|
45
|
+
const code = props.locale?.code
|
|
46
|
+
if (!code) return undefined
|
|
47
|
+
return code.startsWith('ar') ? `${code}-u-nu-arab` : code
|
|
48
|
+
}, [props.locale])
|
|
34
49
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
50
|
+
const monthFormatter = React.useMemo(() => {
|
|
51
|
+
return new Intl.DateTimeFormat(localeTag, { month: 'short' })
|
|
52
|
+
}, [localeTag])
|
|
38
53
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
54
|
+
const captionFormatter = React.useMemo(() => {
|
|
55
|
+
return new Intl.DateTimeFormat(localeTag, { month: 'long', year: 'numeric' })
|
|
56
|
+
}, [localeTag])
|
|
42
57
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
},
|
|
47
|
-
[numberFormatter],
|
|
48
|
-
)
|
|
58
|
+
const numberFormatter = React.useMemo(() => {
|
|
59
|
+
return new Intl.NumberFormat(localeTag)
|
|
60
|
+
}, [localeTag])
|
|
49
61
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
|
|
57
|
-
String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
|
|
58
|
-
className,
|
|
59
|
-
)}
|
|
60
|
-
classNames={{
|
|
61
|
-
button_next: cn(
|
|
62
|
-
buttonVariants({ variant: buttonVariant }),
|
|
63
|
-
'size-(--cell-size) select-none p-0 aria-disabled:opacity-50',
|
|
64
|
-
defaultClassNames.button_next,
|
|
65
|
-
),
|
|
66
|
-
button_previous: cn(
|
|
67
|
-
buttonVariants({ variant: buttonVariant }),
|
|
68
|
-
'size-(--cell-size) select-none p-0 aria-disabled:opacity-50',
|
|
69
|
-
defaultClassNames.button_previous,
|
|
70
|
-
),
|
|
71
|
-
caption_label: cn(
|
|
72
|
-
'select-none font-medium',
|
|
73
|
-
captionLayout === 'label'
|
|
74
|
-
? 'text-sm'
|
|
75
|
-
: 'flex h-8 items-center gap-1 rounded-md ps-2 pe-1 text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground',
|
|
76
|
-
defaultClassNames.caption_label,
|
|
77
|
-
),
|
|
78
|
-
day: cn(
|
|
79
|
-
'group/day relative aspect-square h-full w-full select-none p-0 text-center [&:first-child[data-selected=true]_button]:rounded-s-md [&:last-child[data-selected=true]_button]:rounded-e-md',
|
|
80
|
-
defaultClassNames.day,
|
|
81
|
-
),
|
|
82
|
-
disabled: cn('text-muted-foreground opacity-50', defaultClassNames.disabled),
|
|
83
|
-
dropdown: cn('absolute inset-0 bg-popover opacity-0', defaultClassNames.dropdown),
|
|
84
|
-
dropdown_root: cn(
|
|
85
|
-
'relative rounded-md border border-input shadow-xs has-focus:border-ring has-focus:ring-[3px] has-focus:ring-ring/50',
|
|
86
|
-
defaultClassNames.dropdown_root,
|
|
87
|
-
),
|
|
88
|
-
dropdowns: cn(
|
|
89
|
-
'flex h-(--cell-size) w-full items-center justify-center gap-1.5 font-medium text-sm',
|
|
90
|
-
defaultClassNames.dropdowns,
|
|
91
|
-
),
|
|
92
|
-
hidden: cn('invisible', defaultClassNames.hidden),
|
|
93
|
-
month: cn('flex w-full flex-col gap-4', defaultClassNames.month),
|
|
94
|
-
month_caption: cn(
|
|
95
|
-
'flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)',
|
|
96
|
-
defaultClassNames.month_caption,
|
|
97
|
-
),
|
|
98
|
-
months: cn('relative flex flex-col gap-4 md:flex-row', defaultClassNames.months),
|
|
99
|
-
nav: cn('absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1', defaultClassNames.nav),
|
|
100
|
-
outside: cn('text-muted-foreground aria-selected:text-muted-foreground', defaultClassNames.outside),
|
|
101
|
-
range_end: cn('rounded-e-md bg-accent', defaultClassNames.range_end),
|
|
102
|
-
range_middle: cn('rounded-none', defaultClassNames.range_middle),
|
|
103
|
-
range_start: cn('rounded-s-md bg-accent', defaultClassNames.range_start),
|
|
104
|
-
root: cn('w-fit', defaultClassNames.root),
|
|
105
|
-
table: 'w-full border-collapse',
|
|
106
|
-
today: cn(
|
|
107
|
-
'rounded-md bg-accent text-accent-foreground data-[selected=true]:rounded-none',
|
|
108
|
-
defaultClassNames.today,
|
|
109
|
-
),
|
|
110
|
-
week: cn('mt-2 flex w-full', defaultClassNames.week),
|
|
111
|
-
week_number: cn('select-none text-[0.8rem] text-muted-foreground', defaultClassNames.week_number),
|
|
112
|
-
week_number_header: cn('w-(--cell-size) select-none', defaultClassNames.week_number_header),
|
|
113
|
-
weekday: cn(
|
|
114
|
-
'flex-1 select-none rounded-md font-normal text-[0.8rem] text-muted-foreground',
|
|
115
|
-
defaultClassNames.weekday,
|
|
116
|
-
),
|
|
117
|
-
weekdays: cn('flex', defaultClassNames.weekdays),
|
|
118
|
-
...classNames,
|
|
119
|
-
}}
|
|
120
|
-
components={{
|
|
121
|
-
Chevron: ({ className, orientation, ...props }) => {
|
|
122
|
-
if (orientation === 'left') {
|
|
123
|
-
return <ChevronLeftIcon className={cn('size-4', className)} {...props} />
|
|
124
|
-
}
|
|
62
|
+
const formatLocalizedNumber = React.useCallback(
|
|
63
|
+
(value: number) => {
|
|
64
|
+
return numberFormatter.format(value)
|
|
65
|
+
},
|
|
66
|
+
[numberFormatter],
|
|
67
|
+
)
|
|
125
68
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
69
|
+
return (
|
|
70
|
+
<DayPicker
|
|
71
|
+
dir={direction}
|
|
72
|
+
captionLayout={captionLayout}
|
|
73
|
+
className={cn(
|
|
74
|
+
'group/calendar bg-background in-data-[slot=card-content]:bg-transparent in-data-[slot=popover-content]:bg-transparent p-3 [--cell-size:--spacing(8)]',
|
|
75
|
+
String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
|
|
76
|
+
String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
|
|
77
|
+
className,
|
|
78
|
+
)}
|
|
79
|
+
classNames={{
|
|
80
|
+
button_next: cn(
|
|
81
|
+
buttonVariants({ variant: buttonVariant }),
|
|
82
|
+
'size-(--cell-size) select-none p-0 aria-disabled:opacity-50',
|
|
83
|
+
defaultClassNames.button_next,
|
|
84
|
+
),
|
|
85
|
+
button_previous: cn(
|
|
86
|
+
buttonVariants({ variant: buttonVariant }),
|
|
87
|
+
'size-(--cell-size) select-none p-0 aria-disabled:opacity-50',
|
|
88
|
+
defaultClassNames.button_previous,
|
|
89
|
+
),
|
|
90
|
+
caption_label: cn(
|
|
91
|
+
'select-none font-medium',
|
|
92
|
+
captionLayout === 'label'
|
|
93
|
+
? 'text-sm'
|
|
94
|
+
: 'flex h-8 items-center gap-1 rounded-md ps-2 pe-1 text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground',
|
|
95
|
+
defaultClassNames.caption_label,
|
|
96
|
+
),
|
|
97
|
+
day: cn(
|
|
98
|
+
'group/day relative aspect-square h-full w-full select-none p-0 text-center [&:first-child[data-selected=true]_button]:rounded-s-md [&:last-child[data-selected=true]_button]:rounded-e-md',
|
|
99
|
+
defaultClassNames.day,
|
|
100
|
+
),
|
|
101
|
+
disabled: cn('text-muted-foreground opacity-50', defaultClassNames.disabled),
|
|
102
|
+
dropdown: cn('absolute inset-0 bg-popover opacity-0', defaultClassNames.dropdown),
|
|
103
|
+
dropdown_root: cn(
|
|
104
|
+
'relative rounded-md border border-input shadow-xs has-focus:border-ring has-focus:ring-[3px] has-focus:ring-ring/50',
|
|
105
|
+
defaultClassNames.dropdown_root,
|
|
106
|
+
),
|
|
107
|
+
dropdowns: cn(
|
|
108
|
+
'flex h-(--cell-size) w-full items-center justify-center gap-1.5 font-medium text-sm',
|
|
109
|
+
defaultClassNames.dropdowns,
|
|
110
|
+
),
|
|
111
|
+
hidden: cn('invisible', defaultClassNames.hidden),
|
|
112
|
+
month: cn('flex w-full flex-col gap-4', defaultClassNames.month),
|
|
113
|
+
month_caption: cn(
|
|
114
|
+
'flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)',
|
|
115
|
+
defaultClassNames.month_caption,
|
|
116
|
+
),
|
|
117
|
+
months: cn('relative flex flex-col gap-4 md:flex-row', defaultClassNames.months),
|
|
118
|
+
nav: cn('absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1', defaultClassNames.nav),
|
|
119
|
+
outside: cn('text-muted-foreground aria-selected:text-muted-foreground', defaultClassNames.outside),
|
|
120
|
+
range_end: cn('rounded-e-md bg-accent', defaultClassNames.range_end),
|
|
121
|
+
range_middle: cn('rounded-none', defaultClassNames.range_middle),
|
|
122
|
+
range_start: cn('rounded-s-md bg-accent', defaultClassNames.range_start),
|
|
123
|
+
root: cn('w-fit', defaultClassNames.root),
|
|
124
|
+
table: 'w-full border-collapse',
|
|
125
|
+
today: cn(
|
|
126
|
+
'rounded-md bg-accent text-accent-foreground data-[selected=true]:rounded-none',
|
|
127
|
+
defaultClassNames.today,
|
|
128
|
+
),
|
|
129
|
+
week: cn('mt-2 flex w-full', defaultClassNames.week),
|
|
130
|
+
week_number: cn('select-none text-[0.8rem] text-muted-foreground', defaultClassNames.week_number),
|
|
131
|
+
week_number_header: cn('w-(--cell-size) select-none', defaultClassNames.week_number_header),
|
|
132
|
+
weekday: cn(
|
|
133
|
+
'flex-1 select-none rounded-md font-normal text-[0.8rem] text-muted-foreground',
|
|
134
|
+
defaultClassNames.weekday,
|
|
135
|
+
),
|
|
136
|
+
weekdays: cn('flex', defaultClassNames.weekdays),
|
|
137
|
+
...classNames,
|
|
138
|
+
}}
|
|
139
|
+
components={{
|
|
140
|
+
Chevron: ({ className, orientation, ...props }) => {
|
|
141
|
+
if (orientation === 'left') {
|
|
142
|
+
return <ChevronLeftIcon className={cn('size-4', className)} {...props} />
|
|
143
|
+
}
|
|
129
144
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
<
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
145
|
+
if (orientation === 'right') {
|
|
146
|
+
return <ChevronRightIcon className={cn('size-4', className)} {...props} />
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return <ChevronDownIcon className={cn('size-4', className)} {...props} />
|
|
150
|
+
},
|
|
151
|
+
DayButton: CalendarDayButton,
|
|
152
|
+
Root: ({ className, rootRef, ...props }) => {
|
|
153
|
+
return <div className={cn(className)} data-slot="calendar" ref={mergeRefs(ref, rootRef)} {...props} />
|
|
154
|
+
},
|
|
155
|
+
WeekNumber: ({ children, ...props }) => {
|
|
156
|
+
return (
|
|
157
|
+
<td {...props}>
|
|
158
|
+
<div className="flex size-(--cell-size) items-center justify-center text-center">{children}</div>
|
|
159
|
+
</td>
|
|
160
|
+
)
|
|
161
|
+
},
|
|
162
|
+
...components,
|
|
163
|
+
}}
|
|
164
|
+
formatters={{
|
|
165
|
+
formatCaption: (date) => captionFormatter.format(date),
|
|
166
|
+
formatDay: (date) => formatLocalizedNumber(date.getDate()),
|
|
167
|
+
formatMonthDropdown: (date) => monthFormatter.format(date),
|
|
168
|
+
formatWeekNumber: (weekNumber) => formatLocalizedNumber(weekNumber),
|
|
169
|
+
formatYearDropdown: (date) => String(date.getFullYear()),
|
|
170
|
+
...formatters,
|
|
171
|
+
}}
|
|
172
|
+
showOutsideDays={showOutsideDays}
|
|
173
|
+
{...props}
|
|
174
|
+
/>
|
|
175
|
+
)
|
|
176
|
+
},
|
|
177
|
+
)
|
|
158
178
|
Calendar.displayName = 'Calendar'
|
|
159
179
|
|
|
160
180
|
function CalendarDayButton({ className, day, modifiers, ...props }: React.ComponentProps<typeof DayButton>) {
|
|
@@ -100,6 +100,7 @@ const Carousel = React.forwardRef<HTMLElement, React.HTMLAttributes<HTMLDivEleme
|
|
|
100
100
|
scrollNext,
|
|
101
101
|
scrollPrev,
|
|
102
102
|
}}>
|
|
103
|
+
{/* biome-ignore lint/a11y/useAriaPropsSupportedByRole: carousel is a custom widget needing roledescription */}
|
|
103
104
|
<section
|
|
104
105
|
aria-roledescription="carousel"
|
|
105
106
|
className={cn('relative', className)}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test'
|
|
2
|
+
import * as React from 'react'
|
|
3
|
+
import { renderToStaticMarkup } from 'react-dom/server'
|
|
4
|
+
import { Bar, BarChart, XAxis } from 'recharts'
|
|
5
|
+
import { ChartContainer } from '../chart'
|
|
6
|
+
|
|
7
|
+
const data = [{ name: 'alpha', value: 12 }]
|
|
8
|
+
|
|
9
|
+
describe('registry-ui chart', () => {
|
|
10
|
+
test('ChartContainer server render does not emit invalid size warnings', () => {
|
|
11
|
+
const originalWarn = console.warn
|
|
12
|
+
const warnings: string[] = []
|
|
13
|
+
|
|
14
|
+
console.warn = (...args: unknown[]) => {
|
|
15
|
+
warnings.push(args.map((value) => String(value)).join(' '))
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
const html = renderToStaticMarkup(
|
|
20
|
+
<ChartContainer
|
|
21
|
+
config={{
|
|
22
|
+
value: {
|
|
23
|
+
color: 'hsl(var(--chart-1))',
|
|
24
|
+
label: 'Value',
|
|
25
|
+
},
|
|
26
|
+
}}>
|
|
27
|
+
<BarChart accessibilityLayer data={data}>
|
|
28
|
+
<XAxis dataKey="name" hide />
|
|
29
|
+
<Bar dataKey="value" fill="var(--color-value)" radius={8} />
|
|
30
|
+
</BarChart>
|
|
31
|
+
</ChartContainer>,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
expect(html).toContain('data-slot="chart-container"')
|
|
35
|
+
expect(warnings.some((message) => message.includes('The width(') && message.includes('height('))).toBe(false)
|
|
36
|
+
} finally {
|
|
37
|
+
console.warn = originalWarn
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
})
|
package/src/chart/chart.tsx
CHANGED
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
|
|
16
16
|
// Format: { THEME_NAME: CSS_SELECTOR }
|
|
17
17
|
export const THEMES = { dark: '.dark', light: '' } as const
|
|
18
|
+
const DEFAULT_CHART_INITIAL_DIMENSION = { width: 640, height: 360 } as const
|
|
18
19
|
|
|
19
20
|
const ChartContext = React.createContext<ChartContextProps | null>(null)
|
|
20
21
|
|
|
@@ -28,7 +29,7 @@ function useChart() {
|
|
|
28
29
|
return context
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
function ChartContainer({ id, className, children, config, ref, dir, ...props }: ChartContainerProps) {
|
|
32
33
|
const uniqueId = React.useId()
|
|
33
34
|
const chartId = `chart-${id || uniqueId.replace(/:/g, '')}`
|
|
34
35
|
const direction = useDirection(dir as Direction)
|
|
@@ -46,13 +47,16 @@ const ChartContainer = ({ id, className, children, config, ref, dir, ...props }:
|
|
|
46
47
|
dir={direction}
|
|
47
48
|
ref={ref}>
|
|
48
49
|
<ChartStyle config={config} id={chartId} />
|
|
49
|
-
<RechartsPrimitive.ResponsiveContainer minWidth={0}>
|
|
50
|
+
<RechartsPrimitive.ResponsiveContainer initialDimension={DEFAULT_CHART_INITIAL_DIMENSION} minWidth={0}>
|
|
51
|
+
{children}
|
|
52
|
+
</RechartsPrimitive.ResponsiveContainer>
|
|
50
53
|
</div>
|
|
51
54
|
</ChartContext.Provider>
|
|
52
55
|
)
|
|
53
56
|
}
|
|
57
|
+
ChartContainer.displayName = 'ChartContainer'
|
|
54
58
|
|
|
55
|
-
|
|
59
|
+
function ChartStyle({ id, config }: ChartStyleProps) {
|
|
56
60
|
const colorConfig = Object.entries(config).filter(([_, config]) => config.theme || config.color)
|
|
57
61
|
|
|
58
62
|
if (!colorConfig.length) {
|
|
@@ -61,6 +65,7 @@ const ChartStyle = ({ id, config }: ChartStyleProps) => {
|
|
|
61
65
|
|
|
62
66
|
return (
|
|
63
67
|
<style
|
|
68
|
+
// biome-ignore lint/security/noDangerouslySetInnerHtml: controlled CSS injection for chart color themes
|
|
64
69
|
dangerouslySetInnerHTML={{
|
|
65
70
|
__html: Object.entries(THEMES)
|
|
66
71
|
.map(
|
|
@@ -80,10 +85,11 @@ ${colorConfig
|
|
|
80
85
|
/>
|
|
81
86
|
)
|
|
82
87
|
}
|
|
88
|
+
ChartStyle.displayName = 'ChartStyle'
|
|
83
89
|
|
|
84
90
|
const ChartTooltip = RechartsPrimitive.Tooltip
|
|
85
91
|
|
|
86
|
-
|
|
92
|
+
function ChartTooltipContent({
|
|
87
93
|
active,
|
|
88
94
|
payload,
|
|
89
95
|
className,
|
|
@@ -98,7 +104,7 @@ const ChartTooltipContent = ({
|
|
|
98
104
|
color,
|
|
99
105
|
nameKey,
|
|
100
106
|
labelKey,
|
|
101
|
-
}: ChartTooltipContentProps)
|
|
107
|
+
}: ChartTooltipContentProps) {
|
|
102
108
|
const { config } = useChart()
|
|
103
109
|
|
|
104
110
|
const tooltipLabel = React.useMemo(() => {
|
|
@@ -208,17 +214,19 @@ const ChartTooltipContent = ({
|
|
|
208
214
|
</div>
|
|
209
215
|
)
|
|
210
216
|
}
|
|
217
|
+
ChartTooltipContent.displayName = 'ChartTooltipContent'
|
|
211
218
|
|
|
212
219
|
const ChartLegend = RechartsPrimitive.Legend
|
|
220
|
+
ChartLegend.displayName = 'ChartLegend'
|
|
213
221
|
|
|
214
|
-
|
|
222
|
+
function ChartLegendContent({
|
|
215
223
|
className,
|
|
216
224
|
hideIcon = false,
|
|
217
225
|
payload,
|
|
218
226
|
verticalAlign = 'bottom',
|
|
219
227
|
ref,
|
|
220
228
|
nameKey,
|
|
221
|
-
}: ChartLegendContentProps)
|
|
229
|
+
}: ChartLegendContentProps) {
|
|
222
230
|
const { config } = useChart()
|
|
223
231
|
|
|
224
232
|
if (!payload?.length) {
|
|
@@ -256,5 +264,6 @@ const ChartLegendContent = ({
|
|
|
256
264
|
</div>
|
|
257
265
|
)
|
|
258
266
|
}
|
|
267
|
+
ChartLegendContent.displayName = 'ChartLegendContent'
|
|
259
268
|
|
|
260
269
|
export { ChartContainer, ChartTooltip, ChartTooltipContent, ChartLegend, ChartLegendContent, ChartStyle }
|
|
@@ -37,6 +37,7 @@ const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
|
|
|
37
37
|
onCheckedChange?.(next)
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: changeCheckedState is stable and defined in render scope
|
|
40
41
|
React.useEffect(() => {
|
|
41
42
|
if (ref && typeof ref !== 'function' && checked === 'indeterminate' && ref.current) {
|
|
42
43
|
ref.current.indeterminate = true
|
|
@@ -44,6 +44,7 @@ const Collapsible = React.forwardRef<
|
|
|
44
44
|
onOpenChange?.(state)
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: handleOpenChange and triggerRef are stable refs
|
|
47
48
|
React.useEffect(() => {
|
|
48
49
|
if (open) {
|
|
49
50
|
handleOpenChange(open)
|
|
@@ -56,7 +57,7 @@ const Collapsible = React.forwardRef<
|
|
|
56
57
|
|
|
57
58
|
triggerRef.current?.addEventListener('click', handleClick)
|
|
58
59
|
return () => triggerRef.current?.removeEventListener('click', handleClick)
|
|
59
|
-
}, [open])
|
|
60
|
+
}, [open, onOpenChange])
|
|
60
61
|
|
|
61
62
|
return (
|
|
62
63
|
<CollapsibleContext.Provider
|