@daryasidorovich/modsen-datepicker 1.0.0 → 1.0.2
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/README.md +302 -302
- package/package.json +111 -106
- package/.babelrc.json +0 -7
- package/.github/workflows/chromatic.yml +0 -25
- package/.github/workflows/ci.yml +0 -56
- package/.husky/commit-msg +0 -1
- package/.husky/pre-commit +0 -1
- package/.prettierignore +0 -16
- package/.prettierrc +0 -6
- package/.storybook/main.js +0 -93
- package/.storybook/preview-head.html +0 -6
- package/.storybook/preview.js +0 -26
- package/.storybook/preview.tsx +0 -18
- package/commitlint.config.js +0 -23
- package/eslint.config.ts +0 -80
- package/jest.config.json +0 -21
- package/rollup.config.js +0 -65
- package/src/assets/actions/Delete.svg +0 -4
- package/src/assets/actions/Edit.svg +0 -3
- package/src/assets/arrows/Next.svg +0 -4
- package/src/assets/arrows/Prev.svg +0 -4
- package/src/assets/input/Calendar.svg +0 -3
- package/src/assets/input/Clear.svg +0 -3
- package/src/components/BaseCalendar/BaseCalendar.stories.tsx +0 -77
- package/src/components/BaseCalendar/index.tsx +0 -63
- package/src/components/BaseCalendar/styles.module.scss +0 -15
- package/src/components/CalendarGrid/CalendarGrid.stories.tsx +0 -136
- package/src/components/CalendarGrid/CalendarGridWithTasks/Tooltip/index.tsx +0 -27
- package/src/components/CalendarGrid/CalendarGridWithTasks/Tooltip/styles.module.scss +0 -9
- package/src/components/CalendarGrid/CalendarGridWithTasks/index.tsx +0 -51
- package/src/components/CalendarGrid/CalendarGridWithoutTasks/CalendarGridWithoutTasks.test.tsx +0 -223
- package/src/components/CalendarGrid/CalendarGridWithoutTasks/index.tsx +0 -36
- package/src/components/CalendarGrid/CalendarGridWithoutTasks/styles.module.scss +0 -11
- package/src/components/CalendarGrid/index.tsx +0 -19
- package/src/components/CalendarGrid/types.ts +0 -26
- package/src/components/Clear/Clear.stories.tsx +0 -16
- package/src/components/Clear/index.tsx +0 -12
- package/src/components/Clear/styles.module.scss +0 -34
- package/src/components/DatePicker/DatePicker.stories.tsx +0 -127
- package/src/components/DatePicker/index.tsx +0 -72
- package/src/components/DatePicker/styles.module.scss +0 -10
- package/src/components/Day/Day.stories.tsx +0 -75
- package/src/components/Day/index.tsx +0 -95
- package/src/components/Day/styles.module.scss +0 -97
- package/src/components/Input/Input.stories.tsx +0 -37
- package/src/components/Input/index.tsx +0 -64
- package/src/components/Input/styles.module.scss +0 -79
- package/src/components/Modal/CrudModal/index.tsx +0 -43
- package/src/components/Modal/CrudModal/styles.module.scss +0 -44
- package/src/components/Modal/index.tsx +0 -66
- package/src/components/Modal/styles.module.scss +0 -40
- package/src/components/Modal/types.ts +0 -13
- package/src/components/Month/Month.stories.tsx +0 -19
- package/src/components/Month/index.tsx +0 -31
- package/src/components/Month/styles.module.scss +0 -30
- package/src/components/RangePicker/RangePicker.stories.tsx +0 -134
- package/src/components/RangePicker/index.tsx +0 -144
- package/src/components/RangePicker/styles.module.scss +0 -19
- package/src/components/TasksManager/AddModal/index.tsx +0 -62
- package/src/components/TasksManager/DeleteModal/index.tsx +0 -22
- package/src/components/TasksManager/EditModal/index.tsx +0 -96
- package/src/components/TasksManager/index.tsx +0 -112
- package/src/components/TasksManager/styles.module.scss +0 -62
- package/src/components/Week/Week.stories.tsx +0 -49
- package/src/components/Week/index.tsx +0 -68
- package/src/components/Week/styles.module.scss +0 -7
- package/src/components/WeekDay/WeekDay.stories.tsx +0 -38
- package/src/components/WeekDay/index.tsx +0 -35
- package/src/components/WeekDay/styles.module.scss +0 -19
- package/src/constants/dateMask.ts +0 -23
- package/src/constants/firstDayOfWeek.ts +0 -7
- package/src/constants/holidays.ts +0 -32
- package/src/constants/modes.ts +0 -6
- package/src/constants/monthsNames.ts +0 -14
- package/src/constants/weekdaysNames.ts +0 -1
- package/src/hooks/useCalendar.ts +0 -62
- package/src/hooks/useLockBodyScroll.ts +0 -19
- package/src/hooks/useModal.ts +0 -45
- package/src/hooks/useTooltip.ts +0 -41
- package/src/hooks/useValidate.ts +0 -80
- package/src/index.ts +0 -15
- package/src/services/calendarService.ts +0 -62
- package/src/services/decorators/withHolidays.test.ts +0 -64
- package/src/services/decorators/withHolidays.ts +0 -12
- package/src/services/decorators/withMinMax.test.ts +0 -77
- package/src/services/decorators/withMinMax.ts +0 -19
- package/src/services/holidayService.ts +0 -56
- package/src/setupTests.ts +0 -1
- package/src/store/localStorage.ts +0 -33
- package/src/store/tasksStore.test.tsx +0 -208
- package/src/store/tasksStore.tsx +0 -146
- package/src/store/types.ts +0 -22
- package/src/styles/_border.scss +0 -9
- package/src/styles/_colors.scss +0 -53
- package/src/styles/_gap.scss +0 -4
- package/src/styles/_globals.scss +0 -61
- package/src/styles/_grid.scss +0 -9
- package/src/styles/_mixins.scss +0 -6
- package/src/styles/_reset.scss +0 -98
- package/src/styles/_theme-mixins.scss +0 -51
- package/src/styles/_typography.scss +0 -10
- package/src/styles/_variables.scss +0 -8
- package/src/styles/main.scss +0 -3
- package/src/types/types.d.ts +0 -15
- package/src/utils/calendar.test.ts +0 -154
- package/src/utils/calendar.ts +0 -82
- package/src/utils/controlDate.ts +0 -3
- package/src/utils/dateChecks.test.ts +0 -216
- package/src/utils/dateChecks.ts +0 -75
- package/src/utils/formatDate.test.ts +0 -57
- package/src/utils/formatDate.ts +0 -27
- package/src/utils/schema.test.ts +0 -40
- package/src/utils/schema.ts +0 -8
- package/src/utils/weekdayOrder.test.ts +0 -11
- package/src/utils/weekdayOrder.ts +0 -7
- package/tsconfig.json +0 -31
- package/vitest.config.ts +0 -38
- package/vitest.shims.d.ts +0 -1
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
isInRange,
|
|
3
|
-
isRangeEnd,
|
|
4
|
-
isRangeStart,
|
|
5
|
-
isSelected,
|
|
6
|
-
} from '@/utils/dateChecks';
|
|
7
|
-
|
|
8
|
-
import { Day } from '../Day';
|
|
9
|
-
import styles from './styles.module.scss';
|
|
10
|
-
|
|
11
|
-
export interface WeekProps {
|
|
12
|
-
weekDays: Date[];
|
|
13
|
-
selectedDate?: Date;
|
|
14
|
-
rangeStart?: Date;
|
|
15
|
-
rangeEnd?: Date;
|
|
16
|
-
getIsHoliday?: (date: Date) => boolean;
|
|
17
|
-
getHasTask?: (date: Date) => boolean;
|
|
18
|
-
getIsDisabled?: (date: Date) => boolean;
|
|
19
|
-
getIsCurrentMonth: (date: Date) => boolean;
|
|
20
|
-
getIsWeekend?: (date: Date) => boolean;
|
|
21
|
-
hasTasks?: (date: Date) => boolean;
|
|
22
|
-
onDateClick?: (e: React.MouseEvent<HTMLButtonElement>, date: Date) => void;
|
|
23
|
-
onDateDoubleClick?: (date: Date) => void;
|
|
24
|
-
onMouseEnter?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
25
|
-
onMouseLeave?: () => void;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export const Week = ({
|
|
29
|
-
weekDays,
|
|
30
|
-
selectedDate,
|
|
31
|
-
getIsHoliday,
|
|
32
|
-
getIsDisabled,
|
|
33
|
-
getIsCurrentMonth,
|
|
34
|
-
rangeStart,
|
|
35
|
-
rangeEnd,
|
|
36
|
-
hasTasks,
|
|
37
|
-
onDateClick,
|
|
38
|
-
onDateDoubleClick,
|
|
39
|
-
onMouseEnter,
|
|
40
|
-
onMouseLeave,
|
|
41
|
-
}: WeekProps) => {
|
|
42
|
-
return (
|
|
43
|
-
<div className={styles.week}>
|
|
44
|
-
{weekDays.map((date) => {
|
|
45
|
-
return (
|
|
46
|
-
<Day
|
|
47
|
-
key={date.toISOString()}
|
|
48
|
-
date={date}
|
|
49
|
-
isSelected={isSelected(date, selectedDate)}
|
|
50
|
-
isDisabled={getIsDisabled?.(date) || false}
|
|
51
|
-
isCurrentMonth={getIsCurrentMonth(date)}
|
|
52
|
-
isHoliday={getIsHoliday?.(date) || false}
|
|
53
|
-
hasTasks={hasTasks?.(date) || false}
|
|
54
|
-
isRangeStart={isRangeStart(date, rangeStart)}
|
|
55
|
-
isRangeEnd={isRangeEnd(date, rangeEnd)}
|
|
56
|
-
isRangeMiddle={isInRange(date, rangeStart, rangeEnd)}
|
|
57
|
-
onClick={getIsDisabled?.(date) ? undefined : onDateClick}
|
|
58
|
-
onDoubleClick={
|
|
59
|
-
getIsDisabled?.(date) ? undefined : onDateDoubleClick
|
|
60
|
-
}
|
|
61
|
-
onMouseEnter={getIsDisabled?.(date) ? undefined : onMouseEnter}
|
|
62
|
-
onMouseLeave={getIsDisabled?.(date) ? undefined : onMouseLeave}
|
|
63
|
-
/>
|
|
64
|
-
);
|
|
65
|
-
})}
|
|
66
|
-
</div>
|
|
67
|
-
);
|
|
68
|
-
};
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import { WeekDay } from '.';
|
|
3
|
-
|
|
4
|
-
const meta: Meta<typeof WeekDay> = {
|
|
5
|
-
component: WeekDay,
|
|
6
|
-
parameters: {
|
|
7
|
-
layout: 'centered',
|
|
8
|
-
},
|
|
9
|
-
argTypes: {
|
|
10
|
-
firstDayOfWeek: {
|
|
11
|
-
control: 'select',
|
|
12
|
-
options: [0, 1],
|
|
13
|
-
},
|
|
14
|
-
},
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export default meta;
|
|
18
|
-
|
|
19
|
-
type Story = StoryObj<typeof WeekDay>;
|
|
20
|
-
|
|
21
|
-
export const MondayFirst: Story = {
|
|
22
|
-
args: {
|
|
23
|
-
firstDayOfWeek: 1,
|
|
24
|
-
},
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export const SundayFirst: Story = {
|
|
28
|
-
args: {
|
|
29
|
-
firstDayOfWeek: 0,
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
export const HideWeekends: Story = {
|
|
34
|
-
args: {
|
|
35
|
-
firstDayOfWeek: 0,
|
|
36
|
-
hideWeekends: true,
|
|
37
|
-
},
|
|
38
|
-
};
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import classNames from 'classnames';
|
|
2
|
-
|
|
3
|
-
import { WEEKDAYS_NAMES } from '@/constants/weekdaysNames';
|
|
4
|
-
import { getOrderedDays } from '@/utils/weekdayOrder';
|
|
5
|
-
|
|
6
|
-
import styles from './styles.module.scss';
|
|
7
|
-
|
|
8
|
-
interface WeekDayProps {
|
|
9
|
-
firstDayOfWeek?: 0 | 1;
|
|
10
|
-
className?: string;
|
|
11
|
-
hideWeekends?: boolean;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const WeekDay = ({
|
|
15
|
-
firstDayOfWeek = 1,
|
|
16
|
-
className = '',
|
|
17
|
-
hideWeekends = false,
|
|
18
|
-
}: WeekDayProps) => {
|
|
19
|
-
let days = getOrderedDays(firstDayOfWeek);
|
|
20
|
-
|
|
21
|
-
if (hideWeekends) {
|
|
22
|
-
days = days.filter((dayIndex) => dayIndex !== 0 && dayIndex !== 6);
|
|
23
|
-
}
|
|
24
|
-
return (
|
|
25
|
-
<div className={classNames(styles.weekDay, className)}>
|
|
26
|
-
{days.map((index) => {
|
|
27
|
-
return (
|
|
28
|
-
<span key={WEEKDAYS_NAMES[index]} className={styles.dayName}>
|
|
29
|
-
{WEEKDAYS_NAMES[index]}
|
|
30
|
-
</span>
|
|
31
|
-
);
|
|
32
|
-
})}
|
|
33
|
-
</div>
|
|
34
|
-
);
|
|
35
|
-
};
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
.weekDay {
|
|
2
|
-
display: flex;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
.dayName {
|
|
6
|
-
@include square(32px);
|
|
7
|
-
|
|
8
|
-
@include themify-modules($themes) {
|
|
9
|
-
background-color: themed('background');
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
font-size: $font-size-13;
|
|
13
|
-
padding: $gap-10;
|
|
14
|
-
border-radius: $radius-8;
|
|
15
|
-
display: flex;
|
|
16
|
-
align-items: center;
|
|
17
|
-
justify-content: center;
|
|
18
|
-
font-weight: $font-weight-semibold;
|
|
19
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { IMask } from 'react-imask';
|
|
2
|
-
|
|
3
|
-
export const DATE_MASK = {
|
|
4
|
-
mask: 'dd/mm/yyyy',
|
|
5
|
-
blocks: {
|
|
6
|
-
dd: {
|
|
7
|
-
mask: IMask.MaskedRange,
|
|
8
|
-
from: 1,
|
|
9
|
-
to: 31,
|
|
10
|
-
},
|
|
11
|
-
mm: {
|
|
12
|
-
mask: IMask.MaskedRange,
|
|
13
|
-
from: 1,
|
|
14
|
-
to: 12,
|
|
15
|
-
},
|
|
16
|
-
yyyy: {
|
|
17
|
-
mask: IMask.MaskedRange,
|
|
18
|
-
from: 1900,
|
|
19
|
-
to: 2100,
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
autofix: true,
|
|
23
|
-
} as const;
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
const HOLIDAYS_RULES = [
|
|
2
|
-
{ name: 'New Year', getDate: (year: number) => new Date(year, 0, 1) },
|
|
3
|
-
{ name: 'Christmas', getDate: (year: number) => new Date(year, 11, 25) },
|
|
4
|
-
{
|
|
5
|
-
name: 'Chinese New Year',
|
|
6
|
-
getDate: (year: number) => new Date(year, 1, 17),
|
|
7
|
-
},
|
|
8
|
-
{
|
|
9
|
-
name: "International Women's Day",
|
|
10
|
-
getDate: (year: number) => new Date(year, 2, 8),
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
name: 'Defender of the Fatherland Day',
|
|
14
|
-
getDate: (year: number) => new Date(year, 1, 23),
|
|
15
|
-
},
|
|
16
|
-
{ name: "Children's Day", getDate: (year: number) => new Date(year, 5, 1) },
|
|
17
|
-
{ name: 'Labor Day', getDate: (year: number) => new Date(year, 4, 1) },
|
|
18
|
-
{
|
|
19
|
-
name: 'Thanksgiving Day',
|
|
20
|
-
getDate: (year: number) => new Date(year, 10, 26),
|
|
21
|
-
},
|
|
22
|
-
{ name: 'Easter', getDate: (year: number) => new Date(year, 3, 5) },
|
|
23
|
-
{ name: 'Boxing Day', getDate: (year: number) => new Date(year, 11, 26) },
|
|
24
|
-
{ name: 'Eid al-Fitr', getDate: (year: number) => new Date(year, 2, 20) },
|
|
25
|
-
{ name: 'Eid al-Adha', getDate: (year: number) => new Date(year, 4, 27) },
|
|
26
|
-
{ name: 'Nowruz', getDate: (year: number) => new Date(year, 2, 21) },
|
|
27
|
-
{ name: 'Bastille Day', getDate: (year: number) => new Date(year, 6, 14) },
|
|
28
|
-
];
|
|
29
|
-
|
|
30
|
-
export const getDefaultHolidays = (year: number): Date[] => {
|
|
31
|
-
return HOLIDAYS_RULES.map((rule) => rule.getDate(year));
|
|
32
|
-
};
|
package/src/constants/modes.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const WEEKDAYS_NAMES = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];
|
package/src/hooks/useCalendar.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react';
|
|
2
|
-
|
|
3
|
-
import { CalendarProps } from '@/components/Calendar/types';
|
|
4
|
-
import { getDefaultHolidays } from '@/constants/holidays';
|
|
5
|
-
import { CalendarService } from '@/services/calendarService';
|
|
6
|
-
import { withHolidays } from '@/services/decorators/withHolidays';
|
|
7
|
-
import { withMinMax } from '@/services/decorators/withMinMax';
|
|
8
|
-
import { getHolidays } from '@/services/holidayService';
|
|
9
|
-
|
|
10
|
-
export function useCalendar(props: CalendarProps) {
|
|
11
|
-
const year = props.monthDate.getFullYear();
|
|
12
|
-
const [holidays, setHolidays] = useState<Date[]>([]);
|
|
13
|
-
const [loading, setLoading] = useState(false);
|
|
14
|
-
const [error, setError] = useState('');
|
|
15
|
-
|
|
16
|
-
useEffect(() => {
|
|
17
|
-
const abortController = new AbortController();
|
|
18
|
-
|
|
19
|
-
if (props.showHolidays) {
|
|
20
|
-
setLoading(true);
|
|
21
|
-
setError('');
|
|
22
|
-
getHolidays(year, abortController.signal)
|
|
23
|
-
.then((result) => {
|
|
24
|
-
setHolidays(result);
|
|
25
|
-
})
|
|
26
|
-
.catch((err) => {
|
|
27
|
-
if (err.name === 'AbortError') {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
setHolidays(getDefaultHolidays(year));
|
|
31
|
-
setError(err.message);
|
|
32
|
-
})
|
|
33
|
-
.finally(() => setLoading(false));
|
|
34
|
-
}
|
|
35
|
-
return () => {
|
|
36
|
-
abortController.abort();
|
|
37
|
-
};
|
|
38
|
-
}, [props.showHolidays, year]);
|
|
39
|
-
|
|
40
|
-
const calendar: CalendarService = new CalendarService(
|
|
41
|
-
props.monthDate,
|
|
42
|
-
props.firstDayOfWeek,
|
|
43
|
-
props.selectedDate,
|
|
44
|
-
props.mode,
|
|
45
|
-
props.rangeStart,
|
|
46
|
-
props.rangeEnd
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
if (props.hideWeekends) {
|
|
50
|
-
calendar.setHideWeekends(true);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (props.showHolidays && holidays.length > 0) {
|
|
54
|
-
withHolidays(calendar, holidays);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (props.minDate || props.maxDate) {
|
|
58
|
-
withMinMax(calendar, props.minDate, props.maxDate);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return { calendar, loading, error };
|
|
62
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
2
|
-
|
|
3
|
-
export const useLockBodyScroll = (isLocked: boolean) => {
|
|
4
|
-
useEffect(() => {
|
|
5
|
-
const originalOverflow = document.body.style.overflow;
|
|
6
|
-
|
|
7
|
-
if (isLocked) {
|
|
8
|
-
document.body.style.overflow = 'hidden';
|
|
9
|
-
} else {
|
|
10
|
-
document.body.style.overflow = 'unset';
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
return () => {
|
|
14
|
-
document.body.style.overflow = originalOverflow;
|
|
15
|
-
};
|
|
16
|
-
}, [isLocked]);
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export default useLockBodyScroll;
|
package/src/hooks/useModal.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
2
|
-
|
|
3
|
-
interface UseModalOptions {
|
|
4
|
-
initial?: boolean;
|
|
5
|
-
onOpen?: () => void;
|
|
6
|
-
onClose?: () => void;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export const useModal = (options: UseModalOptions = {}) => {
|
|
10
|
-
const { initial = false, onOpen, onClose } = options;
|
|
11
|
-
const [isOpen, setIsOpen] = useState(initial);
|
|
12
|
-
|
|
13
|
-
const open = () => {
|
|
14
|
-
onOpen?.();
|
|
15
|
-
setIsOpen(true);
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const close = () => {
|
|
19
|
-
onClose?.();
|
|
20
|
-
setIsOpen(false);
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const toggle = () => {
|
|
24
|
-
setIsOpen((prev) => {
|
|
25
|
-
const newState = !prev;
|
|
26
|
-
if (newState) {
|
|
27
|
-
onOpen?.();
|
|
28
|
-
} else {
|
|
29
|
-
onClose?.();
|
|
30
|
-
}
|
|
31
|
-
return newState;
|
|
32
|
-
});
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const setOpen = (value: boolean) => {
|
|
36
|
-
if (value) {
|
|
37
|
-
onOpen?.();
|
|
38
|
-
} else {
|
|
39
|
-
onClose?.();
|
|
40
|
-
}
|
|
41
|
-
setIsOpen(value);
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
return { isOpen, open, close, toggle, setOpen };
|
|
45
|
-
};
|
package/src/hooks/useTooltip.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { useRef, useState } from 'react';
|
|
2
|
-
|
|
3
|
-
export const useTooltip = () => {
|
|
4
|
-
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
5
|
-
|
|
6
|
-
const [tooltip, setTooltip] = useState({
|
|
7
|
-
isVisible: false,
|
|
8
|
-
x: 0,
|
|
9
|
-
y: 0,
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
const handleDayMouseEnter = (e: React.MouseEvent<HTMLButtonElement>) => {
|
|
13
|
-
const rect = e.currentTarget.getBoundingClientRect();
|
|
14
|
-
const coords = {
|
|
15
|
-
x: rect.right - 5,
|
|
16
|
-
y: rect.top - 10,
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
if (timeoutRef.current) {
|
|
20
|
-
clearTimeout(timeoutRef.current);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
timeoutRef.current = setTimeout(() => {
|
|
24
|
-
setTooltip({
|
|
25
|
-
isVisible: true,
|
|
26
|
-
x: coords.x,
|
|
27
|
-
y: coords.y,
|
|
28
|
-
});
|
|
29
|
-
}, 500);
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const handleDayMouseLeave = () => {
|
|
33
|
-
if (timeoutRef.current) {
|
|
34
|
-
clearTimeout(timeoutRef.current);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
setTooltip((prev) => ({ ...prev, isVisible: false }));
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
return { tooltip, handleDayMouseEnter, handleDayMouseLeave };
|
|
41
|
-
};
|
package/src/hooks/useValidate.ts
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react';
|
|
2
|
-
import { useIMask } from 'react-imask';
|
|
3
|
-
|
|
4
|
-
import { DATE_MASK } from '@/constants/dateMask';
|
|
5
|
-
import { getRangeError } from '@/utils/dateChecks';
|
|
6
|
-
import { formatDateForInput, parseDate } from '@/utils/formatDate';
|
|
7
|
-
|
|
8
|
-
export function useValidate(selectedDate: Date | undefined) {
|
|
9
|
-
const [currentDate, setCurrentDate] = useState(selectedDate);
|
|
10
|
-
const [error, setError] = useState('');
|
|
11
|
-
const { ref, value, setValue } = useIMask(DATE_MASK);
|
|
12
|
-
|
|
13
|
-
useEffect(() => {
|
|
14
|
-
setCurrentDate(selectedDate);
|
|
15
|
-
if (selectedDate) {
|
|
16
|
-
setValue(formatDateForInput(selectedDate));
|
|
17
|
-
} else {
|
|
18
|
-
setValue('');
|
|
19
|
-
}
|
|
20
|
-
}, [selectedDate, setValue]);
|
|
21
|
-
|
|
22
|
-
const handleDateValidation = (
|
|
23
|
-
value: string,
|
|
24
|
-
startDate?: Date
|
|
25
|
-
): Date | undefined => {
|
|
26
|
-
if (!value) {
|
|
27
|
-
setError('');
|
|
28
|
-
setCurrentDate(undefined);
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
const parsed = parseDate(value);
|
|
32
|
-
|
|
33
|
-
if (!parsed) {
|
|
34
|
-
setError('Invalid date');
|
|
35
|
-
setCurrentDate(undefined);
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (startDate) {
|
|
40
|
-
const rangeError = getRangeError(parsed, startDate);
|
|
41
|
-
if (rangeError) {
|
|
42
|
-
setError(rangeError);
|
|
43
|
-
setCurrentDate(undefined);
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
setError('');
|
|
49
|
-
setCurrentDate(parsed);
|
|
50
|
-
return parsed;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const handleClearInput = () => {
|
|
54
|
-
setCurrentDate(undefined);
|
|
55
|
-
setValue('');
|
|
56
|
-
setError('');
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const handleDateSelect = (date?: Date) => {
|
|
60
|
-
setCurrentDate(date);
|
|
61
|
-
if (!date) {
|
|
62
|
-
setValue('');
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
setValue(formatDateForInput(date));
|
|
66
|
-
setError('');
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
return {
|
|
70
|
-
currentDate,
|
|
71
|
-
setCurrentDate,
|
|
72
|
-
handleDateValidation,
|
|
73
|
-
handleClearInput,
|
|
74
|
-
handleDateSelect,
|
|
75
|
-
ref,
|
|
76
|
-
value,
|
|
77
|
-
setValue,
|
|
78
|
-
error,
|
|
79
|
-
};
|
|
80
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { FIRST_DAY_OF_WEEK } from './constants/firstDayOfWeek';
|
|
2
|
-
import { MODES } from './constants/modes';
|
|
3
|
-
|
|
4
|
-
export { BaseCalendar } from './components/BaseCalendar';
|
|
5
|
-
export type {
|
|
6
|
-
BaseCalendarProps,
|
|
7
|
-
CalendarProps,
|
|
8
|
-
} from './components/Calendar/types';
|
|
9
|
-
export type { DatePickerProps } from './components/DatePicker';
|
|
10
|
-
export { DatePicker } from './components/DatePicker';
|
|
11
|
-
export type { RangePickerProps } from './components/RangePicker';
|
|
12
|
-
export { RangePicker } from './components/RangePicker';
|
|
13
|
-
export type { FIRST_DAY_OF_WEEK_TYPES } from './constants/firstDayOfWeek';
|
|
14
|
-
export type { MODES_TYPES } from './constants/modes';
|
|
15
|
-
export { FIRST_DAY_OF_WEEK, MODES };
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { FIRST_DAY_OF_WEEK_TYPES } from '@/constants/firstDayOfWeek';
|
|
2
|
-
import { MODES, MODES_TYPES } from '@/constants/modes';
|
|
3
|
-
import { getMonthDays, getWeekDays, getWeeksFromDays } from '@/utils/calendar';
|
|
4
|
-
import { isCurrentMonth, isWeekend } from '@/utils/dateChecks';
|
|
5
|
-
|
|
6
|
-
export class CalendarService {
|
|
7
|
-
private hideWeekends: boolean = false;
|
|
8
|
-
|
|
9
|
-
constructor(
|
|
10
|
-
public monthDate: Date = new Date(),
|
|
11
|
-
public firstDayOfWeek?: FIRST_DAY_OF_WEEK_TYPES,
|
|
12
|
-
public selectedDate?: Date,
|
|
13
|
-
public mode: MODES_TYPES = MODES.MONTH,
|
|
14
|
-
public rangeStart?: Date,
|
|
15
|
-
public rangeEnd?: Date
|
|
16
|
-
) {}
|
|
17
|
-
|
|
18
|
-
setHideWeekends(value: boolean) {
|
|
19
|
-
this.hideWeekends = value;
|
|
20
|
-
return this;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
getDays(): Date[] {
|
|
24
|
-
let days: Date[];
|
|
25
|
-
|
|
26
|
-
if (this.mode === MODES.MONTH) {
|
|
27
|
-
days = getMonthDays(this.monthDate, this.firstDayOfWeek);
|
|
28
|
-
} else {
|
|
29
|
-
days = getWeekDays(this.monthDate, this.firstDayOfWeek);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return this.applyFilters(days);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
private applyFilters(days: Date[]): Date[] {
|
|
36
|
-
let filteredDays = days;
|
|
37
|
-
|
|
38
|
-
if (this.hideWeekends) {
|
|
39
|
-
filteredDays = filteredDays.filter((day) => !isWeekend(day));
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return filteredDays;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
getWeeks(): Date[][] {
|
|
46
|
-
const days = this.getDays();
|
|
47
|
-
const weekLength = this.hideWeekends ? 5 : 7;
|
|
48
|
-
return getWeeksFromDays(days, weekLength);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
getIsCurrentMonth = (date: Date) => {
|
|
52
|
-
return isCurrentMonth(date, this.monthDate);
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
getIsDisabled = (_date: Date) => {
|
|
56
|
-
return false;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
getIsHoliday = (_date: Date) => {
|
|
60
|
-
return false;
|
|
61
|
-
};
|
|
62
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { isSameDay } from '@/utils/dateChecks';
|
|
2
|
-
|
|
3
|
-
import { CalendarService } from '../calendarService';
|
|
4
|
-
import { withHolidays } from './withHolidays';
|
|
5
|
-
|
|
6
|
-
jest.mock('@/utils/dateChecks', () => ({
|
|
7
|
-
isSameDay: jest.fn(),
|
|
8
|
-
}));
|
|
9
|
-
|
|
10
|
-
describe('withHolidays:', () => {
|
|
11
|
-
let calendar: CalendarService = new CalendarService();
|
|
12
|
-
|
|
13
|
-
beforeEach(() => {
|
|
14
|
-
calendar = new CalendarService();
|
|
15
|
-
jest.clearAllMocks();
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('returns the same calendar instance unchanged when the holidays array is empty', () => {
|
|
19
|
-
const originalGetIsHoliday = calendar.getIsHoliday;
|
|
20
|
-
|
|
21
|
-
const result = withHolidays(calendar, []);
|
|
22
|
-
|
|
23
|
-
expect(result).toBe(calendar);
|
|
24
|
-
expect(result.getIsHoliday).toBe(originalGetIsHoliday);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it('returns the same calendar instance (mutates rather than clones)', () => {
|
|
28
|
-
const holidays = [new Date(2026, 0, 1)];
|
|
29
|
-
const result = withHolidays(calendar, holidays);
|
|
30
|
-
|
|
31
|
-
expect(result).toBe(calendar);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('overrides getIsHoliday with a new function when holidays is not empty', () => {
|
|
35
|
-
const holidays = [new Date(2026, 0, 1)];
|
|
36
|
-
const originalGetIsHoliday = calendar.getIsHoliday;
|
|
37
|
-
|
|
38
|
-
withHolidays(calendar, holidays);
|
|
39
|
-
|
|
40
|
-
expect(calendar.getIsHoliday).not.toBe(originalGetIsHoliday);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('returns true when the date matches a holiday', () => {
|
|
44
|
-
(isSameDay as jest.Mock).mockReturnValue(true);
|
|
45
|
-
|
|
46
|
-
const holidays = [new Date(2026, 0, 1)];
|
|
47
|
-
const date = new Date(2026, 0, 1);
|
|
48
|
-
|
|
49
|
-
withHolidays(calendar, holidays);
|
|
50
|
-
|
|
51
|
-
expect(calendar.getIsHoliday(date)).toBe(true);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('returns false when the date does not match a holiday', () => {
|
|
55
|
-
(isSameDay as jest.Mock).mockReturnValue(false);
|
|
56
|
-
|
|
57
|
-
const holidays = [new Date(2026, 0, 1)];
|
|
58
|
-
const date = new Date(2026, 0, 2);
|
|
59
|
-
|
|
60
|
-
withHolidays(calendar, holidays);
|
|
61
|
-
|
|
62
|
-
expect(calendar.getIsHoliday(date)).toBe(false);
|
|
63
|
-
});
|
|
64
|
-
});
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { isSameDay } from '@/utils/dateChecks';
|
|
2
|
-
|
|
3
|
-
import { CalendarService } from '../calendarService';
|
|
4
|
-
|
|
5
|
-
export const withHolidays = (calendar: CalendarService, holidays: Date[]) => {
|
|
6
|
-
if (!holidays.length) return calendar;
|
|
7
|
-
|
|
8
|
-
calendar.getIsHoliday = (date: Date) => {
|
|
9
|
-
return holidays.some((holiday) => isSameDay(holiday, date));
|
|
10
|
-
};
|
|
11
|
-
return calendar;
|
|
12
|
-
};
|