@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.
Files changed (83) hide show
  1. package/LICENSE.md +21 -0
  2. package/dist/components/Alert/Alert.stories.js +18 -0
  3. package/dist/components/Alert/index.js +38 -0
  4. package/dist/components/Button/Button.stories.js +42 -0
  5. package/dist/components/Button/index.js +33 -0
  6. package/dist/components/Checkbox/Checkbox.stories.js +14 -0
  7. package/dist/components/Checkbox/index.js +27 -0
  8. package/dist/components/DatePicker/DatePicker.stories.js +27 -0
  9. package/dist/components/DatePicker/index.js +29 -0
  10. package/dist/components/Dropdown/Dropdown.stories.js +16 -0
  11. package/dist/components/Dropdown/index.js +50 -0
  12. package/dist/components/ImageUploader/ImageUploader.stories.js +9 -0
  13. package/dist/components/ImageUploader/index.js +37 -0
  14. package/dist/components/Modal/Modal.stories.js +13 -0
  15. package/dist/components/Modal/index.js +25 -0
  16. package/dist/components/Pagination/Pagination.stories.js +14 -0
  17. package/dist/components/Pagination/index.js +56 -0
  18. package/dist/components/Radio/Radio.stories.js +14 -0
  19. package/dist/components/Radio/index.js +19 -0
  20. package/dist/components/SearchBar/SearchBar.stories.js +16 -0
  21. package/dist/components/SearchBar/index.js +46 -0
  22. package/dist/components/SegmentButton/SegmentButton.stories.js +14 -0
  23. package/dist/components/SegmentButton/index.js +24 -0
  24. package/dist/components/Tab/Tab.stories.js +28 -0
  25. package/dist/components/Tab/index.js +18 -0
  26. package/dist/components/Table/Table.stories.js +127 -0
  27. package/dist/components/Table/index.js +129 -0
  28. package/dist/components/TextField/TextField.stories.js +36 -0
  29. package/dist/components/TextField/index.js +60 -0
  30. package/dist/components/TimePicker/TimePicker.stories.js +13 -0
  31. package/dist/components/TimePicker/index.js +30 -0
  32. package/dist/components/Toggle/Toggle.stories.js +15 -0
  33. package/dist/components/Toggle/index.js +41 -0
  34. package/dist/components/Tooltip/Tooltip.stories.js +24 -0
  35. package/dist/components/Tooltip/index.js +13 -0
  36. package/dist/components/index.js +17 -0
  37. package/dist/components/shared/styles.js +219 -0
  38. package/dist/core.css +1 -0
  39. package/dist/core.js +746 -0
  40. package/dist/core.umd.cjs +1 -0
  41. package/dist/helpers/checkMessage/checkMessage.test.js +9 -0
  42. package/dist/helpers/checkMessage/index.js +8 -0
  43. package/dist/index.js +1 -0
  44. package/dist/types/components/Alert/Alert.stories.d.ts +3 -0
  45. package/dist/types/components/Alert/index.d.ts +17 -0
  46. package/dist/types/components/Button/Button.stories.d.ts +7 -0
  47. package/dist/types/components/Button/index.d.ts +14 -0
  48. package/dist/types/components/Checkbox/Checkbox.stories.d.ts +3 -0
  49. package/dist/types/components/Checkbox/index.d.ts +11 -0
  50. package/dist/types/components/DatePicker/DatePicker.stories.d.ts +5 -0
  51. package/dist/types/components/DatePicker/index.d.ts +16 -0
  52. package/dist/types/components/Dropdown/Dropdown.stories.d.ts +3 -0
  53. package/dist/types/components/Dropdown/index.d.ts +23 -0
  54. package/dist/types/components/ImageUploader/ImageUploader.stories.d.ts +3 -0
  55. package/dist/types/components/ImageUploader/index.d.ts +22 -0
  56. package/dist/types/components/Modal/Modal.stories.d.ts +3 -0
  57. package/dist/types/components/Modal/index.d.ts +13 -0
  58. package/dist/types/components/Pagination/Pagination.stories.d.ts +3 -0
  59. package/dist/types/components/Pagination/index.d.ts +18 -0
  60. package/dist/types/components/Radio/Radio.stories.d.ts +3 -0
  61. package/dist/types/components/Radio/index.d.ts +11 -0
  62. package/dist/types/components/SearchBar/SearchBar.stories.d.ts +3 -0
  63. package/dist/types/components/SearchBar/index.d.ts +27 -0
  64. package/dist/types/components/SegmentButton/SegmentButton.stories.d.ts +3 -0
  65. package/dist/types/components/SegmentButton/index.d.ts +13 -0
  66. package/dist/types/components/Tab/Tab.stories.d.ts +3 -0
  67. package/dist/types/components/Tab/index.d.ts +24 -0
  68. package/dist/types/components/Table/Table.stories.d.ts +5 -0
  69. package/dist/types/components/Table/index.d.ts +41 -0
  70. package/dist/types/components/TextField/TextField.stories.d.ts +5 -0
  71. package/dist/types/components/TextField/index.d.ts +35 -0
  72. package/dist/types/components/TimePicker/TimePicker.stories.d.ts +3 -0
  73. package/dist/types/components/TimePicker/index.d.ts +11 -0
  74. package/dist/types/components/Toggle/Toggle.stories.d.ts +3 -0
  75. package/dist/types/components/Toggle/index.d.ts +17 -0
  76. package/dist/types/components/Tooltip/Tooltip.stories.d.ts +3 -0
  77. package/dist/types/components/Tooltip/index.d.ts +13 -0
  78. package/dist/types/components/index.d.ts +17 -0
  79. package/dist/types/components/shared/styles.d.ts +86 -0
  80. package/dist/types/helpers/checkMessage/checkMessage.test.d.ts +1 -0
  81. package/dist/types/helpers/checkMessage/index.d.ts +1 -0
  82. package/dist/types/index.d.ts +1 -0
  83. package/package.json +95 -0
@@ -0,0 +1,28 @@
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Tab } from ".";
3
+ export default {
4
+ title: "Core/Tab",
5
+ component: Tab,
6
+ };
7
+ const Template = (args) => _jsx(Tab, { ...args });
8
+ export const defaultTab = Template.bind({});
9
+ defaultTab.args = {
10
+ tabList: [
11
+ {
12
+ title: "tab title 1",
13
+ value: "default tab 1",
14
+ body: _jsx(_Fragment, { children: "default tab body 1" }),
15
+ },
16
+ {
17
+ title: "tab title 2",
18
+ value: "default tab 2",
19
+ body: _jsx(_Fragment, { children: "default tab body 2" }),
20
+ },
21
+ {
22
+ title: "tab title 3",
23
+ value: "default tab 3",
24
+ body: _jsx(_Fragment, { children: "default tab body 3" }),
25
+ },
26
+ ],
27
+ defaultValue: "default tab 1",
28
+ };
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Tabs } from "@mantine/core";
3
+ import styles from "./styles.module.scss";
4
+ /**
5
+ * ----- tab props -----
6
+ ** tabList: {
7
+ title: string;
8
+ value: string;
9
+ body: ReactNode;
10
+ icon?: ReactNode;
11
+ }[];
12
+ ** containerPaddingTop?: "xs" | "sm" | "md" | "lg" | "xl";
13
+ ** 기타 props는 mantine tabs props 사용: https://v6.mantine.dev/core/tabs/?t=props
14
+ */
15
+ export const Tab = ({ tabList = [], containerPaddingTop, ...props }) => {
16
+ return (_jsxs(Tabs, { ...props, children: [_jsx(Tabs.List, { className: styles.tab_title_list, children: tabList?.map((tab, index) => (_jsxs(Tabs.Tab, { value: tab.value, icon: tab.icon, children: [tab.title, _jsx("div", { className: styles.border_bottom })] }, `tab_${index}`))) }), tabList?.map((tab, index) => (_jsx(Tabs.Panel, { value: tab.value, pt: containerPaddingTop, children: tab.body }, `tab_panel_${index}`)))] }));
17
+ };
18
+ export default Tab;
@@ -0,0 +1,127 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Table } from ".";
3
+ export default {
4
+ title: "Core/Table",
5
+ component: Table,
6
+ };
7
+ const Template = (args) => _jsx(Table, { ...args });
8
+ export const defaultTable = Template.bind({});
9
+ defaultTable.args = {
10
+ headerList: ["전기", "불", "물", "풀"],
11
+ striped: true,
12
+ draggable: false,
13
+ tableData: [
14
+ {
15
+ electric: { cell: "피츄", sortTarget: "피츄" },
16
+ fire: { cell: "파이리", sortTarget: "파이리" },
17
+ water: { cell: "꼬부기", sortTarget: "꼬부기" },
18
+ leaf: { cell: "이상해씨", sortTarget: "이상해씨" },
19
+ },
20
+ {
21
+ electric: { cell: "피카츄", sortTarget: "피카츄" },
22
+ fire: { cell: "리자드", sortTarget: "리자드" },
23
+ water: { cell: "어니부기", sortTarget: "어니부기" },
24
+ leaf: { cell: "이상해풀", sortTarget: "이상해풀" },
25
+ },
26
+ {
27
+ electric: { cell: "라이츄", sortTarget: "라이츄" },
28
+ fire: { cell: "리자몽", sortTarget: "리자몽" },
29
+ water: { cell: "거북왕", sortTarget: "거북왕" },
30
+ leaf: { cell: "이상해꽃", sortTarget: "이상해꽃" },
31
+ },
32
+ {
33
+ electric: { cell: "찌리리공", sortTarget: "찌리리공" },
34
+ fire: { cell: "식스테일", sortTarget: "식스테일" },
35
+ water: { cell: "갸라도스", sortTarget: "갸라도스" },
36
+ leaf: { cell: "뚜벅초", sortTarget: "뚜벅초" },
37
+ },
38
+ ],
39
+ };
40
+ export const sortableTable = Template.bind({});
41
+ sortableTable.args = {
42
+ headerList: ["전기", "불", "물", "풀", "순번", "선택(정렬테스트용)"],
43
+ striped: true,
44
+ sortable: true,
45
+ tableData: [
46
+ {
47
+ electric: { cell: "피츄", sortTarget: "피츄" },
48
+ fire: { cell: "파이리", sortTarget: "파이리" },
49
+ water: { cell: "꼬부기", sortTarget: "꼬부기" },
50
+ leaf: { cell: "이상해씨", sortTarget: "이상해씨" },
51
+ num: { cell: 1, sortTarget: 1 },
52
+ select: {
53
+ cell: _jsx("input", { type: "checkbox", readOnly: true, checked: true }),
54
+ sortTarget: true,
55
+ },
56
+ },
57
+ {
58
+ electric: { cell: "피카츄", sortTarget: "피카츄" },
59
+ fire: { cell: "리자드", sortTarget: "리자드" },
60
+ water: { cell: "어니부기", sortTarget: "어니부기" },
61
+ leaf: { cell: "이상해풀", sortTarget: "이상해풀" },
62
+ num: { cell: 2, sortTarget: 2 },
63
+ select: {
64
+ cell: _jsx("input", { type: "checkbox", readOnly: true, checked: false }),
65
+ sortTarget: false,
66
+ },
67
+ },
68
+ {
69
+ electric: { cell: "라이츄", sortTarget: "라이츄" },
70
+ fire: { cell: "리자몽", sortTarget: "리자몽" },
71
+ water: { cell: "거북왕", sortTarget: "거북왕" },
72
+ leaf: { cell: "이상해꽃", sortTarget: "이상해꽃" },
73
+ num: { cell: 3, sortTarget: 3 },
74
+ select: {
75
+ cell: _jsx("input", { type: "checkbox", readOnly: true, checked: true }),
76
+ sortTarget: true,
77
+ },
78
+ },
79
+ {
80
+ electric: { cell: "찌리리공", sortTarget: "찌리리공" },
81
+ fire: { cell: "식스테일", sortTarget: "식스테일" },
82
+ water: { cell: "갸라도스", sortTarget: "갸라도스" },
83
+ leaf: { cell: "뚜벅초", sortTarget: "뚜벅초" },
84
+ num: { cell: 4, sortTarget: 4 },
85
+ select: {
86
+ cell: _jsx("input", { type: "checkbox", readOnly: true, checked: false }),
87
+ sortTarget: false,
88
+ },
89
+ },
90
+ ],
91
+ };
92
+ export const draggableTable = Template.bind({});
93
+ draggableTable.args = {
94
+ headerList: ["전기", "불", "물", "풀"],
95
+ striped: true,
96
+ sortable: false,
97
+ draggable: true,
98
+ onDragEnd: (rows) => {
99
+ console.log(rows);
100
+ },
101
+ tableData: [
102
+ {
103
+ electric: { cell: "피츄", sortTarget: "피츄", dndId: 0 },
104
+ fire: { cell: "파이리", sortTarget: "파이리" },
105
+ water: { cell: "꼬부기", sortTarget: "꼬부기" },
106
+ leaf: { cell: "이상해씨", sortTarget: "이상해씨" },
107
+ },
108
+ {
109
+ electric: { cell: "피카츄", sortTarget: "피카츄", dndId: 1 },
110
+ fire: { cell: "리자드", sortTarget: "리자드" },
111
+ water: { cell: "어니부기", sortTarget: "어니부기" },
112
+ leaf: { cell: "이상해풀", sortTarget: "이상해풀" },
113
+ },
114
+ {
115
+ electric: { cell: "라이츄", sortTarget: "라이츄", dndId: 2 },
116
+ fire: { cell: "리자몽", sortTarget: "리자몽" },
117
+ water: { cell: "거북왕", sortTarget: "거북왕" },
118
+ leaf: { cell: "이상해꽃", sortTarget: "이상해꽃" },
119
+ },
120
+ {
121
+ electric: { cell: "찌리리공", sortTarget: "찌리리공", dndId: 3 },
122
+ fire: { cell: "식스테일", sortTarget: "식스테일" },
123
+ water: { cell: "갸라도스", sortTarget: "갸라도스" },
124
+ leaf: { cell: "뚜벅초", sortTarget: "뚜벅초" },
125
+ },
126
+ ],
127
+ };
@@ -0,0 +1,129 @@
1
+ import { createElement as _createElement } from "react";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import styles from "./styles.module.scss";
4
+ import { useCallback, useMemo, useState } from "react";
5
+ import { DragDropContext, Draggable, Droppable, } from "react-beautiful-dnd";
6
+ import ic_sortable from "../../assets/icons/ic_sortable.svg";
7
+ import ic_chevron_up from "../../assets/icons/ic_chevron_up.svg";
8
+ import ic_chevron_down from "../../assets/icons/ic_chevron_down.svg";
9
+ import ic_drag from "../../assets/icons/ic_drag.svg";
10
+ /**
11
+ * ----- table props -----
12
+ ** tableId: 드래그앤드롭에 사용하는 고유한 id
13
+ ** headerList: ReactNode[]인 헤더 리스트
14
+ ** tableData: {
15
+ [key:string]: {
16
+ cell:ReactNode;
17
+ sortTarget: string | number | boolean;
18
+ dndId:(사용시, 첫번째 key value에선 필수) string | number;
19
+ trClassName:(사용시, 첫번째 key value에선 필수) string;
20
+ }
21
+ }[]
22
+ ** sortable: 정렬 가능여부
23
+ ** draggable: 드래그앤드롭 가능여부
24
+ ** striped: stripe 스타일 적용 여부
25
+ ** onDragEnd: 드래그앤드롭 이후, 새로 정렬된 dndId list return
26
+ ** className: table custom style 적용 필요시 사용
27
+ */
28
+ export const Table = ({ tableId, headerList, tableData, sortable, draggable = false, striped, onDragEnd, className, }) => {
29
+ const [rows, setRows] = useState();
30
+ const [sortedColIndex, setSortedColIndex] = useState();
31
+ const [sortedDirection, setSortedDirection] = useState();
32
+ const rowMaker = useCallback((sortedData) => {
33
+ const tableRows = sortedData?.map((data, index) => {
34
+ const dataKeys = Object.keys(data);
35
+ const row = (_jsx(_Fragment, { children: dataKeys.map((key, keyIndex) => (_jsx("td", { className: styles.td_cell, children: data[key].cell }, `table_${tableId || 0}_tr_${index}_col_${keyIndex}`))) }));
36
+ if (draggable && data[dataKeys[0]]?.dndId === undefined) {
37
+ console.error("draggable table을 사용할 때엔 tableData의 첫번째 필드에 고유한 dndId를 설정해주세요");
38
+ }
39
+ return {
40
+ row: row,
41
+ dndId: data[dataKeys[0]]?.dndId,
42
+ trClassName: data[dataKeys[0]]?.trClassName,
43
+ };
44
+ });
45
+ setRows(tableRows);
46
+ }, [draggable, tableId]);
47
+ useMemo(() => {
48
+ // 테이블 데이터 변경시, sort option 삭제
49
+ setSortedColIndex(undefined);
50
+ setSortedDirection(undefined);
51
+ rowMaker(tableData);
52
+ }, [rowMaker, tableData]);
53
+ const sortingHandler = useCallback((colIndex) => {
54
+ if (tableData) {
55
+ const copyArr = tableData.slice(0);
56
+ // 정렬 기준 키
57
+ const sortBy = Object.keys(copyArr[0])[colIndex];
58
+ setSortedColIndex(colIndex);
59
+ let newSortedData;
60
+ /*
61
+ 정렬 순서
62
+ 1. 내림차순
63
+ 2. 오름차순
64
+ 3. 초기화
65
+ 1, 2, 3을 반복
66
+ */
67
+ if (!sortedDirection) {
68
+ newSortedData = copyArr?.sort((a, b) => String(b[sortBy].sortTarget || b[sortBy].cell).localeCompare(String(a[sortBy].sortTarget || a[sortBy].cell)));
69
+ setSortedDirection("desc");
70
+ }
71
+ else if (sortedDirection === "desc") {
72
+ newSortedData = copyArr?.sort((a, b) => String(a[sortBy].sortTarget || a[sortBy].cell).localeCompare(String(b[sortBy].sortTarget || b[sortBy].cell)));
73
+ setSortedDirection("asc");
74
+ }
75
+ else {
76
+ newSortedData = copyArr;
77
+ setSortedColIndex(undefined);
78
+ setSortedDirection(undefined);
79
+ }
80
+ rowMaker(newSortedData);
81
+ }
82
+ }, [rowMaker, sortedDirection, tableData]);
83
+ const sortableArrow = useCallback((index) => {
84
+ if (!sortable) {
85
+ return null;
86
+ }
87
+ if (sortedColIndex === index) {
88
+ if (sortedDirection === "desc") {
89
+ return _jsx("img", { src: ic_chevron_down, alt: "ic_chevron_down" });
90
+ }
91
+ return _jsx("img", { src: ic_chevron_up, alt: "ic_chevron_up" });
92
+ }
93
+ else {
94
+ return _jsx("img", { src: ic_sortable, alt: "ic_sortable" });
95
+ }
96
+ }, [sortable, sortedColIndex, sortedDirection]);
97
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
98
+ const reorder = useCallback((list, item, insertIdx) => {
99
+ const result = Array.from(list);
100
+ result.splice(insertIdx, 0, item);
101
+ return result;
102
+ }, []);
103
+ const onDragEndHandler = useCallback((result) => {
104
+ // 영역 밖에 drop한 경우
105
+ if (!result.destination) {
106
+ return;
107
+ }
108
+ // rows가 존재하지 않는 경우
109
+ if (!rows) {
110
+ return;
111
+ }
112
+ // reorder 처리를 위한 temp value 선언
113
+ const duplRows = rows?.slice(0);
114
+ const [newItem] = duplRows.splice(result.source.index, 1);
115
+ const items = reorder(duplRows, newItem, result.destination.index);
116
+ setRows(items);
117
+ if (onDragEnd) {
118
+ onDragEnd(items.map((el) => ({ dndId: el?.dndId })));
119
+ }
120
+ }, [onDragEnd, reorder, rows]);
121
+ return (_jsxs("table", { className: `${styles.table} ${className || ""}`, children: [_jsx("thead", { children: _jsxs("tr", { children: [draggable && (_jsx("th", { className: styles.th_cell, style: { padding: 0 } })), headerList?.map((header, index) => (_jsx("th", { className: sortable ? styles.th_cell_sortable : styles.th_cell, onClick: () => {
122
+ if (sortable) {
123
+ sortingHandler(index);
124
+ }
125
+ }, children: _jsxs("div", { children: [header, sortableArrow(index)] }) }, `table_header_col_${index}`)))] }) }), _jsx(DragDropContext, { onDragEnd: onDragEndHandler, children: _jsx(Droppable, { droppableId: `dnd_table_${tableId || 0}_drop_zone`, children: (dropProvided) => (_jsxs("tbody", { ref: dropProvided.innerRef, ...dropProvided.droppableProps, children: [rows?.map((rowData, index) => (_jsx(Draggable, { draggableId: `dnd_table_${tableId || 0}_drag_item_${rowData?.dndId}`, index: index, isDragDisabled: !draggable, children: (dragProvided) => (_createElement("tr", { ...dragProvided.dragHandleProps, ...dragProvided.draggableProps, ref: dragProvided.innerRef, key: `table_${tableId || 0}_tr_${index}`, className: `${striped && index % 2 === 1 ? styles.tr_gray : ""} ${rowData.trClassName}` },
126
+ draggable && (_jsx("td", { className: styles.td_cell, style: { padding: 0 }, children: _jsx("div", { children: _jsx("img", { src: ic_drag, alt: "ic_drag" }) }) })),
127
+ rowData?.row)) }, `dnd_table_${tableId || 0}_drag_item_${rowData?.dndId !== undefined ? rowData.dndId : index}`))), dropProvided.placeholder] })) }) })] }));
128
+ };
129
+ export default Table;
@@ -0,0 +1,36 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { TextField } from ".";
3
+ export default {
4
+ title: "Core/TextField",
5
+ component: TextField,
6
+ };
7
+ const Template = (args) => _jsx(TextField, { ...args });
8
+ export const LabelTextField = Template.bind({});
9
+ LabelTextField.args = {
10
+ label: "label text",
11
+ labelPosition: "top",
12
+ size: "md",
13
+ required: false,
14
+ disabled: false,
15
+ };
16
+ export const ToolTipTextField = Template.bind({});
17
+ ToolTipTextField.args = {
18
+ label: "label text",
19
+ labelPosition: "top",
20
+ tooltip: "tootip text",
21
+ tooltipPosition: "top",
22
+ size: "md",
23
+ required: false,
24
+ disabled: false,
25
+ };
26
+ export const Textarea = Template.bind({});
27
+ Textarea.args = {
28
+ label: "label text",
29
+ labelPosition: "top",
30
+ size: "md",
31
+ required: false,
32
+ disabled: false,
33
+ textarea: true,
34
+ minRows: 4,
35
+ maxTextCount: 100,
36
+ };
@@ -0,0 +1,60 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Input, Textarea, 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 styles from "./styles.module.scss";
6
+ import { useCallback, useState } from "react";
7
+ /**
8
+ * ----- textfield props -----
9
+ ** label: string, 라벨
10
+ ** labelPosition: "top" | "left", 라벨 위치
11
+ ** size: "sm" | "md" | "lg"
12
+ ** required: boolean, 필수 입력여부
13
+ ** tooltip: string, 툴팁
14
+ ** tooltipPosition: "top" | "bottom" | "left" | "right", 툴팁 위치
15
+ ** description: string, 상세 텍스트
16
+ ** errorMsg: string, 에러 메시지
17
+ ** textarea: boolean, textarea element로 사용할지 여부
18
+ ** minRows: number, textarea element 사용시, height 대신 사용
19
+ ** maxTextCount: number, 최대 텍스트 제한
20
+ ** onChange: (event: any) => void
21
+ ** onClear: () => void
22
+ ** 기타 props는 mantine input props 사용: https://v6.mantine.dev/core/input/?t=props
23
+ */
24
+ export const TextField = ({ label, labelPosition = "top", size = "md", required, tooltip, tooltipPosition = "top", errorMsg, description, textarea = false, minRows, maxTextCount, onChange, onClear, ...props }) => {
25
+ const [textCount, setTextCount] = useState(0);
26
+ let labelStyle = styles.md_label;
27
+ let textfieldStyle = styles.md_textfield;
28
+ let tooltipStyle = styles.md_tooltip;
29
+ if (size === "sm") {
30
+ labelStyle = styles.sm_label;
31
+ textfieldStyle = styles.sm_textfield;
32
+ tooltipStyle = styles.sm_tooltip;
33
+ }
34
+ else if (size === "lg") {
35
+ labelStyle = styles.lg_label;
36
+ textfieldStyle = styles.lg_textfield;
37
+ tooltipStyle = styles.lg_tooltip;
38
+ }
39
+ const onChangeHandler = useCallback(
40
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
41
+ (event) => {
42
+ if (maxTextCount) {
43
+ if (event.currentTarget?.value?.length > maxTextCount) {
44
+ return;
45
+ }
46
+ setTextCount(event.currentTarget?.value?.length);
47
+ if (onChange) {
48
+ onChange(event);
49
+ }
50
+ }
51
+ if (onChange) {
52
+ setTextCount(event.currentTarget?.value?.length);
53
+ onChange(event);
54
+ }
55
+ }, [maxTextCount, onChange]);
56
+ return (_jsxs("div", { className: labelPosition === "top"
57
+ ? styles.top_label_textfield
58
+ : 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: [_jsxs("div", { className: styles.textfield_wrapper, children: [textarea ? (_jsx(Textarea, { className: styles.textarea, size: size, minRows: minRows, error: errorMsg, onChange: onChangeHandler, disabled: props?.disabled, ...props })) : (_jsx(Input, { className: textfieldStyle, error: errorMsg, onChange: onChangeHandler, rightSection: onClear && textCount > 0 ? (_jsx("div", { className: styles.clear_button, onClick: onClear, children: _jsx("img", { src: ic_input_clear }) })) : undefined, ...props })), maxTextCount && maxTextCount > 0 && (_jsx("span", { className: styles.text_counter, children: `${textCount}/${maxTextCount}` }))] }), description && (_jsx(Input.Description, { className: styles.input_description, children: description })), errorMsg && (_jsx(Input.Error, { className: styles.input_error_msg, children: errorMsg }))] })] }));
59
+ };
60
+ export default TextField;
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { TimePicker } from ".";
3
+ export default {
4
+ title: "Core/TimePicker",
5
+ component: TimePicker,
6
+ };
7
+ const Template = (args) => _jsx(TimePicker, { ...args });
8
+ export const defaultTimePicker = Template.bind({});
9
+ defaultTimePicker.args = {
10
+ size: "md",
11
+ disabled: false,
12
+ defaultValue: `${new Date().getHours()}:${new Date().getMinutes()}`,
13
+ };
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useRef } from "react";
3
+ import { ActionIcon } from "@mantine/core";
4
+ import { TimeInput } from "@mantine/dates";
5
+ import ic_clock from "../../assets/icons/ic_clock.svg";
6
+ import styles from "./styles.module.scss";
7
+ /**
8
+ * ----- time picker props -----
9
+ ** size: 'sm' | 'md' | 'lg'
10
+ ** 기타 props는 mantine time input props 사용: https://v6.mantine.dev/dates/time-input/?t=props
11
+ */
12
+ export const TimePicker = ({ size = "md", ...props }) => {
13
+ const timeInputRef = useRef(null);
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
+ return (_jsx(TimeInput, { ref: timeInputRef, className: sizeStyle, size: size, ...props, rightSection: _jsx(ActionIcon, { onClick: () => {
25
+ if (timeInputRef) {
26
+ timeInputRef?.current?.showPicker();
27
+ }
28
+ }, children: _jsx("img", { width: iconSize, src: ic_clock, alt: "clock_icon" }) }) }));
29
+ };
30
+ export default TimePicker;
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Toggle } from ".";
3
+ export default {
4
+ title: "Core/Toggle",
5
+ component: Toggle,
6
+ };
7
+ const Template = (args) => _jsx(Toggle, { ...args });
8
+ export const defaultToggle = Template.bind({});
9
+ defaultToggle.args = {
10
+ label: "toggle label",
11
+ labelPosition: "left",
12
+ description: "description text",
13
+ size: "md",
14
+ disabled: false,
15
+ };
@@ -0,0 +1,41 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Switch } from "@mantine/core";
3
+ import styles from "./styles.module.scss";
4
+ import { useCallback, useState } from "react";
5
+ /**
6
+ * ----- toggle props -----
7
+ ** size: 'sm' | 'md' | 'lg'
8
+ ** labelPosition: 'left' | 'right', 라벨 위치
9
+ ** disabled: boolean
10
+ ** onChange: (event) => void
11
+ ** 기타 props는 mantine switch props 사용: https://v6.mantine.dev/core/switch/?t=props
12
+ */
13
+ export const Toggle = ({ size = "md", labelPosition = "right", disabled, onChange, ...props }) => {
14
+ const [isChecked, setIsChecked] = useState(props?.checked || false);
15
+ let sizeStyle = styles.md_toggle;
16
+ let trackWidth = 50;
17
+ if (size === "sm") {
18
+ sizeStyle = styles.sm_toggle;
19
+ trackWidth = 38;
20
+ }
21
+ else if (size === "lg") {
22
+ sizeStyle = styles.lg_toggle;
23
+ trackWidth = 67;
24
+ }
25
+ const onChangeHandler = useCallback(
26
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
27
+ (event) => {
28
+ if (onChange) {
29
+ onChange(event);
30
+ }
31
+ setIsChecked(event?.target?.checked);
32
+ }, [onChange]);
33
+ return (_jsx(Switch, { className: sizeStyle, size: size, labelPosition: labelPosition, disabled: disabled, onChange: onChangeHandler, styles: () => ({
34
+ track: {
35
+ backgroundColor: !disabled && isChecked ? "#0fd3d8 !important" : undefined,
36
+ borderColor: !disabled && isChecked ? "#0fd3d8 !important" : undefined,
37
+ width: trackWidth,
38
+ },
39
+ }), ...props }));
40
+ };
41
+ export default Toggle;
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Tooltip } from ".";
3
+ export default {
4
+ title: "Core/Tooltip",
5
+ component: Tooltip,
6
+ };
7
+ const Template = (args) => _jsx(Tooltip, { ...args });
8
+ export const defaultTooltip = Template.bind({});
9
+ defaultTooltip.args = {
10
+ title: "tooltip title",
11
+ content: "tooltip content content content content content content content content content content content",
12
+ maw: 220,
13
+ multiline: true,
14
+ position: "top",
15
+ children: (_jsx("div", { style: {
16
+ display: "flex",
17
+ alignItems: "center",
18
+ justifyContent: "center",
19
+ width: 280,
20
+ height: 50,
21
+ background: "#e0e0e0",
22
+ fontSize: 25,
23
+ }, children: "hover me" })),
24
+ };
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Tooltip as MantineTooltip, } from "@mantine/core";
3
+ import styles from "./styles.module.scss";
4
+ /**
5
+ * ----- tooltip props -----
6
+ ** title: string
7
+ ** content: string
8
+ ** 기타 props는 mantine tooltip props 사용: https://v6.mantine.dev/core/tooltip/?t=props
9
+ */
10
+ export const Tooltip = ({ title, content, maw = 280, multiline = true, ...props }) => {
11
+ return (_jsx(MantineTooltip, { ...props, maw: maw, multiline: multiline, label: _jsxs("div", { className: styles.tooltip_body, children: [title && _jsx("span", { className: styles.tooltip_title, children: title }), _jsx("span", { className: styles.tooltip_content, children: content })] }) }));
12
+ };
13
+ export default Tooltip;
@@ -0,0 +1,17 @@
1
+ export { default as Button } from "./Button";
2
+ export { TextField } from "./TextField";
3
+ export { SearchBar } from "./SearchBar";
4
+ export { Dropdown } from "./Dropdown";
5
+ export { Checkbox } from "./Checkbox";
6
+ export { Radio } from "./Radio";
7
+ export { Toggle } from "./Toggle";
8
+ export { DatePicker } from "./DatePicker";
9
+ export { TimePicker } from "./TimePicker";
10
+ export { Pagination } from "./Pagination";
11
+ export { Tab } from "./Tab";
12
+ export { SegmentButton } from "./SegmentButton";
13
+ export { Alert } from "./Alert";
14
+ export { Tooltip } from "./Tooltip";
15
+ export { Table } from "./Table";
16
+ export { Modal } from "./Modal";
17
+ export { ImageUploader } from "./ImageUploader";