@auto-engineer/generate-react-client 1.64.0 → 1.66.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +140 -0
- package/dist/starter/.storybook/main.ts +17 -22
- package/dist/starter/.storybook/manager-head.html +31 -31
- package/dist/starter/.storybook/manager.ts +133 -133
- package/dist/starter/.storybook/preview-head.html +12 -12
- package/dist/starter/.storybook/preview.tsx +79 -79
- package/dist/starter/biome.json +126 -0
- package/dist/starter/codegen.ts +11 -11
- package/dist/starter/components.json +27 -27
- package/dist/starter/package.json +86 -80
- package/dist/starter/public/mockServiceWorker.js +261 -261
- package/dist/starter/scripts/build-component-db.ts +17 -20
- package/dist/starter/src/App.tsx +15 -17
- package/dist/starter/src/components/ui/Accordion.stories.tsx +35 -35
- package/dist/starter/src/components/ui/Accordion.tsx +33 -33
- package/dist/starter/src/components/ui/Alert.stories.tsx +15 -15
- package/dist/starter/src/components/ui/Alert.tsx +32 -32
- package/dist/starter/src/components/ui/AlertDialog.stories.tsx +50 -50
- package/dist/starter/src/components/ui/AlertDialog.tsx +114 -115
- package/dist/starter/src/components/ui/AspectRatio.stories.tsx +20 -20
- package/dist/starter/src/components/ui/AspectRatio.tsx +1 -1
- package/dist/starter/src/components/ui/Avatar.stories.tsx +27 -27
- package/dist/starter/src/components/ui/Avatar.tsx +63 -63
- package/dist/starter/src/components/ui/Badge.stories.tsx +14 -14
- package/dist/starter/src/components/ui/Badge.tsx +27 -27
- package/dist/starter/src/components/ui/Breadcrumb.stories.tsx +38 -38
- package/dist/starter/src/components/ui/Breadcrumb.tsx +63 -62
- package/dist/starter/src/components/ui/Button.stories.tsx +55 -55
- package/dist/starter/src/components/ui/Button.tsx +49 -49
- package/dist/starter/src/components/ui/ButtonGroup.stories.tsx +17 -17
- package/dist/starter/src/components/ui/ButtonGroup.tsx +52 -53
- package/dist/starter/src/components/ui/Calendar.stories.tsx +20 -19
- package/dist/starter/src/components/ui/Calendar.tsx +142 -143
- package/dist/starter/src/components/ui/Card.stories.tsx +29 -29
- package/dist/starter/src/components/ui/Card.tsx +31 -31
- package/dist/starter/src/components/ui/Carousel.stories.tsx +41 -41
- package/dist/starter/src/components/ui/Carousel.tsx +171 -172
- package/dist/starter/src/components/ui/Chart.stories.tsx +21 -21
- package/dist/starter/src/components/ui/Chart.tsx +244 -247
- package/dist/starter/src/components/ui/Checkbox.stories.tsx +11 -11
- package/dist/starter/src/components/ui/Checkbox.tsx +18 -18
- package/dist/starter/src/components/ui/Collapsible.stories.tsx +40 -40
- package/dist/starter/src/components/ui/Collapsible.tsx +3 -3
- package/dist/starter/src/components/ui/Combobox.stories.tsx +48 -48
- package/dist/starter/src/components/ui/Combobox.tsx +204 -205
- package/dist/starter/src/components/ui/Command.stories.tsx +55 -55
- package/dist/starter/src/components/ui/Command.tsx +102 -103
- package/dist/starter/src/components/ui/ContextMenu.stories.tsx +52 -52
- package/dist/starter/src/components/ui/ContextMenu.tsx +151 -151
- package/dist/starter/src/components/ui/DesignSystem-Colors.stories.tsx +92 -92
- package/dist/starter/src/components/ui/DesignSystem-Layout.stories.tsx +139 -139
- package/dist/starter/src/components/ui/DesignSystem-Overview.stories.tsx +676 -657
- package/dist/starter/src/components/ui/DesignSystem-Typography.stories.tsx +59 -59
- package/dist/starter/src/components/ui/Dialog.stories.tsx +56 -56
- package/dist/starter/src/components/ui/Dialog.tsx +97 -98
- package/dist/starter/src/components/ui/Direction.stories.tsx +20 -20
- package/dist/starter/src/components/ui/Direction.tsx +7 -7
- package/dist/starter/src/components/ui/Drawer.stories.tsx +54 -54
- package/dist/starter/src/components/ui/Drawer.tsx +70 -70
- package/dist/starter/src/components/ui/DropdownMenu.stories.tsx +58 -58
- package/dist/starter/src/components/ui/DropdownMenu.tsx +157 -157
- package/dist/starter/src/components/ui/Empty.stories.tsx +22 -22
- package/dist/starter/src/components/ui/Empty.tsx +58 -58
- package/dist/starter/src/components/ui/Field.stories.tsx +31 -31
- package/dist/starter/src/components/ui/Field.tsx +180 -181
- package/dist/starter/src/components/ui/Form.stories.tsx +29 -29
- package/dist/starter/src/components/ui/Form.tsx +93 -96
- package/dist/starter/src/components/ui/HoverCard.stories.tsx +34 -34
- package/dist/starter/src/components/ui/HoverCard.tsx +21 -21
- package/dist/starter/src/components/ui/Input.stories.tsx +18 -18
- package/dist/starter/src/components/ui/Input.tsx +14 -14
- package/dist/starter/src/components/ui/InputGroup.stories.tsx +34 -34
- package/dist/starter/src/components/ui/InputGroup.tsx +110 -111
- package/dist/starter/src/components/ui/InputOTP.stories.tsx +28 -28
- package/dist/starter/src/components/ui/InputOTP.tsx +43 -43
- package/dist/starter/src/components/ui/Item.stories.tsx +45 -45
- package/dist/starter/src/components/ui/Item.tsx +113 -114
- package/dist/starter/src/components/ui/Kbd.stories.tsx +31 -31
- package/dist/starter/src/components/ui/Kbd.tsx +11 -11
- package/dist/starter/src/components/ui/Label.stories.tsx +62 -62
- package/dist/starter/src/components/ui/Label.tsx +26 -25
- package/dist/starter/src/components/ui/Menubar.stories.tsx +62 -62
- package/dist/starter/src/components/ui/Menubar.tsx +173 -173
- package/dist/starter/src/components/ui/NativeSelect.stories.tsx +26 -26
- package/dist/starter/src/components/ui/NativeSelect.tsx +29 -29
- package/dist/starter/src/components/ui/NavigationMenu.stories.tsx +64 -64
- package/dist/starter/src/components/ui/NavigationMenu.tsx +103 -103
- package/dist/starter/src/components/ui/Pagination.stories.tsx +61 -61
- package/dist/starter/src/components/ui/Pagination.tsx +69 -71
- package/dist/starter/src/components/ui/Popover.stories.tsx +38 -38
- package/dist/starter/src/components/ui/Popover.tsx +25 -25
- package/dist/starter/src/components/ui/Progress.stories.tsx +9 -9
- package/dist/starter/src/components/ui/Progress.tsx +14 -14
- package/dist/starter/src/components/ui/RadioGroup.stories.tsx +35 -35
- package/dist/starter/src/components/ui/RadioGroup.tsx +19 -19
- package/dist/starter/src/components/ui/Resizable.stories.tsx +54 -54
- package/dist/starter/src/components/ui/Resizable.tsx +29 -29
- package/dist/starter/src/components/ui/ScrollArea.stories.tsx +27 -27
- package/dist/starter/src/components/ui/ScrollArea.tsx +34 -34
- package/dist/starter/src/components/ui/Select.stories.tsx +43 -43
- package/dist/starter/src/components/ui/Select.tsx +120 -120
- package/dist/starter/src/components/ui/Separator.stories.tsx +27 -27
- package/dist/starter/src/components/ui/Separator.tsx +17 -17
- package/dist/starter/src/components/ui/Sheet.stories.tsx +53 -53
- package/dist/starter/src/components/ui/Sheet.tsx +69 -69
- package/dist/starter/src/components/ui/Sidebar.stories.tsx +77 -77
- package/dist/starter/src/components/ui/Sidebar.tsx +563 -564
- package/dist/starter/src/components/ui/Skeleton.stories.tsx +25 -25
- package/dist/starter/src/components/ui/Skeleton.tsx +1 -1
- package/dist/starter/src/components/ui/Slider.stories.tsx +5 -5
- package/dist/starter/src/components/ui/Slider.tsx +45 -44
- package/dist/starter/src/components/ui/Sonner.stories.tsx +32 -32
- package/dist/starter/src/components/ui/Sonner.tsx +23 -23
- package/dist/starter/src/components/ui/Spinner.stories.tsx +8 -8
- package/dist/starter/src/components/ui/Spinner.tsx +1 -1
- package/dist/starter/src/components/ui/Switch.stories.tsx +16 -17
- package/dist/starter/src/components/ui/Switch.tsx +24 -24
- package/dist/starter/src/components/ui/Table.stories.tsx +50 -50
- package/dist/starter/src/components/ui/Table.tsx +45 -45
- package/dist/starter/src/components/ui/Tabs.stories.tsx +39 -39
- package/dist/starter/src/components/ui/Tabs.tsx +47 -47
- package/dist/starter/src/components/ui/Textarea.stories.tsx +9 -9
- package/dist/starter/src/components/ui/Textarea.tsx +11 -11
- package/dist/starter/src/components/ui/Toast.stories.tsx +77 -77
- package/dist/starter/src/components/ui/Toast.tsx +75 -75
- package/dist/starter/src/components/ui/Toaster.tsx +17 -19
- package/dist/starter/src/components/ui/Toggle.stories.tsx +20 -20
- package/dist/starter/src/components/ui/Toggle.tsx +26 -26
- package/dist/starter/src/components/ui/ToggleGroup.stories.tsx +41 -41
- package/dist/starter/src/components/ui/ToggleGroup.tsx +61 -62
- package/dist/starter/src/components/ui/Tooltip.stories.tsx +26 -26
- package/dist/starter/src/components/ui/Tooltip.tsx +24 -24
- package/dist/starter/src/gql/execute.ts +1 -1
- package/dist/starter/src/gql/fragment-masking.ts +1 -1
- package/dist/starter/src/gql/graphql.ts +3 -0
- package/dist/starter/src/hooks/use-mobile.ts +11 -11
- package/dist/starter/src/hooks/use-toast.ts +135 -135
- package/dist/starter/src/index.css +105 -105
- package/dist/starter/src/lib/utils.ts +1 -1
- package/dist/starter/src/main.tsx +4 -1
- package/dist/starter/tsconfig.app.json +24 -24
- package/dist/starter/tsconfig.json +8 -8
- package/dist/starter/vite.config.ts +38 -37
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
|
@@ -7,26 +7,26 @@ import { cn } from '@/lib/utils';
|
|
|
7
7
|
const THEMES = { light: '', dark: '.dark' } as const;
|
|
8
8
|
|
|
9
9
|
export type ChartConfig = {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
[k in string]: {
|
|
11
|
+
label?: React.ReactNode;
|
|
12
|
+
icon?: React.ComponentType;
|
|
13
|
+
} & ({ color?: string; theme?: never } | { color?: never; theme: Record<keyof typeof THEMES, string> });
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
type ChartContextProps = {
|
|
17
|
-
|
|
17
|
+
config: ChartConfig;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
const ChartContext = React.createContext<ChartContextProps | null>(null);
|
|
21
21
|
|
|
22
22
|
function useChart() {
|
|
23
|
-
|
|
23
|
+
const context = React.useContext(ChartContext);
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
if (!context) {
|
|
26
|
+
throw new Error('useChart must be used within a <ChartContainer />');
|
|
27
|
+
}
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
return context;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/**
|
|
@@ -34,63 +34,64 @@ function useChart() {
|
|
|
34
34
|
* Pass a `config` object mapping data keys to labels, colors, and optional icons.
|
|
35
35
|
*/
|
|
36
36
|
function ChartContainer({
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
id,
|
|
38
|
+
className,
|
|
39
|
+
children,
|
|
40
|
+
config,
|
|
41
|
+
...props
|
|
42
42
|
}: React.ComponentProps<'div'> & {
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
config: ChartConfig;
|
|
44
|
+
children: React.ComponentProps<typeof RechartsPrimitive.ResponsiveContainer>['children'];
|
|
45
45
|
}) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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-slot="chart"
|
|
53
|
+
data-chart={chartId}
|
|
54
|
+
className={cn(
|
|
55
|
+
"[&_.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",
|
|
56
|
+
className,
|
|
57
|
+
)}
|
|
58
|
+
{...props}
|
|
59
|
+
>
|
|
60
|
+
<ChartStyle id={chartId} config={config} />
|
|
61
|
+
<RechartsPrimitive.ResponsiveContainer>{children}</RechartsPrimitive.ResponsiveContainer>
|
|
62
|
+
</div>
|
|
63
|
+
</ChartContext.Provider>
|
|
64
|
+
);
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
68
|
+
const colorConfig = Object.entries(config).filter(([, config]) => config.theme || config.color);
|
|
69
|
+
|
|
70
|
+
if (!colorConfig.length) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<style
|
|
76
|
+
// biome-ignore lint/security/noDangerouslySetInnerHtml: Dynamic CSS for chart theme colors - content derived from config, not user input
|
|
77
|
+
dangerouslySetInnerHTML={{
|
|
78
|
+
__html: Object.entries(THEMES)
|
|
79
|
+
.map(
|
|
80
|
+
([theme, prefix]) => `
|
|
80
81
|
${prefix} [data-chart=${id}] {
|
|
81
82
|
${colorConfig
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
.map(([key, itemConfig]) => {
|
|
84
|
+
const color = itemConfig.theme?.[theme as keyof typeof itemConfig.theme] || itemConfig.color;
|
|
85
|
+
return color ? ` --color-${key}: ${color};` : null;
|
|
86
|
+
})
|
|
87
|
+
.join('\n')}
|
|
87
88
|
}
|
|
88
89
|
`,
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
90
|
+
)
|
|
91
|
+
.join('\n'),
|
|
92
|
+
}}
|
|
93
|
+
/>
|
|
94
|
+
);
|
|
94
95
|
};
|
|
95
96
|
|
|
96
97
|
const ChartTooltip = RechartsPrimitive.Tooltip;
|
|
@@ -100,206 +101,202 @@ const ChartTooltip = RechartsPrimitive.Tooltip;
|
|
|
100
101
|
* Supports dot, line, and dashed indicator styles.
|
|
101
102
|
*/
|
|
102
103
|
function ChartTooltipContent({
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
104
|
+
active,
|
|
105
|
+
payload,
|
|
106
|
+
className,
|
|
107
|
+
indicator = 'dot',
|
|
108
|
+
hideLabel = false,
|
|
109
|
+
hideIndicator = false,
|
|
110
|
+
label,
|
|
111
|
+
labelFormatter,
|
|
112
|
+
labelClassName,
|
|
113
|
+
formatter,
|
|
114
|
+
color,
|
|
115
|
+
nameKey,
|
|
116
|
+
labelKey,
|
|
116
117
|
}: React.ComponentProps<typeof RechartsPrimitive.Tooltip> &
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
118
|
+
React.ComponentProps<'div'> & {
|
|
119
|
+
hideLabel?: boolean;
|
|
120
|
+
hideIndicator?: boolean;
|
|
121
|
+
indicator?: 'line' | 'dot' | 'dashed';
|
|
122
|
+
nameKey?: string;
|
|
123
|
+
labelKey?: string;
|
|
124
|
+
}) {
|
|
125
|
+
const { config } = useChart();
|
|
126
|
+
|
|
127
|
+
const tooltipLabel = React.useMemo(() => {
|
|
128
|
+
if (hideLabel || !payload?.length) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const [item] = payload;
|
|
133
|
+
const key = `${labelKey || item?.dataKey || item?.name || 'value'}`;
|
|
134
|
+
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
135
|
+
const value =
|
|
136
|
+
!labelKey && typeof label === 'string' ? config[label as keyof typeof config]?.label || label : itemConfig?.label;
|
|
137
|
+
|
|
138
|
+
if (labelFormatter) {
|
|
139
|
+
return <div className={cn('font-medium', labelClassName)}>{labelFormatter(value, payload)}</div>;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (!value) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return <div className={cn('font-medium', labelClassName)}>{value}</div>;
|
|
147
|
+
}, [label, labelFormatter, payload, hideLabel, labelClassName, config, labelKey]);
|
|
148
|
+
|
|
149
|
+
if (!active || !payload?.length) {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const nestLabel = payload.length === 1 && indicator !== 'dot';
|
|
154
|
+
|
|
155
|
+
return (
|
|
156
|
+
<div
|
|
157
|
+
className={cn(
|
|
158
|
+
'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',
|
|
159
|
+
className,
|
|
160
|
+
)}
|
|
161
|
+
>
|
|
162
|
+
{!nestLabel ? tooltipLabel : null}
|
|
163
|
+
<div className="grid gap-1.5">
|
|
164
|
+
{payload
|
|
165
|
+
.filter((item) => item.type !== 'none')
|
|
166
|
+
.map((item, index) => {
|
|
167
|
+
const key = `${nameKey || item.name || item.dataKey || 'value'}`;
|
|
168
|
+
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
169
|
+
const indicatorColor = color || item.payload.fill || item.color;
|
|
170
|
+
|
|
171
|
+
return (
|
|
172
|
+
<div
|
|
173
|
+
key={item.dataKey}
|
|
174
|
+
className={cn(
|
|
175
|
+
'[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5',
|
|
176
|
+
indicator === 'dot' && 'items-center',
|
|
177
|
+
)}
|
|
178
|
+
>
|
|
179
|
+
{formatter && item?.value !== undefined && item.name ? (
|
|
180
|
+
formatter(item.value, item.name, item, index, item.payload)
|
|
181
|
+
) : (
|
|
182
|
+
<>
|
|
183
|
+
{itemConfig?.icon ? (
|
|
184
|
+
<itemConfig.icon />
|
|
185
|
+
) : (
|
|
186
|
+
!hideIndicator && (
|
|
187
|
+
<div
|
|
188
|
+
className={cn('shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)', {
|
|
189
|
+
'h-2.5 w-2.5': indicator === 'dot',
|
|
190
|
+
'w-1': indicator === 'line',
|
|
191
|
+
'w-0 border-[1.5px] border-dashed bg-transparent': indicator === 'dashed',
|
|
192
|
+
'my-0.5': nestLabel && indicator === 'dashed',
|
|
193
|
+
})}
|
|
194
|
+
style={
|
|
195
|
+
{
|
|
196
|
+
'--color-bg': indicatorColor,
|
|
197
|
+
'--color-border': indicatorColor,
|
|
198
|
+
} as React.CSSProperties
|
|
199
|
+
}
|
|
200
|
+
/>
|
|
201
|
+
)
|
|
202
|
+
)}
|
|
203
|
+
<div
|
|
204
|
+
className={cn(
|
|
205
|
+
'flex flex-1 justify-between leading-none',
|
|
206
|
+
nestLabel ? 'items-end' : 'items-center',
|
|
207
|
+
)}
|
|
208
|
+
>
|
|
209
|
+
<div className="grid gap-1.5">
|
|
210
|
+
{nestLabel ? tooltipLabel : null}
|
|
211
|
+
<span className="text-muted-foreground">{itemConfig?.label || item.name}</span>
|
|
212
|
+
</div>
|
|
213
|
+
{item.value && (
|
|
214
|
+
<span className="text-foreground font-mono font-medium tabular-nums">
|
|
215
|
+
{item.value.toLocaleString()}
|
|
216
|
+
</span>
|
|
217
|
+
)}
|
|
218
|
+
</div>
|
|
219
|
+
</>
|
|
220
|
+
)}
|
|
221
|
+
</div>
|
|
222
|
+
);
|
|
223
|
+
})}
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
);
|
|
226
227
|
}
|
|
227
228
|
|
|
228
229
|
const ChartLegend = RechartsPrimitive.Legend;
|
|
229
230
|
|
|
230
231
|
/** A styled legend content component for Recharts that reads labels, colors, and icons from ChartConfig. */
|
|
231
232
|
function ChartLegendContent({
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
233
|
+
className,
|
|
234
|
+
hideIcon = false,
|
|
235
|
+
payload,
|
|
236
|
+
verticalAlign = 'bottom',
|
|
237
|
+
nameKey,
|
|
237
238
|
}: React.ComponentProps<'div'> &
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
239
|
+
Pick<RechartsPrimitive.LegendProps, 'payload' | 'verticalAlign'> & {
|
|
240
|
+
hideIcon?: boolean;
|
|
241
|
+
nameKey?: string;
|
|
242
|
+
}) {
|
|
243
|
+
const { config } = useChart();
|
|
244
|
+
|
|
245
|
+
if (!payload?.length) {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return (
|
|
250
|
+
<div className={cn('flex items-center justify-center gap-4', verticalAlign === 'top' ? 'pb-3' : 'pt-3', className)}>
|
|
251
|
+
{payload
|
|
252
|
+
.filter((item) => item.type !== 'none')
|
|
253
|
+
.map((item) => {
|
|
254
|
+
const key = `${nameKey || item.dataKey || 'value'}`;
|
|
255
|
+
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
256
|
+
|
|
257
|
+
return (
|
|
258
|
+
<div
|
|
259
|
+
key={item.value}
|
|
260
|
+
className={cn('[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3')}
|
|
261
|
+
>
|
|
262
|
+
{itemConfig?.icon && !hideIcon ? (
|
|
263
|
+
<itemConfig.icon />
|
|
264
|
+
) : (
|
|
265
|
+
<div
|
|
266
|
+
className="h-2 w-2 shrink-0 rounded-[2px]"
|
|
267
|
+
style={{
|
|
268
|
+
backgroundColor: item.color,
|
|
269
|
+
}}
|
|
270
|
+
/>
|
|
271
|
+
)}
|
|
272
|
+
{itemConfig?.label}
|
|
273
|
+
</div>
|
|
274
|
+
);
|
|
275
|
+
})}
|
|
276
|
+
</div>
|
|
277
|
+
);
|
|
277
278
|
}
|
|
278
279
|
|
|
279
280
|
// Helper to extract item config from a payload.
|
|
280
|
-
function getPayloadConfigFromPayload(
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
configLabelKey = payloadPayload[key as keyof typeof payloadPayload] as string;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
return configLabelKey in config ? config[configLabelKey] : config[key as keyof typeof config];
|
|
281
|
+
function getPayloadConfigFromPayload(
|
|
282
|
+
config: ChartConfig,
|
|
283
|
+
payload: Record<string, string | number | Record<string, string>>,
|
|
284
|
+
key: string,
|
|
285
|
+
) {
|
|
286
|
+
const payloadPayload =
|
|
287
|
+
'payload' in payload && typeof payload.payload === 'object' && payload.payload !== null
|
|
288
|
+
? (payload.payload as Record<string, string>)
|
|
289
|
+
: undefined;
|
|
290
|
+
|
|
291
|
+
let configLabelKey: string = key;
|
|
292
|
+
|
|
293
|
+
if (key in payload && typeof payload[key] === 'string') {
|
|
294
|
+
configLabelKey = payload[key] as string;
|
|
295
|
+
} else if (payloadPayload && key in payloadPayload && typeof payloadPayload[key] === 'string') {
|
|
296
|
+
configLabelKey = payloadPayload[key] as string;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return configLabelKey in config ? config[configLabelKey] : config[key as keyof typeof config];
|
|
303
300
|
}
|
|
304
301
|
|
|
305
302
|
export { ChartContainer, ChartTooltip, ChartTooltipContent, ChartLegend, ChartLegendContent, ChartStyle };
|
|
@@ -3,33 +3,33 @@ import { Checkbox } from '@/components/ui/Checkbox';
|
|
|
3
3
|
import { Label } from '@/components/ui/Label';
|
|
4
4
|
|
|
5
5
|
const meta: Meta<typeof Checkbox> = {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
title: 'UI Components/Checkbox',
|
|
7
|
+
component: Checkbox,
|
|
8
8
|
};
|
|
9
9
|
export default meta;
|
|
10
10
|
type Story = StoryObj<typeof Checkbox>;
|
|
11
11
|
|
|
12
12
|
/** Shows an unchecked checkbox in its default state. */
|
|
13
13
|
export const Default: Story = {
|
|
14
|
-
|
|
14
|
+
render: () => <Checkbox />,
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
/** Shows a checkbox that starts in the checked state. */
|
|
18
18
|
export const Checked: Story = {
|
|
19
|
-
|
|
19
|
+
render: () => <Checkbox defaultChecked />,
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
/** Shows a disabled checkbox that cannot be interacted with. */
|
|
23
23
|
export const Disabled: Story = {
|
|
24
|
-
|
|
24
|
+
render: () => <Checkbox disabled />,
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
/** Shows a checkbox paired with a Label component for accessible form usage. */
|
|
28
28
|
export const WithLabel: Story = {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
render: () => (
|
|
30
|
+
<div className="flex items-center space-x-2">
|
|
31
|
+
<Checkbox id="terms" />
|
|
32
|
+
<Label htmlFor="terms">Accept terms and conditions</Label>
|
|
33
|
+
</div>
|
|
34
|
+
),
|
|
35
35
|
};
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import * as React from 'react';
|
|
4
3
|
import { CheckIcon } from 'lucide-react';
|
|
5
4
|
import { Checkbox as CheckboxPrimitive } from 'radix-ui';
|
|
5
|
+
import type * as React from 'react';
|
|
6
6
|
|
|
7
7
|
import { cn } from '@/lib/utils';
|
|
8
8
|
|
|
9
9
|
/** A toggleable boolean input with check icon. Supports checked, unchecked, and indeterminate states. Pair with Label for forms. */
|
|
10
10
|
function Checkbox({ className, ...props }: React.ComponentProps<typeof CheckboxPrimitive.Root>) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
11
|
+
return (
|
|
12
|
+
<CheckboxPrimitive.Root
|
|
13
|
+
data-slot="checkbox"
|
|
14
|
+
className={cn(
|
|
15
|
+
'peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50',
|
|
16
|
+
className,
|
|
17
|
+
)}
|
|
18
|
+
{...props}
|
|
19
|
+
>
|
|
20
|
+
<CheckboxPrimitive.Indicator
|
|
21
|
+
data-slot="checkbox-indicator"
|
|
22
|
+
className="grid place-content-center text-current transition-none"
|
|
23
|
+
>
|
|
24
|
+
<CheckIcon className="size-3.5" />
|
|
25
|
+
</CheckboxPrimitive.Indicator>
|
|
26
|
+
</CheckboxPrimitive.Root>
|
|
27
|
+
);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
export { Checkbox };
|