@mzc-fe/design-system 0.0.1 → 0.0.2-rc.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/dist/components/accordion.d.ts +7 -0
- package/dist/components/alert-dialog.d.ts +14 -0
- package/dist/components/alert.d.ts +9 -0
- package/dist/components/aspect-ratio.d.ts +3 -0
- package/dist/components/avatar.d.ts +6 -0
- package/dist/components/badge.d.ts +9 -0
- package/dist/components/breadcrumb.d.ts +11 -0
- package/dist/components/button-group.d.ts +11 -0
- package/dist/components/button.d.ts +10 -0
- package/dist/components/calendar.d.ts +8 -0
- package/dist/components/card.d.ts +9 -0
- package/dist/components/carousel.d.ts +19 -0
- package/dist/components/chart.d.ts +40 -0
- package/dist/components/checkbox.d.ts +4 -0
- package/dist/components/collapsible.d.ts +5 -0
- package/dist/components/command.d.ts +18 -0
- package/dist/components/context-menu.d.ts +25 -0
- package/dist/components/dialog.d.ts +15 -0
- package/dist/components/drawer.d.ts +13 -0
- package/dist/components/dropdown-menu.d.ts +25 -0
- package/dist/components/empty.d.ts +11 -0
- package/dist/components/field.d.ts +24 -0
- package/dist/components/form.d.ts +24 -0
- package/dist/components/hover-card.d.ts +6 -0
- package/dist/components/input-group.d.ts +16 -0
- package/dist/components/input-otp.d.ts +11 -0
- package/dist/components/input.d.ts +3 -0
- package/dist/components/item.d.ts +23 -0
- package/dist/components/kbd.d.ts +3 -0
- package/dist/components/label.d.ts +4 -0
- package/dist/components/menubar.d.ts +26 -0
- package/dist/components/navigation-menu.d.ts +14 -0
- package/dist/components/pagination.d.ts +13 -0
- package/dist/components/popover.d.ts +7 -0
- package/dist/components/progress.d.ts +4 -0
- package/dist/components/radio-group.d.ts +5 -0
- package/dist/components/resizable.d.ts +8 -0
- package/dist/components/scroll-area.d.ts +5 -0
- package/dist/components/select.d.ts +15 -0
- package/dist/components/separator.d.ts +4 -0
- package/dist/components/sheet.d.ts +13 -0
- package/dist/components/sidebar.d.ts +69 -0
- package/dist/components/skeleton.d.ts +2 -0
- package/dist/components/slider.d.ts +4 -0
- package/dist/components/sonner.d.ts +3 -0
- package/dist/components/spinner.d.ts +2 -0
- package/dist/components/switch.d.ts +4 -0
- package/dist/components/table.d.ts +10 -0
- package/dist/components/tabs.d.ts +7 -0
- package/dist/components/textarea.d.ts +3 -0
- package/dist/components/toggle-group.d.ts +9 -0
- package/dist/components/toggle.d.ts +9 -0
- package/dist/components/tooltip.d.ts +7 -0
- package/dist/design-system.css +1 -0
- package/dist/design-system.es.js +30200 -0
- package/dist/design-system.umd.js +260 -0
- package/dist/foundations/ThemeProvider.d.ts +13 -0
- package/dist/hooks/use-mobile.d.ts +1 -0
- package/dist/index.d.ts +54 -0
- package/dist/lib/utils.d.ts +2 -0
- package/package.json +14 -1
- package/.husky/pre-push +0 -21
- package/.storybook/main.ts +0 -11
- package/.storybook/preview.tsx +0 -30
- package/.vscode/settings.json +0 -12
- package/.vscode/tailwind.json +0 -105
- package/bitbucket-pipelines.yml +0 -50
- package/components.json +0 -21
- package/eslint.config.js +0 -38
- package/src/components/accordion.stories.tsx +0 -258
- package/src/components/accordion.test.tsx +0 -390
- package/src/components/accordion.tsx +0 -64
- package/src/components/alert-dialog.stories.tsx +0 -213
- package/src/components/alert-dialog.test.tsx +0 -80
- package/src/components/alert-dialog.tsx +0 -155
- package/src/components/alert.stories.tsx +0 -84
- package/src/components/alert.test.tsx +0 -35
- package/src/components/alert.tsx +0 -66
- package/src/components/aspect-ratio.stories.tsx +0 -97
- package/src/components/aspect-ratio.test.tsx +0 -47
- package/src/components/aspect-ratio.tsx +0 -11
- package/src/components/avatar.stories.tsx +0 -76
- package/src/components/avatar.test.tsx +0 -50
- package/src/components/avatar.tsx +0 -51
- package/src/components/badge.stories.tsx +0 -64
- package/src/components/badge.test.tsx +0 -34
- package/src/components/badge.tsx +0 -46
- package/src/components/breadcrumb.stories.tsx +0 -86
- package/src/components/breadcrumb.test.tsx +0 -74
- package/src/components/breadcrumb.tsx +0 -109
- package/src/components/button-group.stories.tsx +0 -62
- package/src/components/button-group.tsx +0 -83
- package/src/components/button.stories.tsx +0 -118
- package/src/components/button.test.tsx +0 -64
- package/src/components/button.tsx +0 -62
- package/src/components/calendar.stories.tsx +0 -81
- package/src/components/calendar.tsx +0 -220
- package/src/components/card.stories.tsx +0 -110
- package/src/components/card.test.tsx +0 -56
- package/src/components/card.tsx +0 -92
- package/src/components/carousel.stories.tsx +0 -90
- package/src/components/carousel.tsx +0 -239
- package/src/components/chart.tsx +0 -357
- package/src/components/checkbox.stories.tsx +0 -108
- package/src/components/checkbox.test.tsx +0 -67
- package/src/components/checkbox.tsx +0 -32
- package/src/components/collapsible.stories.tsx +0 -106
- package/src/components/collapsible.test.tsx +0 -92
- package/src/components/collapsible.tsx +0 -31
- package/src/components/command.stories.tsx +0 -90
- package/src/components/command.tsx +0 -182
- package/src/components/context-menu.stories.tsx +0 -63
- package/src/components/context-menu.tsx +0 -252
- package/src/components/dialog.stories.tsx +0 -128
- package/src/components/dialog.tsx +0 -141
- package/src/components/drawer.stories.tsx +0 -104
- package/src/components/drawer.tsx +0 -135
- package/src/components/dropdown-menu.stories.tsx +0 -97
- package/src/components/dropdown-menu.tsx +0 -255
- package/src/components/empty.stories.tsx +0 -90
- package/src/components/empty.test.tsx +0 -55
- package/src/components/empty.tsx +0 -104
- package/src/components/field.tsx +0 -246
- package/src/components/form.tsx +0 -168
- package/src/components/hover-card.stories.tsx +0 -66
- package/src/components/hover-card.tsx +0 -44
- package/src/components/input-group.stories.tsx +0 -57
- package/src/components/input-group.test.tsx +0 -40
- package/src/components/input-group.tsx +0 -170
- package/src/components/input-otp.stories.tsx +0 -94
- package/src/components/input-otp.test.tsx +0 -60
- package/src/components/input-otp.tsx +0 -75
- package/src/components/input.stories.tsx +0 -94
- package/src/components/input.test.tsx +0 -53
- package/src/components/input.tsx +0 -21
- package/src/components/item.tsx +0 -193
- package/src/components/kbd.stories.tsx +0 -100
- package/src/components/kbd.test.tsx +0 -28
- package/src/components/kbd.tsx +0 -28
- package/src/components/label.stories.tsx +0 -48
- package/src/components/label.test.tsx +0 -28
- package/src/components/label.tsx +0 -24
- package/src/components/menubar.tsx +0 -274
- package/src/components/navigation-menu.tsx +0 -168
- package/src/components/pagination.stories.tsx +0 -107
- package/src/components/pagination.tsx +0 -127
- package/src/components/popover.stories.tsx +0 -102
- package/src/components/popover.tsx +0 -48
- package/src/components/progress.stories.tsx +0 -76
- package/src/components/progress.test.tsx +0 -36
- package/src/components/progress.tsx +0 -29
- package/src/components/radio-group.stories.tsx +0 -73
- package/src/components/radio-group.test.tsx +0 -74
- package/src/components/radio-group.tsx +0 -45
- package/src/components/resizable.stories.tsx +0 -120
- package/src/components/resizable.tsx +0 -54
- package/src/components/scroll-area.stories.tsx +0 -64
- package/src/components/scroll-area.test.tsx +0 -46
- package/src/components/scroll-area.tsx +0 -58
- package/src/components/select.stories.tsx +0 -111
- package/src/components/select.test.tsx +0 -90
- package/src/components/select.tsx +0 -188
- package/src/components/separator.stories.tsx +0 -76
- package/src/components/separator.test.tsx +0 -24
- package/src/components/separator.tsx +0 -28
- package/src/components/sheet.stories.tsx +0 -122
- package/src/components/sheet.tsx +0 -137
- package/src/components/sidebar.tsx +0 -726
- package/src/components/skeleton.stories.tsx +0 -53
- package/src/components/skeleton.test.tsx +0 -24
- package/src/components/skeleton.tsx +0 -13
- package/src/components/slider.stories.tsx +0 -97
- package/src/components/slider.test.tsx +0 -49
- package/src/components/slider.tsx +0 -63
- package/src/components/sonner.stories.tsx +0 -96
- package/src/components/sonner.tsx +0 -38
- package/src/components/spinner.stories.tsx +0 -54
- package/src/components/spinner.test.tsx +0 -30
- package/src/components/spinner.tsx +0 -16
- package/src/components/switch.stories.tsx +0 -108
- package/src/components/switch.test.tsx +0 -62
- package/src/components/switch.tsx +0 -31
- package/src/components/table.stories.tsx +0 -139
- package/src/components/table.test.tsx +0 -85
- package/src/components/table.tsx +0 -114
- package/src/components/tabs.stories.tsx +0 -99
- package/src/components/tabs.test.tsx +0 -64
- package/src/components/tabs.tsx +0 -66
- package/src/components/textarea.stories.tsx +0 -89
- package/src/components/textarea.test.tsx +0 -53
- package/src/components/textarea.tsx +0 -18
- package/src/components/toggle-group.stories.tsx +0 -108
- package/src/components/toggle-group.test.tsx +0 -66
- package/src/components/toggle-group.tsx +0 -81
- package/src/components/toggle.stories.tsx +0 -98
- package/src/components/toggle.test.tsx +0 -42
- package/src/components/toggle.tsx +0 -45
- package/src/components/tooltip.stories.tsx +0 -111
- package/src/components/tooltip.tsx +0 -61
- package/src/foundations/README.md +0 -141
- package/src/foundations/ThemeProvider.tsx +0 -77
- package/src/foundations/color.css +0 -232
- package/src/foundations/color.stories.tsx +0 -719
- package/src/foundations/palette.css +0 -249
- package/src/foundations/spacing.css +0 -8
- package/src/foundations/typography.css +0 -143
- package/src/foundations/typography.stories.tsx +0 -17
- package/src/hooks/use-mobile.ts +0 -19
- package/src/index.css +0 -176
- package/src/index.ts +0 -336
- package/src/lib/utils.ts +0 -6
- package/src/test/setup.ts +0 -8
- package/src/vite-env.d.ts +0 -1
- package/tsconfig.app.json +0 -33
- package/tsconfig.json +0 -13
- package/tsconfig.node.json +0 -25
- package/vite.config.ts +0 -30
- package/vitest.config.ts +0 -25
- /package/{public → dist}/vite.svg +0 -0
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
-
import { Skeleton } from "./skeleton";
|
|
3
|
-
|
|
4
|
-
const meta = {
|
|
5
|
-
title: "Components/Skeleton",
|
|
6
|
-
component: Skeleton,
|
|
7
|
-
parameters: {
|
|
8
|
-
layout: "padded",
|
|
9
|
-
},
|
|
10
|
-
tags: ["autodocs"],
|
|
11
|
-
} satisfies Meta<typeof Skeleton>;
|
|
12
|
-
|
|
13
|
-
export default meta;
|
|
14
|
-
type Story = StoryObj<typeof meta>;
|
|
15
|
-
|
|
16
|
-
export const Default: Story = {
|
|
17
|
-
render: () => <Skeleton className="h-4 w-[250px]" />,
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export const Shapes: Story = {
|
|
21
|
-
render: () => (
|
|
22
|
-
<div className="space-y-4">
|
|
23
|
-
<Skeleton className="h-4 w-[250px]" />
|
|
24
|
-
<Skeleton className="h-4 w-[200px]" />
|
|
25
|
-
<Skeleton className="h-4 w-[150px]" />
|
|
26
|
-
</div>
|
|
27
|
-
),
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export const CardSkeleton: Story = {
|
|
31
|
-
render: () => (
|
|
32
|
-
<div className="flex items-center space-x-4 w-[350px]">
|
|
33
|
-
<Skeleton className="h-12 w-12 rounded-full" />
|
|
34
|
-
<div className="space-y-2 flex-1">
|
|
35
|
-
<Skeleton className="h-4 w-full" />
|
|
36
|
-
<Skeleton className="h-4 w-3/4" />
|
|
37
|
-
</div>
|
|
38
|
-
</div>
|
|
39
|
-
),
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export const ArticleSkeleton: Story = {
|
|
43
|
-
render: () => (
|
|
44
|
-
<div className="space-y-4 w-[400px]">
|
|
45
|
-
<Skeleton className="h-8 w-3/4" />
|
|
46
|
-
<Skeleton className="h-4 w-full" />
|
|
47
|
-
<Skeleton className="h-4 w-full" />
|
|
48
|
-
<Skeleton className="h-4 w-5/6" />
|
|
49
|
-
<Skeleton className="h-[200px] w-full rounded-md" />
|
|
50
|
-
</div>
|
|
51
|
-
),
|
|
52
|
-
};
|
|
53
|
-
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { render } from "@testing-library/react";
|
|
3
|
-
import { Skeleton } from "./skeleton";
|
|
4
|
-
|
|
5
|
-
describe("Skeleton", () => {
|
|
6
|
-
it("should render skeleton", () => {
|
|
7
|
-
const { container } = render(<Skeleton />);
|
|
8
|
-
const skeleton = container.querySelector('[data-slot="skeleton"]');
|
|
9
|
-
expect(skeleton).toBeInTheDocument();
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it("should apply custom className", () => {
|
|
13
|
-
const { container } = render(<Skeleton className="w-20 h-20" />);
|
|
14
|
-
const skeleton = container.querySelector('[data-slot="skeleton"]');
|
|
15
|
-
expect(skeleton).toHaveClass("w-20", "h-20");
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it("should have animate-pulse class", () => {
|
|
19
|
-
const { container } = render(<Skeleton />);
|
|
20
|
-
const skeleton = container.querySelector('[data-slot="skeleton"]');
|
|
21
|
-
expect(skeleton).toHaveClass("animate-pulse");
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { cn } from "@/lib/utils"
|
|
2
|
-
|
|
3
|
-
function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
|
|
4
|
-
return (
|
|
5
|
-
<div
|
|
6
|
-
data-slot="skeleton"
|
|
7
|
-
className={cn("bg-accent animate-pulse rounded-md", className)}
|
|
8
|
-
{...props}
|
|
9
|
-
/>
|
|
10
|
-
)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export { Skeleton }
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
-
import { useState } from "react";
|
|
3
|
-
import { Slider } from "./slider";
|
|
4
|
-
|
|
5
|
-
const meta = {
|
|
6
|
-
title: "Components/Slider",
|
|
7
|
-
component: Slider,
|
|
8
|
-
parameters: {
|
|
9
|
-
layout: "padded",
|
|
10
|
-
},
|
|
11
|
-
tags: ["autodocs"],
|
|
12
|
-
argTypes: {
|
|
13
|
-
defaultValue: {
|
|
14
|
-
control: "object",
|
|
15
|
-
description: "The default value of the slider.",
|
|
16
|
-
},
|
|
17
|
-
min: {
|
|
18
|
-
control: "number",
|
|
19
|
-
description: "The minimum value.",
|
|
20
|
-
},
|
|
21
|
-
max: {
|
|
22
|
-
control: "number",
|
|
23
|
-
description: "The maximum value.",
|
|
24
|
-
},
|
|
25
|
-
step: {
|
|
26
|
-
control: "number",
|
|
27
|
-
description: "The step value.",
|
|
28
|
-
},
|
|
29
|
-
},
|
|
30
|
-
} satisfies Meta<typeof Slider>;
|
|
31
|
-
|
|
32
|
-
export default meta;
|
|
33
|
-
type Story = StoryObj<typeof meta>;
|
|
34
|
-
|
|
35
|
-
export const Default: Story = {
|
|
36
|
-
args: {
|
|
37
|
-
defaultValue: [50],
|
|
38
|
-
max: 100,
|
|
39
|
-
},
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export const WithValue: Story = {
|
|
43
|
-
render: () => {
|
|
44
|
-
const [value, setValue] = useState([50]);
|
|
45
|
-
return (
|
|
46
|
-
<div className="space-y-4 w-[350px]">
|
|
47
|
-
<Slider value={value} onValueChange={setValue} max={100} />
|
|
48
|
-
<div className="text-sm text-muted-foreground">
|
|
49
|
-
Value: {value[0]}
|
|
50
|
-
</div>
|
|
51
|
-
</div>
|
|
52
|
-
);
|
|
53
|
-
},
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
export const Range: Story = {
|
|
57
|
-
render: () => {
|
|
58
|
-
const [value, setValue] = useState([20, 80]);
|
|
59
|
-
return (
|
|
60
|
-
<div className="space-y-4 w-[350px]">
|
|
61
|
-
<Slider value={value} onValueChange={setValue} max={100} />
|
|
62
|
-
<div className="text-sm text-muted-foreground">
|
|
63
|
-
Range: {value[0]} - {value[1]}
|
|
64
|
-
</div>
|
|
65
|
-
</div>
|
|
66
|
-
);
|
|
67
|
-
},
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
export const CustomRange: Story = {
|
|
71
|
-
render: () => {
|
|
72
|
-
const [value, setValue] = useState([25]);
|
|
73
|
-
return (
|
|
74
|
-
<div className="space-y-4 w-[350px]">
|
|
75
|
-
<Slider
|
|
76
|
-
value={value}
|
|
77
|
-
onValueChange={setValue}
|
|
78
|
-
min={0}
|
|
79
|
-
max={1000}
|
|
80
|
-
step={10}
|
|
81
|
-
/>
|
|
82
|
-
<div className="text-sm text-muted-foreground">
|
|
83
|
-
Value: {value[0]} (0-1000, step 10)
|
|
84
|
-
</div>
|
|
85
|
-
</div>
|
|
86
|
-
);
|
|
87
|
-
},
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
export const Disabled: Story = {
|
|
91
|
-
render: () => (
|
|
92
|
-
<div className="w-[350px]">
|
|
93
|
-
<Slider defaultValue={[50]} max={100} disabled />
|
|
94
|
-
</div>
|
|
95
|
-
),
|
|
96
|
-
};
|
|
97
|
-
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from "vitest";
|
|
2
|
-
import { render } from "@testing-library/react";
|
|
3
|
-
import { Slider } from "./slider";
|
|
4
|
-
|
|
5
|
-
describe("Slider", () => {
|
|
6
|
-
it("should render slider", () => {
|
|
7
|
-
const { container } = render(<Slider defaultValue={[50]} />);
|
|
8
|
-
const slider = container.querySelector('[data-slot="slider"]');
|
|
9
|
-
expect(slider).toBeInTheDocument();
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it("should render slider track", () => {
|
|
13
|
-
const { container } = render(<Slider defaultValue={[50]} />);
|
|
14
|
-
const track = container.querySelector('[data-slot="slider-track"]');
|
|
15
|
-
expect(track).toBeInTheDocument();
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it("should render slider thumb", () => {
|
|
19
|
-
const { container } = render(<Slider defaultValue={[50]} />);
|
|
20
|
-
const thumb = container.querySelector('[data-slot="slider-thumb"]');
|
|
21
|
-
expect(thumb).toBeInTheDocument();
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it("should call onValueChange when value changes", async () => {
|
|
25
|
-
const handleChange = vi.fn();
|
|
26
|
-
const { container } = render(
|
|
27
|
-
<Slider value={[50]} onValueChange={handleChange} />
|
|
28
|
-
);
|
|
29
|
-
const thumb = container.querySelector(
|
|
30
|
-
'[data-slot="slider-thumb"]'
|
|
31
|
-
) as HTMLElement;
|
|
32
|
-
// Note: 실제 슬라이더 드래그는 더 복잡한 상호작용이 필요합니다
|
|
33
|
-
expect(thumb).toBeInTheDocument();
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it("should support range values", () => {
|
|
37
|
-
const { container } = render(<Slider value={[20, 80]} />);
|
|
38
|
-
const thumbs = container.querySelectorAll('[data-slot="slider-thumb"]');
|
|
39
|
-
expect(thumbs.length).toBe(2);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("should respect min and max values", () => {
|
|
43
|
-
const { container } = render(
|
|
44
|
-
<Slider defaultValue={[25]} min={0} max={100} />
|
|
45
|
-
);
|
|
46
|
-
const slider = container.querySelector('[data-slot="slider"]');
|
|
47
|
-
expect(slider).toBeInTheDocument();
|
|
48
|
-
});
|
|
49
|
-
});
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
import * as React from "react"
|
|
4
|
-
import * as SliderPrimitive from "@radix-ui/react-slider"
|
|
5
|
-
|
|
6
|
-
import { cn } from "@/lib/utils"
|
|
7
|
-
|
|
8
|
-
function Slider({
|
|
9
|
-
className,
|
|
10
|
-
defaultValue,
|
|
11
|
-
value,
|
|
12
|
-
min = 0,
|
|
13
|
-
max = 100,
|
|
14
|
-
...props
|
|
15
|
-
}: React.ComponentProps<typeof SliderPrimitive.Root>) {
|
|
16
|
-
const _values = React.useMemo(
|
|
17
|
-
() =>
|
|
18
|
-
Array.isArray(value)
|
|
19
|
-
? value
|
|
20
|
-
: Array.isArray(defaultValue)
|
|
21
|
-
? defaultValue
|
|
22
|
-
: [min, max],
|
|
23
|
-
[value, defaultValue, min, max]
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
return (
|
|
27
|
-
<SliderPrimitive.Root
|
|
28
|
-
data-slot="slider"
|
|
29
|
-
defaultValue={defaultValue}
|
|
30
|
-
value={value}
|
|
31
|
-
min={min}
|
|
32
|
-
max={max}
|
|
33
|
-
className={cn(
|
|
34
|
-
"relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col",
|
|
35
|
-
className
|
|
36
|
-
)}
|
|
37
|
-
{...props}
|
|
38
|
-
>
|
|
39
|
-
<SliderPrimitive.Track
|
|
40
|
-
data-slot="slider-track"
|
|
41
|
-
className={cn(
|
|
42
|
-
"bg-muted relative grow overflow-hidden rounded-full data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5"
|
|
43
|
-
)}
|
|
44
|
-
>
|
|
45
|
-
<SliderPrimitive.Range
|
|
46
|
-
data-slot="slider-range"
|
|
47
|
-
className={cn(
|
|
48
|
-
"bg-primary absolute data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full"
|
|
49
|
-
)}
|
|
50
|
-
/>
|
|
51
|
-
</SliderPrimitive.Track>
|
|
52
|
-
{Array.from({ length: _values.length }, (_, index) => (
|
|
53
|
-
<SliderPrimitive.Thumb
|
|
54
|
-
data-slot="slider-thumb"
|
|
55
|
-
key={index}
|
|
56
|
-
className="border-primary ring-ring/50 block size-4 shrink-0 rounded-full border bg-white shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"
|
|
57
|
-
/>
|
|
58
|
-
))}
|
|
59
|
-
</SliderPrimitive.Root>
|
|
60
|
-
)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export { Slider }
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
-
import { Toaster } from "./sonner";
|
|
3
|
-
import { Button } from "./button";
|
|
4
|
-
import { toast } from "sonner";
|
|
5
|
-
|
|
6
|
-
const meta = {
|
|
7
|
-
title: "Components/Sonner",
|
|
8
|
-
component: Toaster,
|
|
9
|
-
parameters: {
|
|
10
|
-
layout: "padded",
|
|
11
|
-
},
|
|
12
|
-
tags: ["autodocs"],
|
|
13
|
-
} satisfies Meta<typeof Toaster>;
|
|
14
|
-
|
|
15
|
-
export default meta;
|
|
16
|
-
type Story = StoryObj<typeof meta>;
|
|
17
|
-
|
|
18
|
-
export const Default: Story = {
|
|
19
|
-
render: () => (
|
|
20
|
-
<>
|
|
21
|
-
<Toaster />
|
|
22
|
-
<div className="flex flex-wrap gap-4">
|
|
23
|
-
<Button
|
|
24
|
-
onClick={() => toast("Event has been created", { description: "Monday, January 3rd at 6:00pm" })}
|
|
25
|
-
>
|
|
26
|
-
Show Toast
|
|
27
|
-
</Button>
|
|
28
|
-
<Button
|
|
29
|
-
variant="outline"
|
|
30
|
-
onClick={() => toast.success("Success!", { description: "Your changes have been saved." })}
|
|
31
|
-
>
|
|
32
|
-
Success
|
|
33
|
-
</Button>
|
|
34
|
-
<Button
|
|
35
|
-
variant="destructive"
|
|
36
|
-
onClick={() => toast.error("Error!", { description: "Something went wrong." })}
|
|
37
|
-
>
|
|
38
|
-
Error
|
|
39
|
-
</Button>
|
|
40
|
-
<Button
|
|
41
|
-
variant="secondary"
|
|
42
|
-
onClick={() => toast.info("Info", { description: "Here's some information." })}
|
|
43
|
-
>
|
|
44
|
-
Info
|
|
45
|
-
</Button>
|
|
46
|
-
<Button
|
|
47
|
-
variant="outline"
|
|
48
|
-
onClick={() => toast.warning("Warning", { description: "Please be careful." })}
|
|
49
|
-
>
|
|
50
|
-
Warning
|
|
51
|
-
</Button>
|
|
52
|
-
</div>
|
|
53
|
-
</>
|
|
54
|
-
),
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
export const WithActions: Story = {
|
|
58
|
-
render: () => (
|
|
59
|
-
<>
|
|
60
|
-
<Toaster />
|
|
61
|
-
<div className="flex gap-4">
|
|
62
|
-
<Button
|
|
63
|
-
onClick={() =>
|
|
64
|
-
toast("Event has been created", {
|
|
65
|
-
description: "Monday, January 3rd at 6:00pm",
|
|
66
|
-
action: {
|
|
67
|
-
label: "Undo",
|
|
68
|
-
onClick: () => console.log("Undo"),
|
|
69
|
-
},
|
|
70
|
-
})
|
|
71
|
-
}
|
|
72
|
-
>
|
|
73
|
-
Toast with Action
|
|
74
|
-
</Button>
|
|
75
|
-
</div>
|
|
76
|
-
</>
|
|
77
|
-
),
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
export const LongDuration: Story = {
|
|
81
|
-
render: () => (
|
|
82
|
-
<>
|
|
83
|
-
<Toaster />
|
|
84
|
-
<Button
|
|
85
|
-
onClick={() =>
|
|
86
|
-
toast("This toast will stay for 10 seconds", {
|
|
87
|
-
duration: 10000,
|
|
88
|
-
})
|
|
89
|
-
}
|
|
90
|
-
>
|
|
91
|
-
Long Duration Toast
|
|
92
|
-
</Button>
|
|
93
|
-
</>
|
|
94
|
-
),
|
|
95
|
-
};
|
|
96
|
-
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CircleCheckIcon,
|
|
3
|
-
InfoIcon,
|
|
4
|
-
Loader2Icon,
|
|
5
|
-
OctagonXIcon,
|
|
6
|
-
TriangleAlertIcon,
|
|
7
|
-
} from "lucide-react";
|
|
8
|
-
import { useTheme } from "next-themes";
|
|
9
|
-
import { Toaster as Sonner, type ToasterProps } from "sonner";
|
|
10
|
-
|
|
11
|
-
const Toaster = ({ ...props }: ToasterProps) => {
|
|
12
|
-
const { theme = "system" } = useTheme();
|
|
13
|
-
|
|
14
|
-
return (
|
|
15
|
-
<Sonner
|
|
16
|
-
theme={theme as ToasterProps["theme"]}
|
|
17
|
-
className="toaster group"
|
|
18
|
-
icons={{
|
|
19
|
-
success: <CircleCheckIcon className="size-4" />,
|
|
20
|
-
info: <InfoIcon className="size-4" />,
|
|
21
|
-
warning: <TriangleAlertIcon className="size-4" />,
|
|
22
|
-
error: <OctagonXIcon className="size-4" />,
|
|
23
|
-
loading: <Loader2Icon className="size-4 animate-spin" />,
|
|
24
|
-
}}
|
|
25
|
-
style={
|
|
26
|
-
{
|
|
27
|
-
"--normal-bg": "var(--popover)",
|
|
28
|
-
"--normal-text": "var(--popover-foreground)",
|
|
29
|
-
"--normal-border": "var(--border)",
|
|
30
|
-
"--border-radius": "var(--radius)",
|
|
31
|
-
} as React.CSSProperties
|
|
32
|
-
}
|
|
33
|
-
{...props}
|
|
34
|
-
/>
|
|
35
|
-
);
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export { Toaster };
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
-
import { Spinner } from "./spinner";
|
|
3
|
-
|
|
4
|
-
const meta = {
|
|
5
|
-
title: "Components/Spinner",
|
|
6
|
-
component: Spinner,
|
|
7
|
-
parameters: {
|
|
8
|
-
layout: "padded",
|
|
9
|
-
},
|
|
10
|
-
tags: ["autodocs"],
|
|
11
|
-
} satisfies Meta<typeof Spinner>;
|
|
12
|
-
|
|
13
|
-
export default meta;
|
|
14
|
-
type Story = StoryObj<typeof meta>;
|
|
15
|
-
|
|
16
|
-
export const Default: Story = {
|
|
17
|
-
render: () => <Spinner />,
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export const Sizes: Story = {
|
|
21
|
-
render: () => (
|
|
22
|
-
<div className="flex items-center gap-4">
|
|
23
|
-
<Spinner className="size-4" />
|
|
24
|
-
<Spinner className="size-6" />
|
|
25
|
-
<Spinner className="size-8" />
|
|
26
|
-
<Spinner className="size-12" />
|
|
27
|
-
</div>
|
|
28
|
-
),
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export const InButton: Story = {
|
|
32
|
-
render: () => (
|
|
33
|
-
<div className="flex gap-4">
|
|
34
|
-
<button className="inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-primary-foreground">
|
|
35
|
-
<Spinner className="size-4" />
|
|
36
|
-
Loading...
|
|
37
|
-
</button>
|
|
38
|
-
<button className="inline-flex items-center gap-2 rounded-md border px-4 py-2">
|
|
39
|
-
<Spinner className="size-4" />
|
|
40
|
-
Processing
|
|
41
|
-
</button>
|
|
42
|
-
</div>
|
|
43
|
-
),
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export const WithText: Story = {
|
|
47
|
-
render: () => (
|
|
48
|
-
<div className="flex items-center gap-2">
|
|
49
|
-
<Spinner />
|
|
50
|
-
<span className="text-sm text-muted-foreground">Loading data...</span>
|
|
51
|
-
</div>
|
|
52
|
-
),
|
|
53
|
-
};
|
|
54
|
-
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { render } from "@testing-library/react";
|
|
3
|
-
import { Spinner } from "./spinner";
|
|
4
|
-
|
|
5
|
-
describe("Spinner", () => {
|
|
6
|
-
it("should render spinner", () => {
|
|
7
|
-
const { container } = render(<Spinner />);
|
|
8
|
-
const spinner = container.querySelector('[role="status"]');
|
|
9
|
-
expect(spinner).toBeInTheDocument();
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it("should have aria-label", () => {
|
|
13
|
-
const { container } = render(<Spinner />);
|
|
14
|
-
const spinner = container.querySelector('[role="status"]');
|
|
15
|
-
expect(spinner).toHaveAttribute("aria-label", "Loading");
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it("should apply custom className", () => {
|
|
19
|
-
const { container } = render(<Spinner className="size-8" />);
|
|
20
|
-
const spinner = container.querySelector('[role="status"]');
|
|
21
|
-
expect(spinner).toHaveClass("size-8");
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it("should have animate-spin class", () => {
|
|
25
|
-
const { container } = render(<Spinner />);
|
|
26
|
-
const spinner = container.querySelector('[role="status"]');
|
|
27
|
-
expect(spinner).toHaveClass("animate-spin");
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { Loader2Icon } from "lucide-react"
|
|
2
|
-
|
|
3
|
-
import { cn } from "@/lib/utils"
|
|
4
|
-
|
|
5
|
-
function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
|
|
6
|
-
return (
|
|
7
|
-
<Loader2Icon
|
|
8
|
-
role="status"
|
|
9
|
-
aria-label="Loading"
|
|
10
|
-
className={cn("size-4 animate-spin", className)}
|
|
11
|
-
{...props}
|
|
12
|
-
/>
|
|
13
|
-
)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export { Spinner }
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
-
import { useState } from "react";
|
|
3
|
-
import { Switch } from "./switch";
|
|
4
|
-
import { Label } from "./label";
|
|
5
|
-
|
|
6
|
-
const meta = {
|
|
7
|
-
title: "Components/Switch",
|
|
8
|
-
component: Switch,
|
|
9
|
-
parameters: {
|
|
10
|
-
layout: "padded",
|
|
11
|
-
},
|
|
12
|
-
tags: ["autodocs"],
|
|
13
|
-
argTypes: {
|
|
14
|
-
checked: {
|
|
15
|
-
control: "boolean",
|
|
16
|
-
description: "Whether the switch is checked.",
|
|
17
|
-
},
|
|
18
|
-
disabled: {
|
|
19
|
-
control: "boolean",
|
|
20
|
-
description: "Whether the switch is disabled.",
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
} satisfies Meta<typeof Switch>;
|
|
24
|
-
|
|
25
|
-
export default meta;
|
|
26
|
-
type Story = StoryObj<typeof meta>;
|
|
27
|
-
|
|
28
|
-
export const Default: Story = {
|
|
29
|
-
render: () => {
|
|
30
|
-
const [checked, setChecked] = useState(false);
|
|
31
|
-
return (
|
|
32
|
-
<div className="flex items-center space-x-2">
|
|
33
|
-
<Switch id="airplane-mode" checked={checked} onCheckedChange={setChecked} />
|
|
34
|
-
<Label htmlFor="airplane-mode">Airplane Mode</Label>
|
|
35
|
-
</div>
|
|
36
|
-
);
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export const Checked: Story = {
|
|
41
|
-
render: () => (
|
|
42
|
-
<div className="flex items-center space-x-2">
|
|
43
|
-
<Switch id="checked" defaultChecked />
|
|
44
|
-
<Label htmlFor="checked">Enabled by default</Label>
|
|
45
|
-
</div>
|
|
46
|
-
),
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
export const Disabled: Story = {
|
|
50
|
-
render: () => (
|
|
51
|
-
<div className="space-y-4">
|
|
52
|
-
<div className="flex items-center space-x-2">
|
|
53
|
-
<Switch id="disabled" disabled />
|
|
54
|
-
<Label htmlFor="disabled">Disabled off</Label>
|
|
55
|
-
</div>
|
|
56
|
-
<div className="flex items-center space-x-2">
|
|
57
|
-
<Switch id="disabled-on" disabled defaultChecked />
|
|
58
|
-
<Label htmlFor="disabled-on">Disabled on</Label>
|
|
59
|
-
</div>
|
|
60
|
-
</div>
|
|
61
|
-
),
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
export const Multiple: Story = {
|
|
65
|
-
render: () => {
|
|
66
|
-
const [settings, setSettings] = useState({
|
|
67
|
-
notifications: true,
|
|
68
|
-
email: false,
|
|
69
|
-
sms: true,
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
return (
|
|
73
|
-
<div className="space-y-3">
|
|
74
|
-
<div className="flex items-center space-x-2">
|
|
75
|
-
<Switch
|
|
76
|
-
id="notifications"
|
|
77
|
-
checked={settings.notifications}
|
|
78
|
-
onCheckedChange={(checked) =>
|
|
79
|
-
setSettings({ ...settings, notifications: checked as boolean })
|
|
80
|
-
}
|
|
81
|
-
/>
|
|
82
|
-
<Label htmlFor="notifications">Notifications</Label>
|
|
83
|
-
</div>
|
|
84
|
-
<div className="flex items-center space-x-2">
|
|
85
|
-
<Switch
|
|
86
|
-
id="email"
|
|
87
|
-
checked={settings.email}
|
|
88
|
-
onCheckedChange={(checked) =>
|
|
89
|
-
setSettings({ ...settings, email: checked as boolean })
|
|
90
|
-
}
|
|
91
|
-
/>
|
|
92
|
-
<Label htmlFor="email">Email</Label>
|
|
93
|
-
</div>
|
|
94
|
-
<div className="flex items-center space-x-2">
|
|
95
|
-
<Switch
|
|
96
|
-
id="sms"
|
|
97
|
-
checked={settings.sms}
|
|
98
|
-
onCheckedChange={(checked) =>
|
|
99
|
-
setSettings({ ...settings, sms: checked as boolean })
|
|
100
|
-
}
|
|
101
|
-
/>
|
|
102
|
-
<Label htmlFor="sms">SMS</Label>
|
|
103
|
-
</div>
|
|
104
|
-
</div>
|
|
105
|
-
);
|
|
106
|
-
},
|
|
107
|
-
};
|
|
108
|
-
|