jongsultest 0.1.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/index.d.mts +339 -0
- package/dist/index.d.ts +339 -0
- package/dist/index.js +1280 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1234 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +59 -0
- package/src/atoms/Badge.stories.tsx +136 -0
- package/src/atoms/Badge.tsx +46 -0
- package/src/atoms/Button.stories.tsx +142 -0
- package/src/atoms/Button.tsx +50 -0
- package/src/atoms/ComboboxAutocomplete.stories.tsx +43 -0
- package/src/atoms/ComboboxAutocomplete.tsx +6 -0
- package/src/atoms/ComboboxSelect.stories.tsx +56 -0
- package/src/atoms/ComboboxSelect.tsx +6 -0
- package/src/atoms/DateTimePicker.stories.tsx +42 -0
- package/src/atoms/DateTimePicker.tsx +6 -0
- package/src/atoms/Icon.stories.tsx +86 -0
- package/src/atoms/Icon.tsx +81 -0
- package/src/atoms/IconButton.stories.tsx +59 -0
- package/src/atoms/IconButton.tsx +19 -0
- package/src/atoms/InputColor.stories.tsx +42 -0
- package/src/atoms/InputColor.tsx +6 -0
- package/src/atoms/InputDatePicker.stories.tsx +55 -0
- package/src/atoms/InputDatePicker.tsx +6 -0
- package/src/atoms/InputFile.stories.tsx +57 -0
- package/src/atoms/InputFile.tsx +15 -0
- package/src/atoms/InputNumber.stories.tsx +58 -0
- package/src/atoms/InputNumber.tsx +15 -0
- package/src/atoms/InputPassword.stories.tsx +42 -0
- package/src/atoms/InputPassword.tsx +24 -0
- package/src/atoms/InputRadio.stories.tsx +65 -0
- package/src/atoms/InputRadio.tsx +19 -0
- package/src/atoms/InputSegmentedControl.stories.tsx +44 -0
- package/src/atoms/InputSegmentedControl.tsx +15 -0
- package/src/atoms/InputSwitch.stories.tsx +45 -0
- package/src/atoms/InputSwitch.tsx +23 -0
- package/src/atoms/InputSwitchInTable.stories.tsx +43 -0
- package/src/atoms/InputSwitchInTable.tsx +35 -0
- package/src/atoms/InputText.stories.tsx +42 -0
- package/src/atoms/InputText.tsx +7 -0
- package/src/atoms/InputTextarea.stories.tsx +50 -0
- package/src/atoms/InputTextarea.tsx +6 -0
- package/src/atoms/index.ts +20 -0
- package/src/atoms/inputClassNames.ts +20 -0
- package/src/blocks/Accordion.stories.tsx +102 -0
- package/src/blocks/Accordion.tsx +124 -0
- package/src/blocks/AccordionDraggable.stories.tsx +169 -0
- package/src/blocks/AccordionDraggable.tsx +200 -0
- package/src/blocks/BoxContainer.stories.tsx +34 -0
- package/src/blocks/BoxContainer.tsx +16 -0
- package/src/blocks/DataTable.tsx +127 -0
- package/src/blocks/DescriptionRow.stories.tsx +34 -0
- package/src/blocks/DescriptionRow.tsx +22 -0
- package/src/blocks/EditorLayout.stories.tsx +79 -0
- package/src/blocks/EditorLayout.tsx +43 -0
- package/src/blocks/ImageUpload.tsx +292 -0
- package/src/blocks/LabeledField.stories.tsx +34 -0
- package/src/blocks/LabeledField.tsx +31 -0
- package/src/blocks/MediDrawer.stories.tsx +58 -0
- package/src/blocks/MediDrawer.tsx +34 -0
- package/src/blocks/Modal.stories.tsx +42 -0
- package/src/blocks/Modal.tsx +31 -0
- package/src/blocks/ModalDeleteConfirm.stories.tsx +31 -0
- package/src/blocks/ModalDeleteConfirm.tsx +56 -0
- package/src/blocks/ModalTokenExpired.tsx +52 -0
- package/src/blocks/NavigationBanner.tsx +100 -0
- package/src/blocks/PageHeader.tsx +24 -0
- package/src/blocks/PageLoading.stories.tsx +22 -0
- package/src/blocks/PageLoading.tsx +19 -0
- package/src/blocks/PageTitle.stories.tsx +39 -0
- package/src/blocks/PageTitle.tsx +25 -0
- package/src/blocks/Pagination.tsx +49 -0
- package/src/blocks/Panel.stories.tsx +84 -0
- package/src/blocks/Panel.tsx +97 -0
- package/src/blocks/SectionGroupWithTitle.stories.tsx +24 -0
- package/src/blocks/SectionGroupWithTitle.tsx +21 -0
- package/src/blocks/Table.tsx +114 -0
- package/src/blocks/TagInput.stories.tsx +74 -0
- package/src/blocks/TagInput.tsx +93 -0
- package/src/blocks/index.ts +25 -0
- package/src/index.ts +51 -0
- package/src/utils/file.ts +7 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { InputDatePicker } from "./InputDatePicker";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof InputDatePicker> = {
|
|
5
|
+
title: "Atoms/InputDatePicker",
|
|
6
|
+
component: InputDatePicker,
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
args: {
|
|
9
|
+
label: "날짜",
|
|
10
|
+
placeholder: "날짜를 선택하세요",
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default meta;
|
|
15
|
+
type Story = StoryObj<typeof InputDatePicker>;
|
|
16
|
+
|
|
17
|
+
export const Default: Story = {};
|
|
18
|
+
|
|
19
|
+
export const WithDescription: Story = {
|
|
20
|
+
args: {
|
|
21
|
+
description: "예약 날짜를 선택하세요",
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const WithError: Story = {
|
|
26
|
+
args: {
|
|
27
|
+
error: "필수 입력 항목입니다",
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const Disabled: Story = {
|
|
32
|
+
args: {
|
|
33
|
+
disabled: true,
|
|
34
|
+
value: new Date(),
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const Required: Story = {
|
|
39
|
+
args: {
|
|
40
|
+
withAsterisk: true,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const WithValue: Story = {
|
|
45
|
+
args: {
|
|
46
|
+
value: new Date(),
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const Clearable: Story = {
|
|
51
|
+
args: {
|
|
52
|
+
clearable: true,
|
|
53
|
+
value: new Date(),
|
|
54
|
+
},
|
|
55
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DatePickerInput as MantineDatePicker, DatePickerInputProps } from "@mantine/dates";
|
|
2
|
+
import { inputClassNames } from "./inputClassNames";
|
|
3
|
+
|
|
4
|
+
export const InputDatePicker = (props: DatePickerInputProps) => {
|
|
5
|
+
return <MantineDatePicker classNames={inputClassNames} {...props} valueFormat="YYYY-MM-DD" />;
|
|
6
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { InputFile } from ".";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof InputFile> = {
|
|
5
|
+
title: "Atoms/InputFile",
|
|
6
|
+
component: InputFile,
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
args: {
|
|
9
|
+
label: "파일 업로드",
|
|
10
|
+
placeholder: "파일을 선택하세요",
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default meta;
|
|
15
|
+
type Story = StoryObj<typeof InputFile>;
|
|
16
|
+
|
|
17
|
+
export const Default: Story = {};
|
|
18
|
+
|
|
19
|
+
export const WithDescription: Story = {
|
|
20
|
+
args: {
|
|
21
|
+
description: "PDF, JPG, PNG 파일만 업로드 가능합니다",
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const WithError: Story = {
|
|
26
|
+
args: {
|
|
27
|
+
error: "파일을 첨부해주세요",
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const Disabled: Story = {
|
|
32
|
+
args: {
|
|
33
|
+
disabled: true,
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const Required: Story = {
|
|
38
|
+
args: {
|
|
39
|
+
withAsterisk: true,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const Multiple: Story = {
|
|
44
|
+
args: {
|
|
45
|
+
multiple: true,
|
|
46
|
+
label: "파일 업로드 (복수 선택)",
|
|
47
|
+
placeholder: "파일을 선택하세요",
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const WithAccept: Story = {
|
|
52
|
+
args: {
|
|
53
|
+
accept: "image/png,image/jpeg",
|
|
54
|
+
label: "이미지 업로드",
|
|
55
|
+
placeholder: "이미지를 선택하세요",
|
|
56
|
+
},
|
|
57
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FileInput as MantineFileInput, type FileInputProps } from "@mantine/core";
|
|
2
|
+
import { inputClassNames } from "./inputClassNames";
|
|
3
|
+
import React from "react";
|
|
4
|
+
|
|
5
|
+
type FileInputComponentProps<Multiple extends boolean = false> = Omit<FileInputProps<Multiple>, "translate"> & {
|
|
6
|
+
translate?: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
type FileInputComponent = (<Multiple extends boolean = false>(
|
|
10
|
+
props: FileInputComponentProps<Multiple>,
|
|
11
|
+
) => React.JSX.Element) & { extend: typeof MantineFileInput.extend };
|
|
12
|
+
|
|
13
|
+
export const InputFile = ((props: FileInputComponentProps) => {
|
|
14
|
+
return <MantineFileInput classNames={inputClassNames} {...(props as FileInputProps)} />;
|
|
15
|
+
}) as FileInputComponent;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { InputNumber } from "./InputNumber";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof InputNumber> = {
|
|
5
|
+
title: "Atoms/InputNumber",
|
|
6
|
+
component: InputNumber,
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
args: {
|
|
9
|
+
label: "수량",
|
|
10
|
+
placeholder: "숫자를 입력하세요",
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default meta;
|
|
15
|
+
type Story = StoryObj<typeof InputNumber>;
|
|
16
|
+
|
|
17
|
+
export const Default: Story = {};
|
|
18
|
+
|
|
19
|
+
export const WithDescription: Story = {
|
|
20
|
+
args: {
|
|
21
|
+
description: "1 이상의 숫자를 입력하세요",
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const WithError: Story = {
|
|
26
|
+
args: {
|
|
27
|
+
error: "필수 입력 항목입니다",
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const Disabled: Story = {
|
|
32
|
+
args: {
|
|
33
|
+
disabled: true,
|
|
34
|
+
value: 10,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const Required: Story = {
|
|
39
|
+
args: {
|
|
40
|
+
withAsterisk: true,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const WithMinMax: Story = {
|
|
45
|
+
args: {
|
|
46
|
+
min: 0,
|
|
47
|
+
max: 100,
|
|
48
|
+
value: 50,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const WithStep: Story = {
|
|
53
|
+
args: {
|
|
54
|
+
step: 5,
|
|
55
|
+
min: 0,
|
|
56
|
+
max: 100,
|
|
57
|
+
},
|
|
58
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { NumberInput as MantineNumberInput, NumberInputProps } from "@mantine/core";
|
|
2
|
+
import { inputClassNames } from "./inputClassNames";
|
|
3
|
+
|
|
4
|
+
export const InputNumber = (props: NumberInputProps) => {
|
|
5
|
+
return (
|
|
6
|
+
<MantineNumberInput
|
|
7
|
+
classNames={{
|
|
8
|
+
...inputClassNames,
|
|
9
|
+
controls: "!h-8 !border-input",
|
|
10
|
+
control: "!border-input",
|
|
11
|
+
}}
|
|
12
|
+
{...props}
|
|
13
|
+
/>
|
|
14
|
+
);
|
|
15
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { InputPassword } from "./InputPassword";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof InputPassword> = {
|
|
5
|
+
title: "Atoms/InputPassword",
|
|
6
|
+
component: InputPassword,
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
args: {
|
|
9
|
+
label: "비밀번호",
|
|
10
|
+
placeholder: "비밀번호를 입력하세요",
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default meta;
|
|
15
|
+
type Story = StoryObj<typeof InputPassword>;
|
|
16
|
+
|
|
17
|
+
export const Default: Story = {};
|
|
18
|
+
|
|
19
|
+
export const WithDescription: Story = {
|
|
20
|
+
args: {
|
|
21
|
+
description: "8자 이상 입력해주세요",
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const WithError: Story = {
|
|
26
|
+
args: {
|
|
27
|
+
error: "비밀번호가 올바르지 않습니다",
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const Disabled: Story = {
|
|
32
|
+
args: {
|
|
33
|
+
disabled: true,
|
|
34
|
+
value: "password123",
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const Required: Story = {
|
|
39
|
+
args: {
|
|
40
|
+
withAsterisk: true,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { PasswordInput as MantinePasswordInput, PasswordInputProps } from "@mantine/core";
|
|
2
|
+
import { IconAlertCircle } from "@tabler/icons-react";
|
|
3
|
+
import { inputClassNames } from "./inputClassNames";
|
|
4
|
+
|
|
5
|
+
export const InputPassword = (props: PasswordInputProps) => {
|
|
6
|
+
const { error } = props;
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<MantinePasswordInput
|
|
10
|
+
classNames={inputClassNames}
|
|
11
|
+
error={
|
|
12
|
+
typeof error === "string" ? (
|
|
13
|
+
<span className="flex items-start gap-2">
|
|
14
|
+
<IconAlertCircle size={16} className="mt-[2px] shrink-0" />
|
|
15
|
+
<span>{error}</span>
|
|
16
|
+
</span>
|
|
17
|
+
) : (
|
|
18
|
+
error
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
{...props}
|
|
22
|
+
/>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { InputRadio } from "./InputRadio";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof InputRadio.Group> = {
|
|
5
|
+
title: "Atoms/InputRadio",
|
|
6
|
+
component: InputRadio.Group,
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default meta;
|
|
11
|
+
type Story = StoryObj<typeof InputRadio.Group>;
|
|
12
|
+
|
|
13
|
+
export const Default: Story = {
|
|
14
|
+
args: {
|
|
15
|
+
label: "성별",
|
|
16
|
+
defaultValue: "male",
|
|
17
|
+
children: (
|
|
18
|
+
<>
|
|
19
|
+
<InputRadio value="male" label="남성" />
|
|
20
|
+
<InputRadio value="female" label="여성" />
|
|
21
|
+
</>
|
|
22
|
+
),
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const WithDescription: Story = {
|
|
27
|
+
args: {
|
|
28
|
+
label: "알림 수단",
|
|
29
|
+
description: "알림을 받을 수단을 선택해주세요",
|
|
30
|
+
children: (
|
|
31
|
+
<>
|
|
32
|
+
<InputRadio value="sms" label="SMS" />
|
|
33
|
+
<InputRadio value="email" label="이메일" />
|
|
34
|
+
<InputRadio value="push" label="푸시 알림" />
|
|
35
|
+
</>
|
|
36
|
+
),
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const WithError: Story = {
|
|
41
|
+
args: {
|
|
42
|
+
label: "필수 선택",
|
|
43
|
+
error: "항목을 선택해주세요",
|
|
44
|
+
children: (
|
|
45
|
+
<>
|
|
46
|
+
<InputRadio value="a" label="옵션 A" />
|
|
47
|
+
<InputRadio value="b" label="옵션 B" />
|
|
48
|
+
</>
|
|
49
|
+
),
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const Required: Story = {
|
|
54
|
+
args: {
|
|
55
|
+
label: "통화",
|
|
56
|
+
withAsterisk: true,
|
|
57
|
+
defaultValue: "KRW",
|
|
58
|
+
children: (
|
|
59
|
+
<>
|
|
60
|
+
<InputRadio value="KRW" label="원화 (KRW)" />
|
|
61
|
+
<InputRadio value="CNY" label="위안화 (CNY)" />
|
|
62
|
+
</>
|
|
63
|
+
),
|
|
64
|
+
},
|
|
65
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Radio as MantineRadio,
|
|
3
|
+
RadioProps as MantineRadioProps,
|
|
4
|
+
RadioGroupProps as MantineRadioGroupProps,
|
|
5
|
+
} from "@mantine/core";
|
|
6
|
+
|
|
7
|
+
import { inputClassNames } from "./inputClassNames";
|
|
8
|
+
|
|
9
|
+
const RadioBase = (props: MantineRadioProps) => {
|
|
10
|
+
return <MantineRadio {...props} />;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const RadioGroup = (props: MantineRadioGroupProps) => {
|
|
14
|
+
return <MantineRadio.Group classNames={{ label: inputClassNames.label }} {...props} />;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const InputRadio = Object.assign(RadioBase, {
|
|
18
|
+
Group: RadioGroup,
|
|
19
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { InputSegmentedControl } from "./InputSegmentedControl";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof InputSegmentedControl> = {
|
|
5
|
+
title: "Atoms/InputSegmentedControl",
|
|
6
|
+
component: InputSegmentedControl,
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
args: {
|
|
9
|
+
data: ["전체", "활성", "비활성"],
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
type Story = StoryObj<typeof InputSegmentedControl>;
|
|
15
|
+
|
|
16
|
+
export const Default: Story = {};
|
|
17
|
+
|
|
18
|
+
export const WithDefaultValue: Story = {
|
|
19
|
+
args: {
|
|
20
|
+
defaultValue: "비활성",
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const Disabled: Story = {
|
|
25
|
+
args: {
|
|
26
|
+
disabled: true,
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const FullWidth: Story = {
|
|
31
|
+
args: {
|
|
32
|
+
fullWidth: true,
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const WithObjectData: Story = {
|
|
37
|
+
args: {
|
|
38
|
+
data: [
|
|
39
|
+
{ label: "일별", value: "daily" },
|
|
40
|
+
{ label: "주별", value: "weekly" },
|
|
41
|
+
{ label: "월별", value: "monthly" },
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { SegmentedControl as MantineSegmentedControl, type SegmentedControlProps } from "@mantine/core";
|
|
2
|
+
|
|
3
|
+
export const InputSegmentedControl = (props: SegmentedControlProps) => {
|
|
4
|
+
return (
|
|
5
|
+
<MantineSegmentedControl
|
|
6
|
+
classNames={{
|
|
7
|
+
root: "p-2! rounded-md!", // 루트
|
|
8
|
+
control: "", // 버튼
|
|
9
|
+
label: "h-10 px-4 text-sm", // 텍스트 패딩/타이포
|
|
10
|
+
innerLabel: "leading-9 color-white", // 선택 인디케이터 높이도 같이
|
|
11
|
+
}}
|
|
12
|
+
{...props}
|
|
13
|
+
/>
|
|
14
|
+
);
|
|
15
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { InputSwitch } from "./InputSwitch";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof InputSwitch> = {
|
|
5
|
+
title: "Atoms/InputSwitch",
|
|
6
|
+
component: InputSwitch,
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
args: {
|
|
9
|
+
label: "활성화",
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
type Story = StoryObj<typeof InputSwitch>;
|
|
15
|
+
|
|
16
|
+
export const Default: Story = {};
|
|
17
|
+
|
|
18
|
+
export const Checked: Story = {
|
|
19
|
+
args: {
|
|
20
|
+
checked: true,
|
|
21
|
+
label: "활성",
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const Unchecked: Story = {
|
|
26
|
+
args: {
|
|
27
|
+
checked: false,
|
|
28
|
+
label: "비활성",
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const Disabled: Story = {
|
|
33
|
+
args: {
|
|
34
|
+
disabled: true,
|
|
35
|
+
checked: true,
|
|
36
|
+
label: "변경 불가",
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const WithoutLabel: Story = {
|
|
41
|
+
args: {
|
|
42
|
+
label: undefined,
|
|
43
|
+
checked: true,
|
|
44
|
+
},
|
|
45
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Switch as MantineSwitch, SwitchProps as MantineSwitchProps } from "@mantine/core";
|
|
2
|
+
import { IconCheck } from "@tabler/icons-react";
|
|
3
|
+
|
|
4
|
+
type SwitchProps = MantineSwitchProps;
|
|
5
|
+
|
|
6
|
+
export const InputSwitch = ({ checked, style, classNames, ...props }: SwitchProps) => {
|
|
7
|
+
return (
|
|
8
|
+
<MantineSwitch
|
|
9
|
+
checked={checked}
|
|
10
|
+
thumbIcon={<IconCheck size={10} color="white" stroke={3} />}
|
|
11
|
+
{...props}
|
|
12
|
+
style={{
|
|
13
|
+
...((typeof style === "object" && style) || {}),
|
|
14
|
+
...(!checked && { "--switch-thumb-start": "6px" }),
|
|
15
|
+
}}
|
|
16
|
+
classNames={{
|
|
17
|
+
thumb: "!w-[10px] !h-[10px] text-white",
|
|
18
|
+
label: "!text-gray-6 !font-medium",
|
|
19
|
+
...classNames,
|
|
20
|
+
}}
|
|
21
|
+
/>
|
|
22
|
+
);
|
|
23
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { InputSwitchInTable } from "./InputSwitchInTable";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof InputSwitchInTable> = {
|
|
5
|
+
title: "Atoms/InputSwitchInTable",
|
|
6
|
+
component: InputSwitchInTable,
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
args: {
|
|
9
|
+
id: 1,
|
|
10
|
+
onStatusChange: () => {},
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default meta;
|
|
15
|
+
type Story = StoryObj<typeof InputSwitchInTable>;
|
|
16
|
+
|
|
17
|
+
export const Active: Story = {
|
|
18
|
+
args: {
|
|
19
|
+
status: "ACTIVE",
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const Hidden: Story = {
|
|
24
|
+
args: {
|
|
25
|
+
status: "HIDDEN",
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const CustomLabels: Story = {
|
|
30
|
+
args: {
|
|
31
|
+
status: "ACTIVE",
|
|
32
|
+
activeLabel: "공개",
|
|
33
|
+
inactiveLabel: "비공개",
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const CustomValues: Story = {
|
|
38
|
+
args: {
|
|
39
|
+
status: "ON",
|
|
40
|
+
activeValue: "ON",
|
|
41
|
+
inactiveValue: "OFF",
|
|
42
|
+
},
|
|
43
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Box } from "@mantine/core";
|
|
2
|
+
import { InputSwitch } from "./InputSwitch";
|
|
3
|
+
|
|
4
|
+
interface SwitchInTableProps<T extends string> {
|
|
5
|
+
status: T;
|
|
6
|
+
onStatusChange: (id: number, status: T) => void;
|
|
7
|
+
id: number;
|
|
8
|
+
activeValue?: T;
|
|
9
|
+
inactiveValue?: T;
|
|
10
|
+
activeLabel?: string;
|
|
11
|
+
inactiveLabel?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const InputSwitchInTable = <T extends string>({
|
|
15
|
+
status,
|
|
16
|
+
onStatusChange,
|
|
17
|
+
id,
|
|
18
|
+
activeValue = "ACTIVE" as T,
|
|
19
|
+
inactiveValue = "HIDDEN" as T,
|
|
20
|
+
activeLabel = "활성",
|
|
21
|
+
inactiveLabel = "숨김",
|
|
22
|
+
}: SwitchInTableProps<T>) => {
|
|
23
|
+
const isActive = status === activeValue;
|
|
24
|
+
return (
|
|
25
|
+
<Box onClick={(e) => e.stopPropagation()}>
|
|
26
|
+
<InputSwitch
|
|
27
|
+
checked={isActive}
|
|
28
|
+
// label={isActive ? activeLabel : inactiveLabel}
|
|
29
|
+
onChange={() => onStatusChange(id, isActive ? inactiveValue : activeValue)}
|
|
30
|
+
size="sm"
|
|
31
|
+
classNames={{ label: "!font-semibold" }}
|
|
32
|
+
/>
|
|
33
|
+
</Box>
|
|
34
|
+
);
|
|
35
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { InputText } from "./InputText";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof InputText> = {
|
|
5
|
+
title: "Atoms/InputText",
|
|
6
|
+
component: InputText,
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
args: {
|
|
9
|
+
label: "이름",
|
|
10
|
+
placeholder: "이름을 입력하세요",
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default meta;
|
|
15
|
+
type Story = StoryObj<typeof InputText>;
|
|
16
|
+
|
|
17
|
+
export const Default: Story = {};
|
|
18
|
+
|
|
19
|
+
export const WithDescription: Story = {
|
|
20
|
+
args: {
|
|
21
|
+
description: "한글 또는 영문으로 입력해주세요",
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const WithError: Story = {
|
|
26
|
+
args: {
|
|
27
|
+
error: "필수 입력 항목입니다",
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const Disabled: Story = {
|
|
32
|
+
args: {
|
|
33
|
+
disabled: true,
|
|
34
|
+
value: "홍길동",
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const Required: Story = {
|
|
39
|
+
args: {
|
|
40
|
+
withAsterisk: true,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { TextInput as MantineTextInput, TextInputProps } from "@mantine/core";
|
|
2
|
+
|
|
3
|
+
import { inputClassNames } from "./inputClassNames";
|
|
4
|
+
|
|
5
|
+
export const InputText = (props: TextInputProps) => {
|
|
6
|
+
return <MantineTextInput classNames={inputClassNames} {...props} />;
|
|
7
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { InputTextarea } from "./InputTextarea";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof InputTextarea> = {
|
|
5
|
+
title: "Atoms/InputTextarea",
|
|
6
|
+
component: InputTextarea,
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
args: {
|
|
9
|
+
label: "내용",
|
|
10
|
+
placeholder: "내용을 입력하세요",
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default meta;
|
|
15
|
+
type Story = StoryObj<typeof InputTextarea>;
|
|
16
|
+
|
|
17
|
+
export const Default: Story = {};
|
|
18
|
+
|
|
19
|
+
export const WithDescription: Story = {
|
|
20
|
+
args: {
|
|
21
|
+
description: "최대 500자까지 입력 가능합니다",
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const WithError: Story = {
|
|
26
|
+
args: {
|
|
27
|
+
error: "필수 입력 항목입니다",
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const Disabled: Story = {
|
|
32
|
+
args: {
|
|
33
|
+
disabled: true,
|
|
34
|
+
value: "비활성화된 텍스트",
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const Required: Story = {
|
|
39
|
+
args: {
|
|
40
|
+
withAsterisk: true,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const Autosize: Story = {
|
|
45
|
+
args: {
|
|
46
|
+
autosize: true,
|
|
47
|
+
minRows: 3,
|
|
48
|
+
maxRows: 6,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Textarea as MantineTextarea, TextareaProps } from "@mantine/core";
|
|
2
|
+
import { inputClassNames } from "./inputClassNames";
|
|
3
|
+
|
|
4
|
+
export const InputTextarea = (props: TextareaProps) => {
|
|
5
|
+
return <MantineTextarea classNames={{ ...inputClassNames, input: `${inputClassNames.input} !py-3` }} {...props} />;
|
|
6
|
+
};
|