sonance-brand-mcp 1.2.5 → 1.3.2
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/dist/assets/api/sonance-analyze/route.ts +1116 -0
- package/dist/assets/api/sonance-assets/route.ts +113 -0
- package/dist/assets/api/sonance-components/route.ts +41 -0
- package/dist/assets/api/sonance-inject-id/route.ts +363 -0
- package/dist/assets/api/sonance-save-logo/route.ts +426 -0
- package/dist/assets/api/sonance-theme/route.ts +106 -0
- package/dist/assets/brand-system.ts +1265 -0
- package/dist/assets/components/accordion.stories.tsx +26 -26
- package/dist/assets/components/accordion.tsx +3 -3
- package/dist/assets/components/alert-dialog.stories.tsx +142 -0
- package/dist/assets/components/alert-dialog.tsx +143 -0
- package/dist/assets/components/alert.stories.tsx +3 -3
- package/dist/assets/components/alert.tsx +4 -3
- package/dist/assets/components/aspect-ratio.stories.tsx +70 -0
- package/dist/assets/components/aspect-ratio.tsx +8 -0
- package/dist/assets/components/autocomplete.stories.tsx +9 -9
- package/dist/assets/components/autocomplete.tsx +3 -3
- package/dist/assets/components/avatar.stories.tsx +5 -5
- package/dist/assets/components/avatar.tsx +67 -23
- package/dist/assets/components/badge.stories.tsx +10 -10
- package/dist/assets/components/badge.tsx +3 -3
- package/dist/assets/components/breadcrumbs.stories.tsx +7 -7
- package/dist/assets/components/breadcrumbs.tsx +13 -8
- package/dist/assets/components/button.stories.tsx +74 -74
- package/dist/assets/components/button.tsx +2 -0
- package/dist/assets/components/calendar.stories.tsx +11 -11
- package/dist/assets/components/calendar.tsx +4 -4
- package/dist/assets/components/card.stories.tsx +22 -22
- package/dist/assets/components/card.tsx +7 -3
- package/dist/assets/components/carousel.stories.tsx +158 -0
- package/dist/assets/components/carousel.tsx +264 -0
- package/dist/assets/components/chart.stories.tsx +376 -0
- package/dist/assets/components/chart.tsx +384 -0
- package/dist/assets/components/checkbox-group.stories.tsx +6 -6
- package/dist/assets/components/checkbox-group.tsx +3 -3
- package/dist/assets/components/checkbox.stories.tsx +23 -20
- package/dist/assets/components/checkbox.tsx +13 -6
- package/dist/assets/components/code.stories.tsx +24 -24
- package/dist/assets/components/code.tsx +22 -27
- package/dist/assets/components/collapsible.stories.tsx +128 -0
- package/dist/assets/components/collapsible.tsx +10 -0
- package/dist/assets/components/command.stories.tsx +183 -0
- package/dist/assets/components/command.tsx +171 -0
- package/dist/assets/components/context-menu.stories.tsx +159 -0
- package/dist/assets/components/context-menu.tsx +214 -0
- package/dist/assets/components/date-input.stories.tsx +9 -9
- package/dist/assets/components/date-input.tsx +2 -2
- package/dist/assets/components/date-picker.stories.tsx +9 -9
- package/dist/assets/components/date-picker.tsx +3 -3
- package/dist/assets/components/date-range-picker.stories.tsx +12 -12
- package/dist/assets/components/date-range-picker.tsx +3 -3
- package/dist/assets/components/dialog.stories.tsx +40 -40
- package/dist/assets/components/dialog.tsx +8 -12
- package/dist/assets/components/divider.stories.tsx +30 -30
- package/dist/assets/components/divider.tsx +34 -35
- package/dist/assets/components/drawer.stories.tsx +32 -31
- package/dist/assets/components/drawer.tsx +7 -6
- package/dist/assets/components/dropdown-menu.tsx +213 -0
- package/dist/assets/components/dropdown.stories.tsx +12 -12
- package/dist/assets/components/dropdown.tsx +5 -5
- package/dist/assets/components/form.stories.tsx +30 -29
- package/dist/assets/components/form.tsx +5 -5
- package/dist/assets/components/hover-card.stories.tsx +115 -0
- package/dist/assets/components/hover-card.tsx +35 -0
- package/dist/assets/components/image.stories.tsx +48 -25
- package/dist/assets/components/image.tsx +8 -5
- package/dist/assets/components/input-otp.stories.tsx +15 -15
- package/dist/assets/components/input-otp.tsx +5 -5
- package/dist/assets/components/input.stories.tsx +30 -25
- package/dist/assets/components/input.tsx +7 -4
- package/dist/assets/components/kbd.stories.tsx +34 -34
- package/dist/assets/components/kbd.tsx +9 -9
- package/dist/assets/components/link.stories.tsx +36 -36
- package/dist/assets/components/link.tsx +4 -0
- package/dist/assets/components/listbox.stories.tsx +5 -5
- package/dist/assets/components/listbox.tsx +4 -4
- package/dist/assets/components/menubar.stories.tsx +208 -0
- package/dist/assets/components/menubar.tsx +247 -0
- package/dist/assets/components/navbar.stories.tsx +24 -24
- package/dist/assets/components/navbar.tsx +8 -14
- package/dist/assets/components/navigation-menu.stories.tsx +239 -0
- package/dist/assets/components/navigation-menu.tsx +135 -0
- package/dist/assets/components/number-input.stories.tsx +11 -11
- package/dist/assets/components/number-input.tsx +3 -3
- package/dist/assets/components/pagination.stories.tsx +13 -13
- package/dist/assets/components/pagination.tsx +6 -6
- package/dist/assets/components/popover.stories.tsx +35 -35
- package/dist/assets/components/popover.tsx +98 -15
- package/dist/assets/components/progress.stories.tsx +5 -5
- package/dist/assets/components/progress.tsx +5 -5
- package/dist/assets/components/radio-group.stories.tsx +7 -7
- package/dist/assets/components/radio-group.tsx +3 -3
- package/dist/assets/components/range-calendar.stories.tsx +18 -18
- package/dist/assets/components/range-calendar.tsx +3 -3
- package/dist/assets/components/resizable.stories.tsx +197 -0
- package/dist/assets/components/resizable.tsx +47 -0
- package/dist/assets/components/scroll-area.stories.tsx +123 -0
- package/dist/assets/components/scroll-area.tsx +48 -0
- package/dist/assets/components/scroll-shadow.stories.tsx +17 -17
- package/dist/assets/components/scroll-shadow.tsx +31 -9
- package/dist/assets/components/select.stories.tsx +20 -19
- package/dist/assets/components/select.tsx +10 -6
- package/dist/assets/components/separator.tsx +32 -0
- package/dist/assets/components/sheet.tsx +137 -0
- package/dist/assets/components/sidebar.stories.tsx +351 -0
- package/dist/assets/components/sidebar.tsx +757 -0
- package/dist/assets/components/skeleton.stories.tsx +3 -3
- package/dist/assets/components/skeleton.tsx +2 -2
- package/dist/assets/components/slider.stories.tsx +6 -6
- package/dist/assets/components/slider.tsx +3 -3
- package/dist/assets/components/spacer.stories.tsx +11 -11
- package/dist/assets/components/spacer.tsx +2 -2
- package/dist/assets/components/spinner.stories.tsx +8 -8
- package/dist/assets/components/spinner.tsx +5 -5
- package/dist/assets/components/switch.stories.tsx +24 -20
- package/dist/assets/components/switch.tsx +14 -6
- package/dist/assets/components/table.stories.tsx +7 -7
- package/dist/assets/components/table.tsx +8 -8
- package/dist/assets/components/tabs.stories.tsx +37 -37
- package/dist/assets/components/tabs.tsx +3 -3
- package/dist/assets/components/textarea.stories.tsx +13 -12
- package/dist/assets/components/textarea.tsx +3 -3
- package/dist/assets/components/theme-toggle.stories.tsx +31 -30
- package/dist/assets/components/theme-toggle.tsx +2 -2
- package/dist/assets/components/time-input.stories.tsx +16 -16
- package/dist/assets/components/time-input.tsx +2 -2
- package/dist/assets/components/toast.stories.tsx +8 -5
- package/dist/assets/components/toast.tsx +6 -6
- package/dist/assets/components/toggle-group.stories.tsx +153 -0
- package/dist/assets/components/toggle-group.tsx +61 -0
- package/dist/assets/components/toggle.stories.tsx +77 -0
- package/dist/assets/components/toggle.tsx +46 -0
- package/dist/assets/components/tooltip.stories.tsx +49 -27
- package/dist/assets/components/tooltip.tsx +23 -90
- package/dist/assets/components/user.stories.tsx +23 -23
- package/dist/assets/components/user.tsx +7 -4
- package/dist/assets/dev-tools/SonanceDevTools.tsx +4201 -0
- package/dist/assets/dev-tools/index.ts +10 -0
- package/dist/assets/globals.css +39 -0
- package/dist/assets/logos/40th-anniversary/Sonance_40_Logo_CMYK_BEAM_BLUE_40_AND_BEAM_DARK.png +0 -0
- package/dist/assets/logos/Sonance logo dark mode.png +0 -0
- package/dist/assets/logos/Sonance logo light mode.png +0 -0
- package/dist/assets/logos/blaze/BlazeBySonance_Logo_Lockup_2C_Light_RGB_05162025.png +0 -0
- package/dist/assets/logos/blaze/BlazeBySonance_Logo_Lockup_3C_Dark_RGB_05162025.png +0 -0
- package/dist/assets/logos/blaze/BlazeBySonance_Logo_Lockup_White_RGB_05162025.png +0 -0
- package/dist/assets/logos/iport/IPORT_Sonance_LockUp_2C_Dark_RGB.png +0 -0
- package/dist/assets/logos/iport/IPORT_Sonance_LockUp_2C_Light_RGB.png +0 -0
- package/dist/assets/logos/james/James_Logo_Black_CMYK.png +0 -0
- package/dist/assets/logos/james/James_Logo_Black_RGB.png +0 -0
- package/dist/assets/logos/james/James_Logo_LtGray_CMYK.png +0 -0
- package/dist/assets/logos/james/James_Logo_LtGray_RGB.png +0 -0
- package/dist/assets/logos/james/James_Logo_Polished_RGB.png +0 -0
- package/dist/assets/logos/james/James_Logo_Reverse_CMYK.png +0 -0
- package/dist/assets/logos/james/James_Logo_Reverse_RGB.png +0 -0
- package/dist/assets/logos/james/James_Logo_White_CMYK.png +0 -0
- package/dist/assets/logos/life-is-better/Sonance_LifeisBetter_Dark_RGB.png +0 -0
- package/dist/assets/logos/life-is-better/Sonance_LifeisBetter_Light_RGB.png +0 -0
- package/dist/assets/logos/my-sonance/My.Sonance_Logo_2C_Dark_RGB.png +0 -0
- package/dist/assets/logos/my-sonance/My.Sonance_Logo_2C_Light_RGB.png +0 -0
- package/dist/assets/logos/my-sonance/My.Sonance_Logo_2C_Reverse_RGB.png +0 -0
- package/dist/assets/logos/my-sonance/My.Sonance_Logo_Black_RGB.png +0 -0
- package/dist/assets/logos/my-sonance/My.Sonance_Logo_Reverse_RGB.png +0 -0
- package/dist/assets/logos/sonance/Sonance_Logo_2C_Dark_RGB.png +0 -0
- package/dist/assets/logos/sonance/Sonance_Logo_2C_Light_RGB.png +0 -0
- package/dist/assets/logos/sonance/Sonance_Logo_2C_Reverse_RGB.png +0 -0
- package/dist/assets/logos/sonance/Sonance_Logo_Black_RGB.png +0 -0
- package/dist/assets/logos/sonance/Sonance_Logo_Grayscale_RGB.png +0 -0
- package/dist/assets/logos/sonance/Sonance_Logo_Reverse_RGB.png +0 -0
- package/dist/assets/logos/sonance-academy/SonanceAcademy_Logo_Dark_CMYK.png +0 -0
- package/dist/assets/logos/sonance-academy/SonanceAcademy_Logo_Light_CMYK.png +0 -0
- package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_3C_Dark_RGB.png +0 -0
- package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_3C_Light_RGB.png +0 -0
- package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_3C_Reverse_RGB.png +0 -0
- package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_Black_RGB.png +0 -0
- package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_Grayscale_RGB.png +0 -0
- package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_Reverse_RGB.png +0 -0
- package/dist/assets/logos/sonance-james/Sonance_James_Lockup_Dark.png +0 -0
- package/dist/assets/logos/sonance-james/Sonance_James_Lockup_Light.png +0 -0
- package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_LockupStacked_Dark.png +0 -0
- package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_LockupStacked_Light.png +0 -0
- package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_Lockup_Dark.png +0 -0
- package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_Lockup_Light.png +0 -0
- package/dist/assets/logos/trufig/TrufigLogo_Black.png +0 -0
- package/dist/assets/logos/trufig/TrufigLogo_Light.png +0 -0
- package/dist/assets/logos/trufig/TrufigWatermark_Black.png +0 -0
- package/dist/assets/logos/trufig/TrufigWatermark_Light.png +0 -0
- package/dist/assets/styles/brand-overrides.css +37 -0
- package/dist/index.js +2055 -15
- package/package.json +1 -1
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import * as RechartsPrimitive from "recharts";
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
|
|
7
|
+
// Format: { THEME_NAME: CSS_SELECTOR }
|
|
8
|
+
const THEMES = { light: "", dark: ".dark" } as const;
|
|
9
|
+
|
|
10
|
+
export type ChartConfig = {
|
|
11
|
+
[k in string]: {
|
|
12
|
+
label?: React.ReactNode;
|
|
13
|
+
icon?: React.ComponentType;
|
|
14
|
+
} & (
|
|
15
|
+
| { color?: string; theme?: never }
|
|
16
|
+
| { color?: never; theme: Record<keyof typeof THEMES, string> }
|
|
17
|
+
);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
type ChartContextProps = {
|
|
21
|
+
config: ChartConfig;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const ChartContext = React.createContext<ChartContextProps | null>(null);
|
|
25
|
+
|
|
26
|
+
function useChart() {
|
|
27
|
+
const context = React.useContext(ChartContext);
|
|
28
|
+
|
|
29
|
+
if (!context) {
|
|
30
|
+
throw new Error("useChart must be used within a <ChartContainer />");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return context;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const ChartContainer = React.forwardRef<
|
|
37
|
+
HTMLDivElement,
|
|
38
|
+
React.ComponentProps<"div"> & {
|
|
39
|
+
config: ChartConfig;
|
|
40
|
+
children: React.ComponentProps<
|
|
41
|
+
typeof RechartsPrimitive.ResponsiveContainer
|
|
42
|
+
>["children"];
|
|
43
|
+
}
|
|
44
|
+
>(({ id, className, children, config, ...props }, ref) => {
|
|
45
|
+
const uniqueId = React.useId();
|
|
46
|
+
const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`;
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<ChartContext.Provider value={{ config }}>
|
|
50
|
+
<div
|
|
51
|
+
data-chart={chartId}
|
|
52
|
+
ref={ref}
|
|
53
|
+
className={cn(
|
|
54
|
+
"flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-foreground-muted [&_.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-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-secondary-hover [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-secondary-hover [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none",
|
|
55
|
+
className
|
|
56
|
+
)} data-sonance-name="chart"
|
|
57
|
+
{...props}
|
|
58
|
+
>
|
|
59
|
+
<ChartStyle id={chartId} config={config} />
|
|
60
|
+
<RechartsPrimitive.ResponsiveContainer>
|
|
61
|
+
{children}
|
|
62
|
+
</RechartsPrimitive.ResponsiveContainer>
|
|
63
|
+
</div>
|
|
64
|
+
</ChartContext.Provider>
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
ChartContainer.displayName = "Chart";
|
|
68
|
+
|
|
69
|
+
const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
|
|
70
|
+
const colorConfig = Object.entries(config).filter(
|
|
71
|
+
([, config]) => config.theme || config.color
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
if (!colorConfig.length) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<style data-sonance-name="chart"
|
|
80
|
+
dangerouslySetInnerHTML={{
|
|
81
|
+
__html: Object.entries(THEMES)
|
|
82
|
+
.map(
|
|
83
|
+
([theme, prefix]) => `
|
|
84
|
+
${prefix} [data-chart=${id}] {
|
|
85
|
+
${colorConfig
|
|
86
|
+
.map(([key, itemConfig]) => {
|
|
87
|
+
const color =
|
|
88
|
+
itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||
|
|
89
|
+
itemConfig.color;
|
|
90
|
+
return color ? ` --color-${key}: ${color};` : null;
|
|
91
|
+
})
|
|
92
|
+
.join("\n")}
|
|
93
|
+
}
|
|
94
|
+
`
|
|
95
|
+
)
|
|
96
|
+
.join("\n"),
|
|
97
|
+
}}
|
|
98
|
+
/>
|
|
99
|
+
);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const ChartTooltip = RechartsPrimitive.Tooltip;
|
|
103
|
+
|
|
104
|
+
interface ChartTooltipContentProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
105
|
+
active?: boolean;
|
|
106
|
+
payload?: Array<{
|
|
107
|
+
name?: string;
|
|
108
|
+
value?: number | string;
|
|
109
|
+
dataKey?: string | number;
|
|
110
|
+
color?: string;
|
|
111
|
+
payload?: Record<string, unknown>;
|
|
112
|
+
fill?: string;
|
|
113
|
+
}>;
|
|
114
|
+
label?: string;
|
|
115
|
+
hideLabel?: boolean;
|
|
116
|
+
hideIndicator?: boolean;
|
|
117
|
+
indicator?: "line" | "dot" | "dashed";
|
|
118
|
+
nameKey?: string;
|
|
119
|
+
labelKey?: string;
|
|
120
|
+
labelFormatter?: (value: unknown, payload: unknown[]) => React.ReactNode;
|
|
121
|
+
labelClassName?: string;
|
|
122
|
+
formatter?: (
|
|
123
|
+
value: unknown,
|
|
124
|
+
name: unknown,
|
|
125
|
+
item: unknown,
|
|
126
|
+
index: number,
|
|
127
|
+
payload: unknown
|
|
128
|
+
) => React.ReactNode;
|
|
129
|
+
color?: string;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const ChartTooltipContent = React.forwardRef<HTMLDivElement, ChartTooltipContentProps>(
|
|
133
|
+
(
|
|
134
|
+
{
|
|
135
|
+
active,
|
|
136
|
+
payload,
|
|
137
|
+
className,
|
|
138
|
+
indicator = "dot",
|
|
139
|
+
hideLabel = false,
|
|
140
|
+
hideIndicator = false,
|
|
141
|
+
label,
|
|
142
|
+
labelFormatter,
|
|
143
|
+
labelClassName,
|
|
144
|
+
formatter,
|
|
145
|
+
color,
|
|
146
|
+
nameKey,
|
|
147
|
+
labelKey,
|
|
148
|
+
},
|
|
149
|
+
ref
|
|
150
|
+
) => {
|
|
151
|
+
const { config } = useChart();
|
|
152
|
+
|
|
153
|
+
const tooltipLabel = React.useMemo(() => {
|
|
154
|
+
if (hideLabel || !payload?.length) {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const [item] = payload;
|
|
159
|
+
const key = `${labelKey || item.dataKey || item.name || "value"}`;
|
|
160
|
+
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
161
|
+
const value =
|
|
162
|
+
!labelKey && typeof label === "string"
|
|
163
|
+
? config[label as keyof typeof config]?.label || label
|
|
164
|
+
: itemConfig?.label;
|
|
165
|
+
|
|
166
|
+
if (labelFormatter) {
|
|
167
|
+
return (
|
|
168
|
+
<div data-sonance-name="chart" className={cn("font-medium", labelClassName)}>
|
|
169
|
+
{labelFormatter(value, payload)}
|
|
170
|
+
</div>
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (!value) {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return <div className={cn("font-medium", labelClassName)}>{value}</div>;
|
|
179
|
+
}, [
|
|
180
|
+
label,
|
|
181
|
+
labelFormatter,
|
|
182
|
+
payload,
|
|
183
|
+
hideLabel,
|
|
184
|
+
labelClassName,
|
|
185
|
+
config,
|
|
186
|
+
labelKey,
|
|
187
|
+
]);
|
|
188
|
+
|
|
189
|
+
if (!active || !payload?.length) {
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const nestLabel = payload.length === 1 && indicator !== "dot";
|
|
194
|
+
|
|
195
|
+
return (
|
|
196
|
+
<div
|
|
197
|
+
ref={ref}
|
|
198
|
+
className={cn(
|
|
199
|
+
"grid min-w-[8rem] items-start gap-1.5 rounded-sm border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl",
|
|
200
|
+
className
|
|
201
|
+
)}
|
|
202
|
+
>
|
|
203
|
+
{!nestLabel ? tooltipLabel : null}
|
|
204
|
+
<div className="grid gap-1.5">
|
|
205
|
+
{payload.map((item, index) => {
|
|
206
|
+
const key = `${nameKey || item.name || item.dataKey || "value"}`;
|
|
207
|
+
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
208
|
+
const indicatorColor = color || (item.payload as Record<string, unknown>)?.fill as string || item.color;
|
|
209
|
+
|
|
210
|
+
return (
|
|
211
|
+
<div
|
|
212
|
+
key={String(item.dataKey)}
|
|
213
|
+
className={cn(
|
|
214
|
+
"flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-foreground-muted",
|
|
215
|
+
indicator === "dot" && "items-center"
|
|
216
|
+
)}
|
|
217
|
+
>
|
|
218
|
+
{formatter && item?.value !== undefined && item.name ? (
|
|
219
|
+
formatter(item.value, item.name, item, index, item.payload)
|
|
220
|
+
) : (
|
|
221
|
+
<>
|
|
222
|
+
{itemConfig?.icon ? (
|
|
223
|
+
<itemConfig.icon />
|
|
224
|
+
) : (
|
|
225
|
+
!hideIndicator && (
|
|
226
|
+
<div
|
|
227
|
+
className={cn(
|
|
228
|
+
"shrink-0 rounded-[2px] border-[--color-border] bg-[--color-bg]",
|
|
229
|
+
{
|
|
230
|
+
"h-2.5 w-2.5": indicator === "dot",
|
|
231
|
+
"w-1": indicator === "line",
|
|
232
|
+
"w-0 border-[1.5px] border-dashed bg-transparent":
|
|
233
|
+
indicator === "dashed",
|
|
234
|
+
"my-0.5": nestLabel && indicator === "dashed",
|
|
235
|
+
}
|
|
236
|
+
)}
|
|
237
|
+
style={
|
|
238
|
+
{
|
|
239
|
+
"--color-bg": indicatorColor,
|
|
240
|
+
"--color-border": indicatorColor,
|
|
241
|
+
} as React.CSSProperties
|
|
242
|
+
}
|
|
243
|
+
/>
|
|
244
|
+
)
|
|
245
|
+
)}
|
|
246
|
+
<div
|
|
247
|
+
className={cn(
|
|
248
|
+
"flex flex-1 justify-between leading-none",
|
|
249
|
+
nestLabel ? "items-end" : "items-center"
|
|
250
|
+
)}
|
|
251
|
+
>
|
|
252
|
+
<div className="grid gap-1.5">
|
|
253
|
+
{nestLabel ? tooltipLabel : null}
|
|
254
|
+
<span id="span-itemconfiglabel-item" className="text-foreground-muted">
|
|
255
|
+
{itemConfig?.label || item.name}
|
|
256
|
+
</span>
|
|
257
|
+
</div>
|
|
258
|
+
{item.value && (
|
|
259
|
+
<span id="span-typeof-itemvalue-num" className="font-mono font-medium tabular-nums text-foreground">
|
|
260
|
+
{typeof item.value === 'number' ? item.value.toLocaleString() : item.value}
|
|
261
|
+
</span>
|
|
262
|
+
)}
|
|
263
|
+
</div>
|
|
264
|
+
</>
|
|
265
|
+
)}
|
|
266
|
+
</div>
|
|
267
|
+
);
|
|
268
|
+
})}
|
|
269
|
+
</div>
|
|
270
|
+
</div>
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
);
|
|
274
|
+
ChartTooltipContent.displayName = "ChartTooltip";
|
|
275
|
+
|
|
276
|
+
const ChartLegend = RechartsPrimitive.Legend;
|
|
277
|
+
|
|
278
|
+
interface ChartLegendContentProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
279
|
+
payload?: Array<{
|
|
280
|
+
value?: string;
|
|
281
|
+
dataKey?: string | number;
|
|
282
|
+
color?: string;
|
|
283
|
+
}>;
|
|
284
|
+
verticalAlign?: "top" | "bottom";
|
|
285
|
+
hideIcon?: boolean;
|
|
286
|
+
nameKey?: string;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const ChartLegendContent = React.forwardRef<HTMLDivElement, ChartLegendContentProps>(
|
|
290
|
+
(
|
|
291
|
+
{ className, hideIcon = false, payload, verticalAlign = "bottom", nameKey },
|
|
292
|
+
ref
|
|
293
|
+
) => {
|
|
294
|
+
const { config } = useChart();
|
|
295
|
+
|
|
296
|
+
if (!payload?.length) {
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return (
|
|
301
|
+
<div
|
|
302
|
+
ref={ref}
|
|
303
|
+
className={cn(
|
|
304
|
+
"flex items-center justify-center gap-4",
|
|
305
|
+
verticalAlign === "top" ? "pb-3" : "pt-3",
|
|
306
|
+
className
|
|
307
|
+
)}
|
|
308
|
+
>
|
|
309
|
+
{payload.map((item) => {
|
|
310
|
+
const key = `${nameKey || item.dataKey || "value"}`;
|
|
311
|
+
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
312
|
+
|
|
313
|
+
return (
|
|
314
|
+
<div
|
|
315
|
+
key={item.value}
|
|
316
|
+
className={cn(
|
|
317
|
+
"flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-foreground-muted"
|
|
318
|
+
)}
|
|
319
|
+
>
|
|
320
|
+
{itemConfig?.icon && !hideIcon ? (
|
|
321
|
+
<itemConfig.icon />
|
|
322
|
+
) : (
|
|
323
|
+
<div
|
|
324
|
+
className="h-2 w-2 shrink-0 rounded-[2px]"
|
|
325
|
+
style={{
|
|
326
|
+
backgroundColor: item.color,
|
|
327
|
+
}}
|
|
328
|
+
/>
|
|
329
|
+
)}
|
|
330
|
+
{itemConfig?.label}
|
|
331
|
+
</div>
|
|
332
|
+
);
|
|
333
|
+
})}
|
|
334
|
+
</div>
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
);
|
|
338
|
+
ChartLegendContent.displayName = "ChartLegend";
|
|
339
|
+
|
|
340
|
+
// Helper to extract item config from a payload.
|
|
341
|
+
function getPayloadConfigFromPayload(
|
|
342
|
+
config: ChartConfig,
|
|
343
|
+
payload: unknown,
|
|
344
|
+
key: string
|
|
345
|
+
) {
|
|
346
|
+
if (typeof payload !== "object" || payload === null) {
|
|
347
|
+
return undefined;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
const payloadPayload =
|
|
351
|
+
"payload" in payload &&
|
|
352
|
+
typeof payload.payload === "object" &&
|
|
353
|
+
payload.payload !== null
|
|
354
|
+
? payload.payload
|
|
355
|
+
: undefined;
|
|
356
|
+
|
|
357
|
+
let configLabelKey: string = key;
|
|
358
|
+
|
|
359
|
+
if (
|
|
360
|
+
key in payload &&
|
|
361
|
+
typeof (payload as Record<string, unknown>)[key] === "string"
|
|
362
|
+
) {
|
|
363
|
+
configLabelKey = (payload as Record<string, unknown>)[key] as string;
|
|
364
|
+
} else if (
|
|
365
|
+
payloadPayload &&
|
|
366
|
+
key in payloadPayload &&
|
|
367
|
+
typeof (payloadPayload as Record<string, unknown>)[key] === "string"
|
|
368
|
+
) {
|
|
369
|
+
configLabelKey = (payloadPayload as Record<string, unknown>)[key] as string;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
return configLabelKey in config
|
|
373
|
+
? config[configLabelKey]
|
|
374
|
+
: config[key as keyof typeof config];
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
export {
|
|
378
|
+
ChartContainer,
|
|
379
|
+
ChartTooltip,
|
|
380
|
+
ChartTooltipContent,
|
|
381
|
+
ChartLegend,
|
|
382
|
+
ChartLegendContent,
|
|
383
|
+
ChartStyle,
|
|
384
|
+
};
|
|
@@ -45,7 +45,7 @@ export const Default: Story = {
|
|
|
45
45
|
render: () => {
|
|
46
46
|
const [values, setValues] = useState<string[]>([]);
|
|
47
47
|
return (
|
|
48
|
-
<CheckboxGroup value={values} onValueChange={setValues}>
|
|
48
|
+
<CheckboxGroup data-sonance-name="checkbox-group.stories" value={values} onValueChange={setValues}>
|
|
49
49
|
<CheckboxGroupItem value="option1" label="Option 1" />
|
|
50
50
|
<CheckboxGroupItem value="option2" label="Option 2" />
|
|
51
51
|
<CheckboxGroupItem value="option3" label="Option 3" />
|
|
@@ -224,8 +224,8 @@ export const FormExample: Story = {
|
|
|
224
224
|
</CheckboxGroup>
|
|
225
225
|
|
|
226
226
|
<div className="text-sm text-foreground-muted">
|
|
227
|
-
<p>Interests: {interests.join(', ') || 'None selected'}</p>
|
|
228
|
-
<p>Agreements: {agreements.join(', ') || 'None selected'}</p>
|
|
227
|
+
<p id="form-example-p-interests-interestsj">Interests: {interests.join(', ') || 'None selected'}</p>
|
|
228
|
+
<p id="form-example-p-agreements-agreement">Agreements: {agreements.join(', ') || 'None selected'}</p>
|
|
229
229
|
</div>
|
|
230
230
|
</div>
|
|
231
231
|
);
|
|
@@ -238,7 +238,7 @@ export const ResponsiveMatrix: Story = {
|
|
|
238
238
|
<div className="space-y-8">
|
|
239
239
|
{/* Mobile */}
|
|
240
240
|
<div>
|
|
241
|
-
<h4 className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
|
|
241
|
+
<h4 id="responsive-matrix-h4-mobile-375px" className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
|
|
242
242
|
<div className="w-[375px] border border-dashed border-border p-4">
|
|
243
243
|
<CheckboxGroup label="Select Options" defaultValue={['option1']}>
|
|
244
244
|
<CheckboxGroupItem value="option1" label="Option 1" />
|
|
@@ -249,7 +249,7 @@ export const ResponsiveMatrix: Story = {
|
|
|
249
249
|
</div>
|
|
250
250
|
{/* Tablet */}
|
|
251
251
|
<div>
|
|
252
|
-
<h4 className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
|
|
252
|
+
<h4 id="responsive-matrix-h4-tablet-768px" className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
|
|
253
253
|
<div className="w-[768px] border border-dashed border-border p-4">
|
|
254
254
|
<CheckboxGroup label="Select Sizes" orientation="horizontal" defaultValue={['medium']}>
|
|
255
255
|
<CheckboxGroupItem value="small" label="Small" />
|
|
@@ -261,7 +261,7 @@ export const ResponsiveMatrix: Story = {
|
|
|
261
261
|
</div>
|
|
262
262
|
{/* Desktop */}
|
|
263
263
|
<div>
|
|
264
|
-
<h4 className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
|
|
264
|
+
<h4 id="responsive-matrix-h4-desktop-1280px" className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
|
|
265
265
|
<div className="w-[1280px] border border-dashed border-border p-4">
|
|
266
266
|
<div className="grid grid-cols-2 gap-8">
|
|
267
267
|
<CheckboxGroup label="Features" defaultValue={['basic']}>
|
|
@@ -79,7 +79,7 @@ export function CheckboxGroup({
|
|
|
79
79
|
>
|
|
80
80
|
{children}
|
|
81
81
|
</div>
|
|
82
|
-
{error && <p className="mt-2 text-sm text-error">{error}</p>}
|
|
82
|
+
{error && <p id="checkbox-group-p-error" className="mt-2 text-sm text-error">{error}</p>}
|
|
83
83
|
</div>
|
|
84
84
|
</CheckboxGroupContext.Provider>
|
|
85
85
|
);
|
|
@@ -109,7 +109,7 @@ export function CheckboxGroupItem({
|
|
|
109
109
|
};
|
|
110
110
|
|
|
111
111
|
return (
|
|
112
|
-
<Checkbox
|
|
112
|
+
<Checkbox id="checkbox-group-item-checkbox-checkboxgroup" data-sonance-name="checkbox-group"
|
|
113
113
|
checked={isChecked}
|
|
114
114
|
onChange={handleChange}
|
|
115
115
|
disabled={isDisabled}
|
|
@@ -145,7 +145,7 @@ export function CheckboxList({
|
|
|
145
145
|
className,
|
|
146
146
|
}: CheckboxListProps) {
|
|
147
147
|
return (
|
|
148
|
-
<CheckboxGroup
|
|
148
|
+
<CheckboxGroup data-sonance-name="checkbox-group"
|
|
149
149
|
value={value}
|
|
150
150
|
defaultValue={defaultValue}
|
|
151
151
|
onValueChange={onValueChange}
|
|
@@ -84,11 +84,11 @@ export const DisabledChecked: Story = {
|
|
|
84
84
|
export const AllStates: Story = {
|
|
85
85
|
render: () => (
|
|
86
86
|
<div className="space-y-4">
|
|
87
|
-
<Checkbox label="Unchecked" />
|
|
88
|
-
<Checkbox label="Checked" defaultChecked />
|
|
89
|
-
<Checkbox label="With description" description="Additional information about this option" />
|
|
90
|
-
<Checkbox label="Disabled" disabled />
|
|
91
|
-
<Checkbox label="Disabled checked" disabled defaultChecked />
|
|
87
|
+
<Checkbox id="all-states-checkbox" label="Unchecked" />
|
|
88
|
+
<Checkbox id="all-states-checkbox" label="Checked" defaultChecked />
|
|
89
|
+
<Checkbox id="all-states-checkbox" label="With description" description="Additional information about this option" />
|
|
90
|
+
<Checkbox id="all-states-checkbox" label="Disabled" disabled />
|
|
91
|
+
<Checkbox id="all-states-checkbox" label="Disabled checked" disabled defaultChecked />
|
|
92
92
|
</div>
|
|
93
93
|
),
|
|
94
94
|
};
|
|
@@ -98,17 +98,20 @@ export const FormExample: Story = {
|
|
|
98
98
|
render: () => (
|
|
99
99
|
<div className="space-y-6 w-80">
|
|
100
100
|
<div className="space-y-4">
|
|
101
|
-
<h3 className="text-sm font-medium text-foreground">Notification Preferences</h3>
|
|
101
|
+
<h3 id="form-example-h3-notification-prefere" className="text-sm font-medium text-foreground">Notification Preferences</h3>
|
|
102
102
|
<Checkbox
|
|
103
|
+
id="form-example-checkbox"
|
|
103
104
|
label="Email notifications"
|
|
104
105
|
description="Get notified about account activity via email"
|
|
105
106
|
defaultChecked
|
|
106
107
|
/>
|
|
107
108
|
<Checkbox
|
|
109
|
+
id="form-example-checkbox"
|
|
108
110
|
label="SMS notifications"
|
|
109
111
|
description="Get notified via text message"
|
|
110
112
|
/>
|
|
111
113
|
<Checkbox
|
|
114
|
+
id="form-example-checkbox"
|
|
112
115
|
label="Push notifications"
|
|
113
116
|
description="Get notified on your mobile device"
|
|
114
117
|
defaultChecked
|
|
@@ -124,34 +127,34 @@ export const ResponsiveMatrix: Story = {
|
|
|
124
127
|
<div className="space-y-8">
|
|
125
128
|
{/* Mobile */}
|
|
126
129
|
<div>
|
|
127
|
-
<h4 className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
|
|
130
|
+
<h4 id="responsive-matrix-h4-mobile-375px" className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
|
|
128
131
|
<div className="w-[375px] border border-dashed border-border p-4 space-y-4">
|
|
129
|
-
<Checkbox label="Accept terms and conditions" />
|
|
130
|
-
<Checkbox label="Subscribe to newsletter" description="Receive updates about new features" />
|
|
131
|
-
<Checkbox label="Remember me" defaultChecked />
|
|
132
|
+
<Checkbox id="responsive-matrix-checkbox" label="Accept terms and conditions" />
|
|
133
|
+
<Checkbox id="responsive-matrix-checkbox" label="Subscribe to newsletter" description="Receive updates about new features" />
|
|
134
|
+
<Checkbox id="responsive-matrix-checkbox" label="Remember me" defaultChecked />
|
|
132
135
|
</div>
|
|
133
136
|
</div>
|
|
134
137
|
{/* Tablet */}
|
|
135
138
|
<div>
|
|
136
|
-
<h4 className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
|
|
139
|
+
<h4 id="responsive-matrix-h4-tablet-768px" className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
|
|
137
140
|
<div className="w-[768px] border border-dashed border-border p-4">
|
|
138
141
|
<div className="grid grid-cols-2 gap-4">
|
|
139
|
-
<Checkbox label="Email notifications" description="Get notified via email" defaultChecked />
|
|
140
|
-
<Checkbox label="SMS notifications" description="Get notified via text" />
|
|
141
|
-
<Checkbox label="Push notifications" description="Mobile app notifications" defaultChecked />
|
|
142
|
-
<Checkbox label="Marketing emails" description="Product updates and offers" />
|
|
142
|
+
<Checkbox id="responsive-matrix-checkbox" label="Email notifications" description="Get notified via email" defaultChecked />
|
|
143
|
+
<Checkbox id="responsive-matrix-checkbox" label="SMS notifications" description="Get notified via text" />
|
|
144
|
+
<Checkbox id="responsive-matrix-checkbox" label="Push notifications" description="Mobile app notifications" defaultChecked />
|
|
145
|
+
<Checkbox id="responsive-matrix-checkbox" label="Marketing emails" description="Product updates and offers" />
|
|
143
146
|
</div>
|
|
144
147
|
</div>
|
|
145
148
|
</div>
|
|
146
149
|
{/* Desktop */}
|
|
147
150
|
<div>
|
|
148
|
-
<h4 className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
|
|
151
|
+
<h4 id="responsive-matrix-h4-desktop-1280px" className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
|
|
149
152
|
<div className="w-[1280px] border border-dashed border-border p-4">
|
|
150
153
|
<div className="grid grid-cols-4 gap-4">
|
|
151
|
-
<Checkbox label="Unchecked" />
|
|
152
|
-
<Checkbox label="Checked" defaultChecked />
|
|
153
|
-
<Checkbox label="Disabled" disabled />
|
|
154
|
-
<Checkbox label="Disabled checked" disabled defaultChecked />
|
|
154
|
+
<Checkbox id="responsive-matrix-checkbox" label="Unchecked" />
|
|
155
|
+
<Checkbox id="responsive-matrix-checkbox" label="Checked" defaultChecked />
|
|
156
|
+
<Checkbox id="responsive-matrix-checkbox" label="Disabled" disabled />
|
|
157
|
+
<Checkbox id="responsive-matrix-checkbox" label="Disabled checked" disabled defaultChecked />
|
|
155
158
|
</div>
|
|
156
159
|
</div>
|
|
157
160
|
</div>
|
|
@@ -28,21 +28,28 @@ const getStateStyles = (state?: CheckboxState) => {
|
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
|
|
31
|
-
({ className, label, description, id, state, disabled, checked, ...props }, ref) => {
|
|
31
|
+
({ className, label, description, id, state, disabled, checked, defaultChecked, onChange, style, ...props }, ref) => {
|
|
32
32
|
const uniqueId = useId();
|
|
33
33
|
const inputId = id || `checkbox-${uniqueId}`;
|
|
34
34
|
const isDisabled = disabled || state === "disabled";
|
|
35
|
-
|
|
35
|
+
|
|
36
|
+
// Determine if we're in controlled mode
|
|
37
|
+
const isControlled = checked !== undefined || onChange !== undefined;
|
|
38
|
+
const isCheckedForState = state === "checked";
|
|
36
39
|
|
|
37
40
|
return (
|
|
38
|
-
<div className="flex items-start gap-3">
|
|
41
|
+
<div data-sonance-name="checkbox" className="flex items-start gap-3">
|
|
39
42
|
<div className="relative flex items-center justify-center">
|
|
40
43
|
<input
|
|
41
44
|
type="checkbox"
|
|
42
45
|
id={inputId}
|
|
43
46
|
ref={ref}
|
|
44
47
|
disabled={isDisabled}
|
|
45
|
-
|
|
48
|
+
style={style}
|
|
49
|
+
{...(isControlled
|
|
50
|
+
? { checked: checked || isCheckedForState, onChange }
|
|
51
|
+
: { defaultChecked: defaultChecked || isCheckedForState }
|
|
52
|
+
)}
|
|
46
53
|
className={cn(
|
|
47
54
|
"peer h-5 w-5 shrink-0 appearance-none border border-border bg-input",
|
|
48
55
|
"hover:border-border-hover",
|
|
@@ -52,7 +59,7 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
|
|
|
52
59
|
"transition-colors duration-150",
|
|
53
60
|
getStateStyles(state),
|
|
54
61
|
className
|
|
55
|
-
)}
|
|
62
|
+
)} data-sonance-name="checkbox"
|
|
56
63
|
{...props}
|
|
57
64
|
/>
|
|
58
65
|
<Check
|
|
@@ -73,7 +80,7 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
|
|
|
73
80
|
</label>
|
|
74
81
|
)}
|
|
75
82
|
{description && (
|
|
76
|
-
<p className="text-xs text-foreground-muted">{description}</p>
|
|
83
|
+
<p id="p-description" className="text-xs text-foreground-muted">{description}</p>
|
|
77
84
|
)}
|
|
78
85
|
</div>
|
|
79
86
|
)}
|