@daryasidorovich/modsen-datepicker 1.0.1 → 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/main.ts +0 -16
- 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/Button/Button.stories.tsx +0 -16
- package/src/components/Button/Button.tsx +0 -14
- package/src/components/Button/index.ts +0 -1
- package/src/components/Button/styles.module.scss +0 -3
- 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/stories/Button.stories.ts +0 -54
- package/src/stories/Button.tsx +0 -37
- package/src/stories/Configure.mdx +0 -388
- package/src/stories/Header.stories.ts +0 -34
- package/src/stories/Header.tsx +0 -56
- package/src/stories/Page.stories.ts +0 -33
- package/src/stories/Page.tsx +0 -73
- package/src/stories/assets/accessibility.png +0 -0
- package/src/stories/assets/accessibility.svg +0 -1
- package/src/stories/assets/addon-library.png +0 -0
- package/src/stories/assets/assets.png +0 -0
- package/src/stories/assets/avif-test-image.avif +0 -0
- package/src/stories/assets/context.png +0 -0
- package/src/stories/assets/discord.svg +0 -1
- package/src/stories/assets/docs.png +0 -0
- package/src/stories/assets/figma-plugin.png +0 -0
- package/src/stories/assets/github.svg +0 -1
- package/src/stories/assets/share.png +0 -0
- package/src/stories/assets/styling.png +0 -0
- package/src/stories/assets/testing.png +0 -0
- package/src/stories/assets/theming.png +0 -0
- package/src/stories/assets/tutorials.svg +0 -1
- package/src/stories/assets/youtube.svg +0 -1
- package/src/stories/button.css +0 -30
- package/src/stories/header.css +0 -32
- package/src/stories/page.css +0 -68
- 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
|
-
};
|