@daryasidorovich/modsen-datepicker 1.0.0 → 1.0.1

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 (128) hide show
  1. package/.prettierrc +6 -6
  2. package/.storybook/main.js +93 -93
  3. package/.storybook/main.ts +16 -0
  4. package/.storybook/preview.js +26 -26
  5. package/.storybook/preview.tsx +18 -18
  6. package/README.md +5 -5
  7. package/commitlint.config.js +23 -23
  8. package/package.json +1 -1
  9. package/rollup.config.js +65 -65
  10. package/src/components/BaseCalendar/BaseCalendar.stories.tsx +77 -77
  11. package/src/components/BaseCalendar/index.tsx +63 -63
  12. package/src/components/BaseCalendar/styles.module.scss +15 -15
  13. package/src/components/Button/Button.stories.tsx +16 -0
  14. package/src/components/Button/Button.tsx +14 -0
  15. package/src/components/Button/index.ts +1 -0
  16. package/src/components/Button/styles.module.scss +3 -0
  17. package/src/components/CalendarGrid/CalendarGrid.stories.tsx +136 -136
  18. package/src/components/CalendarGrid/CalendarGridWithTasks/Tooltip/index.tsx +27 -27
  19. package/src/components/CalendarGrid/CalendarGridWithTasks/Tooltip/styles.module.scss +9 -9
  20. package/src/components/CalendarGrid/CalendarGridWithTasks/index.tsx +51 -51
  21. package/src/components/CalendarGrid/CalendarGridWithoutTasks/index.tsx +36 -36
  22. package/src/components/CalendarGrid/CalendarGridWithoutTasks/styles.module.scss +11 -11
  23. package/src/components/CalendarGrid/index.tsx +19 -19
  24. package/src/components/CalendarGrid/types.ts +26 -26
  25. package/src/components/Clear/Clear.stories.tsx +16 -16
  26. package/src/components/Clear/index.tsx +12 -12
  27. package/src/components/Clear/styles.module.scss +34 -34
  28. package/src/components/DatePicker/DatePicker.stories.tsx +127 -127
  29. package/src/components/DatePicker/index.tsx +72 -72
  30. package/src/components/DatePicker/styles.module.scss +10 -10
  31. package/src/components/Day/Day.stories.tsx +75 -75
  32. package/src/components/Day/index.tsx +95 -95
  33. package/src/components/Day/styles.module.scss +97 -97
  34. package/src/components/Input/Input.stories.tsx +37 -37
  35. package/src/components/Input/index.tsx +64 -64
  36. package/src/components/Input/styles.module.scss +79 -79
  37. package/src/components/Modal/CrudModal/index.tsx +43 -43
  38. package/src/components/Modal/CrudModal/styles.module.scss +44 -44
  39. package/src/components/Modal/index.tsx +66 -66
  40. package/src/components/Modal/styles.module.scss +40 -40
  41. package/src/components/Modal/types.ts +13 -13
  42. package/src/components/Month/Month.stories.tsx +19 -19
  43. package/src/components/Month/index.tsx +31 -31
  44. package/src/components/Month/styles.module.scss +30 -30
  45. package/src/components/RangePicker/RangePicker.stories.tsx +134 -134
  46. package/src/components/RangePicker/index.tsx +144 -144
  47. package/src/components/RangePicker/styles.module.scss +19 -19
  48. package/src/components/TasksManager/AddModal/index.tsx +62 -62
  49. package/src/components/TasksManager/DeleteModal/index.tsx +22 -22
  50. package/src/components/TasksManager/EditModal/index.tsx +96 -96
  51. package/src/components/TasksManager/index.tsx +112 -112
  52. package/src/components/TasksManager/styles.module.scss +62 -62
  53. package/src/components/Week/Week.stories.tsx +49 -49
  54. package/src/components/Week/index.tsx +68 -68
  55. package/src/components/Week/styles.module.scss +7 -7
  56. package/src/components/WeekDay/WeekDay.stories.tsx +38 -38
  57. package/src/components/WeekDay/index.tsx +35 -35
  58. package/src/components/WeekDay/styles.module.scss +19 -19
  59. package/src/constants/dateMask.ts +23 -23
  60. package/src/constants/firstDayOfWeek.ts +7 -7
  61. package/src/constants/holidays.ts +32 -32
  62. package/src/constants/modes.ts +6 -6
  63. package/src/constants/monthsNames.ts +14 -14
  64. package/src/constants/weekdaysNames.ts +1 -1
  65. package/src/hooks/useCalendar.ts +62 -62
  66. package/src/hooks/useLockBodyScroll.ts +19 -19
  67. package/src/hooks/useModal.ts +45 -45
  68. package/src/hooks/useTooltip.ts +41 -41
  69. package/src/hooks/useValidate.ts +80 -80
  70. package/src/index.ts +15 -15
  71. package/src/services/calendarService.ts +62 -62
  72. package/src/services/decorators/withHolidays.ts +12 -12
  73. package/src/services/decorators/withMinMax.test.ts +77 -77
  74. package/src/services/decorators/withMinMax.ts +19 -19
  75. package/src/services/holidayService.ts +56 -56
  76. package/src/store/localStorage.ts +33 -33
  77. package/src/store/tasksStore.tsx +146 -146
  78. package/src/store/types.ts +22 -22
  79. package/src/stories/Button.stories.ts +54 -0
  80. package/src/stories/Button.tsx +37 -0
  81. package/src/stories/Configure.mdx +388 -0
  82. package/src/stories/Header.stories.ts +34 -0
  83. package/src/stories/Header.tsx +56 -0
  84. package/src/stories/Page.stories.ts +33 -0
  85. package/src/stories/Page.tsx +73 -0
  86. package/src/stories/assets/accessibility.png +0 -0
  87. package/src/stories/assets/accessibility.svg +1 -0
  88. package/src/stories/assets/addon-library.png +0 -0
  89. package/src/stories/assets/assets.png +0 -0
  90. package/src/stories/assets/avif-test-image.avif +0 -0
  91. package/src/stories/assets/context.png +0 -0
  92. package/src/stories/assets/discord.svg +1 -0
  93. package/src/stories/assets/docs.png +0 -0
  94. package/src/stories/assets/figma-plugin.png +0 -0
  95. package/src/stories/assets/github.svg +1 -0
  96. package/src/stories/assets/share.png +0 -0
  97. package/src/stories/assets/styling.png +0 -0
  98. package/src/stories/assets/testing.png +0 -0
  99. package/src/stories/assets/theming.png +0 -0
  100. package/src/stories/assets/tutorials.svg +1 -0
  101. package/src/stories/assets/youtube.svg +1 -0
  102. package/src/stories/button.css +30 -0
  103. package/src/stories/header.css +32 -0
  104. package/src/stories/page.css +68 -0
  105. package/src/styles/_border.scss +9 -9
  106. package/src/styles/_colors.scss +53 -53
  107. package/src/styles/_gap.scss +4 -4
  108. package/src/styles/_globals.scss +61 -61
  109. package/src/styles/_grid.scss +9 -9
  110. package/src/styles/_mixins.scss +6 -6
  111. package/src/styles/_reset.scss +98 -98
  112. package/src/styles/_theme-mixins.scss +51 -51
  113. package/src/styles/_typography.scss +10 -10
  114. package/src/styles/_variables.scss +8 -8
  115. package/src/styles/main.scss +3 -3
  116. package/src/types/types.d.ts +15 -15
  117. package/src/utils/calendar.test.ts +154 -154
  118. package/src/utils/calendar.ts +82 -82
  119. package/src/utils/controlDate.ts +3 -3
  120. package/src/utils/dateChecks.test.ts +216 -216
  121. package/src/utils/dateChecks.ts +75 -75
  122. package/src/utils/formatDate.ts +27 -27
  123. package/src/utils/schema.test.ts +40 -40
  124. package/src/utils/schema.ts +8 -8
  125. package/src/utils/weekdayOrder.test.ts +11 -11
  126. package/src/utils/weekdayOrder.ts +7 -7
  127. package/vitest.config.ts +38 -38
  128. package/vitest.shims.d.ts +1 -1
@@ -1,30 +1,30 @@
1
- .month {
2
- @include themify-modules($themes) {
3
- color: themed('text');
4
- background-color: themed('background');
5
- }
6
-
7
- display: flex;
8
- justify-content: space-between;
9
- align-items: center;
10
- width: 100%;
11
- padding-block: 5px;
12
- gap: 2px;
13
- font-weight: $font-weight-bold;
14
- }
15
-
16
- .arrow {
17
- @include themify-modules($themes) {
18
- color: themed('text');
19
- }
20
-
21
- width: max-content;
22
- border: none;
23
- background-color: transparent;
24
-
25
- &:hover {
26
- @include themify-modules($themes) {
27
- color: themed('middle-blue');
28
- }
29
- }
30
- }
1
+ .month {
2
+ @include themify-modules($themes) {
3
+ color: themed('text');
4
+ background-color: themed('background');
5
+ }
6
+
7
+ display: flex;
8
+ justify-content: space-between;
9
+ align-items: center;
10
+ width: 100%;
11
+ padding-block: 5px;
12
+ gap: 2px;
13
+ font-weight: $font-weight-bold;
14
+ }
15
+
16
+ .arrow {
17
+ @include themify-modules($themes) {
18
+ color: themed('text');
19
+ }
20
+
21
+ width: max-content;
22
+ border: none;
23
+ background-color: transparent;
24
+
25
+ &:hover {
26
+ @include themify-modules($themes) {
27
+ color: themed('middle-blue');
28
+ }
29
+ }
30
+ }
@@ -1,134 +1,134 @@
1
- import type { Meta, StoryObj } from '@storybook/react';
2
- import { RangePicker } from './index';
3
- import { setControlDate } from '../../utils/controlDate';
4
-
5
- const meta: Meta<typeof RangePicker> = {
6
- component: RangePicker,
7
- parameters: {
8
- layout: 'centered',
9
- },
10
- argTypes: {
11
- monthDate: { control: 'date' },
12
- minDate: { control: 'date' },
13
- maxDate: { control: 'date' },
14
- rangeStart: { control: 'date' },
15
- rangeEnd: { control: 'date' },
16
- firstDayOfWeek: {
17
- control: 'select',
18
- options: [0, 1],
19
- },
20
- },
21
- };
22
-
23
- export default meta;
24
- type Story = StoryObj<typeof RangePicker>;
25
-
26
- export const Default: Story = {
27
- args: {
28
- monthDate: new Date(2026, 7, 1),
29
- firstDayOfWeek: 1,
30
- rangeStart: new Date(2026, 7, 10),
31
- rangeEnd: new Date(2026, 7, 15),
32
- },
33
- render: (args) => (
34
- <RangePicker
35
- {...args}
36
- monthDate={new Date(args.monthDate)}
37
- minDate={setControlDate(args.minDate)}
38
- maxDate={setControlDate(args.maxDate)}
39
- rangeStart={setControlDate(args.rangeStart)}
40
- rangeEnd={setControlDate(args.rangeEnd)}
41
- />
42
- ),
43
- };
44
-
45
- export const WithTasks: Story = {
46
- args: {
47
- monthDate: new Date(2026, 7, 25),
48
- firstDayOfWeek: 1,
49
- enableTasks: true,
50
- },
51
- render: (args) => (
52
- <RangePicker
53
- {...args}
54
- monthDate={new Date(args.monthDate)}
55
- minDate={setControlDate(args.minDate)}
56
- maxDate={setControlDate(args.maxDate)}
57
- rangeStart={setControlDate(args.rangeStart)}
58
- rangeEnd={setControlDate(args.rangeEnd)}
59
- />
60
- ),
61
- };
62
-
63
- export const HideWeekends: Story = {
64
- args: {
65
- monthDate: new Date(2026, 8, 7),
66
- firstDayOfWeek: 1,
67
- hideWeekends: true,
68
- },
69
- render: (args) => (
70
- <RangePicker
71
- {...args}
72
- monthDate={new Date(args.monthDate)}
73
- minDate={setControlDate(args.minDate)}
74
- maxDate={setControlDate(args.maxDate)}
75
- rangeStart={setControlDate(args.rangeStart)}
76
- rangeEnd={setControlDate(args.rangeEnd)}
77
- />
78
- ),
79
- };
80
-
81
- export const ShowHolidays: Story = {
82
- args: {
83
- monthDate: new Date(2025, 0, 3),
84
- firstDayOfWeek: 1,
85
- showHolidays: true,
86
- },
87
- render: (args) => (
88
- <RangePicker
89
- {...args}
90
- monthDate={new Date(args.monthDate)}
91
- minDate={setControlDate(args.minDate)}
92
- maxDate={setControlDate(args.maxDate)}
93
- rangeStart={setControlDate(args.rangeStart)}
94
- rangeEnd={setControlDate(args.rangeEnd)}
95
- />
96
- ),
97
- };
98
-
99
- export const WeekMode: Story = {
100
- args: {
101
- monthDate: new Date(2025, 0, 31),
102
- firstDayOfWeek: 1,
103
- showHolidays: true,
104
- mode: 'week',
105
- },
106
- render: (args) => (
107
- <RangePicker
108
- {...args}
109
- monthDate={new Date(args.monthDate)}
110
- minDate={setControlDate(args.minDate)}
111
- maxDate={setControlDate(args.maxDate)}
112
- rangeStart={setControlDate(args.rangeStart)}
113
- rangeEnd={setControlDate(args.rangeEnd)}
114
- />
115
- ),
116
- };
117
-
118
- export const WithMinMaxDates: Story = {
119
- args: {
120
- monthDate: new Date(2026, 7, 1),
121
- firstDayOfWeek: 1,
122
- minDate: new Date(2026, 7, 10),
123
- maxDate: new Date(2026, 7, 20),
124
- },
125
- render: (args) => (
126
- <RangePicker
127
- {...args}
128
- minDate={setControlDate(args.minDate)}
129
- maxDate={setControlDate(args.maxDate)}
130
- rangeStart={setControlDate(args.rangeStart)}
131
- rangeEnd={setControlDate(args.rangeEnd)}
132
- />
133
- ),
134
- };
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { RangePicker } from './index';
3
+ import { setControlDate } from '../../utils/controlDate';
4
+
5
+ const meta: Meta<typeof RangePicker> = {
6
+ component: RangePicker,
7
+ parameters: {
8
+ layout: 'centered',
9
+ },
10
+ argTypes: {
11
+ monthDate: { control: 'date' },
12
+ minDate: { control: 'date' },
13
+ maxDate: { control: 'date' },
14
+ rangeStart: { control: 'date' },
15
+ rangeEnd: { control: 'date' },
16
+ firstDayOfWeek: {
17
+ control: 'select',
18
+ options: [0, 1],
19
+ },
20
+ },
21
+ };
22
+
23
+ export default meta;
24
+ type Story = StoryObj<typeof RangePicker>;
25
+
26
+ export const Default: Story = {
27
+ args: {
28
+ monthDate: new Date(2026, 7, 1),
29
+ firstDayOfWeek: 1,
30
+ rangeStart: new Date(2026, 7, 10),
31
+ rangeEnd: new Date(2026, 7, 15),
32
+ },
33
+ render: (args) => (
34
+ <RangePicker
35
+ {...args}
36
+ monthDate={new Date(args.monthDate)}
37
+ minDate={setControlDate(args.minDate)}
38
+ maxDate={setControlDate(args.maxDate)}
39
+ rangeStart={setControlDate(args.rangeStart)}
40
+ rangeEnd={setControlDate(args.rangeEnd)}
41
+ />
42
+ ),
43
+ };
44
+
45
+ export const WithTasks: Story = {
46
+ args: {
47
+ monthDate: new Date(2026, 7, 25),
48
+ firstDayOfWeek: 1,
49
+ enableTasks: true,
50
+ },
51
+ render: (args) => (
52
+ <RangePicker
53
+ {...args}
54
+ monthDate={new Date(args.monthDate)}
55
+ minDate={setControlDate(args.minDate)}
56
+ maxDate={setControlDate(args.maxDate)}
57
+ rangeStart={setControlDate(args.rangeStart)}
58
+ rangeEnd={setControlDate(args.rangeEnd)}
59
+ />
60
+ ),
61
+ };
62
+
63
+ export const HideWeekends: Story = {
64
+ args: {
65
+ monthDate: new Date(2026, 8, 7),
66
+ firstDayOfWeek: 1,
67
+ hideWeekends: true,
68
+ },
69
+ render: (args) => (
70
+ <RangePicker
71
+ {...args}
72
+ monthDate={new Date(args.monthDate)}
73
+ minDate={setControlDate(args.minDate)}
74
+ maxDate={setControlDate(args.maxDate)}
75
+ rangeStart={setControlDate(args.rangeStart)}
76
+ rangeEnd={setControlDate(args.rangeEnd)}
77
+ />
78
+ ),
79
+ };
80
+
81
+ export const ShowHolidays: Story = {
82
+ args: {
83
+ monthDate: new Date(2025, 0, 3),
84
+ firstDayOfWeek: 1,
85
+ showHolidays: true,
86
+ },
87
+ render: (args) => (
88
+ <RangePicker
89
+ {...args}
90
+ monthDate={new Date(args.monthDate)}
91
+ minDate={setControlDate(args.minDate)}
92
+ maxDate={setControlDate(args.maxDate)}
93
+ rangeStart={setControlDate(args.rangeStart)}
94
+ rangeEnd={setControlDate(args.rangeEnd)}
95
+ />
96
+ ),
97
+ };
98
+
99
+ export const WeekMode: Story = {
100
+ args: {
101
+ monthDate: new Date(2025, 0, 31),
102
+ firstDayOfWeek: 1,
103
+ showHolidays: true,
104
+ mode: 'week',
105
+ },
106
+ render: (args) => (
107
+ <RangePicker
108
+ {...args}
109
+ monthDate={new Date(args.monthDate)}
110
+ minDate={setControlDate(args.minDate)}
111
+ maxDate={setControlDate(args.maxDate)}
112
+ rangeStart={setControlDate(args.rangeStart)}
113
+ rangeEnd={setControlDate(args.rangeEnd)}
114
+ />
115
+ ),
116
+ };
117
+
118
+ export const WithMinMaxDates: Story = {
119
+ args: {
120
+ monthDate: new Date(2026, 7, 1),
121
+ firstDayOfWeek: 1,
122
+ minDate: new Date(2026, 7, 10),
123
+ maxDate: new Date(2026, 7, 20),
124
+ },
125
+ render: (args) => (
126
+ <RangePicker
127
+ {...args}
128
+ minDate={setControlDate(args.minDate)}
129
+ maxDate={setControlDate(args.maxDate)}
130
+ rangeStart={setControlDate(args.rangeStart)}
131
+ rangeEnd={setControlDate(args.rangeEnd)}
132
+ />
133
+ ),
134
+ };
@@ -1,144 +1,144 @@
1
- import { ChangeEvent, KeyboardEvent, Ref } from 'react';
2
-
3
- import { useValidate } from '@/hooks/useValidate';
4
-
5
- import { BaseCalendar } from '../BaseCalendar';
6
- import { BaseCalendarProps, CalendarProps } from '../CalendarGrid/types';
7
- import { Clear } from '../Clear';
8
- import { Input } from '../Input';
9
- import styles from './styles.module.scss';
10
-
11
- export interface RangePickerProps
12
- extends BaseCalendarProps, Pick<CalendarProps, 'rangeStart' | 'rangeEnd'> {
13
- onChangeStart?: (date?: Date) => void;
14
- onChangeEnd?: (date?: Date) => void;
15
- }
16
-
17
- export const RangePicker = ({
18
- rangeStart,
19
- rangeEnd,
20
- monthDate = new Date(),
21
- onChangeStart,
22
- onChangeEnd,
23
- ...props
24
- }: RangePickerProps) => {
25
- const {
26
- currentDate: startDate,
27
- value: startValue,
28
- error: startError,
29
- ref: startRef,
30
- handleDateSelect: handleStartDateSelect,
31
- handleDateValidation: handleStartDateValidation,
32
- handleClearInput: handleStartClearInput,
33
- } = useValidate(rangeStart);
34
-
35
- const {
36
- currentDate: endDate,
37
- value: endValue,
38
- error: endError,
39
- ref: endRef,
40
- handleDateSelect: handleEndDateSelect,
41
- handleDateValidation: handleEndDateValidation,
42
- handleClearInput: handleEndClearInput,
43
- } = useValidate(rangeEnd);
44
-
45
- const handleDateSelectAndExternalUpdate = (
46
- e: React.MouseEvent<HTMLButtonElement>,
47
- date: Date
48
- ) => {
49
- if (!startDate) {
50
- handleStartDateSelect(date);
51
- onChangeStart?.(date);
52
- return;
53
- }
54
-
55
- if (!endDate || e.ctrlKey) {
56
- if (startDate && date < startDate) {
57
- handleStartDateSelect(date);
58
- handleEndDateSelect(startDate);
59
- onChangeStart?.(date);
60
- onChangeEnd?.(startDate);
61
- } else {
62
- handleEndDateSelect(date);
63
- onChangeEnd?.(date);
64
- }
65
- return;
66
- }
67
-
68
- handleStartDateSelect(date);
69
- handleEndDateSelect();
70
- onChangeStart?.(date);
71
- onChangeEnd?.();
72
- };
73
-
74
- const handleStartChange = (e: ChangeEvent<HTMLInputElement>) => {
75
- const parsed = handleStartDateValidation(e.target.value);
76
- if (!parsed) return;
77
- onChangeStart?.(parsed);
78
- if (endValue) handleEndDateValidation(endValue, parsed);
79
- };
80
-
81
- const handleStartKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
82
- if (e.key !== 'Enter') return;
83
- const parsed = handleStartDateValidation(e.currentTarget.value);
84
- if (!parsed) return;
85
- onChangeStart?.(parsed);
86
- if (endValue) handleEndDateValidation(endValue, parsed);
87
- };
88
-
89
- const handleEndChange = (e: ChangeEvent<HTMLInputElement>) => {
90
- const parsed = handleEndDateValidation(e.target.value, startDate);
91
- if (parsed) onChangeEnd?.(parsed);
92
- };
93
-
94
- const handleEndKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
95
- if (e.key !== 'Enter') return;
96
- const parsed = handleEndDateValidation(e.currentTarget.value, startDate);
97
- if (parsed) onChangeEnd?.(parsed);
98
- };
99
-
100
- const handleClearRange = () => {
101
- handleStartClearInput();
102
- handleEndClearInput();
103
- };
104
-
105
- return (
106
- <div className={styles.rangePicker}>
107
- <div className={styles.inputs}>
108
- <Input
109
- isDateInput
110
- label="From"
111
- value={startValue}
112
- ref={startRef as Ref<HTMLInputElement>}
113
- placeholder="dd/mm/yyyy"
114
- onBlur={handleStartChange}
115
- onReset={handleStartClearInput}
116
- onKeyDown={handleStartKeyDown}
117
- error={startError}
118
- />
119
- <Input
120
- isDateInput
121
- label="To"
122
- value={endValue}
123
- ref={endRef as Ref<HTMLInputElement>}
124
- placeholder="dd/mm/yyyy"
125
- onBlur={handleEndChange}
126
- onReset={handleEndClearInput}
127
- onKeyDown={handleEndKeyDown}
128
- error={endError}
129
- />
130
- </div>
131
-
132
- <div className={styles.calendar}>
133
- <BaseCalendar
134
- monthDate={monthDate}
135
- rangeStart={startDate}
136
- rangeEnd={endDate}
137
- onDateClick={handleDateSelectAndExternalUpdate}
138
- {...props}
139
- />
140
- <Clear onClick={handleClearRange} />
141
- </div>
142
- </div>
143
- );
144
- };
1
+ import { ChangeEvent, KeyboardEvent, Ref } from 'react';
2
+
3
+ import { useValidate } from '@/hooks/useValidate';
4
+
5
+ import { BaseCalendar } from '../BaseCalendar';
6
+ import { BaseCalendarProps, CalendarProps } from '../CalendarGrid/types';
7
+ import { Clear } from '../Clear';
8
+ import { Input } from '../Input';
9
+ import styles from './styles.module.scss';
10
+
11
+ export interface RangePickerProps
12
+ extends BaseCalendarProps, Pick<CalendarProps, 'rangeStart' | 'rangeEnd'> {
13
+ onChangeStart?: (date?: Date) => void;
14
+ onChangeEnd?: (date?: Date) => void;
15
+ }
16
+
17
+ export const RangePicker = ({
18
+ rangeStart,
19
+ rangeEnd,
20
+ monthDate = new Date(),
21
+ onChangeStart,
22
+ onChangeEnd,
23
+ ...props
24
+ }: RangePickerProps) => {
25
+ const {
26
+ currentDate: startDate,
27
+ value: startValue,
28
+ error: startError,
29
+ ref: startRef,
30
+ handleDateSelect: handleStartDateSelect,
31
+ handleDateValidation: handleStartDateValidation,
32
+ handleClearInput: handleStartClearInput,
33
+ } = useValidate(rangeStart);
34
+
35
+ const {
36
+ currentDate: endDate,
37
+ value: endValue,
38
+ error: endError,
39
+ ref: endRef,
40
+ handleDateSelect: handleEndDateSelect,
41
+ handleDateValidation: handleEndDateValidation,
42
+ handleClearInput: handleEndClearInput,
43
+ } = useValidate(rangeEnd);
44
+
45
+ const handleDateSelectAndExternalUpdate = (
46
+ e: React.MouseEvent<HTMLButtonElement>,
47
+ date: Date
48
+ ) => {
49
+ if (!startDate) {
50
+ handleStartDateSelect(date);
51
+ onChangeStart?.(date);
52
+ return;
53
+ }
54
+
55
+ if (!endDate || e.ctrlKey) {
56
+ if (startDate && date < startDate) {
57
+ handleStartDateSelect(date);
58
+ handleEndDateSelect(startDate);
59
+ onChangeStart?.(date);
60
+ onChangeEnd?.(startDate);
61
+ } else {
62
+ handleEndDateSelect(date);
63
+ onChangeEnd?.(date);
64
+ }
65
+ return;
66
+ }
67
+
68
+ handleStartDateSelect(date);
69
+ handleEndDateSelect();
70
+ onChangeStart?.(date);
71
+ onChangeEnd?.();
72
+ };
73
+
74
+ const handleStartChange = (e: ChangeEvent<HTMLInputElement>) => {
75
+ const parsed = handleStartDateValidation(e.target.value);
76
+ if (!parsed) return;
77
+ onChangeStart?.(parsed);
78
+ if (endValue) handleEndDateValidation(endValue, parsed);
79
+ };
80
+
81
+ const handleStartKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
82
+ if (e.key !== 'Enter') return;
83
+ const parsed = handleStartDateValidation(e.currentTarget.value);
84
+ if (!parsed) return;
85
+ onChangeStart?.(parsed);
86
+ if (endValue) handleEndDateValidation(endValue, parsed);
87
+ };
88
+
89
+ const handleEndChange = (e: ChangeEvent<HTMLInputElement>) => {
90
+ const parsed = handleEndDateValidation(e.target.value, startDate);
91
+ if (parsed) onChangeEnd?.(parsed);
92
+ };
93
+
94
+ const handleEndKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
95
+ if (e.key !== 'Enter') return;
96
+ const parsed = handleEndDateValidation(e.currentTarget.value, startDate);
97
+ if (parsed) onChangeEnd?.(parsed);
98
+ };
99
+
100
+ const handleClearRange = () => {
101
+ handleStartClearInput();
102
+ handleEndClearInput();
103
+ };
104
+
105
+ return (
106
+ <div className={styles.rangePicker}>
107
+ <div className={styles.inputs}>
108
+ <Input
109
+ isDateInput
110
+ label="From"
111
+ value={startValue}
112
+ ref={startRef as Ref<HTMLInputElement>}
113
+ placeholder="dd/mm/yyyy"
114
+ onBlur={handleStartChange}
115
+ onReset={handleStartClearInput}
116
+ onKeyDown={handleStartKeyDown}
117
+ error={startError}
118
+ />
119
+ <Input
120
+ isDateInput
121
+ label="To"
122
+ value={endValue}
123
+ ref={endRef as Ref<HTMLInputElement>}
124
+ placeholder="dd/mm/yyyy"
125
+ onBlur={handleEndChange}
126
+ onReset={handleEndClearInput}
127
+ onKeyDown={handleEndKeyDown}
128
+ error={endError}
129
+ />
130
+ </div>
131
+
132
+ <div className={styles.calendar}>
133
+ <BaseCalendar
134
+ monthDate={monthDate}
135
+ rangeStart={startDate}
136
+ rangeEnd={endDate}
137
+ onDateClick={handleDateSelectAndExternalUpdate}
138
+ {...props}
139
+ />
140
+ <Clear onClick={handleClearRange} />
141
+ </div>
142
+ </div>
143
+ );
144
+ };
@@ -1,19 +1,19 @@
1
- .rangePicker {
2
- display: flex;
3
- flex-direction: column;
4
- padding: $gap-8;
5
-
6
- @include themify-modules($themes) {
7
- background-color: themed('background');
8
- }
9
- }
10
-
11
- .calendar {
12
- margin-top: 15px;
13
- }
14
-
15
- .inputs {
16
- display: flex;
17
- flex-direction: column;
18
- gap: $gap-8;
19
- }
1
+ .rangePicker {
2
+ display: flex;
3
+ flex-direction: column;
4
+ padding: $gap-8;
5
+
6
+ @include themify-modules($themes) {
7
+ background-color: themed('background');
8
+ }
9
+ }
10
+
11
+ .calendar {
12
+ margin-top: 15px;
13
+ }
14
+
15
+ .inputs {
16
+ display: flex;
17
+ flex-direction: column;
18
+ gap: $gap-8;
19
+ }