@jk-core/components 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +399 -471
- package/dist/index.js.map +1 -1
- package/dist/index.umd.cjs +19 -10
- package/dist/index.umd.cjs.map +1 -1
- package/dist/main.d.ts +1 -0
- package/dist/style.css +402 -1
- package/dist/style.css.map +1 -0
- package/package.json +10 -4
- package/src/Calendar/{Calendar.module.scss → scss/_calendar.scss} +9 -0
- package/src/Calendar/scss/_tile.scss +214 -0
- package/src/{styles/color.scss → Calendar/scss/_variables.scss} +1 -0
- package/src/Calendar/scss/main.scss +3 -0
- package/src/Calendar/components/DayTile/DayTile.module.scss +0 -79
- package/src/Calendar/components/DayTile/index.tsx +0 -52
- package/src/Calendar/components/MonthTile/MonthTile.module.scss +0 -44
- package/src/Calendar/components/MonthTile/index.tsx +0 -38
- package/src/Calendar/components/YearTile/YearTile.module.scss +0 -85
- package/src/Calendar/components/YearTile/index.tsx +0 -60
- package/src/Calendar/components/mixin.module.scss +0 -5
- package/src/Calendar/hooks/useCalendarNav.ts +0 -80
- package/src/Calendar/hooks/useDateSelect.ts +0 -47
- package/src/Calendar/index.tsx +0 -166
- package/src/Calendar/type.ts +0 -6
- package/src/Calendar/utils/getWeeksInMonth.ts +0 -45
- package/src/Calendar/utils/isInRange.ts +0 -8
- package/src/Calendar/utils/isSameDay.ts +0 -21
- package/src/assets/close.svg +0 -16
- package/src/assets/drop-arrow.svg +0 -3
- package/src/index.tsx +0 -3
- package/src/styles/mediaQuery.scss +0 -22
- package/src/svg.d.ts +0 -6
- package/src/vite-env.d.ts +0 -1
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
@use "../mixin.module.scss" as mixin;
|
|
2
|
-
@use "../../../styles/mediaQuery.scss" as media;
|
|
3
|
-
|
|
4
|
-
.body {
|
|
5
|
-
@include mixin.body;
|
|
6
|
-
|
|
7
|
-
&__tile {
|
|
8
|
-
display: flex;
|
|
9
|
-
flex-direction: column;
|
|
10
|
-
justify-content: space-between;
|
|
11
|
-
gap: 5px;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
&__weeks {
|
|
15
|
-
display: flex;
|
|
16
|
-
justify-content: space-between;
|
|
17
|
-
font-weight: 400;
|
|
18
|
-
font-size: 1em;
|
|
19
|
-
|
|
20
|
-
&--date {
|
|
21
|
-
flex: 1 0;
|
|
22
|
-
display: flex;
|
|
23
|
-
justify-content: center;
|
|
24
|
-
align-items: center;
|
|
25
|
-
min-width: 40px;
|
|
26
|
-
padding: 5px 0;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
&__week {
|
|
31
|
-
display: flex;
|
|
32
|
-
justify-content: space-between;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
&__day {
|
|
36
|
-
display: flex;
|
|
37
|
-
justify-content: center;
|
|
38
|
-
align-items: center;
|
|
39
|
-
flex-direction: column;
|
|
40
|
-
width: 100%;
|
|
41
|
-
min-width: 40px;
|
|
42
|
-
min-height: 40px;
|
|
43
|
-
border-radius: 100%;
|
|
44
|
-
padding: 5px;
|
|
45
|
-
border: none;
|
|
46
|
-
font-weight: 400;
|
|
47
|
-
font-size: 1em;
|
|
48
|
-
|
|
49
|
-
&:hover {
|
|
50
|
-
@include media.pc {
|
|
51
|
-
background-color: var(--G-5);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
&:active {
|
|
56
|
-
background-color: var(--G-10);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
&--today {
|
|
60
|
-
color: var(--P-50);
|
|
61
|
-
font-weight: 600;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
&--selected {
|
|
65
|
-
background-color: var(--P-50) !important;
|
|
66
|
-
color: var(--white) !important;
|
|
67
|
-
font-weight: 600;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
&--before {
|
|
71
|
-
color: var(--G-40);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
&--tile {
|
|
75
|
-
border-radius: 10px;
|
|
76
|
-
gap: 5px;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/* eslint-disable max-len */
|
|
2
|
-
/* eslint-disable react/no-array-index-key */
|
|
3
|
-
import { cn } from '@jk-core/utils';
|
|
4
|
-
import isSameDay from '../../utils/isSameDay';
|
|
5
|
-
import styles from './DayTile.module.scss';
|
|
6
|
-
|
|
7
|
-
const WEEKS = ['일', '월', '화', '수', '목', '금', '토'];
|
|
8
|
-
|
|
9
|
-
interface Props {
|
|
10
|
-
selectedDate?: Date;
|
|
11
|
-
weeksInMonth: {
|
|
12
|
-
thisMonth: boolean;
|
|
13
|
-
date: Date;
|
|
14
|
-
}[][];
|
|
15
|
-
tileContent?: () => React.ReactNode;
|
|
16
|
-
handleDayClick: (day: Date) => void;
|
|
17
|
-
}
|
|
18
|
-
export default function DayTile({
|
|
19
|
-
selectedDate, weeksInMonth, tileContent, handleDayClick,
|
|
20
|
-
}: Props) {
|
|
21
|
-
return (
|
|
22
|
-
<div className={styles.body}>
|
|
23
|
-
<div className={styles.body__weeks}>
|
|
24
|
-
{WEEKS.map((week) => (<div className={styles['body__weeks--date']} key={week}>{week}</div>))}
|
|
25
|
-
</div>
|
|
26
|
-
|
|
27
|
-
<div className={styles.body__tile}>
|
|
28
|
-
{weeksInMonth.map((week, index) => (
|
|
29
|
-
<div key={index} className={styles.body__week}>
|
|
30
|
-
{week.map((day, idx) => (
|
|
31
|
-
<button
|
|
32
|
-
className={cn({
|
|
33
|
-
[styles.body__day]: true,
|
|
34
|
-
[styles['body__day--today']]: isSameDay(day.date, new Date()),
|
|
35
|
-
[styles['body__day--selected']]: !!selectedDate && isSameDay(day.date, selectedDate),
|
|
36
|
-
[styles['body__day--before']]: !day.thisMonth,
|
|
37
|
-
[styles['body__day--tile']]: !!(tileContent && tileContent()),
|
|
38
|
-
})}
|
|
39
|
-
type="button"
|
|
40
|
-
key={idx}
|
|
41
|
-
onClick={() => handleDayClick(day.date)}
|
|
42
|
-
>
|
|
43
|
-
{day.date.getDate()}
|
|
44
|
-
{tileContent && tileContent()}
|
|
45
|
-
</button>
|
|
46
|
-
))}
|
|
47
|
-
</div>
|
|
48
|
-
))}
|
|
49
|
-
</div>
|
|
50
|
-
</div>
|
|
51
|
-
);
|
|
52
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
@use "../mixin.module.scss" as mixin;
|
|
2
|
-
|
|
3
|
-
.body {
|
|
4
|
-
display: grid;
|
|
5
|
-
grid-template-columns: repeat(3, 1fr);
|
|
6
|
-
grid-template-rows: repeat(4, 1fr);
|
|
7
|
-
gap: 5px;
|
|
8
|
-
|
|
9
|
-
@include mixin.body;
|
|
10
|
-
|
|
11
|
-
&__month {
|
|
12
|
-
display: flex;
|
|
13
|
-
flex-direction: column;
|
|
14
|
-
justify-content: center;
|
|
15
|
-
align-items: center;
|
|
16
|
-
padding: 5px;
|
|
17
|
-
border-radius: 10px;
|
|
18
|
-
|
|
19
|
-
svg {
|
|
20
|
-
width: 15px;
|
|
21
|
-
height: 15px;
|
|
22
|
-
cursor: pointer;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
&:active {
|
|
26
|
-
background-color: var(--G-10);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
&--selected {
|
|
30
|
-
background-color: var(--P-50) !important;
|
|
31
|
-
color: var(--white) !important;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
&--today {
|
|
35
|
-
color: var(--P-50);
|
|
36
|
-
font-weight: 600;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
&--tile {
|
|
40
|
-
justify-content: flex-start;
|
|
41
|
-
gap: 5px;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { cn } from '@jk-core/utils';
|
|
2
|
-
import styles from './MonthTile.module.scss';
|
|
3
|
-
import isSameDay from '../../utils/isSameDay';
|
|
4
|
-
import { CalendarView } from '../../type';
|
|
5
|
-
|
|
6
|
-
const MONTHS = Array.from({ length: 12 }, (_, i) => i);
|
|
7
|
-
|
|
8
|
-
interface Props {
|
|
9
|
-
selectedDate?: Date;
|
|
10
|
-
viewDate: Date;
|
|
11
|
-
handleMonthClick: (month: number) => void;
|
|
12
|
-
tileContent?: (date: Date, view:CalendarView) => React.ReactNode;
|
|
13
|
-
}
|
|
14
|
-
export default function MonthTile({
|
|
15
|
-
selectedDate, viewDate, handleMonthClick, tileContent = () => false,
|
|
16
|
-
}: Props) {
|
|
17
|
-
return (
|
|
18
|
-
<div className={styles.body}>
|
|
19
|
-
{MONTHS.map((month) => (
|
|
20
|
-
<button
|
|
21
|
-
className={cn({
|
|
22
|
-
[styles.body__month]: true,
|
|
23
|
-
[styles['body__month--selected']]: !!selectedDate && isSameDay(selectedDate, new Date(viewDate.getFullYear(), month), 'month'),
|
|
24
|
-
[styles['body__month--today']]: isSameDay(new Date(viewDate.getFullYear(), month), new Date(), 'month'),
|
|
25
|
-
[styles['body__month--tile']]: !!tileContent(new Date(viewDate.getFullYear(), month - 1, 1), 'month'),
|
|
26
|
-
})}
|
|
27
|
-
type="button"
|
|
28
|
-
key={month}
|
|
29
|
-
onClick={() => handleMonthClick(month)}
|
|
30
|
-
>
|
|
31
|
-
<span>{`${month + 1}월`}</span>
|
|
32
|
-
{!!tileContent(new Date(viewDate.getFullYear(), month - 1, 1), 'month')
|
|
33
|
-
&& tileContent(new Date(viewDate.getFullYear(), month - 1, 1), 'month')}
|
|
34
|
-
</button>
|
|
35
|
-
))}
|
|
36
|
-
</div>
|
|
37
|
-
);
|
|
38
|
-
}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
@use "../mixin.module.scss" as mixin;
|
|
2
|
-
@use "../../../styles/mediaQuery.scss" as media;
|
|
3
|
-
|
|
4
|
-
.body {
|
|
5
|
-
@include mixin.body;
|
|
6
|
-
|
|
7
|
-
position: relative;
|
|
8
|
-
height: 310px;
|
|
9
|
-
display: flex;
|
|
10
|
-
flex-direction: column;
|
|
11
|
-
align-items: center;
|
|
12
|
-
overflow: auto;
|
|
13
|
-
gap: 10px;
|
|
14
|
-
|
|
15
|
-
&::-webkit-scrollbar {
|
|
16
|
-
display: none;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
&__blank {
|
|
20
|
-
height: calc(50% - 40px);
|
|
21
|
-
flex-shrink: 0;
|
|
22
|
-
|
|
23
|
-
&:last-child {
|
|
24
|
-
height: 50%;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
&__year {
|
|
29
|
-
min-width: 50%;
|
|
30
|
-
display: flex;
|
|
31
|
-
flex-direction: column;
|
|
32
|
-
align-items: center;
|
|
33
|
-
justify-content: center;
|
|
34
|
-
min-height: 40px;
|
|
35
|
-
border-radius: 6px;
|
|
36
|
-
flex-shrink: 0;
|
|
37
|
-
overflow: hidden;
|
|
38
|
-
font-weight: 400;
|
|
39
|
-
font-size: 1.2em;
|
|
40
|
-
|
|
41
|
-
&:hover {
|
|
42
|
-
@include media.pc {
|
|
43
|
-
background-color: var(--P-5);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
&:active {
|
|
48
|
-
background-color: var(--P-10);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
&--border {
|
|
52
|
-
border: 1px solid var(--G-30);
|
|
53
|
-
background-color: var(--P-5);
|
|
54
|
-
|
|
55
|
-
&:hover {
|
|
56
|
-
@include media.pc {
|
|
57
|
-
background-color: var(--P-10);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
&--year {
|
|
63
|
-
height: 40px;
|
|
64
|
-
display: flex;
|
|
65
|
-
align-items: center;
|
|
66
|
-
justify-content: center;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
&--selected {
|
|
70
|
-
color: var(--white);
|
|
71
|
-
background-color: var(--P-50) !important;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
&--tile {
|
|
75
|
-
display: flex;
|
|
76
|
-
align-items: center;
|
|
77
|
-
justify-content: center;
|
|
78
|
-
min-height: 40px;
|
|
79
|
-
color: var(--G-80);
|
|
80
|
-
width: 100%;
|
|
81
|
-
background-color: var(--white);
|
|
82
|
-
border-top: var(--P-50);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { cn } from '@jk-core/utils';
|
|
2
|
-
import { useEffect, useRef } from 'react';
|
|
3
|
-
import styles from './YearTile.module.scss';
|
|
4
|
-
import { CalendarView } from '../../type';
|
|
5
|
-
|
|
6
|
-
interface Props {
|
|
7
|
-
selectedDate?: Date;
|
|
8
|
-
onClick: (year: number) => void;
|
|
9
|
-
tileContent?: (date: Date, view:CalendarView) => React.ReactNode;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const YEARS = Array.from({ length: 100 }, (_, i) => i + 2000);
|
|
13
|
-
|
|
14
|
-
export default function YearTile({
|
|
15
|
-
selectedDate, onClick,
|
|
16
|
-
tileContent = () => false,
|
|
17
|
-
}: Props) {
|
|
18
|
-
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
19
|
-
const selectedRef = useRef<HTMLButtonElement>(null);
|
|
20
|
-
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
const selectedElement = selectedRef.current;
|
|
23
|
-
const wrapperElement = wrapperRef.current;
|
|
24
|
-
if (!selectedElement || !wrapperElement) return;
|
|
25
|
-
|
|
26
|
-
const { clientHeight } = wrapperElement;
|
|
27
|
-
const { offsetTop, clientHeight: selectedHeight } = selectedElement;
|
|
28
|
-
|
|
29
|
-
wrapperElement.scrollTo({
|
|
30
|
-
top: offsetTop - clientHeight / 2 + selectedHeight,
|
|
31
|
-
});
|
|
32
|
-
}, []);
|
|
33
|
-
|
|
34
|
-
return (
|
|
35
|
-
<div className={styles.body} ref={wrapperRef}>
|
|
36
|
-
<div className={styles.body__blank} />
|
|
37
|
-
{YEARS.map((year) => (
|
|
38
|
-
<button
|
|
39
|
-
className={cn({
|
|
40
|
-
[styles.body__year]: true,
|
|
41
|
-
[styles['body__year--selected']]: !!selectedDate && selectedDate.getFullYear() === year,
|
|
42
|
-
[styles['body__year--border']]: !!tileContent(new Date(year, 1, 1), 'year'),
|
|
43
|
-
})}
|
|
44
|
-
key={year}
|
|
45
|
-
type="button"
|
|
46
|
-
ref={!!selectedDate && selectedDate.getFullYear() === year ? selectedRef : null}
|
|
47
|
-
onClick={() => onClick(year)}
|
|
48
|
-
>
|
|
49
|
-
<span className={styles['body__year--year']}>{year}</span>
|
|
50
|
-
{tileContent(new Date(year, 1, 1), 'year') && (
|
|
51
|
-
<div className={styles['body__year--tile']}>
|
|
52
|
-
{tileContent(new Date(year, 1, 1), 'year')}
|
|
53
|
-
</div>
|
|
54
|
-
)}
|
|
55
|
-
</button>
|
|
56
|
-
))}
|
|
57
|
-
<div className={styles.body__blank} />
|
|
58
|
-
</div>
|
|
59
|
-
);
|
|
60
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { CalendarView } from '../type';
|
|
2
|
-
|
|
3
|
-
interface Props {
|
|
4
|
-
method: CalendarView;
|
|
5
|
-
selectMode: CalendarView;
|
|
6
|
-
date: Date;
|
|
7
|
-
setDate:(date: Date) => void;
|
|
8
|
-
min: Date;
|
|
9
|
-
max: Date;
|
|
10
|
-
}
|
|
11
|
-
const useCalendarNav = ({
|
|
12
|
-
method, selectMode, date, setDate, min, max,
|
|
13
|
-
}:Props) => {
|
|
14
|
-
const disabled = (direction: 'prev' | 'next') => {
|
|
15
|
-
if (selectMode === 'year' || method !== selectMode) return true;
|
|
16
|
-
|
|
17
|
-
if (method === 'day') {
|
|
18
|
-
if (direction === 'prev') {
|
|
19
|
-
const prevMonth = new Date(date.getFullYear(), date.getMonth() - 1, 1);
|
|
20
|
-
return prevMonth < min;
|
|
21
|
-
}
|
|
22
|
-
const nextMonth = new Date(date.getFullYear(), date.getMonth() + 1, 1);
|
|
23
|
-
return nextMonth > max;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (method === 'month') {
|
|
27
|
-
if (direction === 'prev') {
|
|
28
|
-
const prevYear = new Date(date.getFullYear() - 1, date.getMonth(), 1);
|
|
29
|
-
return prevYear < min;
|
|
30
|
-
}
|
|
31
|
-
const nextYear = new Date(date.getFullYear() + 1, date.getMonth(), 1);
|
|
32
|
-
return nextYear > max;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (method === 'year') {
|
|
36
|
-
if (direction === 'prev') {
|
|
37
|
-
const prevDecade = new Date(date.getFullYear() - 10, date.getMonth(), 1);
|
|
38
|
-
return prevDecade < min;
|
|
39
|
-
}
|
|
40
|
-
const nextDecade = new Date(date.getFullYear() + 10, date.getMonth(), 1);
|
|
41
|
-
return nextDecade > max;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return false;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const onArrowClick = (direction: 'prev' | 'next') => {
|
|
48
|
-
const offset = direction === 'prev' ? -1 : 1;
|
|
49
|
-
const minDate = new Date(2000, 0, 1);
|
|
50
|
-
const maxDate = new Date(2099, 11, 31);
|
|
51
|
-
|
|
52
|
-
if (method === 'day') {
|
|
53
|
-
const newDate = new Date(date.getFullYear(), date.getMonth() + offset, 1);
|
|
54
|
-
|
|
55
|
-
if (newDate >= minDate && newDate <= maxDate) {
|
|
56
|
-
setDate(newDate);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (method === 'month') {
|
|
61
|
-
const newDate = new Date(date.getFullYear() + offset, date.getMonth(), 1);
|
|
62
|
-
|
|
63
|
-
if (newDate >= minDate && newDate <= maxDate) {
|
|
64
|
-
setDate(newDate);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (method === 'year') {
|
|
69
|
-
const newDate = new Date(date.getFullYear() + offset * 10, date.getMonth(), 1);
|
|
70
|
-
|
|
71
|
-
if (newDate >= minDate && newDate <= maxDate) {
|
|
72
|
-
setDate(newDate);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
return { disabled, onArrowClick };
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
export default useCalendarNav;
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { CalendarView } from '../type';
|
|
2
|
-
|
|
3
|
-
interface UseDateSelectProps {
|
|
4
|
-
viewDate: Date;
|
|
5
|
-
setViewDate: (date: Date) => void;
|
|
6
|
-
method: CalendarView;
|
|
7
|
-
setSelectMode:(mode:CalendarView) => void;
|
|
8
|
-
onChange:(date:Date) => void;
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const useDateSelect = ({
|
|
13
|
-
viewDate, setViewDate, onChange, setSelectMode, method,
|
|
14
|
-
}: UseDateSelectProps) => {
|
|
15
|
-
const min = new Date(2000, 0, 1);
|
|
16
|
-
const max = new Date(2099, 11, 31);
|
|
17
|
-
|
|
18
|
-
const onDayClick = (day: Date) => {
|
|
19
|
-
if (day < min || day > max) {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
setViewDate(day);
|
|
24
|
-
onChange(day);
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const onMonthClick = (month:number) => {
|
|
28
|
-
const newDate = new Date(viewDate.getFullYear(), month, 1);
|
|
29
|
-
|
|
30
|
-
setViewDate(newDate);
|
|
31
|
-
|
|
32
|
-
if (method !== 'month') setSelectMode(method);
|
|
33
|
-
if (method === 'month') onChange(newDate);
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const onYearClick = (year:number) => {
|
|
37
|
-
const newDate = new Date(year, 0, 1);
|
|
38
|
-
|
|
39
|
-
setViewDate(newDate);
|
|
40
|
-
if (method !== 'year') setSelectMode(method);
|
|
41
|
-
if (method === 'year') onChange(newDate);
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
return { onDayClick, onMonthClick, onYearClick };
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
export default useDateSelect;
|
package/src/Calendar/index.tsx
DELETED
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
/* eslint-disable react/no-array-index-key */
|
|
2
|
-
import { useState } from 'react';
|
|
3
|
-
import { cn } from '@jk-core/utils';
|
|
4
|
-
import CloseIcon from '../assets/close.svg';
|
|
5
|
-
import DropIcon from '../assets/drop-arrow.svg';
|
|
6
|
-
import styles from './Calendar.module.scss';
|
|
7
|
-
import { CalendarView } from './type';
|
|
8
|
-
import getWeeksInMonth from './utils/getWeeksInMonth';
|
|
9
|
-
import DayTile from './components/DayTile';
|
|
10
|
-
import MonthTile from './components/MonthTile';
|
|
11
|
-
import YearTile from './components/YearTile';
|
|
12
|
-
import useCalendarNav from './hooks/useCalendarNav';
|
|
13
|
-
import useDateSelect from './hooks/useDateSelect';
|
|
14
|
-
|
|
15
|
-
import '../styles/color.scss';
|
|
16
|
-
|
|
17
|
-
interface CalendarProps {
|
|
18
|
-
date?: Date;
|
|
19
|
-
view?: CalendarView;
|
|
20
|
-
tileContent?: (date: Date | undefined, view: CalendarView) => React.ReactNode;
|
|
21
|
-
onChange?:(date:Date)=>void;
|
|
22
|
-
min?: Date;
|
|
23
|
-
max?: Date;
|
|
24
|
-
onClose?:()=>void;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export default function Calendar({
|
|
28
|
-
date: selectedDate, view, tileContent, onChange = () => { }, onClose,
|
|
29
|
-
min = new Date(2000, 0, 1), max = new Date(2099, 11, 31),
|
|
30
|
-
}:CalendarProps) {
|
|
31
|
-
const [viewDate, setViewDate] = useState<Date>(selectedDate || new Date());
|
|
32
|
-
const [method, setMethod] = useState<CalendarView>(view || 'day');
|
|
33
|
-
const [selectMode, setSelectMode] = useState<CalendarView>('day');
|
|
34
|
-
const weeksInMonth = getWeeksInMonth(viewDate);
|
|
35
|
-
const { onDayClick, onMonthClick, onYearClick } = useDateSelect({
|
|
36
|
-
viewDate,
|
|
37
|
-
setViewDate: (data) => setViewDate(data),
|
|
38
|
-
onChange,
|
|
39
|
-
setSelectMode,
|
|
40
|
-
method,
|
|
41
|
-
});
|
|
42
|
-
const { disabled, onArrowClick } = useCalendarNav({
|
|
43
|
-
method, selectMode, date: viewDate, setDate: setViewDate, min, max,
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
return (
|
|
47
|
-
<div className={styles.calendar}>
|
|
48
|
-
<div className={styles.calendar__close}>
|
|
49
|
-
{onClose
|
|
50
|
-
&& (
|
|
51
|
-
<CloseIcon onClick={onClose} />
|
|
52
|
-
)}
|
|
53
|
-
</div>
|
|
54
|
-
{/* 일/월/년 선택 버튼 */}
|
|
55
|
-
<div className={styles.view}>
|
|
56
|
-
<div className={cn({
|
|
57
|
-
[styles.view__block]: true,
|
|
58
|
-
[styles['view__block--second']]: method === 'month',
|
|
59
|
-
[styles['view__block--last']]: method === 'year',
|
|
60
|
-
})}
|
|
61
|
-
/>
|
|
62
|
-
<button
|
|
63
|
-
className={cn({
|
|
64
|
-
[styles.view__selector]: true,
|
|
65
|
-
[styles['view__selector--selected']]: method === 'day',
|
|
66
|
-
})}
|
|
67
|
-
type="button"
|
|
68
|
-
onClick={() => { setMethod('day'); setSelectMode('day'); }}
|
|
69
|
-
>일
|
|
70
|
-
</button>
|
|
71
|
-
<button
|
|
72
|
-
className={cn({
|
|
73
|
-
[styles.view__selector]: true,
|
|
74
|
-
[styles['view__selector--selected']]: method === 'month',
|
|
75
|
-
})}
|
|
76
|
-
type="button"
|
|
77
|
-
onClick={() => { setMethod('month'); setSelectMode('month'); }}
|
|
78
|
-
>월
|
|
79
|
-
</button>
|
|
80
|
-
<button
|
|
81
|
-
className={cn({
|
|
82
|
-
[styles.view__selector]: true,
|
|
83
|
-
[styles['view__selector--selected']]: method === 'year',
|
|
84
|
-
})}
|
|
85
|
-
type="button"
|
|
86
|
-
onClick={() => { setMethod('year'); setSelectMode('year'); }}
|
|
87
|
-
>년
|
|
88
|
-
</button>
|
|
89
|
-
</div>
|
|
90
|
-
|
|
91
|
-
<div className={styles.nav}>
|
|
92
|
-
<button
|
|
93
|
-
className={styles.nav__button}
|
|
94
|
-
type="button"
|
|
95
|
-
onClick={() => onArrowClick('prev')}
|
|
96
|
-
disabled={disabled('prev')}
|
|
97
|
-
>
|
|
98
|
-
◀︎
|
|
99
|
-
</button>
|
|
100
|
-
<div className={styles.nav__label}>
|
|
101
|
-
{method === 'year' && '연도 선택'}
|
|
102
|
-
{method !== 'year' && (
|
|
103
|
-
<button
|
|
104
|
-
className={cn({
|
|
105
|
-
[styles['nav__label--date']]: true,
|
|
106
|
-
[styles['nav__label--date-selected']]: selectMode === 'year',
|
|
107
|
-
})}
|
|
108
|
-
type="button"
|
|
109
|
-
onClick={() => setSelectMode('year')}
|
|
110
|
-
>
|
|
111
|
-
{`${viewDate.getFullYear()}년`}<DropIcon />
|
|
112
|
-
</button>
|
|
113
|
-
)}
|
|
114
|
-
{method === 'day' && (
|
|
115
|
-
<button
|
|
116
|
-
className={cn({
|
|
117
|
-
[styles['nav__label--date']]: true,
|
|
118
|
-
[styles['nav__label--date-selected']]: selectMode === 'month',
|
|
119
|
-
})}
|
|
120
|
-
type="button"
|
|
121
|
-
onClick={() => setSelectMode('month')}
|
|
122
|
-
>
|
|
123
|
-
{`${viewDate.getMonth() + 1}월`}<DropIcon />
|
|
124
|
-
</button>
|
|
125
|
-
)}
|
|
126
|
-
</div>
|
|
127
|
-
<button
|
|
128
|
-
className={styles.nav__button}
|
|
129
|
-
type="button"
|
|
130
|
-
onClick={() => onArrowClick('next')}
|
|
131
|
-
disabled={disabled('next')}
|
|
132
|
-
>►
|
|
133
|
-
</button>
|
|
134
|
-
</div>
|
|
135
|
-
|
|
136
|
-
{(method === 'day' && selectMode === 'day') && (
|
|
137
|
-
<DayTile
|
|
138
|
-
selectedDate={selectedDate}
|
|
139
|
-
weeksInMonth={weeksInMonth}
|
|
140
|
-
// selectRange={selectRange}
|
|
141
|
-
// selectedRange={selectedRange}
|
|
142
|
-
handleDayClick={onDayClick}
|
|
143
|
-
tileContent={() => (tileContent ? tileContent(selectedDate, method) : null)}
|
|
144
|
-
/>
|
|
145
|
-
)}
|
|
146
|
-
|
|
147
|
-
{((method === 'month' || selectMode === 'month') && selectMode !== 'year') && (
|
|
148
|
-
<MonthTile
|
|
149
|
-
selectedDate={selectedDate}
|
|
150
|
-
viewDate={viewDate}
|
|
151
|
-
handleMonthClick={onMonthClick}
|
|
152
|
-
tileContent={tileContent}
|
|
153
|
-
|
|
154
|
-
/>
|
|
155
|
-
)}
|
|
156
|
-
|
|
157
|
-
{(method === 'year' || selectMode === 'year') && (
|
|
158
|
-
<YearTile
|
|
159
|
-
selectedDate={selectedDate}
|
|
160
|
-
onClick={onYearClick}
|
|
161
|
-
tileContent={tileContent}
|
|
162
|
-
/>
|
|
163
|
-
)}
|
|
164
|
-
</div>
|
|
165
|
-
);
|
|
166
|
-
}
|