@pop-ui/core 0.0.10
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/LICENSE.md +21 -0
- package/dist/components/Alert/Alert.stories.js +18 -0
- package/dist/components/Alert/index.js +38 -0
- package/dist/components/Button/Button.stories.js +42 -0
- package/dist/components/Button/index.js +33 -0
- package/dist/components/Checkbox/Checkbox.stories.js +14 -0
- package/dist/components/Checkbox/index.js +27 -0
- package/dist/components/DatePicker/DatePicker.stories.js +27 -0
- package/dist/components/DatePicker/index.js +29 -0
- package/dist/components/Dropdown/Dropdown.stories.js +16 -0
- package/dist/components/Dropdown/index.js +50 -0
- package/dist/components/ImageUploader/ImageUploader.stories.js +9 -0
- package/dist/components/ImageUploader/index.js +37 -0
- package/dist/components/Modal/Modal.stories.js +13 -0
- package/dist/components/Modal/index.js +25 -0
- package/dist/components/Pagination/Pagination.stories.js +14 -0
- package/dist/components/Pagination/index.js +56 -0
- package/dist/components/Radio/Radio.stories.js +14 -0
- package/dist/components/Radio/index.js +19 -0
- package/dist/components/SearchBar/SearchBar.stories.js +16 -0
- package/dist/components/SearchBar/index.js +46 -0
- package/dist/components/SegmentButton/SegmentButton.stories.js +14 -0
- package/dist/components/SegmentButton/index.js +24 -0
- package/dist/components/Tab/Tab.stories.js +28 -0
- package/dist/components/Tab/index.js +18 -0
- package/dist/components/Table/Table.stories.js +127 -0
- package/dist/components/Table/index.js +129 -0
- package/dist/components/TextField/TextField.stories.js +36 -0
- package/dist/components/TextField/index.js +60 -0
- package/dist/components/TimePicker/TimePicker.stories.js +13 -0
- package/dist/components/TimePicker/index.js +30 -0
- package/dist/components/Toggle/Toggle.stories.js +15 -0
- package/dist/components/Toggle/index.js +41 -0
- package/dist/components/Tooltip/Tooltip.stories.js +24 -0
- package/dist/components/Tooltip/index.js +13 -0
- package/dist/components/index.js +17 -0
- package/dist/components/shared/styles.js +219 -0
- package/dist/core.css +1 -0
- package/dist/core.js +746 -0
- package/dist/core.umd.cjs +1 -0
- package/dist/helpers/checkMessage/checkMessage.test.js +9 -0
- package/dist/helpers/checkMessage/index.js +8 -0
- package/dist/index.js +1 -0
- package/dist/types/components/Alert/Alert.stories.d.ts +3 -0
- package/dist/types/components/Alert/index.d.ts +17 -0
- package/dist/types/components/Button/Button.stories.d.ts +7 -0
- package/dist/types/components/Button/index.d.ts +14 -0
- package/dist/types/components/Checkbox/Checkbox.stories.d.ts +3 -0
- package/dist/types/components/Checkbox/index.d.ts +11 -0
- package/dist/types/components/DatePicker/DatePicker.stories.d.ts +5 -0
- package/dist/types/components/DatePicker/index.d.ts +16 -0
- package/dist/types/components/Dropdown/Dropdown.stories.d.ts +3 -0
- package/dist/types/components/Dropdown/index.d.ts +23 -0
- package/dist/types/components/ImageUploader/ImageUploader.stories.d.ts +3 -0
- package/dist/types/components/ImageUploader/index.d.ts +22 -0
- package/dist/types/components/Modal/Modal.stories.d.ts +3 -0
- package/dist/types/components/Modal/index.d.ts +13 -0
- package/dist/types/components/Pagination/Pagination.stories.d.ts +3 -0
- package/dist/types/components/Pagination/index.d.ts +18 -0
- package/dist/types/components/Radio/Radio.stories.d.ts +3 -0
- package/dist/types/components/Radio/index.d.ts +11 -0
- package/dist/types/components/SearchBar/SearchBar.stories.d.ts +3 -0
- package/dist/types/components/SearchBar/index.d.ts +27 -0
- package/dist/types/components/SegmentButton/SegmentButton.stories.d.ts +3 -0
- package/dist/types/components/SegmentButton/index.d.ts +13 -0
- package/dist/types/components/Tab/Tab.stories.d.ts +3 -0
- package/dist/types/components/Tab/index.d.ts +24 -0
- package/dist/types/components/Table/Table.stories.d.ts +5 -0
- package/dist/types/components/Table/index.d.ts +41 -0
- package/dist/types/components/TextField/TextField.stories.d.ts +5 -0
- package/dist/types/components/TextField/index.d.ts +35 -0
- package/dist/types/components/TimePicker/TimePicker.stories.d.ts +3 -0
- package/dist/types/components/TimePicker/index.d.ts +11 -0
- package/dist/types/components/Toggle/Toggle.stories.d.ts +3 -0
- package/dist/types/components/Toggle/index.d.ts +17 -0
- package/dist/types/components/Tooltip/Tooltip.stories.d.ts +3 -0
- package/dist/types/components/Tooltip/index.d.ts +13 -0
- package/dist/types/components/index.d.ts +17 -0
- package/dist/types/components/shared/styles.d.ts +86 -0
- package/dist/types/helpers/checkMessage/checkMessage.test.d.ts +1 -0
- package/dist/types/helpers/checkMessage/index.d.ts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +95 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 (주)텐핑거스
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Alert } from ".";
|
|
3
|
+
export default {
|
|
4
|
+
title: "Core/Alert",
|
|
5
|
+
component: Alert,
|
|
6
|
+
};
|
|
7
|
+
const Template = (args) => _jsx(Alert, { ...args });
|
|
8
|
+
export const defaultAlert = Template.bind({});
|
|
9
|
+
defaultAlert.args = {
|
|
10
|
+
visible: true,
|
|
11
|
+
type: "success",
|
|
12
|
+
variant: "light",
|
|
13
|
+
title: "alert title",
|
|
14
|
+
children: "alert content",
|
|
15
|
+
top: 0,
|
|
16
|
+
left: 0,
|
|
17
|
+
right: 0,
|
|
18
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Alert as MantineAlert, } from "@mantine/core";
|
|
3
|
+
import ic_success from "../../assets/icons/ic_success.svg";
|
|
4
|
+
import ic_error from "../../assets/icons/ic_error.svg";
|
|
5
|
+
import styles from "./styles.module.scss";
|
|
6
|
+
/**
|
|
7
|
+
* ----- alert props -----
|
|
8
|
+
** visible: 노출 여부
|
|
9
|
+
** type: 'success' | 'error'
|
|
10
|
+
** variant: 'fill' | 'light'
|
|
11
|
+
** title: alert 타이틀
|
|
12
|
+
** 기타 props는 mantine alert props 사용: https://v6.mantine.dev/core/alert/?t=props
|
|
13
|
+
*/
|
|
14
|
+
export const Alert = ({ visible = false, type = "success", variant = "light", top = 48, right = 48, ...props }) => {
|
|
15
|
+
let typeStyle = styles.light_success;
|
|
16
|
+
if (variant === "fill") {
|
|
17
|
+
if (type === "success") {
|
|
18
|
+
typeStyle = styles.fill_success;
|
|
19
|
+
}
|
|
20
|
+
else if (type === "error") {
|
|
21
|
+
typeStyle = styles.fill_error;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
if (type === "success") {
|
|
26
|
+
typeStyle = styles.light_success;
|
|
27
|
+
}
|
|
28
|
+
else if (type === "error") {
|
|
29
|
+
typeStyle = styles.light_error;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return visible ? (_jsx(MantineAlert, { className: typeStyle, icon: _jsx("img", { src: type === "success" ? ic_success : ic_error, alt: "alert_icon" }), styles: {
|
|
33
|
+
title: {
|
|
34
|
+
marginBottom: !props?.children ? 0 : undefined,
|
|
35
|
+
},
|
|
36
|
+
}, pos: "fixed", top: top, right: right, ...props })) : null;
|
|
37
|
+
};
|
|
38
|
+
export default Alert;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Button } from ".";
|
|
3
|
+
export default {
|
|
4
|
+
title: "Core/Button",
|
|
5
|
+
component: Button,
|
|
6
|
+
};
|
|
7
|
+
const Template = (args) => _jsx(Button, { ...args });
|
|
8
|
+
export const PrimaryButton = Template.bind({});
|
|
9
|
+
PrimaryButton.args = {
|
|
10
|
+
children: "데이트팝 Button",
|
|
11
|
+
styleType: "primary",
|
|
12
|
+
size: "md",
|
|
13
|
+
disabled: false,
|
|
14
|
+
};
|
|
15
|
+
export const PrimaryLineButton = Template.bind({});
|
|
16
|
+
PrimaryLineButton.args = {
|
|
17
|
+
children: "데이트팝 Button",
|
|
18
|
+
styleType: "primaryline",
|
|
19
|
+
size: "md",
|
|
20
|
+
disabled: false,
|
|
21
|
+
};
|
|
22
|
+
export const BasicButton = Template.bind({});
|
|
23
|
+
BasicButton.args = {
|
|
24
|
+
children: "데이트팝 Button",
|
|
25
|
+
styleType: "basic",
|
|
26
|
+
size: "md",
|
|
27
|
+
disabled: false,
|
|
28
|
+
};
|
|
29
|
+
export const DangerButton = Template.bind({});
|
|
30
|
+
DangerButton.args = {
|
|
31
|
+
children: "데이트팝 Button",
|
|
32
|
+
styleType: "danger",
|
|
33
|
+
size: "md",
|
|
34
|
+
disabled: false,
|
|
35
|
+
};
|
|
36
|
+
export const SettingButton = Template.bind({});
|
|
37
|
+
SettingButton.args = {
|
|
38
|
+
children: "데이트팝 Button",
|
|
39
|
+
styleType: "setting",
|
|
40
|
+
size: "md",
|
|
41
|
+
disabled: false,
|
|
42
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Button as MantineButton, } from "@mantine/core";
|
|
3
|
+
import styles from "./styles.module.scss";
|
|
4
|
+
/**
|
|
5
|
+
* ----- button props -----
|
|
6
|
+
** size: 'sm' | 'md' | 'lg'
|
|
7
|
+
** styleType: 'primary' | 'primaryline' | 'basic' | 'danger' | 'setting'
|
|
8
|
+
** 기타 props는 mantine button props 사용: https://v6.mantine.dev/core/button/?t=props
|
|
9
|
+
*/
|
|
10
|
+
export const Button = ({ children, size = "md", styleType = "primary", ...props }) => {
|
|
11
|
+
let sizeStyle = styles.md_button;
|
|
12
|
+
if (size === "sm") {
|
|
13
|
+
sizeStyle = styles.sm_button;
|
|
14
|
+
}
|
|
15
|
+
else if (size === "lg") {
|
|
16
|
+
sizeStyle = styles.lg_button;
|
|
17
|
+
}
|
|
18
|
+
let buttonStyle = styles.primary;
|
|
19
|
+
if (styleType === "basic") {
|
|
20
|
+
buttonStyle = styles.basic;
|
|
21
|
+
}
|
|
22
|
+
else if (styleType === "primaryline") {
|
|
23
|
+
buttonStyle = styles.primaryline;
|
|
24
|
+
}
|
|
25
|
+
else if (styleType === "danger") {
|
|
26
|
+
buttonStyle = styles.danger;
|
|
27
|
+
}
|
|
28
|
+
else if (styleType === "setting") {
|
|
29
|
+
buttonStyle = styles.setting;
|
|
30
|
+
}
|
|
31
|
+
return (_jsx(MantineButton, { type: "button", className: `${buttonStyle} ${sizeStyle}`, ...props, children: children }));
|
|
32
|
+
};
|
|
33
|
+
export default Button;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Checkbox } from ".";
|
|
3
|
+
export default {
|
|
4
|
+
title: "Core/Checkbox",
|
|
5
|
+
component: Checkbox,
|
|
6
|
+
};
|
|
7
|
+
const Template = (args) => _jsx(Checkbox, { ...args });
|
|
8
|
+
export const defaultCheckbox = Template.bind({});
|
|
9
|
+
defaultCheckbox.args = {
|
|
10
|
+
label: "checkbox label",
|
|
11
|
+
description: "description text",
|
|
12
|
+
size: "md",
|
|
13
|
+
disabled: false,
|
|
14
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Checkbox as MantineCheckbox, } from "@mantine/core";
|
|
3
|
+
import styles from "./styles.module.scss";
|
|
4
|
+
/**
|
|
5
|
+
* ----- checkbox props -----
|
|
6
|
+
** size: 'sm' | 'md' | 'lg'
|
|
7
|
+
** 기타 props는 mantine checkbox props 사용: https://v6.mantine.dev/core/checkbox/?t=props
|
|
8
|
+
*/
|
|
9
|
+
export const Checkbox = ({ size = "md", ...props }) => {
|
|
10
|
+
let sizeStyle = styles.md_checkbox;
|
|
11
|
+
let sizeNumber = 24;
|
|
12
|
+
if (size === "sm") {
|
|
13
|
+
sizeStyle = styles.sm_checkbox;
|
|
14
|
+
sizeNumber = 18;
|
|
15
|
+
}
|
|
16
|
+
else if (size === "lg") {
|
|
17
|
+
sizeStyle = styles.lg_checkbox;
|
|
18
|
+
sizeNumber = 32;
|
|
19
|
+
}
|
|
20
|
+
return (_jsx(MantineCheckbox, { className: sizeStyle, styles: {
|
|
21
|
+
inner: {
|
|
22
|
+
width: sizeNumber,
|
|
23
|
+
height: sizeNumber,
|
|
24
|
+
},
|
|
25
|
+
}, ...props }));
|
|
26
|
+
};
|
|
27
|
+
export default Checkbox;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { DatePicker } from ".";
|
|
3
|
+
export default {
|
|
4
|
+
title: "Core/DatePicker",
|
|
5
|
+
component: DatePicker,
|
|
6
|
+
};
|
|
7
|
+
const Template = (args) => _jsx(DatePicker, { ...args });
|
|
8
|
+
export const datePicker = Template.bind({});
|
|
9
|
+
datePicker.args = {
|
|
10
|
+
size: "md",
|
|
11
|
+
type: "default",
|
|
12
|
+
disabled: false,
|
|
13
|
+
withTime: false,
|
|
14
|
+
};
|
|
15
|
+
export const datetimePicker = Template.bind({});
|
|
16
|
+
datetimePicker.args = {
|
|
17
|
+
size: "md",
|
|
18
|
+
disabled: false,
|
|
19
|
+
withTime: true,
|
|
20
|
+
};
|
|
21
|
+
export const rangePicker = Template.bind({});
|
|
22
|
+
rangePicker.args = {
|
|
23
|
+
size: "md",
|
|
24
|
+
type: "range",
|
|
25
|
+
disabled: false,
|
|
26
|
+
withTime: false,
|
|
27
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import "dayjs/locale/ko";
|
|
3
|
+
import { DatePickerInput, DateTimePicker, } from "@mantine/dates";
|
|
4
|
+
import ic_calendar from "../../assets/icons/ic_calendar.svg";
|
|
5
|
+
import styles from "./styles.module.scss";
|
|
6
|
+
/**
|
|
7
|
+
* ----- datepicker props -----
|
|
8
|
+
** size: 'sm' | 'md' | 'lg'
|
|
9
|
+
** type: 'default' | 'multiple' | 'range'
|
|
10
|
+
** withTime: 시간 포함 여부
|
|
11
|
+
** 기타 props는 mantine datepicker props 사용: https://v6.mantine.dev/dates/date-picker-input/?t=props
|
|
12
|
+
*/
|
|
13
|
+
export const DatePicker = ({ size = "md", type = "default", withTime, ...props }) => {
|
|
14
|
+
let sizeStyle = styles.md_textfield;
|
|
15
|
+
let iconSize = 18;
|
|
16
|
+
if (size === "sm") {
|
|
17
|
+
sizeStyle = styles.sm_textfield;
|
|
18
|
+
iconSize = 14;
|
|
19
|
+
}
|
|
20
|
+
else if (size === "lg") {
|
|
21
|
+
sizeStyle = styles.lg_textfield;
|
|
22
|
+
iconSize = 24;
|
|
23
|
+
}
|
|
24
|
+
if (withTime) {
|
|
25
|
+
return (_jsx(DateTimePicker, { placeholder: undefined, onPointerEnterCapture: undefined, onPointerLeaveCapture: undefined, className: sizeStyle, size: size, locale: "ko", firstDayOfWeek: 0, monthLabelFormat: "YYYY년 MM월", valueFormat: "YYYY-MM-DD | a hh:mm", rightSection: _jsx("img", { width: iconSize, src: ic_calendar }), ...props }));
|
|
26
|
+
}
|
|
27
|
+
return (_jsx(DatePickerInput, { className: sizeStyle, type: type, size: size, locale: "ko", firstDayOfWeek: 0, monthLabelFormat: "YYYY년 MM월", valueFormat: "YYYY-MM-DD", rightSection: _jsx("img", { width: iconSize, src: ic_calendar }), ...props }));
|
|
28
|
+
};
|
|
29
|
+
export default DatePicker;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Dropdown } from ".";
|
|
3
|
+
export default {
|
|
4
|
+
title: "Core/Dropdown",
|
|
5
|
+
component: Dropdown,
|
|
6
|
+
};
|
|
7
|
+
const Template = (args) => _jsx(Dropdown, { ...args });
|
|
8
|
+
export const defaultDropdown = Template.bind({});
|
|
9
|
+
defaultDropdown.args = {
|
|
10
|
+
label: "label text",
|
|
11
|
+
labelPosition: "top",
|
|
12
|
+
size: "md",
|
|
13
|
+
required: false,
|
|
14
|
+
disabled: false,
|
|
15
|
+
data: ["select 1", "select 2", "select 3"],
|
|
16
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Input, Select, Tooltip } from "@mantine/core";
|
|
3
|
+
import ic_tooltip from "../../assets/icons/ic_tooltip.svg";
|
|
4
|
+
import ic_chevron_up from "../../assets/icons/ic_chevron_up.svg";
|
|
5
|
+
import ic_chevron_down from "../../assets/icons/ic_chevron_down.svg";
|
|
6
|
+
import styles from "./styles.module.scss";
|
|
7
|
+
import { useState } from "react";
|
|
8
|
+
/**
|
|
9
|
+
* ----- dropdown props -----
|
|
10
|
+
** label: string, 라벨
|
|
11
|
+
** labelPosition: 'top' | 'left', 라벨위치
|
|
12
|
+
** size: 'sm' | 'md' | 'lg'
|
|
13
|
+
** tooltip: string, 툴팁
|
|
14
|
+
** tooltipPosition: 'top' | 'bottom' | 'left' | 'right', 툴팁 위치
|
|
15
|
+
** description: string, 상세 설명
|
|
16
|
+
** errorMsg: string, 에러 메시지
|
|
17
|
+
** 기타 props는 mantine select props 사용: https://v6.mantine.dev/core/select/?t=props
|
|
18
|
+
*/
|
|
19
|
+
export const Dropdown = ({ label, labelPosition = "top", size = "md", required, tooltip, tooltipPosition = "top", errorMsg, description, ...props }) => {
|
|
20
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
21
|
+
let labelStyle = styles.md_label;
|
|
22
|
+
let selectStyle = styles.md_textfield;
|
|
23
|
+
let tooltipStyle = styles.md_tooltip;
|
|
24
|
+
let chevronSize = 18;
|
|
25
|
+
if (size === "sm") {
|
|
26
|
+
labelStyle = styles.sm_label;
|
|
27
|
+
selectStyle = styles.sm_textfield;
|
|
28
|
+
tooltipStyle = styles.sm_tooltip;
|
|
29
|
+
chevronSize = 14;
|
|
30
|
+
}
|
|
31
|
+
else if (size === "lg") {
|
|
32
|
+
labelStyle = styles.lg_label;
|
|
33
|
+
selectStyle = styles.lg_textfield;
|
|
34
|
+
tooltipStyle = styles.lg_tooltip;
|
|
35
|
+
chevronSize = 24;
|
|
36
|
+
}
|
|
37
|
+
return (_jsxs("div", { className: labelPosition === "top"
|
|
38
|
+
? styles.top_label_textfield
|
|
39
|
+
: styles.left_label_textfield, children: [_jsxs("div", { children: [label && (_jsx(Input.Label, { required: required, className: labelStyle, children: label })), tooltip && (_jsx(Tooltip, { label: tooltip, position: tooltipPosition, children: _jsx("img", { className: tooltipStyle, src: ic_tooltip, alt: "tooltip_icon" }) }))] }), _jsxs("div", { children: [_jsx(Select, { ...props, size: size, error: errorMsg, className: selectStyle, rightSection: isOpen ? (_jsx("img", { width: chevronSize, src: ic_chevron_up })) : (_jsx("img", { width: chevronSize, src: ic_chevron_down })), onDropdownOpen: () => setIsOpen(true), onDropdownClose: () => setIsOpen(false), styles: () => ({
|
|
40
|
+
item: {
|
|
41
|
+
"&[data-selected]": {
|
|
42
|
+
"&, &:hover": {
|
|
43
|
+
backgroundColor: "#e7e7e7",
|
|
44
|
+
color: "#000000",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
}) }), description && (_jsx(Input.Description, { className: styles.input_description, children: description })), errorMsg && (_jsx(Input.Error, { className: styles.input_error_msg, children: errorMsg }))] })] }));
|
|
49
|
+
};
|
|
50
|
+
export default Dropdown;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { ImageUploader } from ".";
|
|
3
|
+
export default {
|
|
4
|
+
title: "Core/ImageUploader",
|
|
5
|
+
component: ImageUploader,
|
|
6
|
+
};
|
|
7
|
+
const Template = (args) => (_jsx(ImageUploader, { ...args }));
|
|
8
|
+
export const defaultImageUploader = Template.bind({});
|
|
9
|
+
defaultImageUploader.args = {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useState } from "react";
|
|
3
|
+
import { Dropzone, IMAGE_MIME_TYPE, } from "@mantine/dropzone";
|
|
4
|
+
import styles from "./styles.module.scss";
|
|
5
|
+
import ic_image_colored from "../../assets/icons/ic_image_colored.svg";
|
|
6
|
+
import ic_cancel_circle from "../../assets/icons/ic_cancel_circle.svg";
|
|
7
|
+
/**
|
|
8
|
+
* ----- image uploader props -----
|
|
9
|
+
** width: number
|
|
10
|
+
** height: number
|
|
11
|
+
** defaultMsg: ReactNode, placeholder 대체
|
|
12
|
+
** file: string | FileWithPath
|
|
13
|
+
** showClearButton: boolean, 업로드 파일 clear 버튼 노출 여부
|
|
14
|
+
** onClear: () => void, 업로드 파일 clear시 실행될 함수
|
|
15
|
+
** 기타 props는 mantine dropzone props 사용: https://v6.mantine.dev/others/dropzone/?t=props
|
|
16
|
+
*/
|
|
17
|
+
export const ImageUploader = ({ width, height, defaultMsg = "이미지 업로드", file, onDrop, showClearButton, onClear, ...props }) => {
|
|
18
|
+
const [fileData, setFileData] = useState(file);
|
|
19
|
+
const handleFileDataClear = useCallback(() => {
|
|
20
|
+
setFileData(undefined);
|
|
21
|
+
if (onClear) {
|
|
22
|
+
onClear();
|
|
23
|
+
}
|
|
24
|
+
}, [onClear]);
|
|
25
|
+
return (_jsxs("div", { className: styles.image_uploader_wrapper, children: [showClearButton && fileData ? (_jsx("div", { className: styles.file_clear_button, onClick: handleFileDataClear, children: _jsx("img", { src: ic_cancel_circle, alt: "clear_file_data" }) })) : null, _jsx(Dropzone, { ...props, maxFiles: 1, className: styles.image_uploader, accept: IMAGE_MIME_TYPE, onDrop: (e) => {
|
|
26
|
+
setFileData(e[0]);
|
|
27
|
+
if (onDrop) {
|
|
28
|
+
onDrop(e);
|
|
29
|
+
}
|
|
30
|
+
}, style: {
|
|
31
|
+
width,
|
|
32
|
+
height,
|
|
33
|
+
}, children: _jsx(_Fragment, { children: fileData ? (_jsx("img", { className: styles.preview, src: typeof fileData === "string"
|
|
34
|
+
? fileData
|
|
35
|
+
: URL.createObjectURL(fileData), alt: `파일명: ${typeof fileData === "string" ? fileData : fileData.name}`, title: `파일명: ${typeof fileData === "string" ? fileData : fileData.name}` })) : (_jsxs("div", { children: [_jsx("img", { src: ic_image_colored, alt: "ic_image_colored" }), _jsx("span", { children: defaultMsg })] })) }) })] }));
|
|
36
|
+
};
|
|
37
|
+
export default ImageUploader;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Modal } from ".";
|
|
3
|
+
export default {
|
|
4
|
+
title: "Core/Modal",
|
|
5
|
+
component: Modal,
|
|
6
|
+
};
|
|
7
|
+
const Template = (args) => _jsx(Modal, { ...args });
|
|
8
|
+
export const defaultModal = Template.bind({});
|
|
9
|
+
defaultModal.args = {
|
|
10
|
+
children: "test",
|
|
11
|
+
opened: true,
|
|
12
|
+
centered: false,
|
|
13
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Modal as MantineModal, } from "@mantine/core";
|
|
3
|
+
/**
|
|
4
|
+
* ----- modal props -----
|
|
5
|
+
** size: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
|
6
|
+
** width: number
|
|
7
|
+
** 기타 props는 mantine modal props 사용: https://v6.mantine.dev/core/modal/?t=props
|
|
8
|
+
*/
|
|
9
|
+
export const Modal = ({ size = "md", width, withCloseButton = false, ...props }) => {
|
|
10
|
+
let sizeNumber = 768;
|
|
11
|
+
if (size === "xs") {
|
|
12
|
+
sizeNumber = 360;
|
|
13
|
+
}
|
|
14
|
+
else if (size === "sm") {
|
|
15
|
+
sizeNumber = 544;
|
|
16
|
+
}
|
|
17
|
+
else if (size === "lg") {
|
|
18
|
+
sizeNumber = 1000;
|
|
19
|
+
}
|
|
20
|
+
else if (size === "xl") {
|
|
21
|
+
sizeNumber = 1200;
|
|
22
|
+
}
|
|
23
|
+
return (_jsx(MantineModal, { size: width || sizeNumber, withCloseButton: withCloseButton, ...props }));
|
|
24
|
+
};
|
|
25
|
+
export default Modal;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Pagination } from ".";
|
|
3
|
+
export default {
|
|
4
|
+
title: "Core/Pagination",
|
|
5
|
+
component: Pagination,
|
|
6
|
+
};
|
|
7
|
+
const Template = (args) => _jsx(Pagination, { ...args });
|
|
8
|
+
export const defaultPagination = Template.bind({});
|
|
9
|
+
defaultPagination.args = {
|
|
10
|
+
currentPageIdx: 0,
|
|
11
|
+
rowsPerPage: 10,
|
|
12
|
+
totalLength: 50,
|
|
13
|
+
paginationSize: 5,
|
|
14
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo, useState } from "react";
|
|
3
|
+
import chevron_left from "../../assets/icons/ic_chevron_left.svg";
|
|
4
|
+
import chevron_right from "../../assets/icons/ic_chevron_right.svg";
|
|
5
|
+
import style from "./style.module.scss";
|
|
6
|
+
/**
|
|
7
|
+
* ----- pagination props -----
|
|
8
|
+
** currentPageIdx: 0부터 시작, 현재 page index
|
|
9
|
+
** rowsPerPage: 한 페이지에 보이는 아이템 개수
|
|
10
|
+
** totalLength: 페이지네이션 사용할 data의 총 개수
|
|
11
|
+
** paginationSize: 페이지네이션 숫자 노출 수 default: 5 (1~5)
|
|
12
|
+
** onPageChange: (page: number) => void
|
|
13
|
+
*/
|
|
14
|
+
export const Pagination = ({ currentPageIdx, rowsPerPage, totalLength, paginationSize, onPageChange, ...props }) => {
|
|
15
|
+
const [currentIdx, setCurrentIdx] = useState(currentPageIdx);
|
|
16
|
+
const [maxPageRows, setMaxPageRows] = useState(50);
|
|
17
|
+
const [totalrows, setTotalRows] = useState(1);
|
|
18
|
+
const [paginationLength, setPaginationLength] = useState(5);
|
|
19
|
+
useMemo(() => {
|
|
20
|
+
setCurrentIdx(currentPageIdx);
|
|
21
|
+
setMaxPageRows(rowsPerPage || 50);
|
|
22
|
+
setTotalRows(totalLength || 1);
|
|
23
|
+
setPaginationLength(paginationSize || 5);
|
|
24
|
+
}, [currentPageIdx, rowsPerPage, totalLength, paginationSize]);
|
|
25
|
+
const onClickPrev = () => {
|
|
26
|
+
if (onPageChange) {
|
|
27
|
+
onPageChange(currentIdx - ((currentIdx % paginationLength) + 1));
|
|
28
|
+
}
|
|
29
|
+
setCurrentIdx((prev) => prev - ((prev % paginationLength) + 1));
|
|
30
|
+
};
|
|
31
|
+
const onClickNext = () => {
|
|
32
|
+
if (onPageChange) {
|
|
33
|
+
onPageChange(currentIdx + paginationLength - (currentIdx % paginationLength));
|
|
34
|
+
}
|
|
35
|
+
setCurrentIdx((prev) => prev + paginationLength - (prev % paginationLength));
|
|
36
|
+
};
|
|
37
|
+
return (_jsxs("div", { ...props, className: style.pagination, children: [currentIdx >= paginationLength ? (_jsx("button", { className: style.arrow, onClick: onClickPrev, children: _jsx("img", { src: chevron_left, alt: "prev" }) })) : null, new Array(paginationLength).fill(0).map((_v, index) => {
|
|
38
|
+
const indexNumber = Math.floor(currentIdx / paginationLength) * paginationLength +
|
|
39
|
+
index +
|
|
40
|
+
1;
|
|
41
|
+
if (indexNumber > Math.ceil(totalrows / maxPageRows)) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
return (_jsx("button", { className: currentIdx === indexNumber - 1
|
|
45
|
+
? style.page_index_active
|
|
46
|
+
: style.page_index, onClick: () => {
|
|
47
|
+
setCurrentIdx(indexNumber - 1);
|
|
48
|
+
if (onPageChange) {
|
|
49
|
+
onPageChange(indexNumber - 1);
|
|
50
|
+
}
|
|
51
|
+
}, children: indexNumber }, `pagination_${index}`));
|
|
52
|
+
}), Math.floor(currentIdx / paginationLength) * paginationLength +
|
|
53
|
+
paginationLength <
|
|
54
|
+
Math.ceil(totalrows / maxPageRows) ? (_jsx("button", { className: style.arrow, onClick: onClickNext, children: _jsx("img", { src: chevron_right, alt: "next" }) })) : null] }));
|
|
55
|
+
};
|
|
56
|
+
export default Pagination;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Radio } from ".";
|
|
3
|
+
export default {
|
|
4
|
+
title: "Core/Radio",
|
|
5
|
+
component: Radio,
|
|
6
|
+
};
|
|
7
|
+
const Template = (args) => _jsx(Radio, { ...args });
|
|
8
|
+
export const defaultRadio = Template.bind({});
|
|
9
|
+
defaultRadio.args = {
|
|
10
|
+
label: "radio label",
|
|
11
|
+
description: "description text",
|
|
12
|
+
size: "md",
|
|
13
|
+
disabled: false,
|
|
14
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Radio as MantineRadio, } from "@mantine/core";
|
|
3
|
+
import styles from "./styles.module.scss";
|
|
4
|
+
/**
|
|
5
|
+
* ----- radio props -----
|
|
6
|
+
** size: 'sm' | 'md' | 'lg'
|
|
7
|
+
** 기타 props는 mantine radio props 사용: https://v6.mantine.dev/core/radio/?t=props
|
|
8
|
+
*/
|
|
9
|
+
export const Radio = ({ size = "md", ...props }) => {
|
|
10
|
+
let sizeStyle = styles.md_radio;
|
|
11
|
+
if (size === "sm") {
|
|
12
|
+
sizeStyle = styles.sm_radio;
|
|
13
|
+
}
|
|
14
|
+
else if (size === "lg") {
|
|
15
|
+
sizeStyle = styles.lg_radio;
|
|
16
|
+
}
|
|
17
|
+
return _jsx(MantineRadio, { className: sizeStyle, size: size, ...props });
|
|
18
|
+
};
|
|
19
|
+
export default Radio;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { SearchBar } from ".";
|
|
3
|
+
export default {
|
|
4
|
+
title: "Core/SearchBar",
|
|
5
|
+
component: SearchBar,
|
|
6
|
+
};
|
|
7
|
+
const Template = (args) => _jsx(SearchBar, { ...args });
|
|
8
|
+
export const defaultSearchBar = Template.bind({});
|
|
9
|
+
defaultSearchBar.args = {
|
|
10
|
+
label: "label text",
|
|
11
|
+
labelPosition: "top",
|
|
12
|
+
size: "md",
|
|
13
|
+
required: false,
|
|
14
|
+
disabled: false,
|
|
15
|
+
data: ["select 1", "select 2", "select 3"],
|
|
16
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Autocomplete, Input, Tooltip } from "@mantine/core";
|
|
3
|
+
import ic_tooltip from "../../assets/icons/ic_tooltip.svg";
|
|
4
|
+
import ic_input_clear from "../../assets/icons/ic_input_clear.svg";
|
|
5
|
+
import ic_search from "../../assets/icons/ic_search.svg";
|
|
6
|
+
import styles from "./styles.module.scss";
|
|
7
|
+
import { useCallback, useState } from "react";
|
|
8
|
+
/**
|
|
9
|
+
* ----- search bar props -----
|
|
10
|
+
** label?: string, 라벨
|
|
11
|
+
** labelPosition?: "top" | "left", 라벨 위치
|
|
12
|
+
** size?: "sm" | "md" | "lg"
|
|
13
|
+
** tooltip?: string, 툴팁
|
|
14
|
+
** tooltipPosition?: "top" | "bottom" | "left" | "right", 툴팁 위치
|
|
15
|
+
** description?: string, 상세 텍스트
|
|
16
|
+
** errorMsg?: string, 에러 메시지
|
|
17
|
+
** onChange?: (event: any) => void
|
|
18
|
+
** onClear?: () => void, clear button 노출시 필요
|
|
19
|
+
** 기타 props는 mantine autocomplete props 사용: https://v6.mantine.dev/core/autocomplete/?t=props
|
|
20
|
+
*/
|
|
21
|
+
export const SearchBar = ({ label, labelPosition = "top", size = "md", required, tooltip, tooltipPosition = "top", errorMsg, description, onChange, onClear, ...props }) => {
|
|
22
|
+
const [textCount, setTextCount] = useState(0);
|
|
23
|
+
let labelStyle = styles.md_label;
|
|
24
|
+
let searchBarStyle = styles.md_textfield;
|
|
25
|
+
let tooltipStyle = styles.md_tooltip;
|
|
26
|
+
if (size === "sm") {
|
|
27
|
+
labelStyle = styles.sm_label;
|
|
28
|
+
searchBarStyle = styles.sm_textfield;
|
|
29
|
+
tooltipStyle = styles.sm_tooltip;
|
|
30
|
+
}
|
|
31
|
+
else if (size === "lg") {
|
|
32
|
+
labelStyle = styles.lg_label;
|
|
33
|
+
searchBarStyle = styles.lg_textfield;
|
|
34
|
+
tooltipStyle = styles.lg_tooltip;
|
|
35
|
+
}
|
|
36
|
+
const onChangeHandler = useCallback((value) => {
|
|
37
|
+
if (onChange) {
|
|
38
|
+
setTextCount(value?.length);
|
|
39
|
+
onChange(value);
|
|
40
|
+
}
|
|
41
|
+
}, [onChange]);
|
|
42
|
+
return (_jsxs("div", { className: labelPosition === "top"
|
|
43
|
+
? styles.top_label_textfield
|
|
44
|
+
: styles.left_label_textfield, children: [_jsxs("div", { children: [label && (_jsx(Input.Label, { required: required, className: labelStyle, children: label })), tooltip && (_jsx(Tooltip, { label: tooltip, position: tooltipPosition, children: _jsx("img", { className: tooltipStyle, src: ic_tooltip, alt: "tooltip_icon" }) }))] }), _jsxs("div", { children: [_jsx("div", { className: styles.textfield_wrapper, children: _jsx(Autocomplete, { ...props, size: size, error: errorMsg, className: searchBarStyle, onChange: onChangeHandler, icon: _jsx("img", { src: ic_search }), iconWidth: 48, rightSection: onClear && textCount > 0 ? (_jsx("div", { className: styles.clear_button, onClick: onClear, children: _jsx("img", { src: ic_input_clear }) })) : undefined }) }), description && (_jsx(Input.Description, { className: styles.input_description, children: description })), errorMsg && (_jsx(Input.Error, { className: styles.input_error_msg, children: errorMsg }))] })] }));
|
|
45
|
+
};
|
|
46
|
+
export default SearchBar;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { SegmentButton } from ".";
|
|
3
|
+
export default {
|
|
4
|
+
title: "Core/SegmentButton",
|
|
5
|
+
component: SegmentButton,
|
|
6
|
+
};
|
|
7
|
+
const Template = (args) => (_jsx(SegmentButton, { ...args }));
|
|
8
|
+
export const defaultSegmentButton = Template.bind({});
|
|
9
|
+
defaultSegmentButton.args = {
|
|
10
|
+
data: ["data1", "data2", "data3"],
|
|
11
|
+
size: "md",
|
|
12
|
+
radius: 6,
|
|
13
|
+
disabled: false,
|
|
14
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { SegmentedControl } from "@mantine/core";
|
|
3
|
+
import styles from "./styles.module.scss";
|
|
4
|
+
/**
|
|
5
|
+
* ----- segment button props -----
|
|
6
|
+
** size: 'sm' | 'md' | 'lg'
|
|
7
|
+
** radius: number | 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
|
8
|
+
** 기타 props는 mantine segmented control props 사용: https://v6.mantine.dev/core/segmented-control/?t=props
|
|
9
|
+
*/
|
|
10
|
+
export const SegmentButton = ({ size = "md", radius = 6, ...props }) => {
|
|
11
|
+
let sizeStyle = styles.md_segment_button;
|
|
12
|
+
if (size === "sm") {
|
|
13
|
+
sizeStyle = styles.sm_segment_button;
|
|
14
|
+
}
|
|
15
|
+
else if (size === "lg") {
|
|
16
|
+
sizeStyle = styles.lg_segment_button;
|
|
17
|
+
}
|
|
18
|
+
return (_jsx(SegmentedControl, { className: sizeStyle, size: size, radius: radius, styles: {
|
|
19
|
+
control: {
|
|
20
|
+
borderWidth: "0 !important",
|
|
21
|
+
},
|
|
22
|
+
}, ...props }));
|
|
23
|
+
};
|
|
24
|
+
export default SegmentButton;
|