@inspirare/design-system 0.0.22 → 0.0.24
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/README.md +82 -61
- package/dist/book-logo-filled.svg +55 -0
- package/dist/components/ui/accessibility-improvements.js +26 -23
- package/dist/components/ui/accordion.js +34 -24
- package/dist/components/ui/alert-dialog.js +91 -57
- package/dist/components/ui/alert.js +38 -26
- package/dist/components/ui/aspect-ratio.js +11 -3
- package/dist/components/ui/avatar.js +30 -8
- package/dist/components/ui/badge.js +20 -14
- package/dist/components/ui/breadcrumb.js +69 -56
- package/dist/components/ui/button-group.js +17 -13
- package/dist/components/ui/button.js +19 -15
- package/dist/components/ui/calendar.js +63 -59
- package/dist/components/ui/card.js +11 -9
- package/dist/components/ui/carousel.js +70 -75
- package/dist/components/ui/chart.js +75 -72
- package/dist/components/ui/checkbox.js +4 -5
- package/dist/components/ui/collapsible.js +12 -14
- package/dist/components/ui/color-picker.js +60 -80
- package/dist/components/ui/combobox.js +153 -33
- package/dist/components/ui/command.js +50 -48
- package/dist/components/ui/context-menu.js +129 -68
- package/dist/components/ui/dialog.js +65 -60
- package/dist/components/ui/drawer.js +81 -40
- package/dist/components/ui/dropdown-menu.js +100 -87
- package/dist/components/ui/empty.js +7 -6
- package/dist/components/ui/field.js +44 -47
- package/dist/components/ui/form.js +22 -23
- package/dist/components/ui/hover-card.js +14 -11
- package/dist/components/ui/input-group.js +16 -13
- package/dist/components/ui/input-otp.js +37 -32
- package/dist/components/ui/input.js +9 -7
- package/dist/components/ui/item.js +42 -36
- package/dist/components/ui/kbd.js +2 -1
- package/dist/components/ui/label.js +6 -7
- package/dist/components/ui/menubar.js +124 -93
- package/dist/components/ui/navigation-menu.js +79 -54
- package/dist/components/ui/pagination.js +78 -58
- package/dist/components/ui/popover.js +35 -16
- package/dist/components/ui/progress.js +37 -13
- package/dist/components/ui/radio-group.js +14 -14
- package/dist/components/ui/resizable.js +24 -15
- package/dist/components/ui/scroll-area.js +29 -11
- package/dist/components/ui/select.js +98 -56
- package/dist/components/ui/separator.js +5 -7
- package/dist/components/ui/sheet.js +47 -42
- package/dist/components/ui/sidebar.js +279 -248
- package/dist/components/ui/skeleton.js +4 -40
- package/dist/components/ui/slider.js +27 -29
- package/dist/components/ui/sonner.js +27 -10
- package/dist/components/ui/spinner.js +2 -0
- package/dist/components/ui/switch.js +3 -4
- package/dist/components/ui/table.js +6 -6
- package/dist/components/ui/tabs.js +45 -22
- package/dist/components/ui/textarea.js +3 -2
- package/dist/components/ui/theme-toggle.js +38 -41
- package/dist/components/ui/toggle-group.js +30 -21
- package/dist/components/ui/toggle.js +8 -9
- package/dist/components/ui/tooltip.js +28 -23
- package/dist/index.css +1 -1
- package/dist/index.d.ts +446 -468
- package/dist/index.js +58 -58
- package/package.json +42 -41
- package/src/App.tsx +28 -34
- package/src/components/branding/assets/book-logo-filled.svg +55 -0
- package/src/components/branding/logo/logo.tsx +56 -0
- package/src/components/ui/accessibility-improvements.stories.tsx +18 -0
- package/src/components/ui/accessibility-improvements.test.tsx +13 -0
- package/src/components/ui/accessibility-improvements.tsx +16 -6
- package/src/components/ui/accordion.stories.tsx +19 -0
- package/src/components/ui/accordion.test.tsx +14 -0
- package/src/components/ui/accordion.tsx +28 -20
- package/src/components/ui/alert-dialog.stories.tsx +19 -0
- package/src/components/ui/alert-dialog.test.tsx +14 -0
- package/src/components/ui/alert-dialog.tsx +159 -123
- package/src/components/ui/alert.stories.tsx +19 -0
- package/src/components/ui/alert.test.tsx +14 -0
- package/src/components/ui/alert.tsx +60 -41
- package/src/components/ui/aspect-ratio.stories.tsx +19 -0
- package/src/components/ui/aspect-ratio.test.tsx +14 -0
- package/src/components/ui/aspect-ratio.tsx +19 -2
- package/src/components/ui/attachment.stories.tsx +19 -0
- package/src/components/ui/attachment.test.tsx +14 -0
- package/src/components/ui/attachment.tsx +209 -0
- package/src/components/ui/avatar.stories.tsx +19 -0
- package/src/components/ui/avatar.test.tsx +14 -0
- package/src/components/ui/avatar.tsx +73 -17
- package/src/components/ui/badge.stories.tsx +19 -0
- package/src/components/ui/badge.test.tsx +14 -0
- package/src/components/ui/badge.tsx +33 -25
- package/src/components/ui/breadcrumb.stories.tsx +19 -0
- package/src/components/ui/breadcrumb.test.tsx +14 -0
- package/src/components/ui/breadcrumb.tsx +98 -86
- package/src/components/ui/bubble.stories.tsx +19 -0
- package/src/components/ui/bubble.test.tsx +14 -0
- package/src/components/ui/bubble.tsx +130 -0
- package/src/components/ui/button-group.stories.tsx +19 -0
- package/src/components/ui/button-group.test.tsx +14 -0
- package/src/components/ui/button-group.tsx +26 -20
- package/src/components/ui/button.stories.tsx +19 -0
- package/src/components/ui/button.test.tsx +14 -0
- package/src/components/ui/button.tsx +30 -31
- package/src/components/ui/calendar.stories.tsx +19 -0
- package/src/components/ui/calendar.test.tsx +14 -0
- package/src/components/ui/calendar.tsx +28 -26
- package/src/components/ui/card.stories.tsx +19 -0
- package/src/components/ui/card.test.tsx +14 -0
- package/src/components/ui/card.tsx +30 -17
- package/src/components/ui/carousel.stories.tsx +19 -0
- package/src/components/ui/carousel.test.tsx +14 -0
- package/src/components/ui/carousel.tsx +115 -135
- package/src/components/ui/chart.stories.tsx +18 -0
- package/src/components/ui/chart.test.tsx +13 -0
- package/src/components/ui/chart.tsx +220 -216
- package/src/components/ui/checkbox.stories.tsx +19 -0
- package/src/components/ui/checkbox.test.tsx +14 -0
- package/src/components/ui/checkbox.tsx +7 -10
- package/src/components/ui/collapsible.stories.tsx +19 -0
- package/src/components/ui/collapsible.test.tsx +14 -0
- package/src/components/ui/collapsible.tsx +11 -26
- package/src/components/ui/color-picker.stories.tsx +19 -0
- package/src/components/ui/color-picker.test.tsx +14 -0
- package/src/components/ui/color-picker.tsx +36 -26
- package/src/components/ui/combobox.stories.tsx +19 -0
- package/src/components/ui/combobox.test.tsx +14 -0
- package/src/components/ui/combobox.tsx +281 -96
- package/src/components/ui/command.stories.tsx +19 -0
- package/src/components/ui/command.test.tsx +14 -0
- package/src/components/ui/command.tsx +59 -47
- package/src/components/ui/context-menu.stories.tsx +19 -0
- package/src/components/ui/context-menu.test.tsx +14 -0
- package/src/components/ui/context-menu.tsx +231 -160
- package/src/components/ui/dialog.stories.tsx +19 -0
- package/src/components/ui/dialog.test.tsx +14 -0
- package/src/components/ui/dialog.tsx +81 -72
- package/src/components/ui/direction.stories.tsx +19 -0
- package/src/components/ui/direction.test.tsx +14 -0
- package/src/components/ui/direction.tsx +6 -0
- package/src/components/ui/drawer.stories.tsx +19 -0
- package/src/components/ui/drawer.test.tsx +14 -0
- package/src/components/ui/drawer.tsx +143 -64
- package/src/components/ui/dropdown-menu.stories.tsx +19 -0
- package/src/components/ui/dropdown-menu.test.tsx +14 -0
- package/src/components/ui/dropdown-menu.tsx +199 -153
- package/src/components/ui/empty.stories.tsx +18 -0
- package/src/components/ui/empty.test.tsx +13 -0
- package/src/components/ui/empty.tsx +11 -9
- package/src/components/ui/field.stories.tsx +18 -0
- package/src/components/ui/field.test.tsx +13 -0
- package/src/components/ui/field.tsx +26 -32
- package/src/components/ui/form.stories.tsx +22 -0
- package/src/components/ui/form.test.tsx +15 -0
- package/src/components/ui/form.tsx +1 -2
- package/src/components/ui/hover-card.stories.tsx +19 -0
- package/src/components/ui/hover-card.test.tsx +14 -0
- package/src/components/ui/hover-card.tsx +34 -32
- package/src/components/ui/input-group.stories.tsx +18 -0
- package/src/components/ui/input-group.test.tsx +13 -0
- package/src/components/ui/input-group.tsx +21 -28
- package/src/components/ui/input-otp.stories.tsx +19 -0
- package/src/components/ui/input-otp.test.tsx +14 -0
- package/src/components/ui/input-otp.tsx +58 -42
- package/src/components/ui/input.stories.tsx +19 -0
- package/src/components/ui/input.test.tsx +14 -0
- package/src/components/ui/input.tsx +9 -8
- package/src/components/ui/item.stories.tsx +18 -0
- package/src/components/ui/item.test.tsx +13 -0
- package/src/components/ui/item.tsx +38 -28
- package/src/components/ui/kbd.stories.tsx +18 -0
- package/src/components/ui/kbd.test.tsx +13 -0
- package/src/components/ui/kbd.tsx +3 -3
- package/src/components/ui/label.stories.tsx +18 -0
- package/src/components/ui/label.test.tsx +13 -0
- package/src/components/ui/label.tsx +7 -11
- package/src/components/ui/marker.stories.tsx +19 -0
- package/src/components/ui/marker.test.tsx +14 -0
- package/src/components/ui/marker.tsx +73 -0
- package/src/components/ui/menubar.stories.tsx +19 -0
- package/src/components/ui/menubar.test.tsx +14 -0
- package/src/components/ui/menubar.tsx +226 -202
- package/src/components/ui/message-scroller.stories.tsx +19 -0
- package/src/components/ui/message-scroller.test.tsx +14 -0
- package/src/components/ui/message-scroller.tsx +131 -0
- package/src/components/ui/message.stories.tsx +19 -0
- package/src/components/ui/message.test.tsx +14 -0
- package/src/components/ui/message.tsx +94 -0
- package/src/components/ui/native-select.stories.tsx +18 -0
- package/src/components/ui/native-select.test.tsx +13 -0
- package/src/components/ui/native-select.tsx +63 -0
- package/src/components/ui/navigation-menu.stories.tsx +19 -0
- package/src/components/ui/navigation-menu.test.tsx +14 -0
- package/src/components/ui/navigation-menu.tsx +145 -103
- package/src/components/ui/pagination.stories.tsx +19 -0
- package/src/components/ui/pagination.test.tsx +14 -0
- package/src/components/ui/pagination.tsx +114 -83
- package/src/components/ui/popover.stories.tsx +19 -0
- package/src/components/ui/popover.test.tsx +14 -0
- package/src/components/ui/popover.tsx +68 -33
- package/src/components/ui/progress.stories.tsx +19 -0
- package/src/components/ui/progress.test.tsx +14 -0
- package/src/components/ui/progress.tsx +67 -15
- package/src/components/ui/questionnaire.stories.tsx +19 -0
- package/src/components/ui/questionnaire.test.tsx +14 -0
- package/src/components/ui/questionnaire.tsx +324 -0
- package/src/components/ui/radio-group.stories.tsx +19 -0
- package/src/components/ui/radio-group.test.tsx +14 -0
- package/src/components/ui/radio-group.tsx +15 -20
- package/src/components/ui/resizable.stories.tsx +19 -0
- package/src/components/ui/resizable.test.tsx +14 -0
- package/src/components/ui/resizable.tsx +37 -30
- package/src/components/ui/scroll-area.stories.tsx +19 -0
- package/src/components/ui/scroll-area.test.tsx +14 -0
- package/src/components/ui/scroll-area.tsx +41 -19
- package/src/components/ui/select.stories.tsx +19 -0
- package/src/components/ui/select.test.tsx +14 -0
- package/src/components/ui/select.tsx +145 -78
- package/src/components/ui/separator.stories.tsx +19 -0
- package/src/components/ui/separator.test.tsx +14 -0
- package/src/components/ui/separator.tsx +8 -11
- package/src/components/ui/sheet.stories.tsx +19 -0
- package/src/components/ui/sheet.test.tsx +14 -0
- package/src/components/ui/sheet.tsx +56 -71
- package/src/components/ui/sidebar.stories.tsx +18 -0
- package/src/components/ui/sidebar.test.tsx +13 -0
- package/src/components/ui/sidebar.tsx +469 -513
- package/src/components/ui/skeleton.stories.tsx +19 -0
- package/src/components/ui/skeleton.test.tsx +14 -0
- package/src/components/ui/skeleton.tsx +8 -114
- package/src/components/ui/slider.stories.tsx +19 -0
- package/src/components/ui/slider.test.tsx +14 -0
- package/src/components/ui/slider.tsx +31 -40
- package/src/components/ui/sonner.stories.tsx +19 -0
- package/src/components/ui/sonner.test.tsx +14 -0
- package/src/components/ui/sonner.tsx +39 -7
- package/src/components/ui/spinner.stories.tsx +18 -0
- package/src/components/ui/spinner.test.tsx +13 -0
- package/src/components/ui/spinner.tsx +3 -7
- package/src/components/ui/switch.stories.tsx +19 -0
- package/src/components/ui/switch.test.tsx +14 -0
- package/src/components/ui/switch.tsx +4 -7
- package/src/components/ui/table.stories.tsx +19 -0
- package/src/components/ui/table.test.tsx +14 -0
- package/src/components/ui/table.tsx +17 -17
- package/src/components/ui/tabs.stories.tsx +19 -0
- package/src/components/ui/tabs.test.tsx +14 -0
- package/src/components/ui/tabs.tsx +71 -31
- package/src/components/ui/textarea.stories.tsx +19 -0
- package/src/components/ui/textarea.test.tsx +14 -0
- package/src/components/ui/textarea.tsx +7 -5
- package/src/components/ui/theme-toggle.stories.tsx +18 -0
- package/src/components/ui/theme-toggle.test.tsx +13 -0
- package/src/components/ui/theme-toggle.tsx +35 -37
- package/src/components/ui/toggle-group.stories.tsx +19 -0
- package/src/components/ui/toggle-group.test.tsx +14 -0
- package/src/components/ui/toggle-group.tsx +41 -25
- package/src/components/ui/toggle.stories.tsx +19 -0
- package/src/components/ui/toggle.test.tsx +14 -0
- package/src/components/ui/toggle.tsx +17 -19
- package/src/components/ui/tooltip.stories.tsx +19 -0
- package/src/components/ui/tooltip.test.tsx +14 -0
- package/src/components/ui/tooltip.tsx +53 -44
- package/src/demo/AIDemo.tsx +50 -0
- package/src/demo/ButtonsDemo.tsx +41 -18
- package/src/demo/CalendarDemo.tsx +1 -1
- package/src/demo/FeedbackDemo.tsx +4 -6
- package/src/demo/FormsDemo.tsx +34 -11
- package/src/demo/NavigationDemo.tsx +38 -13
- package/src/demo/OverlaysDemo.tsx +22 -36
- package/src/demo/update-demos.js +82 -0
- package/src/index.css +66 -46
- package/src/lib/utils.ts +3 -3
- package/src/stories/Button.stories.ts +54 -0
- package/src/stories/Button.tsx +36 -0
- package/src/stories/Configure.mdx +388 -0
- package/src/stories/Header.stories.ts +34 -0
- package/src/stories/Header.tsx +55 -0
- package/src/stories/Page.stories.ts +33 -0
- package/src/stories/Page.tsx +73 -0
- package/src/stories/assets/accessibility.png +0 -0
- package/src/stories/assets/accessibility.svg +1 -0
- package/src/stories/assets/addon-library.png +0 -0
- package/src/stories/assets/assets.png +0 -0
- package/src/stories/assets/avif-test-image.avif +0 -0
- package/src/stories/assets/context.png +0 -0
- package/src/stories/assets/discord.svg +1 -0
- package/src/stories/assets/docs.png +0 -0
- package/src/stories/assets/figma-plugin.png +0 -0
- package/src/stories/assets/github.svg +1 -0
- package/src/stories/assets/share.png +0 -0
- package/src/stories/assets/styling.png +0 -0
- package/src/stories/assets/testing.png +0 -0
- package/src/stories/assets/theming.png +0 -0
- package/src/stories/assets/tutorials.svg +1 -0
- package/src/stories/assets/youtube.svg +1 -0
- package/src/stories/button.css +30 -0
- package/src/stories/header.css +32 -0
- package/src/stories/page.css +68 -0
|
@@ -2,21 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
import * as React from "react"
|
|
4
4
|
import * as RechartsPrimitive from "recharts"
|
|
5
|
+
import type { TooltipValueType } from "recharts"
|
|
5
6
|
|
|
6
7
|
import { cn } from "@/lib/utils"
|
|
7
8
|
|
|
8
9
|
// Format: { THEME_NAME: CSS_SELECTOR }
|
|
9
10
|
const THEMES = { light: "", dark: ".dark" } as const
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
const INITIAL_DIMENSION = { width: 320, height: 200 } as const
|
|
13
|
+
type TooltipNameType = number | string
|
|
14
|
+
|
|
15
|
+
export type ChartConfig = Record<
|
|
16
|
+
string,
|
|
17
|
+
{
|
|
13
18
|
label?: React.ReactNode
|
|
14
19
|
icon?: React.ComponentType
|
|
15
20
|
} & (
|
|
16
21
|
| { color?: string; theme?: never }
|
|
17
22
|
| { color?: never; theme: Record<keyof typeof THEMES, string> }
|
|
18
23
|
)
|
|
19
|
-
|
|
24
|
+
>
|
|
20
25
|
|
|
21
26
|
type ChartContextProps = {
|
|
22
27
|
config: ChartConfig
|
|
@@ -34,42 +39,51 @@ function useChart() {
|
|
|
34
39
|
return context
|
|
35
40
|
}
|
|
36
41
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
function ChartContainer({
|
|
43
|
+
id,
|
|
44
|
+
className,
|
|
45
|
+
children,
|
|
46
|
+
config,
|
|
47
|
+
initialDimension = INITIAL_DIMENSION,
|
|
48
|
+
...props
|
|
49
|
+
}: React.ComponentProps<"div"> & {
|
|
50
|
+
config: ChartConfig
|
|
51
|
+
children: React.ComponentProps<
|
|
52
|
+
typeof RechartsPrimitive.ResponsiveContainer
|
|
53
|
+
>["children"]
|
|
54
|
+
initialDimension?: {
|
|
55
|
+
width: number
|
|
56
|
+
height: number
|
|
44
57
|
}
|
|
45
|
-
|
|
58
|
+
}) {
|
|
46
59
|
const uniqueId = React.useId()
|
|
47
|
-
const chartId = `chart-${id
|
|
60
|
+
const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}`
|
|
48
61
|
|
|
49
62
|
return (
|
|
50
63
|
<ChartContext.Provider value={{ config }}>
|
|
51
64
|
<div
|
|
65
|
+
data-slot="chart"
|
|
52
66
|
data-chart={chartId}
|
|
53
|
-
ref={ref}
|
|
54
67
|
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-
|
|
68
|
+
"flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden",
|
|
56
69
|
className
|
|
57
70
|
)}
|
|
58
71
|
{...props}
|
|
59
72
|
>
|
|
60
73
|
<ChartStyle id={chartId} config={config} />
|
|
61
|
-
<RechartsPrimitive.ResponsiveContainer
|
|
74
|
+
<RechartsPrimitive.ResponsiveContainer
|
|
75
|
+
initialDimension={initialDimension}
|
|
76
|
+
>
|
|
62
77
|
{children}
|
|
63
78
|
</RechartsPrimitive.ResponsiveContainer>
|
|
64
79
|
</div>
|
|
65
80
|
</ChartContext.Provider>
|
|
66
81
|
)
|
|
67
|
-
}
|
|
68
|
-
ChartContainer.displayName = "Chart"
|
|
82
|
+
}
|
|
69
83
|
|
|
70
84
|
const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
|
|
71
85
|
const colorConfig = Object.entries(config).filter(
|
|
72
|
-
([, config]) => config.theme
|
|
86
|
+
([, config]) => config.theme ?? config.color
|
|
73
87
|
)
|
|
74
88
|
|
|
75
89
|
if (!colorConfig.length) {
|
|
@@ -86,7 +100,7 @@ ${prefix} [data-chart=${id}] {
|
|
|
86
100
|
${colorConfig
|
|
87
101
|
.map(([key, itemConfig]) => {
|
|
88
102
|
const color =
|
|
89
|
-
itemConfig.theme?.[theme as keyof typeof itemConfig.theme]
|
|
103
|
+
itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ??
|
|
90
104
|
itemConfig.color
|
|
91
105
|
return color ? ` --color-${key}: ${color};` : null
|
|
92
106
|
})
|
|
@@ -102,225 +116,217 @@ ${colorConfig
|
|
|
102
116
|
|
|
103
117
|
const ChartTooltip = RechartsPrimitive.Tooltip
|
|
104
118
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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) {
|
|
119
|
+
function ChartTooltipContent({
|
|
120
|
+
active,
|
|
121
|
+
payload,
|
|
122
|
+
className,
|
|
123
|
+
indicator = "dot",
|
|
124
|
+
hideLabel = false,
|
|
125
|
+
hideIndicator = false,
|
|
126
|
+
label,
|
|
127
|
+
labelFormatter,
|
|
128
|
+
labelClassName,
|
|
129
|
+
formatter,
|
|
130
|
+
color,
|
|
131
|
+
nameKey,
|
|
132
|
+
labelKey,
|
|
133
|
+
}: React.ComponentProps<typeof RechartsPrimitive.Tooltip> &
|
|
134
|
+
React.ComponentProps<"div"> & {
|
|
135
|
+
hideLabel?: boolean
|
|
136
|
+
hideIndicator?: boolean
|
|
137
|
+
indicator?: "line" | "dot" | "dashed"
|
|
138
|
+
nameKey?: string
|
|
139
|
+
labelKey?: string
|
|
140
|
+
} & Omit<
|
|
141
|
+
RechartsPrimitive.DefaultTooltipContentProps<
|
|
142
|
+
TooltipValueType,
|
|
143
|
+
TooltipNameType
|
|
144
|
+
>,
|
|
145
|
+
"accessibilityLayer"
|
|
146
|
+
>) {
|
|
147
|
+
const { config } = useChart()
|
|
148
|
+
|
|
149
|
+
const tooltipLabel = React.useMemo(() => {
|
|
150
|
+
if (hideLabel || !payload?.length) {
|
|
173
151
|
return null
|
|
174
152
|
}
|
|
175
153
|
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
{
|
|
187
|
-
|
|
188
|
-
{payload
|
|
189
|
-
.filter((item) => item.type !== "none")
|
|
190
|
-
.map((item, index) => {
|
|
191
|
-
const key = `${nameKey || item.name || item.dataKey || "value"}`
|
|
192
|
-
const itemConfig = getPayloadConfigFromPayload(config, item, key)
|
|
193
|
-
const indicatorColor = color || item.payload.fill || item.color
|
|
194
|
-
|
|
195
|
-
return (
|
|
196
|
-
<div
|
|
197
|
-
key={item.dataKey}
|
|
198
|
-
className={cn(
|
|
199
|
-
"flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground",
|
|
200
|
-
indicator === "dot" && "items-center"
|
|
201
|
-
)}
|
|
202
|
-
>
|
|
203
|
-
{formatter && item?.value !== undefined && item.name ? (
|
|
204
|
-
formatter(item.value, item.name, item, index, item.payload)
|
|
205
|
-
) : (
|
|
206
|
-
<>
|
|
207
|
-
{itemConfig?.icon ? (
|
|
208
|
-
<itemConfig.icon />
|
|
209
|
-
) : (
|
|
210
|
-
!hideIndicator && (
|
|
211
|
-
<div
|
|
212
|
-
className={cn(
|
|
213
|
-
"shrink-0 rounded-[2px] border-[--color-border] bg-[--color-bg]",
|
|
214
|
-
{
|
|
215
|
-
"h-2.5 w-2.5": indicator === "dot",
|
|
216
|
-
"w-1": indicator === "line",
|
|
217
|
-
"w-0 border-[1.5px] border-dashed bg-transparent":
|
|
218
|
-
indicator === "dashed",
|
|
219
|
-
"my-0.5": nestLabel && indicator === "dashed",
|
|
220
|
-
}
|
|
221
|
-
)}
|
|
222
|
-
style={
|
|
223
|
-
{
|
|
224
|
-
"--color-bg": indicatorColor,
|
|
225
|
-
"--color-border": indicatorColor,
|
|
226
|
-
} as React.CSSProperties
|
|
227
|
-
}
|
|
228
|
-
/>
|
|
229
|
-
)
|
|
230
|
-
)}
|
|
231
|
-
<div
|
|
232
|
-
className={cn(
|
|
233
|
-
"flex flex-1 justify-between leading-none",
|
|
234
|
-
nestLabel ? "items-end" : "items-center"
|
|
235
|
-
)}
|
|
236
|
-
>
|
|
237
|
-
<div className="grid gap-1.5">
|
|
238
|
-
{nestLabel ? tooltipLabel : null}
|
|
239
|
-
<span className="text-muted-foreground">
|
|
240
|
-
{itemConfig?.label || item.name}
|
|
241
|
-
</span>
|
|
242
|
-
</div>
|
|
243
|
-
{item.value && (
|
|
244
|
-
<span className="font-mono font-medium tabular-nums text-foreground">
|
|
245
|
-
{item.value.toLocaleString()}
|
|
246
|
-
</span>
|
|
247
|
-
)}
|
|
248
|
-
</div>
|
|
249
|
-
</>
|
|
250
|
-
)}
|
|
251
|
-
</div>
|
|
252
|
-
)
|
|
253
|
-
})}
|
|
154
|
+
const [item] = payload
|
|
155
|
+
const key = `${labelKey ?? item?.dataKey ?? item?.name ?? "value"}`
|
|
156
|
+
const itemConfig = getPayloadConfigFromPayload(config, item, key)
|
|
157
|
+
const value =
|
|
158
|
+
!labelKey && typeof label === "string"
|
|
159
|
+
? (config[label]?.label ?? label)
|
|
160
|
+
: itemConfig?.label
|
|
161
|
+
|
|
162
|
+
if (labelFormatter) {
|
|
163
|
+
return (
|
|
164
|
+
<div className={cn("font-medium", labelClassName)}>
|
|
165
|
+
{labelFormatter(value, payload)}
|
|
254
166
|
</div>
|
|
255
|
-
|
|
256
|
-
)
|
|
257
|
-
}
|
|
258
|
-
)
|
|
259
|
-
ChartTooltipContent.displayName = "ChartTooltip"
|
|
260
|
-
|
|
261
|
-
const ChartLegend = RechartsPrimitive.Legend
|
|
262
|
-
|
|
263
|
-
const ChartLegendContent = React.forwardRef<
|
|
264
|
-
HTMLDivElement,
|
|
265
|
-
React.ComponentProps<"div"> &
|
|
266
|
-
Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & {
|
|
267
|
-
hideIcon?: boolean
|
|
268
|
-
nameKey?: string
|
|
167
|
+
)
|
|
269
168
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
{ className, hideIcon = false, payload, verticalAlign = "bottom", nameKey },
|
|
273
|
-
ref
|
|
274
|
-
) => {
|
|
275
|
-
const { config } = useChart()
|
|
276
|
-
|
|
277
|
-
if (!payload?.length) {
|
|
169
|
+
|
|
170
|
+
if (!value) {
|
|
278
171
|
return null
|
|
279
172
|
}
|
|
280
173
|
|
|
281
|
-
return (
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
174
|
+
return <div className={cn("font-medium", labelClassName)}>{value}</div>
|
|
175
|
+
}, [
|
|
176
|
+
label,
|
|
177
|
+
labelFormatter,
|
|
178
|
+
payload,
|
|
179
|
+
hideLabel,
|
|
180
|
+
labelClassName,
|
|
181
|
+
config,
|
|
182
|
+
labelKey,
|
|
183
|
+
])
|
|
184
|
+
|
|
185
|
+
if (!active || !payload?.length) {
|
|
186
|
+
return null
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const nestLabel = payload.length === 1 && indicator !== "dot"
|
|
190
|
+
|
|
191
|
+
return (
|
|
192
|
+
<div
|
|
193
|
+
className={cn(
|
|
194
|
+
"grid min-w-32 items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl",
|
|
195
|
+
className
|
|
196
|
+
)}
|
|
197
|
+
>
|
|
198
|
+
{!nestLabel ? tooltipLabel : null}
|
|
199
|
+
<div className="grid gap-1.5">
|
|
290
200
|
{payload
|
|
291
201
|
.filter((item) => item.type !== "none")
|
|
292
|
-
.map((item) => {
|
|
293
|
-
const key = `${nameKey
|
|
202
|
+
.map((item, index) => {
|
|
203
|
+
const key = `${nameKey ?? item.name ?? item.dataKey ?? "value"}`
|
|
294
204
|
const itemConfig = getPayloadConfigFromPayload(config, item, key)
|
|
205
|
+
const indicatorColor = color ?? item.payload?.fill ?? item.color
|
|
295
206
|
|
|
296
207
|
return (
|
|
297
208
|
<div
|
|
298
|
-
key={
|
|
209
|
+
key={index}
|
|
299
210
|
className={cn(
|
|
300
|
-
"flex items-
|
|
211
|
+
"flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground",
|
|
212
|
+
indicator === "dot" && "items-center"
|
|
301
213
|
)}
|
|
302
214
|
>
|
|
303
|
-
{
|
|
304
|
-
|
|
215
|
+
{formatter && item?.value !== undefined && item.name ? (
|
|
216
|
+
formatter(item.value, item.name, item, index, item.payload)
|
|
305
217
|
) : (
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
218
|
+
<>
|
|
219
|
+
{itemConfig?.icon ? (
|
|
220
|
+
<itemConfig.icon />
|
|
221
|
+
) : (
|
|
222
|
+
!hideIndicator && (
|
|
223
|
+
<div
|
|
224
|
+
className={cn(
|
|
225
|
+
"shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)",
|
|
226
|
+
{
|
|
227
|
+
"h-2.5 w-2.5": indicator === "dot",
|
|
228
|
+
"w-1": indicator === "line",
|
|
229
|
+
"w-0 border-[1.5px] border-dashed bg-transparent":
|
|
230
|
+
indicator === "dashed",
|
|
231
|
+
"my-0.5": nestLabel && indicator === "dashed",
|
|
232
|
+
}
|
|
233
|
+
)}
|
|
234
|
+
style={
|
|
235
|
+
{
|
|
236
|
+
"--color-bg": indicatorColor,
|
|
237
|
+
"--color-border": indicatorColor,
|
|
238
|
+
} as React.CSSProperties
|
|
239
|
+
}
|
|
240
|
+
/>
|
|
241
|
+
)
|
|
242
|
+
)}
|
|
243
|
+
<div
|
|
244
|
+
className={cn(
|
|
245
|
+
"flex flex-1 justify-between leading-none",
|
|
246
|
+
nestLabel ? "items-end" : "items-center"
|
|
247
|
+
)}
|
|
248
|
+
>
|
|
249
|
+
<div className="grid gap-1.5">
|
|
250
|
+
{nestLabel ? tooltipLabel : null}
|
|
251
|
+
<span className="text-muted-foreground">
|
|
252
|
+
{itemConfig?.label ?? item.name}
|
|
253
|
+
</span>
|
|
254
|
+
</div>
|
|
255
|
+
{item.value != null && (
|
|
256
|
+
<span className="font-mono font-medium text-foreground tabular-nums">
|
|
257
|
+
{typeof item.value === "number"
|
|
258
|
+
? item.value.toLocaleString()
|
|
259
|
+
: String(item.value)}
|
|
260
|
+
</span>
|
|
261
|
+
)}
|
|
262
|
+
</div>
|
|
263
|
+
</>
|
|
312
264
|
)}
|
|
313
|
-
{itemConfig?.label}
|
|
314
265
|
</div>
|
|
315
266
|
)
|
|
316
267
|
})}
|
|
317
268
|
</div>
|
|
318
|
-
|
|
269
|
+
</div>
|
|
270
|
+
)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const ChartLegend = RechartsPrimitive.Legend
|
|
274
|
+
|
|
275
|
+
function ChartLegendContent({
|
|
276
|
+
className,
|
|
277
|
+
hideIcon = false,
|
|
278
|
+
payload,
|
|
279
|
+
verticalAlign = "bottom",
|
|
280
|
+
nameKey,
|
|
281
|
+
}: React.ComponentProps<"div"> & {
|
|
282
|
+
hideIcon?: boolean
|
|
283
|
+
nameKey?: string
|
|
284
|
+
} & RechartsPrimitive.DefaultLegendContentProps) {
|
|
285
|
+
const { config } = useChart()
|
|
286
|
+
|
|
287
|
+
if (!payload?.length) {
|
|
288
|
+
return null
|
|
319
289
|
}
|
|
320
|
-
)
|
|
321
|
-
ChartLegendContent.displayName = "ChartLegend"
|
|
322
290
|
|
|
323
|
-
|
|
291
|
+
return (
|
|
292
|
+
<div
|
|
293
|
+
className={cn(
|
|
294
|
+
"flex items-center justify-center gap-4",
|
|
295
|
+
verticalAlign === "top" ? "pb-3" : "pt-3",
|
|
296
|
+
className
|
|
297
|
+
)}
|
|
298
|
+
>
|
|
299
|
+
{payload
|
|
300
|
+
.filter((item) => item.type !== "none")
|
|
301
|
+
.map((item, index) => {
|
|
302
|
+
const key = `${nameKey ?? item.dataKey ?? "value"}`
|
|
303
|
+
const itemConfig = getPayloadConfigFromPayload(config, item, key)
|
|
304
|
+
|
|
305
|
+
return (
|
|
306
|
+
<div
|
|
307
|
+
key={index}
|
|
308
|
+
className={cn(
|
|
309
|
+
"flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground"
|
|
310
|
+
)}
|
|
311
|
+
>
|
|
312
|
+
{itemConfig?.icon && !hideIcon ? (
|
|
313
|
+
<itemConfig.icon />
|
|
314
|
+
) : (
|
|
315
|
+
<div
|
|
316
|
+
className="h-2 w-2 shrink-0 rounded-[2px]"
|
|
317
|
+
style={{
|
|
318
|
+
backgroundColor: item.color,
|
|
319
|
+
}}
|
|
320
|
+
/>
|
|
321
|
+
)}
|
|
322
|
+
{itemConfig?.label}
|
|
323
|
+
</div>
|
|
324
|
+
)
|
|
325
|
+
})}
|
|
326
|
+
</div>
|
|
327
|
+
)
|
|
328
|
+
}
|
|
329
|
+
|
|
324
330
|
function getPayloadConfigFromPayload(
|
|
325
331
|
config: ChartConfig,
|
|
326
332
|
payload: unknown,
|
|
@@ -354,9 +360,7 @@ function getPayloadConfigFromPayload(
|
|
|
354
360
|
] as string
|
|
355
361
|
}
|
|
356
362
|
|
|
357
|
-
return configLabelKey in config
|
|
358
|
-
? config[configLabelKey]
|
|
359
|
-
: config[key as keyof typeof config]
|
|
363
|
+
return configLabelKey in config ? config[configLabelKey] : config[key]
|
|
360
364
|
}
|
|
361
365
|
|
|
362
366
|
export {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { Checkbox } from "./checkbox";
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'Design System/Checkbox',
|
|
6
|
+
parameters: { layout: 'centered' },
|
|
7
|
+
tags: ['autodocs'],
|
|
8
|
+
} satisfies Meta;
|
|
9
|
+
|
|
10
|
+
export default meta;
|
|
11
|
+
type Story = StoryObj<typeof meta>;
|
|
12
|
+
|
|
13
|
+
export const Default: Story = {
|
|
14
|
+
render: () => (
|
|
15
|
+
<div className="p-4 w-full h-full flex items-center justify-center">
|
|
16
|
+
<div className="flex items-center space-x-2"><Checkbox id="terms" /><label htmlFor="terms" className="text-sm font-medium leading-none">Accept terms and conditions</label></div>
|
|
17
|
+
</div>
|
|
18
|
+
)
|
|
19
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { render } from '@testing-library/react';
|
|
2
|
+
import { axe } from 'jest-axe';
|
|
3
|
+
import { Checkbox } from "./checkbox";
|
|
4
|
+
|
|
5
|
+
describe('Checkbox Accessibility', () => {
|
|
6
|
+
it('should have no accessibility violations in basic render', async () => {
|
|
7
|
+
const Wrapper = () => (
|
|
8
|
+
<div className="flex items-center space-x-2"><Checkbox id="terms" /><label htmlFor="terms" className="text-sm font-medium leading-none">Accept terms and conditions</label></div>
|
|
9
|
+
);
|
|
10
|
+
const { container } = render(<Wrapper />);
|
|
11
|
+
const results = await axe(container);
|
|
12
|
+
expect(results).toHaveNoViolations();
|
|
13
|
+
});
|
|
14
|
+
});
|
|
@@ -1,29 +1,26 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import { CheckIcon } from "lucide-react"
|
|
5
|
-
import { Checkbox as CheckboxPrimitive } from "radix-ui"
|
|
3
|
+
import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox"
|
|
6
4
|
|
|
7
5
|
import { cn } from "@/lib/utils"
|
|
6
|
+
import { CheckIcon } from "lucide-react"
|
|
8
7
|
|
|
9
|
-
function Checkbox({
|
|
10
|
-
className,
|
|
11
|
-
...props
|
|
12
|
-
}: React.ComponentProps<typeof CheckboxPrimitive.Root>) {
|
|
8
|
+
function Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) {
|
|
13
9
|
return (
|
|
14
10
|
<CheckboxPrimitive.Root
|
|
15
11
|
data-slot="checkbox"
|
|
16
12
|
className={cn(
|
|
17
|
-
"peer size-4 shrink-0 rounded-[4px] border border-input
|
|
13
|
+
"peer relative flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input transition-colors outline-none group-has-disabled/field:opacity-50 group-has-[:focus-visible]/field-label:ring-0 group-has-[:focus-visible]/field-label:not-data-checked:border-input after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary cursor-pointer dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary cursor-pointer data-checked:bg-primary data-checked:text-primary-foreground group-has-[:focus-visible]/field-label:data-checked:border-primary cursor-pointer dark:data-checked:bg-primary",
|
|
18
14
|
className
|
|
19
15
|
)}
|
|
20
16
|
{...props}
|
|
21
17
|
>
|
|
22
18
|
<CheckboxPrimitive.Indicator
|
|
23
19
|
data-slot="checkbox-indicator"
|
|
24
|
-
className="grid place-content-center text-current transition-none"
|
|
20
|
+
className="grid place-content-center text-current transition-none [&>svg]:size-3.5"
|
|
25
21
|
>
|
|
26
|
-
<CheckIcon
|
|
22
|
+
<CheckIcon
|
|
23
|
+
/>
|
|
27
24
|
</CheckboxPrimitive.Indicator>
|
|
28
25
|
</CheckboxPrimitive.Root>
|
|
29
26
|
)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { Collapsible, CollapsibleTrigger, CollapsibleContent } from "./collapsible";
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'Design System/Collapsible',
|
|
6
|
+
parameters: { layout: 'centered' },
|
|
7
|
+
tags: ['autodocs'],
|
|
8
|
+
} satisfies Meta;
|
|
9
|
+
|
|
10
|
+
export default meta;
|
|
11
|
+
type Story = StoryObj<typeof meta>;
|
|
12
|
+
|
|
13
|
+
export const Default: Story = {
|
|
14
|
+
render: () => (
|
|
15
|
+
<div className="p-4 w-full h-full flex items-center justify-center">
|
|
16
|
+
<Collapsible><CollapsibleTrigger>Can I use this in my project?</CollapsibleTrigger><CollapsibleContent>Yes. Free to use for personal and commercial projects.</CollapsibleContent></Collapsible>
|
|
17
|
+
</div>
|
|
18
|
+
)
|
|
19
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { render } from '@testing-library/react';
|
|
2
|
+
import { axe } from 'jest-axe';
|
|
3
|
+
import { Collapsible, CollapsibleTrigger, CollapsibleContent } from "./collapsible";
|
|
4
|
+
|
|
5
|
+
describe('Collapsible Accessibility', () => {
|
|
6
|
+
it('should have no accessibility violations in basic render', async () => {
|
|
7
|
+
const Wrapper = () => (
|
|
8
|
+
<Collapsible><CollapsibleTrigger>Can I use this in my project?</CollapsibleTrigger><CollapsibleContent>Yes. Free to use for personal and commercial projects.</CollapsibleContent></Collapsible>
|
|
9
|
+
);
|
|
10
|
+
const { container } = render(<Wrapper />);
|
|
11
|
+
const results = await axe(container);
|
|
12
|
+
expect(results).toHaveNoViolations();
|
|
13
|
+
});
|
|
14
|
+
});
|