@jk-core/components 0.1.16 → 1.0.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.
Files changed (53) hide show
  1. package/dist/index.d.ts +2 -4
  2. package/dist/index.js +661 -1026
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.umd.cjs +7 -15
  5. package/dist/index.umd.cjs.map +1 -1
  6. package/dist/src/index.d.ts +4 -0
  7. package/dist/vite.config.d.ts +2 -0
  8. package/package.json +24 -21
  9. package/src/Calendar/Calendar.module.scss +213 -0
  10. package/src/Calendar/RangeCalendar.tsx +125 -0
  11. package/src/Calendar/ScrollCalendar.module.scss +214 -0
  12. package/src/Calendar/ScrollCalendar.tsx +124 -0
  13. package/src/Calendar/SingleCalendar.tsx +121 -0
  14. package/src/Calendar/components/DateLabel/DateLabel.module.scss +89 -0
  15. package/src/Calendar/components/DateLabel/index.tsx +91 -0
  16. package/src/Calendar/components/DayTile/DayTile.module.scss +117 -0
  17. package/src/Calendar/components/DayTile/index.tsx +100 -0
  18. package/src/Calendar/components/MonthTile/MonthTile.module.scss +59 -0
  19. package/src/Calendar/components/MonthTile/index.tsx +50 -0
  20. package/src/Calendar/components/ViewSelector/ViewSelector.module.scss +48 -0
  21. package/src/Calendar/components/ViewSelector/index.tsx +49 -0
  22. package/src/Calendar/components/YearTile/YearTile.module.scss +86 -0
  23. package/src/Calendar/components/YearTile/index.tsx +65 -0
  24. package/src/Calendar/hooks/useCalendarNav.ts +80 -0
  25. package/src/Calendar/hooks/useDateSelect.ts +54 -0
  26. package/src/Calendar/index.scss +189 -0
  27. package/src/Calendar/index.tsx +66 -0
  28. package/src/Calendar/type.ts +3 -0
  29. package/src/Calendar/utils/getWeeksInMonth.ts +45 -0
  30. package/src/Calendar/utils/isInRange.ts +8 -0
  31. package/src/Calendar/utils/isSameDay.ts +21 -0
  32. package/src/assets/arrow.svg +12 -0
  33. package/src/assets/close.svg +16 -0
  34. package/src/assets/drop-arrow.svg +3 -0
  35. package/src/index.tsx +5 -0
  36. package/src/styles/mediaQuery.scss +22 -0
  37. package/src/svg.d.ts +4 -0
  38. package/src/vite-env.d.ts +2 -0
  39. /package/dist/{Calendar → src/Calendar}/RangeCalendar.d.ts +0 -0
  40. /package/dist/{Calendar → src/Calendar}/ScrollCalendar.d.ts +0 -0
  41. /package/dist/{Calendar → src/Calendar}/SingleCalendar.d.ts +0 -0
  42. /package/dist/{Calendar → src/Calendar}/components/DateLabel/index.d.ts +0 -0
  43. /package/dist/{Calendar → src/Calendar}/components/DayTile/index.d.ts +0 -0
  44. /package/dist/{Calendar → src/Calendar}/components/MonthTile/index.d.ts +0 -0
  45. /package/dist/{Calendar → src/Calendar}/components/ViewSelector/index.d.ts +0 -0
  46. /package/dist/{Calendar → src/Calendar}/components/YearTile/index.d.ts +0 -0
  47. /package/dist/{Calendar → src/Calendar}/hooks/useCalendarNav.d.ts +0 -0
  48. /package/dist/{Calendar → src/Calendar}/hooks/useDateSelect.d.ts +0 -0
  49. /package/dist/{Calendar → src/Calendar}/index.d.ts +0 -0
  50. /package/dist/{Calendar → src/Calendar}/type.d.ts +0 -0
  51. /package/dist/{Calendar → src/Calendar}/utils/getWeeksInMonth.d.ts +0 -0
  52. /package/dist/{Calendar → src/Calendar}/utils/isInRange.d.ts +0 -0
  53. /package/dist/{Calendar → src/Calendar}/utils/isSameDay.d.ts +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jk-core/components",
3
- "version": "0.1.16",
3
+ "version": "1.0.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.umd.cjs",
6
6
  "types": "./dist/index.d.ts",
@@ -27,7 +27,7 @@
27
27
  },
28
28
  "files": [
29
29
  "./dist",
30
- "./`src"
30
+ "./src"
31
31
  ],
32
32
  "keywords": [
33
33
  "utils",
@@ -36,9 +36,9 @@
36
36
  "components",
37
37
  "calendar"
38
38
  ],
39
- "dependencies": {
40
- "react": "^18.3.1",
41
- "react-dom": "^18.3.1"
39
+ "peerDependencies": {
40
+ "react": "^19.1.0",
41
+ "react-dom": "^19.1.0"
42
42
  },
43
43
  "scripts": {
44
44
  "build": "yarn clean && vite build",
@@ -47,15 +47,18 @@
47
47
  "lint:eslint": "eslint ./src/ --ext .tsx,.ts",
48
48
  "lint:stylelint": "stylelint \"./src/**/*.scss\" --config .stylelintrc.json"
49
49
  },
50
+ "dependencies": {
51
+ "@jk-core/hooks": "workspace:^",
52
+ "@jk-core/utils": "workspace:^",
53
+ "react": "^19.0.0",
54
+ "react-dom": "^19.0.0"
55
+ },
50
56
  "devDependencies": {
51
- "@jk-core/hooks": "workspace:*",
52
- "@jk-core/utils": "workspace:*",
53
- "@types/node": "^22.7.4",
54
- "@types/react": "^18.3.11",
55
- "@types/react-dom": "^18.3.0",
56
- "@typescript-eslint/eslint-plugin": "^7.2.0",
57
- "@typescript-eslint/parser": "^7.2.0",
58
- "@vitejs/plugin-react-swc": "^3.7.1",
57
+ "@eslint/js": "^9.21.0",
58
+ "@types/node": "^22.14.0",
59
+ "@types/react": "^19.0.10",
60
+ "@types/react-dom": "^19.0.4",
61
+ "@vitejs/plugin-react": "^4.3.4",
59
62
  "eslint": "^8.57.0",
60
63
  "eslint-config-airbnb": "^19.0.4",
61
64
  "eslint-config-airbnb-typescript": "^18.0.0",
@@ -65,9 +68,9 @@
65
68
  "eslint-plugin-react": "^7.34.2",
66
69
  "eslint-plugin-react-hooks": "^4.6.2",
67
70
  "eslint-plugin-react-refresh": "^0.4.6",
71
+ "globals": "^15.15.0",
68
72
  "optionator": "^0.9.4",
69
73
  "postcss": "^8.4.38",
70
- "prettier": "^3.3.3",
71
74
  "sass": "^1.80.0",
72
75
  "sass-loader": "^16.0.2",
73
76
  "stylelint": "^16.6.1",
@@ -75,13 +78,13 @@
75
78
  "stylelint-config-standard-scss": "^13.1.0",
76
79
  "stylelint-scss": "^6.8.0",
77
80
  "stylelint-selector-bem-pattern": "^4.0.0",
78
- "typescript": "^5.5.3",
79
- "vite": "^5.4.8",
80
- "vite-plugin-checker": "^0.8.0",
81
+ "typescript": "~5.7.2",
82
+ "vite": "^6.2.0",
83
+ "vite-plugin-checker": "^0.9.1",
81
84
  "vite-plugin-css-injected-by-js": "^3.5.2",
82
- "vite-plugin-dts": "^4.2.3",
83
- "vite-plugin-sass-dts": "^1.3.29",
84
- "vite-plugin-svgr": "^4.2.0",
85
- "vite-tsconfig-paths": "^5.0.1"
85
+ "vite-plugin-dts": "^4.5.3",
86
+ "vite-plugin-sass-dts": "^1.3.31",
87
+ "vite-plugin-svgr": "^4.3.0",
88
+ "vite-tsconfig-paths": "^5.1.4"
86
89
  }
87
90
  }
@@ -0,0 +1,213 @@
1
+ @use "../styles/mediaQuery.scss" as media;
2
+
3
+ button {
4
+ border: none;
5
+ background-color: transparent;
6
+ user-select: none;
7
+ -webkit-user-select: none;
8
+ -moz-user-select: none;
9
+ cursor: pointer;
10
+ }
11
+
12
+ .calendar {
13
+ width: 100%;
14
+ min-width: 300px;
15
+ border: 1px solid var(--calendar-G-30);
16
+ border-radius: 10px;
17
+ overflow: hidden;
18
+ color: var(--calendar-G-80);
19
+ background-color: var(--calendar-white);
20
+
21
+ &--range {
22
+ box-sizing: border-box;
23
+ }
24
+
25
+ &--scroll {
26
+ height: 100%;
27
+ border: none;
28
+ border-radius: 0;
29
+ }
30
+
31
+ &__scroll {
32
+ height: 100%;
33
+ flex-shrink: 0;
34
+ display: flex;
35
+ flex-direction: column-reverse;
36
+ box-sizing: border-box;
37
+ gap: 10px;
38
+ overflow-y: scroll;
39
+
40
+ &::-webkit-scrollbar {
41
+ width: 0;
42
+ }
43
+
44
+ &--wrapper {
45
+ flex: 1 0;
46
+ width: 100%;
47
+ height: 100%;
48
+ display: flex;
49
+ flex-direction: column;
50
+ }
51
+
52
+ &--button {
53
+ width: 95%;
54
+ margin: 5px auto;
55
+ display: flex;
56
+ align-items: center;
57
+ justify-content: center;
58
+ border-radius: 10px;
59
+ background-color: var(--calendar-white);
60
+ border: 2px solid var(--calendar-G-50);
61
+ padding: 15px 0;
62
+ transition: 0.2s;
63
+ font-size: 1.2em;
64
+
65
+ &:active {
66
+ scale: 0.98;
67
+ background-color: var(--calendar-G-5);
68
+ }
69
+ }
70
+ }
71
+
72
+ &__close {
73
+ display: flex;
74
+ justify-content: flex-end;
75
+ align-items: center;
76
+ padding: 7px 10px 7px 0;
77
+ box-sizing: border-box;
78
+
79
+ svg {
80
+ width: 18px;
81
+ height: 18px;
82
+ cursor: pointer;
83
+ }
84
+ }
85
+
86
+ &__range-tile {
87
+ position: relative;
88
+ width: 100%;
89
+ display: flex;
90
+ gap: 10px;
91
+ }
92
+
93
+ &__wrapper {
94
+ flex: 1 0;
95
+ width: 100%;
96
+ height: 100%;
97
+ display: flex;
98
+ flex-direction: column;
99
+ }
100
+ }
101
+
102
+ .view {
103
+ position: relative;
104
+ margin: 0 auto;
105
+ width: 90%;
106
+ display: flex;
107
+ justify-content: space-between;
108
+ align-items: center;
109
+ background-color: #f3f4f8;
110
+ border-radius: 10px;
111
+
112
+ &__block {
113
+ position: absolute;
114
+ background-color: #fff;
115
+ left: 0;
116
+ height: 100%;
117
+ border: 2px solid var(--calendar-G-30);
118
+ width: 33.3%;
119
+ border-radius: 10px;
120
+ transition: 0.3s;
121
+
122
+ &--second {
123
+ left: 33%;
124
+ }
125
+
126
+ &--last {
127
+ left: 66.6%;
128
+ }
129
+ }
130
+
131
+ &__selector {
132
+ position: relative;
133
+ height: 40px;
134
+ flex: 1 0;
135
+ display: flex;
136
+ align-items: center;
137
+ justify-content: center;
138
+ color: var(--calendar-G-60);
139
+ font-size: 1em;
140
+ font-weight: 400;
141
+
142
+ &--selected {
143
+ color: var(--calendar-G-80);
144
+ font-size: 1em;
145
+ font-weight: 600;
146
+ }
147
+ }
148
+ }
149
+
150
+ .nav {
151
+ height: 60px;
152
+ display: flex;
153
+ justify-content: space-between;
154
+ align-items: center;
155
+ padding: 0 5px;
156
+ border-bottom: 1px solid var(--calendar-G-30);
157
+ font-size: 1.3em;
158
+ font-weight: 400;
159
+
160
+ &__button {
161
+ display: flex;
162
+ align-items: center;
163
+ justify-content: center;
164
+ width: 40px;
165
+ height: 40px;
166
+ padding: 10px;
167
+ border-radius: 100%;
168
+
169
+ &:hover {
170
+ @include media.pc {
171
+ background-color: var(--calendar-G-10);
172
+ }
173
+ }
174
+
175
+ &:active {
176
+ background-color: var(--calendar-G-30);
177
+ }
178
+
179
+ &:disabled {
180
+ cursor: not-allowed;
181
+ fill: var(--calendar-G-40);
182
+ background-color: transparent;
183
+ }
184
+ }
185
+
186
+ &__label {
187
+ flex: 1 0;
188
+ display: flex;
189
+ align-items: center;
190
+ justify-content: space-around;
191
+ font-size: 1.1em;
192
+ font-weight: 400;
193
+
194
+ &--date {
195
+ display: flex;
196
+ align-items: center;
197
+ justify-content: center;
198
+ border-radius: 5px;
199
+ padding: 5px 10px;
200
+ font-weight: 400;
201
+ font-size: 1em;
202
+
203
+ svg {
204
+ width: 15px;
205
+ height: 15px;
206
+ }
207
+ }
208
+
209
+ &--date-selected {
210
+ background-color: var(--calendar-S-10);
211
+ }
212
+ }
213
+ }
@@ -0,0 +1,125 @@
1
+ /* eslint-disable react/no-array-index-key */
2
+ import { cn } from '@jk-core/utils';
3
+ import { useEffect, useState } from 'react';
4
+ import CloseIcon from '../assets/close.svg';
5
+ import DayTile from './components/DayTile';
6
+ import styles from './Calendar.module.scss';
7
+ import { CalendarRange } from './type';
8
+ import DateLabel from './components/DateLabel';
9
+ import useCalendarNav from './hooks/useCalendarNav';
10
+ import getWeeksInMonth from './utils/getWeeksInMonth';
11
+
12
+ interface CalendarProps {
13
+ className?: string;
14
+ date: CalendarRange;
15
+ onChange:(date:CalendarRange)=>void;
16
+ min: Date;
17
+ max: Date;
18
+ onClose?: () => void;
19
+ }
20
+
21
+ export default function RangeCalendar({
22
+ className = '', date: selectedDate = [null, null], onChange, onClose,
23
+ min, max,
24
+ }: CalendarProps) {
25
+ const method = 'day';
26
+ const [viewDate, setViewDate] = useState<Date>(selectedDate?.[0] || new Date());
27
+ const [hoverDate, setHoverDate] = useState<Date | null>(null);
28
+ const weeksInMonth = getWeeksInMonth(viewDate);
29
+
30
+ const onDayClick = (day: Date, maintenance = false) => {
31
+ if (!maintenance) setViewDate(day);
32
+ if (!selectedDate[0] || (!!selectedDate[0] && !!selectedDate[1])) {
33
+ onChange([day, null]);
34
+ }
35
+ if (!!selectedDate[0] && !selectedDate[1]) {
36
+ if (day < selectedDate[0]) {
37
+ onChange([day, null]);
38
+ } else {
39
+ onChange([selectedDate[0], day]);
40
+ }
41
+ }
42
+ };
43
+
44
+ const { disabled, onArrowClick } = useCalendarNav({
45
+ method, selectMode: 'day', viewDate, setDate: setViewDate, min, max,
46
+ });
47
+
48
+ useEffect(() => {
49
+ if (viewDate > max) {
50
+ setViewDate(max);
51
+ }
52
+ if (viewDate < min) {
53
+ setViewDate(min);
54
+ }
55
+ }, [viewDate, max, min]);
56
+
57
+ return (
58
+ <div className={cn({
59
+ [styles.calendar]: true,
60
+ [styles['calendar--range']]: true,
61
+ [className]: !!className,
62
+ })}
63
+ >
64
+ <div className={styles.calendar__close}>
65
+ {onClose && (
66
+ <CloseIcon onClick={onClose} />
67
+ )}
68
+ </div>
69
+ {/* 일/월/년 선택 버튼 */}
70
+ <div className={styles['calendar__range-tile']}>
71
+ <div className={styles.calendar__wrapper}>
72
+ <DateLabel
73
+ viewDate={viewDate}
74
+ method="day"
75
+ onArrowClick={onArrowClick}
76
+ disabled={disabled}
77
+ hideArrow="next"
78
+ range
79
+ />
80
+ <DayTile
81
+ hoverDate={hoverDate}
82
+ setHoverDate={(day) => setHoverDate(day)}
83
+ selectedDate={selectedDate}
84
+ weeksInMonth={weeksInMonth}
85
+ handleDayClick={onDayClick}
86
+ hideAfter
87
+ max={max}
88
+ min={min}
89
+ range
90
+ />
91
+ </div>
92
+ <div className={styles.calendar__wrapper}>
93
+ <DateLabel
94
+ viewDate={new Date(
95
+ viewDate.getFullYear(),
96
+ viewDate.getMonth() + 1,
97
+ 1,
98
+ )}
99
+ method="day"
100
+ onArrowClick={onArrowClick}
101
+ disabled={disabled}
102
+ hideArrow="prev"
103
+ range
104
+ />
105
+ <DayTile
106
+ hoverDate={hoverDate}
107
+ setHoverDate={(day) => setHoverDate(day)}
108
+ selectedDate={selectedDate}
109
+ weeksInMonth={getWeeksInMonth(new Date(
110
+ viewDate.getFullYear(),
111
+ viewDate.getMonth() + 1,
112
+ 1,
113
+ ))}
114
+ handleDayClick={(day) => onDayClick(day, true)}
115
+ hideBefore
116
+ hideAfter
117
+ max={max}
118
+ min={min}
119
+ range
120
+ />
121
+ </div>
122
+ </div>
123
+ </div>
124
+ );
125
+ }
@@ -0,0 +1,214 @@
1
+ @use "../styles/mediaQuery.scss" as media;
2
+
3
+ button {
4
+ border: none;
5
+ background-color: transparent;
6
+ user-select: none;
7
+ -webkit-user-select: none;
8
+ -moz-user-select: none;
9
+ cursor: pointer;
10
+ -webkit-tap-highlight-color: transparent; // 모바일 터치 하이라이트 색상 제거
11
+ }
12
+
13
+ .calendar {
14
+ width: 100%;
15
+ min-width: 300px;
16
+ border: 1px solid var(--calendar-G-30);
17
+ border-radius: 10px;
18
+ overflow: hidden;
19
+ color: var(--calendar-G-80);
20
+ background-color: var(--calendar-white);
21
+
22
+ &--range {
23
+ box-sizing: border-box;
24
+ }
25
+
26
+ &--scroll {
27
+ height: 100%;
28
+ border: none;
29
+ border-radius: 0;
30
+ }
31
+
32
+ &__scroll {
33
+ height: 100%;
34
+ flex-shrink: 0;
35
+ display: flex;
36
+ flex-direction: column-reverse;
37
+ box-sizing: border-box;
38
+ gap: 10px;
39
+ overflow-y: scroll;
40
+
41
+ &::-webkit-scrollbar {
42
+ width: 0;
43
+ }
44
+
45
+ &--wrapper {
46
+ flex: 1 0;
47
+ width: 100%;
48
+ height: 100%;
49
+ display: flex;
50
+ flex-direction: column;
51
+ }
52
+
53
+ &--button {
54
+ width: 95%;
55
+ margin: 5px auto;
56
+ display: flex;
57
+ align-items: center;
58
+ justify-content: center;
59
+ border-radius: 10px;
60
+ background-color: var(--calendar-white);
61
+ border: 2px solid var(--calendar-G-50);
62
+ padding: 15px 0;
63
+ transition: 0.2s;
64
+ font-size: 1.2em;
65
+
66
+ &:active {
67
+ scale: 0.98;
68
+ background-color: var(--calendar-G-5);
69
+ }
70
+ }
71
+ }
72
+
73
+ &__close {
74
+ display: flex;
75
+ justify-content: flex-end;
76
+ align-items: center;
77
+ padding: 7px 10px 7px 0;
78
+ box-sizing: border-box;
79
+
80
+ svg {
81
+ width: 18px;
82
+ height: 18px;
83
+ cursor: pointer;
84
+ }
85
+ }
86
+
87
+ &__range-tile {
88
+ position: relative;
89
+ width: 100%;
90
+ display: flex;
91
+ gap: 10px;
92
+ }
93
+
94
+ &__wrapper {
95
+ flex: 1 0;
96
+ width: 100%;
97
+ height: 100%;
98
+ display: flex;
99
+ flex-direction: column;
100
+ }
101
+ }
102
+
103
+ .view {
104
+ position: relative;
105
+ margin: 0 auto;
106
+ width: 90%;
107
+ display: flex;
108
+ justify-content: space-between;
109
+ align-items: center;
110
+ background-color: #f3f4f8;
111
+ border-radius: 10px;
112
+
113
+ &__block {
114
+ position: absolute;
115
+ background-color: #fff;
116
+ left: 0;
117
+ height: 100%;
118
+ border: 2px solid var(--calendar-G-30);
119
+ width: 33.3%;
120
+ border-radius: 10px;
121
+ transition: 0.3s;
122
+
123
+ &--second {
124
+ left: 33%;
125
+ }
126
+
127
+ &--last {
128
+ left: 66.6%;
129
+ }
130
+ }
131
+
132
+ &__selector {
133
+ position: relative;
134
+ height: 40px;
135
+ flex: 1 0;
136
+ display: flex;
137
+ align-items: center;
138
+ justify-content: center;
139
+ color: var(--calendar-G-60);
140
+ font-size: 1em;
141
+ font-weight: 400;
142
+
143
+ &--selected {
144
+ color: var(--calendar-G-80);
145
+ font-size: 1em;
146
+ font-weight: 600;
147
+ }
148
+ }
149
+ }
150
+
151
+ .nav {
152
+ height: 60px;
153
+ display: flex;
154
+ justify-content: space-between;
155
+ align-items: center;
156
+ padding: 0 5px;
157
+ border-bottom: 1px solid var(--calendar-G-30);
158
+ font-size: 1.3em;
159
+ font-weight: 400;
160
+
161
+ &__button {
162
+ display: flex;
163
+ align-items: center;
164
+ justify-content: center;
165
+ width: 40px;
166
+ height: 40px;
167
+ padding: 10px;
168
+ border-radius: 100%;
169
+
170
+ &:hover {
171
+ @include media.pc {
172
+ background-color: var(--calendar-G-10);
173
+ }
174
+ }
175
+
176
+ &:active {
177
+ background-color: var(--calendar-G-30);
178
+ }
179
+
180
+ &:disabled {
181
+ cursor: not-allowed;
182
+ fill: var(--calendar-G-40);
183
+ background-color: transparent;
184
+ }
185
+ }
186
+
187
+ &__label {
188
+ flex: 1 0;
189
+ display: flex;
190
+ align-items: center;
191
+ justify-content: space-around;
192
+ font-size: 1.1em;
193
+ font-weight: 400;
194
+
195
+ &--date {
196
+ display: flex;
197
+ align-items: center;
198
+ justify-content: center;
199
+ border-radius: 5px;
200
+ padding: 5px 10px;
201
+ font-weight: 400;
202
+ font-size: 1em;
203
+
204
+ svg {
205
+ width: 15px;
206
+ height: 15px;
207
+ }
208
+ }
209
+
210
+ &--date-selected {
211
+ background-color: var(--calendar-S-10);
212
+ }
213
+ }
214
+ }