@jk-core/components 1.1.9 → 1.1.11

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 (85) hide show
  1. package/README.md +73 -73
  2. package/dist/index.js +17 -17
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.umd.cjs +8 -8
  5. package/dist/index.umd.cjs.map +1 -1
  6. package/dist/src/common/Breadcrumbs/index.d.ts +1 -1
  7. package/dist/src/common/Divider/index.d.ts +8 -0
  8. package/package.json +99 -99
  9. package/src/Calendar/Calendar.module.scss +213 -213
  10. package/src/Calendar/RangeCalendar.tsx +125 -125
  11. package/src/Calendar/ScrollCalendar.module.scss +214 -214
  12. package/src/Calendar/ScrollCalendar.tsx +124 -124
  13. package/src/Calendar/SingleCalendar.tsx +121 -121
  14. package/src/Calendar/components/DateLabel/DateLabel.module.scss +89 -89
  15. package/src/Calendar/components/DateLabel/index.tsx +91 -91
  16. package/src/Calendar/components/DayTile/DayTile.module.scss +117 -117
  17. package/src/Calendar/components/DayTile/index.tsx +108 -108
  18. package/src/Calendar/components/MonthTile/MonthTile.module.scss +59 -59
  19. package/src/Calendar/components/MonthTile/index.tsx +50 -50
  20. package/src/Calendar/components/ViewSelector/ViewSelector.module.scss +48 -48
  21. package/src/Calendar/components/ViewSelector/index.tsx +49 -49
  22. package/src/Calendar/components/YearTile/YearTile.module.scss +85 -85
  23. package/src/Calendar/components/YearTile/index.tsx +65 -65
  24. package/src/Calendar/hooks/useCalendarNav.ts +83 -83
  25. package/src/Calendar/hooks/useDateSelect.ts +54 -54
  26. package/src/Calendar/index.scss +189 -189
  27. package/src/Calendar/index.tsx +66 -66
  28. package/src/Calendar/type.ts +3 -3
  29. package/src/Calendar/utils/getWeeksInMonth.ts +45 -45
  30. package/src/Calendar/utils/isInRange.ts +8 -8
  31. package/src/Calendar/utils/isSameDay.ts +21 -21
  32. package/src/assets/arrow.svg +11 -11
  33. package/src/assets/close.svg +15 -15
  34. package/src/assets/drop-arrow.svg +3 -3
  35. package/src/common/Accordion/Accordion.module.scss +53 -53
  36. package/src/common/Accordion/arrow-down.svg +3 -3
  37. package/src/common/Accordion/arrow-up.svg +3 -3
  38. package/src/common/Accordion/index.tsx +54 -54
  39. package/src/common/Breadcrumbs/Breadcrumbs.module.scss +46 -45
  40. package/src/common/Breadcrumbs/home.svg +5 -5
  41. package/src/common/Breadcrumbs/index.tsx +82 -81
  42. package/src/common/Button/Button.module.scss +127 -127
  43. package/src/common/Button/index.tsx +60 -60
  44. package/src/common/Card/Card.module.scss +28 -28
  45. package/src/common/Card/index.tsx +19 -19
  46. package/src/common/Divider/Divider.module.scss +101 -0
  47. package/src/common/Divider/index.tsx +25 -0
  48. package/src/common/DropDown/DropDown.module.scss +135 -135
  49. package/src/common/DropDown/List.tsx +156 -156
  50. package/src/common/DropDown/arrow-down.svg +3 -3
  51. package/src/common/DropDown/index.tsx +103 -103
  52. package/src/common/DropDown/search.svg +4 -4
  53. package/src/common/Pagination/Pagination.module.scss +210 -210
  54. package/src/common/Pagination/arrow-left.svg +11 -11
  55. package/src/common/Pagination/arrow-right.svg +11 -11
  56. package/src/common/Pagination/index.tsx +156 -156
  57. package/src/common/SegmentButton/SegmentButton.module.scss +45 -45
  58. package/src/common/SegmentButton/index.tsx +79 -79
  59. package/src/common/Skeleton/Skeleton.module.scss +80 -80
  60. package/src/common/Skeleton/index.tsx +47 -47
  61. package/src/common/SwitchButton/SwitchButton.module.scss +65 -65
  62. package/src/common/SwitchButton/index.tsx +56 -56
  63. package/src/common/Table/Table.module.scss +70 -70
  64. package/src/common/Table/index.tsx +128 -128
  65. package/src/index.scss +1 -1
  66. package/src/index.tsx +21 -21
  67. package/src/styles/color.scss +346 -94
  68. package/src/styles/font-face.scss +18 -18
  69. package/src/styles/font.scss +49 -49
  70. package/src/styles/mediaQuery.scss +22 -22
  71. package/src/styles/scrollbar.scss +71 -71
  72. package/src/svg.d.ts +6 -6
  73. package/src/utils/styles/mediaQuery.scss +22 -22
  74. package/src/utils/ts/allowDecimal.ts +4 -4
  75. package/src/utils/ts/autoHypen.ts +33 -33
  76. package/src/utils/ts/calculateMax.ts +24 -24
  77. package/src/utils/ts/checkIsMobilePlatform.ts +15 -15
  78. package/src/utils/ts/formatFileSize.ts +16 -16
  79. package/src/utils/ts/formatMoney.ts +16 -16
  80. package/src/utils/ts/gradientRatio.ts +61 -61
  81. package/src/utils/ts/kiloToMega.ts +30 -30
  82. package/src/utils/ts/maskingPhone.ts +8 -8
  83. package/src/utils/ts/toQueryString.ts +7 -7
  84. package/src/utils/ts/valueAsNumber.ts +15 -15
  85. package/src/vite-env.d.ts +2 -2
@@ -1,156 +1,156 @@
1
-
2
- import { useMemo, useState } from 'react';
3
- import LeftArrowIcon from './arrow-left.svg';
4
- import RightArrowIcon from './arrow-right.svg';
5
- import styles from './Pagination.module.scss';
6
-
7
- interface PaginationProps {
8
- /**
9
- * 총 페이지 수
10
- */
11
- totalPage: number;
12
- /**
13
- * 현재 페이지
14
- */
15
- currentPage: number;
16
-
17
- /**
18
- * 페이지 크기 (기본값: false)
19
- * true로 설정하면 보여지는 페이지의 개수가 5개에서 7개로 늘어납니다.
20
- */
21
- large?: boolean;
22
- /**
23
- * 페이지 클릭 핸들러
24
- */
25
- onPageClick: (page: number) => void;
26
- }
27
-
28
- export default function Pagination({ totalPage, currentPage, onPageClick, large = false }: PaginationProps) {
29
- const [animation, setAnimation] = useState<'left' | 'right' | 'doubleRight' | 'doubleLeft' | 'tripleRight' | 'tripleLeft' | ''>('');
30
- const [selectedPage, setSelectedPage] = useState(currentPage || 1);
31
- const weight = useMemo(() => (large ? 2 : 0), [large]);
32
-
33
- const pageArray = useMemo(() => {
34
- if (!totalPage) return Array.from({ length: 9 + weight }).map((_, i) => (i === 2 ? 1 : null));
35
-
36
- return Array.from({ length: 9 + weight }).map((_, i) => {
37
- const pageIndex = selectedPage + i - 2 - (weight / 2) ;
38
-
39
- if (pageIndex < 1 || pageIndex > totalPage) {
40
- return null;
41
- }
42
- return pageIndex;
43
- });
44
- }, [selectedPage, totalPage, weight]);
45
-
46
- const handlePageClick = (page: number) => {
47
- if (page > totalPage || page < 1) return;
48
- onPageClick(page);
49
- if (page === null) return;
50
- const diff = page - selectedPage;
51
-
52
- switch (diff) {
53
- case 1:
54
- setAnimation('right');
55
- break;
56
- case -1:
57
- setAnimation('left');
58
- break;
59
- case 2:
60
- setAnimation('doubleRight');
61
- break;
62
- case -2:
63
- setAnimation('doubleLeft');
64
- break;
65
- case 3:
66
- setAnimation('tripleRight');
67
- break;
68
- case -3:
69
- setAnimation('tripleLeft');
70
- break;
71
- default:
72
- setAnimation('');
73
- }
74
-
75
- setSelectedPage(page);
76
-
77
- setTimeout(() => {
78
- setAnimation('');
79
- }, 200);
80
- };
81
-
82
- return (
83
- <div className={styles.pagination}>
84
- <button
85
- className={`${styles.arrow} ${selectedPage <= 1 ? styles['arrow--disabled'] : '' }`}
86
- type="button"
87
- onClick={() => handlePageClick(selectedPage - 1)}
88
- >
89
- <LeftArrowIcon />
90
- </button>
91
- <div
92
- className={styles.slider}
93
- style={{ width: `${(8 + weight) * 40}px` }}
94
- >
95
- <div
96
- className={styles.track}
97
- />
98
- <div className={styles.portal}>
99
- {selectedPage > (3 + weight / 2) && (
100
- < >
101
- <button
102
- className={styles.page}
103
- type="button"
104
- onClick={() => handlePageClick(1)}
105
- >1
106
- </button>
107
- <span className={styles.portal__ellipsis}>•••</span>
108
- </>
109
- )}
110
- </div>
111
- <div
112
- className={styles.pages}
113
- style={{ width: `${(5 + weight) * 40}px` }}
114
- >
115
- <div className={`${styles.pageWrapper} ${animation === 'left' ? styles.left : ''} ${styles[animation]}`}>
116
- {pageArray.map((page, index) => (
117
- <button
118
- className={`${styles.page} ${selectedPage === page ? styles['page--selected'] : ''}`}
119
- key={index}
120
- type="button"
121
- disabled={page === null}
122
- onClick={() => {
123
- if (page !== null) {
124
- handlePageClick(page);
125
- }
126
- }}
127
- >
128
- <span>{page}</span>
129
- </button>
130
- ))}
131
- </div>
132
- </div>
133
- <div className={styles.portal}>
134
- {selectedPage < totalPage - (2 + weight / 2) && (
135
- <>
136
- <span className={styles.portal__ellipsis}>•••</span>
137
- <button
138
- className={styles.page}
139
- type="button"
140
- onClick={() => handlePageClick(totalPage)}
141
- >{totalPage}
142
- </button>
143
- </>
144
- )}
145
- </div>
146
- </div>
147
- <button
148
- className={`${styles.arrow} ${selectedPage >= totalPage ? styles['arrow--disabled'] : ''}`}
149
- type="button"
150
- onClick={() => handlePageClick(selectedPage + 1)}
151
- >
152
- <RightArrowIcon />
153
- </button>
154
- </div>
155
- );
156
- }
1
+
2
+ import { useMemo, useState } from 'react';
3
+ import LeftArrowIcon from './arrow-left.svg';
4
+ import RightArrowIcon from './arrow-right.svg';
5
+ import styles from './Pagination.module.scss';
6
+
7
+ interface PaginationProps {
8
+ /**
9
+ * 총 페이지 수
10
+ */
11
+ totalPage: number;
12
+ /**
13
+ * 현재 페이지
14
+ */
15
+ currentPage: number;
16
+
17
+ /**
18
+ * 페이지 크기 (기본값: false)
19
+ * true로 설정하면 보여지는 페이지의 개수가 5개에서 7개로 늘어납니다.
20
+ */
21
+ large?: boolean;
22
+ /**
23
+ * 페이지 클릭 핸들러
24
+ */
25
+ onPageClick: (page: number) => void;
26
+ }
27
+
28
+ export default function Pagination({ totalPage, currentPage, onPageClick, large = false }: PaginationProps) {
29
+ const [animation, setAnimation] = useState<'left' | 'right' | 'doubleRight' | 'doubleLeft' | 'tripleRight' | 'tripleLeft' | ''>('');
30
+ const [selectedPage, setSelectedPage] = useState(currentPage || 1);
31
+ const weight = useMemo(() => (large ? 2 : 0), [large]);
32
+
33
+ const pageArray = useMemo(() => {
34
+ if (!totalPage) return Array.from({ length: 9 + weight }).map((_, i) => (i === 2 ? 1 : null));
35
+
36
+ return Array.from({ length: 9 + weight }).map((_, i) => {
37
+ const pageIndex = selectedPage + i - 2 - (weight / 2) ;
38
+
39
+ if (pageIndex < 1 || pageIndex > totalPage) {
40
+ return null;
41
+ }
42
+ return pageIndex;
43
+ });
44
+ }, [selectedPage, totalPage, weight]);
45
+
46
+ const handlePageClick = (page: number) => {
47
+ if (page > totalPage || page < 1) return;
48
+ onPageClick(page);
49
+ if (page === null) return;
50
+ const diff = page - selectedPage;
51
+
52
+ switch (diff) {
53
+ case 1:
54
+ setAnimation('right');
55
+ break;
56
+ case -1:
57
+ setAnimation('left');
58
+ break;
59
+ case 2:
60
+ setAnimation('doubleRight');
61
+ break;
62
+ case -2:
63
+ setAnimation('doubleLeft');
64
+ break;
65
+ case 3:
66
+ setAnimation('tripleRight');
67
+ break;
68
+ case -3:
69
+ setAnimation('tripleLeft');
70
+ break;
71
+ default:
72
+ setAnimation('');
73
+ }
74
+
75
+ setSelectedPage(page);
76
+
77
+ setTimeout(() => {
78
+ setAnimation('');
79
+ }, 200);
80
+ };
81
+
82
+ return (
83
+ <div className={styles.pagination}>
84
+ <button
85
+ className={`${styles.arrow} ${selectedPage <= 1 ? styles['arrow--disabled'] : '' }`}
86
+ type="button"
87
+ onClick={() => handlePageClick(selectedPage - 1)}
88
+ >
89
+ <LeftArrowIcon />
90
+ </button>
91
+ <div
92
+ className={styles.slider}
93
+ style={{ width: `${(8 + weight) * 40}px` }}
94
+ >
95
+ <div
96
+ className={styles.track}
97
+ />
98
+ <div className={styles.portal}>
99
+ {selectedPage > (3 + weight / 2) && (
100
+ < >
101
+ <button
102
+ className={styles.page}
103
+ type="button"
104
+ onClick={() => handlePageClick(1)}
105
+ >1
106
+ </button>
107
+ <span className={styles.portal__ellipsis}>•••</span>
108
+ </>
109
+ )}
110
+ </div>
111
+ <div
112
+ className={styles.pages}
113
+ style={{ width: `${(5 + weight) * 40}px` }}
114
+ >
115
+ <div className={`${styles.pageWrapper} ${animation === 'left' ? styles.left : ''} ${styles[animation]}`}>
116
+ {pageArray.map((page, index) => (
117
+ <button
118
+ className={`${styles.page} ${selectedPage === page ? styles['page--selected'] : ''}`}
119
+ key={index}
120
+ type="button"
121
+ disabled={page === null}
122
+ onClick={() => {
123
+ if (page !== null) {
124
+ handlePageClick(page);
125
+ }
126
+ }}
127
+ >
128
+ <span>{page}</span>
129
+ </button>
130
+ ))}
131
+ </div>
132
+ </div>
133
+ <div className={styles.portal}>
134
+ {selectedPage < totalPage - (2 + weight / 2) && (
135
+ <>
136
+ <span className={styles.portal__ellipsis}>•••</span>
137
+ <button
138
+ className={styles.page}
139
+ type="button"
140
+ onClick={() => handlePageClick(totalPage)}
141
+ >{totalPage}
142
+ </button>
143
+ </>
144
+ )}
145
+ </div>
146
+ </div>
147
+ <button
148
+ className={`${styles.arrow} ${selectedPage >= totalPage ? styles['arrow--disabled'] : ''}`}
149
+ type="button"
150
+ onClick={() => handlePageClick(selectedPage + 1)}
151
+ >
152
+ <RightArrowIcon />
153
+ </button>
154
+ </div>
155
+ );
156
+ }
@@ -1,45 +1,45 @@
1
- .segment {
2
- position: relative;
3
- display: grid;
4
- width: fit-content;
5
- background-color: var(--G-10);
6
- border-radius: 8px;
7
- z-index: 0;
8
- overflow: hidden;
9
- font-size: 1em;
10
-
11
- &--selector {
12
- position: absolute;
13
- top: 0;
14
- left: 0;
15
- display: flex;
16
- align-items: center;
17
- justify-content: center;
18
- height: 100%;
19
- background-color: var(--white);
20
- border: 2px solid var(--G-10);
21
- border-radius: 8px;
22
- transition: all 0.2s;
23
- z-index: 1;
24
- }
25
- }
26
-
27
- .button {
28
- height: 100%;
29
- padding: 8px 5px;
30
- color: var(--G-40);
31
- transition: color 0.2s;
32
- font-weight: 500;
33
-
34
- & > div {
35
- position: relative;
36
- display: flex;
37
- align-items: center;
38
- justify-content: center;
39
- z-index: 10;
40
- }
41
-
42
- &--selected {
43
- color: var(--G-80);
44
- }
45
- }
1
+ .segment {
2
+ position: relative;
3
+ display: grid;
4
+ width: fit-content;
5
+ background-color: var(--G-10);
6
+ border-radius: 8px;
7
+ z-index: 0;
8
+ overflow: hidden;
9
+ font-size: 1em;
10
+
11
+ &--selector {
12
+ position: absolute;
13
+ top: 0;
14
+ left: 0;
15
+ display: flex;
16
+ align-items: center;
17
+ justify-content: center;
18
+ height: 100%;
19
+ background-color: var(--white);
20
+ border: 2px solid var(--G-10);
21
+ border-radius: 8px;
22
+ transition: all 0.2s;
23
+ z-index: 1;
24
+ }
25
+ }
26
+
27
+ .button {
28
+ height: 100%;
29
+ padding: 8px 5px;
30
+ color: var(--G-40);
31
+ transition: color 0.2s;
32
+ font-weight: 500;
33
+
34
+ & > div {
35
+ position: relative;
36
+ display: flex;
37
+ align-items: center;
38
+ justify-content: center;
39
+ z-index: 10;
40
+ }
41
+
42
+ &--selected {
43
+ color: var(--G-80);
44
+ }
45
+ }
@@ -1,80 +1,80 @@
1
- import { useMemo, useState } from 'react';
2
- import { cn } from '@jk-core/utils';
3
- import styles from './SegmentButton.module.scss';
4
-
5
- interface SegmentButtonProps {
6
- /**
7
- * 세그먼트 버튼의 너비를 지정합니다. 기본값은 'auto'입니다.
8
- * 만약 stretch가 true로 설정되면, 너비는 'auto'로 설정됩니다.
9
- */
10
- width?: string;
11
- /**
12
- * 세그먼트 버튼이 전체 너비를 차지하도록 설정합니다.
13
- * true로 설정하면 버튼이 부모 요소의 너비를 채웁니다.
14
- */
15
- stretch?: boolean;
16
-
17
- /**
18
- * 현재 세그먼트 버튼에서 선택된 인덱스입니다.
19
- * 값을 설정시, 해당 인덱스의 버튼이 선택된 상태로 표시됩니다.
20
- * 기본값은 0입니다.
21
- */
22
- selected?: number;
23
- /**
24
- * 세그먼트 버튼의 옵션을 설정합니다.
25
- * 각 옵션은 텍스트와 클릭 이벤트 핸들러를 포함합니다.
26
- * 예시:
27
- * ```ts
28
- * option: [
29
- * { text: '오늘', onClick: () => setDate(new Date()) },
30
- * { text: '내일', onClick: () => setDate(new Date(Date.now() + 24 * 60 * 60 * 1000)) },
31
- */
32
- option:Array<{ text: string; onClick: () => void }>;
33
- }
34
-
35
- /**
36
- * 세그먼트 버튼 컴포넌트는 여러 개의 버튼을 세그먼트 형태로 표시합니다.
37
- * 각 버튼은 클릭 시 지정된 함수를 실행합니다.
38
- */
39
- export default function SegmentButton({ width, stretch, option, selected }: SegmentButtonProps) {
40
- const [index, setIndex] = useState(selected ?? 0);
41
-
42
- const selectedIndex = useMemo(() => selected ?? index, [index, selected]);
43
-
44
- return (
45
- <div
46
- className={styles.segment}
47
- style={{
48
- width: stretch ? '100%' : undefined,
49
- gridTemplateColumns: `repeat(${option.length},1fr)`,
50
- }}
51
- >
52
- <div
53
- className={styles['segment--selector']}
54
- style={{
55
- width: `${100 / option.length}%`,
56
- left: `${selectedIndex * 100 / option.length}%`,
57
- }}
58
- />
59
- {option.map((item, optionIndex) => (
60
- <button
61
- className={cn({
62
- [styles.button]: true,
63
- [styles['button--selected']]: optionIndex === selectedIndex,
64
- })}
65
- key={item.text}
66
- type="button"
67
- style={{ width: stretch ? 'auto' : (width || 'auto') }}
68
- onClick={() => {
69
- item.onClick();
70
- setIndex(optionIndex);
71
- }}
72
- >
73
- <div>
74
- {item.text}
75
- </div>
76
- </button>
77
- ))}
78
- </div>
79
- );
1
+ import { useMemo, useState } from 'react';
2
+ import { cn } from '@jk-core/utils';
3
+ import styles from './SegmentButton.module.scss';
4
+
5
+ interface SegmentButtonProps {
6
+ /**
7
+ * 세그먼트 버튼의 너비를 지정합니다. 기본값은 'auto'입니다.
8
+ * 만약 stretch가 true로 설정되면, 너비는 'auto'로 설정됩니다.
9
+ */
10
+ width?: string;
11
+ /**
12
+ * 세그먼트 버튼이 전체 너비를 차지하도록 설정합니다.
13
+ * true로 설정하면 버튼이 부모 요소의 너비를 채웁니다.
14
+ */
15
+ stretch?: boolean;
16
+
17
+ /**
18
+ * 현재 세그먼트 버튼에서 선택된 인덱스입니다.
19
+ * 값을 설정시, 해당 인덱스의 버튼이 선택된 상태로 표시됩니다.
20
+ * 기본값은 0입니다.
21
+ */
22
+ selected?: number;
23
+ /**
24
+ * 세그먼트 버튼의 옵션을 설정합니다.
25
+ * 각 옵션은 텍스트와 클릭 이벤트 핸들러를 포함합니다.
26
+ * 예시:
27
+ * ```ts
28
+ * option: [
29
+ * { text: '오늘', onClick: () => setDate(new Date()) },
30
+ * { text: '내일', onClick: () => setDate(new Date(Date.now() + 24 * 60 * 60 * 1000)) },
31
+ */
32
+ option:Array<{ text: string; onClick: () => void }>;
33
+ }
34
+
35
+ /**
36
+ * 세그먼트 버튼 컴포넌트는 여러 개의 버튼을 세그먼트 형태로 표시합니다.
37
+ * 각 버튼은 클릭 시 지정된 함수를 실행합니다.
38
+ */
39
+ export default function SegmentButton({ width, stretch, option, selected }: SegmentButtonProps) {
40
+ const [index, setIndex] = useState(selected ?? 0);
41
+
42
+ const selectedIndex = useMemo(() => selected ?? index, [index, selected]);
43
+
44
+ return (
45
+ <div
46
+ className={styles.segment}
47
+ style={{
48
+ width: stretch ? '100%' : undefined,
49
+ gridTemplateColumns: `repeat(${option.length},1fr)`,
50
+ }}
51
+ >
52
+ <div
53
+ className={styles['segment--selector']}
54
+ style={{
55
+ width: `${100 / option.length}%`,
56
+ left: `${selectedIndex * 100 / option.length}%`,
57
+ }}
58
+ />
59
+ {option.map((item, optionIndex) => (
60
+ <button
61
+ className={cn({
62
+ [styles.button]: true,
63
+ [styles['button--selected']]: optionIndex === selectedIndex,
64
+ })}
65
+ key={item.text}
66
+ type="button"
67
+ style={{ width: stretch ? 'auto' : (width || 'auto') }}
68
+ onClick={() => {
69
+ item.onClick();
70
+ setIndex(optionIndex);
71
+ }}
72
+ >
73
+ <div>
74
+ {item.text}
75
+ </div>
76
+ </button>
77
+ ))}
78
+ </div>
79
+ );
80
80
  }