@alfalab/core-components-calendar-range 7.1.5 → 7.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/Component-5684a67d.d.ts +18 -0
  2. package/Component-63dec22f.d.ts +24 -0
  3. package/Component-8c6198cc.d.ts +23 -0
  4. package/Component.desktop-2e2b2125.d.ts +6 -0
  5. package/Component.desktop-8c6198cc.d.ts +134 -0
  6. package/Component.js +4 -2
  7. package/Component.responsive-2e2b2125.d.ts +68 -0
  8. package/components/divider/Component.js +1 -1
  9. package/components/divider/index.css +8 -8
  10. package/cssm/Component-5684a67d.d.ts +18 -0
  11. package/cssm/Component-63dec22f.d.ts +24 -0
  12. package/cssm/Component-8c6198cc.d.ts +23 -0
  13. package/cssm/Component.desktop-2e2b2125.d.ts +6 -0
  14. package/cssm/Component.desktop-8c6198cc.d.ts +134 -0
  15. package/cssm/Component.js +3 -1
  16. package/cssm/Component.responsive-2e2b2125.d.ts +68 -0
  17. package/cssm/desktop-63dec22f.d.ts +2 -0
  18. package/cssm/index-9211a437.d.ts +2 -0
  19. package/cssm/index-ebda875c.d.ts +2 -0
  20. package/cssm/index-f034f741.d.ts +2 -0
  21. package/cssm/index.js +3 -1
  22. package/cssm/shared-848397c5.d.ts +35 -0
  23. package/cssm/shared-c111a9fd.d.ts +13 -0
  24. package/cssm/typings-5684a67d.d.ts +23 -0
  25. package/cssm/typings-9211a437.d.ts +95 -0
  26. package/cssm/useCalendar-71d94e2b.d.ts +97 -0
  27. package/cssm/utils-8c6198cc.d.ts +88 -0
  28. package/cssm/utils-e0a54580.d.ts +8 -0
  29. package/cssm/views/popover.js +9 -8
  30. package/cssm/views/static.js +18 -17
  31. package/desktop-63dec22f.d.ts +2 -0
  32. package/esm/Component-5684a67d.d.ts +18 -0
  33. package/esm/Component-63dec22f.d.ts +24 -0
  34. package/esm/Component-8c6198cc.d.ts +23 -0
  35. package/esm/Component.desktop-2e2b2125.d.ts +6 -0
  36. package/esm/Component.desktop-8c6198cc.d.ts +134 -0
  37. package/esm/Component.js +4 -2
  38. package/esm/Component.responsive-2e2b2125.d.ts +68 -0
  39. package/esm/components/divider/Component.js +1 -1
  40. package/esm/components/divider/index.css +8 -8
  41. package/esm/desktop-63dec22f.d.ts +2 -0
  42. package/esm/index-9211a437.d.ts +2 -0
  43. package/esm/index-ebda875c.d.ts +2 -0
  44. package/esm/index-f034f741.d.ts +2 -0
  45. package/esm/index.js +4 -2
  46. package/esm/index.module-a7e95baa.js +4 -0
  47. package/esm/shared-848397c5.d.ts +35 -0
  48. package/esm/shared-c111a9fd.d.ts +13 -0
  49. package/esm/typings-5684a67d.d.ts +23 -0
  50. package/esm/typings-9211a437.d.ts +95 -0
  51. package/esm/useCalendar-71d94e2b.d.ts +97 -0
  52. package/esm/utils-8c6198cc.d.ts +88 -0
  53. package/esm/utils-e0a54580.d.ts +8 -0
  54. package/esm/views/index.css +7 -7
  55. package/esm/views/popover.js +3 -2
  56. package/esm/views/static.js +6 -5
  57. package/index-9211a437.d.ts +2 -0
  58. package/index-ebda875c.d.ts +2 -0
  59. package/index-f034f741.d.ts +2 -0
  60. package/index.js +4 -2
  61. package/index.module-41e6ec4a.js +6 -0
  62. package/modern/Component-5684a67d.d.ts +18 -0
  63. package/modern/Component-63dec22f.d.ts +24 -0
  64. package/modern/Component-8c6198cc.d.ts +23 -0
  65. package/modern/Component.desktop-2e2b2125.d.ts +6 -0
  66. package/modern/Component.desktop-8c6198cc.d.ts +134 -0
  67. package/modern/Component.js +4 -2
  68. package/modern/Component.responsive-2e2b2125.d.ts +68 -0
  69. package/modern/components/divider/Component.js +1 -1
  70. package/modern/components/divider/index.css +8 -8
  71. package/modern/desktop-63dec22f.d.ts +2 -0
  72. package/modern/index-9211a437.d.ts +2 -0
  73. package/modern/index-ebda875c.d.ts +2 -0
  74. package/modern/index-f034f741.d.ts +2 -0
  75. package/modern/index.js +4 -2
  76. package/modern/index.module-f2d65966.js +4 -0
  77. package/modern/shared-848397c5.d.ts +35 -0
  78. package/modern/shared-c111a9fd.d.ts +13 -0
  79. package/modern/typings-5684a67d.d.ts +23 -0
  80. package/modern/typings-9211a437.d.ts +95 -0
  81. package/modern/useCalendar-71d94e2b.d.ts +97 -0
  82. package/modern/utils-8c6198cc.d.ts +88 -0
  83. package/modern/utils-e0a54580.d.ts +8 -0
  84. package/modern/views/index.css +7 -7
  85. package/modern/views/popover.js +3 -2
  86. package/modern/views/static.js +6 -5
  87. package/package.json +4 -4
  88. package/shared-848397c5.d.ts +35 -0
  89. package/shared-c111a9fd.d.ts +13 -0
  90. package/src/Component.tsx +113 -0
  91. package/src/components/divider/Component.tsx +23 -0
  92. package/src/components/divider/index.module.css +41 -0
  93. package/src/components/divider/index.ts +1 -0
  94. package/src/hooks.ts +201 -0
  95. package/src/index.ts +1 -0
  96. package/src/utils.ts +2 -0
  97. package/src/views/index.module.css +28 -0
  98. package/src/views/popover.tsx +223 -0
  99. package/src/views/static.tsx +338 -0
  100. package/typings-5684a67d.d.ts +23 -0
  101. package/typings-9211a437.d.ts +95 -0
  102. package/useCalendar-71d94e2b.d.ts +97 -0
  103. package/utils-8c6198cc.d.ts +88 -0
  104. package/utils-e0a54580.d.ts +8 -0
  105. package/views/index.css +7 -7
  106. package/views/popover.js +10 -9
  107. package/views/static.js +19 -18
  108. package/esm/index.module-f83e6044.js +0 -4
  109. package/index.module-5cfcb7b2.js +0 -6
  110. package/modern/index.module-7414a15d.js +0 -4
@@ -0,0 +1,41 @@
1
+ @import '@alfalab/core-components-themes/src/default.css';
2
+ @import '@alfalab/core-components-calendar/src/vars.css';
3
+
4
+ .component {
5
+ display: flex;
6
+ align-items: center;
7
+ justify-content: center;
8
+ width: 16px;
9
+ margin: 0 var(--gap-xs);
10
+
11
+ &:after {
12
+ content: '';
13
+ display: block;
14
+ width: 100%;
15
+ height: 1px;
16
+ background-color: var(--color-light-graphic-primary);
17
+ }
18
+ }
19
+
20
+ .outer {
21
+ position: relative;
22
+
23
+ /* FormControl .above height + margin-bottom */
24
+ top: 24px;
25
+ }
26
+
27
+ .s {
28
+ height: var(--size-s-height);
29
+ }
30
+
31
+ .m {
32
+ height: var(--size-m-height);
33
+ }
34
+
35
+ .l {
36
+ height: var(--size-l-height);
37
+ }
38
+
39
+ .xl {
40
+ height: var(--size-xl-height);
41
+ }
@@ -0,0 +1 @@
1
+ export * from './Component';
package/src/hooks.ts ADDED
@@ -0,0 +1,201 @@
1
+ import { useCallback, useEffect, useMemo, useState } from 'react';
2
+ import addMonths from 'date-fns/addMonths';
3
+ import isEqual from 'date-fns/isEqual';
4
+ import max from 'date-fns/max';
5
+ import min from 'date-fns/min';
6
+ import startOfMonth from 'date-fns/startOfMonth';
7
+ import subMonths from 'date-fns/subMonths';
8
+
9
+ export function usePopoverViewMonthes({
10
+ dateFrom,
11
+ dateTo,
12
+ defaultMonth,
13
+ resetKey,
14
+ }: {
15
+ defaultMonth: number;
16
+ dateFrom: number | null;
17
+ dateTo: number | null;
18
+ resetKey?: number;
19
+ }) {
20
+ const [monthFrom, setMonthFrom] = useState<number>();
21
+ const [monthTo, setMonthTo] = useState<number>();
22
+
23
+ const handleMonthFromChange = useCallback(
24
+ (newMonthFrom: number) => {
25
+ setMonthFrom(newMonthFrom);
26
+
27
+ if (!dateTo) {
28
+ setMonthTo(newMonthFrom);
29
+ }
30
+ },
31
+ [dateTo],
32
+ );
33
+
34
+ const handleMonthToChange = useCallback(
35
+ (newMonthTo: number) => {
36
+ setMonthTo(newMonthTo);
37
+
38
+ if (!dateFrom) {
39
+ setMonthFrom(newMonthTo);
40
+ }
41
+ },
42
+ [dateFrom],
43
+ );
44
+
45
+ useEffect(() => {
46
+ setMonthFrom(dateFrom ? startOfMonth(dateFrom).getTime() : defaultMonth);
47
+ }, [defaultMonth, dateFrom, resetKey]);
48
+
49
+ useEffect(() => {
50
+ setMonthTo(dateTo ? startOfMonth(dateTo).getTime() : monthFrom);
51
+ // eslint-disable-next-line react-hooks/exhaustive-deps
52
+ }, [dateTo, resetKey]);
53
+
54
+ return {
55
+ monthFrom,
56
+ monthTo,
57
+ handleMonthFromChange,
58
+ handleMonthToChange,
59
+ };
60
+ }
61
+
62
+ export function useStaticViewMonthes({
63
+ selectedFrom,
64
+ selectedTo,
65
+ defaultMonth,
66
+ defaultMonthPosition,
67
+ }: {
68
+ selectedFrom?: number;
69
+ selectedTo?: number;
70
+ defaultMonth: number;
71
+ defaultMonthPosition?: 'left' | 'right';
72
+ }) {
73
+ /**
74
+ * Если указана начальная дата — левый месяц равен ей, иначе используется дата конца.
75
+ * Если обе даты не указаны, то используется дефолтный месяц
76
+ */
77
+ let initialMonthFrom = useMemo(
78
+ () => startOfMonth(selectedFrom || selectedTo || defaultMonth).getTime(),
79
+ // eslint-disable-next-line react-hooks/exhaustive-deps
80
+ [],
81
+ );
82
+
83
+ /**
84
+ * Правый месяц должен быть как минимум на 1 месяц больше левого
85
+ */
86
+ let initialMonthTo = useMemo(
87
+ () =>
88
+ max([
89
+ selectedTo ? startOfMonth(selectedTo) : 0,
90
+ addMonths(initialMonthFrom, 1),
91
+ ]).getTime(),
92
+ // eslint-disable-next-line react-hooks/exhaustive-deps
93
+ [],
94
+ );
95
+
96
+ if (defaultMonthPosition === 'right') {
97
+ initialMonthTo = initialMonthFrom;
98
+ initialMonthFrom = subMonths(initialMonthFrom, 1).getTime();
99
+ }
100
+
101
+ const [monthFrom, setMonthFrom] = useState<number>(initialMonthFrom);
102
+ const [monthTo, setMonthTo] = useState<number>(initialMonthTo);
103
+
104
+ const handleMonthFromChange = useCallback(
105
+ (newMonthFrom: number) => {
106
+ setMonthFrom(newMonthFrom);
107
+
108
+ if (monthTo && isEqual(newMonthFrom, monthTo)) {
109
+ const nextMonth = addMonths(newMonthFrom, 1).getTime();
110
+
111
+ setMonthTo(nextMonth);
112
+ }
113
+ },
114
+ [monthTo],
115
+ );
116
+
117
+ const handleMonthToChange = useCallback(
118
+ (newMonthTo: number) => {
119
+ setMonthTo(newMonthTo);
120
+
121
+ if (monthFrom && isEqual(newMonthTo, monthFrom)) {
122
+ const prevMonth = subMonths(newMonthTo, 1).getTime();
123
+
124
+ setMonthFrom(prevMonth);
125
+ }
126
+ },
127
+ [monthFrom],
128
+ );
129
+
130
+ // eslint-disable-next-line complexity
131
+ useEffect(() => {
132
+ const selectedFromMonth = selectedFrom ? startOfMonth(selectedFrom).getTime() : undefined;
133
+ const selectedToMonth = selectedTo ? startOfMonth(selectedTo).getTime() : undefined;
134
+
135
+ // Проверяем, показываются ли выбранные месяцы в левой или правой части компонента
136
+ const fromMonthOnLeft = selectedFromMonth && selectedFromMonth === monthFrom;
137
+ const fromMonthOnRight = selectedFromMonth && selectedFromMonth === monthTo;
138
+ const toMonthOnRight = selectedToMonth && selectedToMonth === monthTo;
139
+ const toMonthOnLeft = selectedToMonth && selectedToMonth === monthFrom;
140
+ const fromMonthOnScreen = fromMonthOnLeft || fromMonthOnRight;
141
+ const toMonthOnScreen = toMonthOnLeft || toMonthOnRight;
142
+
143
+ if (fromMonthOnLeft && toMonthOnLeft) {
144
+ setMonthTo(max([addMonths(selectedFromMonth as number, 1), monthTo]).getTime());
145
+
146
+ return;
147
+ }
148
+
149
+ if (fromMonthOnRight && toMonthOnRight) {
150
+ setMonthFrom(min([subMonths(selectedToMonth as number, 1), monthFrom]).getTime());
151
+
152
+ return;
153
+ }
154
+
155
+ if (selectedFromMonth && selectedToMonth) {
156
+ setMonthFrom(selectedFromMonth);
157
+ setMonthTo(max([addMonths(selectedFromMonth, 1), selectedToMonth]).getTime());
158
+
159
+ return;
160
+ }
161
+
162
+ if (selectedFromMonth && !selectedToMonth && !fromMonthOnScreen) {
163
+ setMonthFrom(selectedFromMonth);
164
+ setMonthTo(max([addMonths(selectedFromMonth, 1), monthTo]).getTime());
165
+ }
166
+
167
+ if (selectedToMonth && !selectedFromMonth && !toMonthOnScreen) {
168
+ setMonthTo(selectedToMonth);
169
+ setMonthFrom(min([subMonths(selectedToMonth, 1), monthFrom]).getTime());
170
+ }
171
+
172
+ // eslint-disable-next-line react-hooks/exhaustive-deps
173
+ }, [selectedFrom, selectedTo]);
174
+
175
+ return {
176
+ monthFrom,
177
+ monthTo,
178
+ handleMonthFromChange,
179
+ handleMonthToChange,
180
+ };
181
+ }
182
+
183
+ export function useSelectionProps(from?: number, to?: number, highlighted?: number) {
184
+ return useMemo(() => {
185
+ if (from && to) {
186
+ return {
187
+ rangeComplete: true,
188
+ selectedFrom: min([from, to]).getTime(),
189
+ selectedTo: max([from, to]).getTime(),
190
+ };
191
+ }
192
+
193
+ const dates = [from, to, highlighted].filter((date) => date !== undefined) as number[];
194
+
195
+ return {
196
+ rangeComplete: false,
197
+ selectedFrom: from || dates.length === 2 ? min(dates).getTime() : undefined,
198
+ selectedTo: to || dates.length === 2 ? max(dates).getTime() : undefined,
199
+ };
200
+ }, [from, highlighted, to]);
201
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './Component';
package/src/utils.ts ADDED
@@ -0,0 +1,2 @@
1
+ export const isDayButton = (node: HTMLElement | null) =>
2
+ node && node.tagName === 'BUTTON' && node.dataset.date;
@@ -0,0 +1,28 @@
1
+ @import '@alfalab/core-components-themes/src/default.css';
2
+ @import '@alfalab/core-components-calendar/src/vars.css';
3
+
4
+ .component {
5
+ display: flex;
6
+
7
+ & button[aria-selected='true'] {
8
+ cursor: pointer;
9
+ }
10
+
11
+ & *[class*='errorIcon_'] {
12
+ display: none;
13
+ }
14
+
15
+ & *[class*='calendarIcon_'] {
16
+ margin-right: 0;
17
+ }
18
+ }
19
+
20
+ .static {
21
+ & .calendar {
22
+ width: var(--calendar-inner-width);
23
+
24
+ & > div:first-child {
25
+ padding: var(--gap-m) 0 var(--gap-s);
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,223 @@
1
+ import React, { FC, useCallback, useEffect, useState } from 'react';
2
+ import cn from 'classnames';
3
+ import startOfMonth from 'date-fns/startOfMonth';
4
+
5
+ import { CalendarInput, CalendarInputProps } from '@alfalab/core-components-calendar-input';
6
+ import { isValidInputValue, parseDateString } from '@alfalab/core-components-calendar-input/shared';
7
+ import { isCompleteDateInput } from '@alfalab/core-components-date-input';
8
+ import { useDidUpdateEffect } from '@alfalab/hooks';
9
+
10
+ import { CalendarRangeProps } from '../Component';
11
+ import { Divider } from '../components/divider';
12
+ import { usePopoverViewMonthes } from '../hooks';
13
+
14
+ import styles from './index.module.css';
15
+
16
+ export type CalendarRangePopoverProps = Omit<CalendarRangeProps, 'calendarPosition'>;
17
+
18
+ export const CalendarRangePopover: FC<CalendarRangePopoverProps> = ({
19
+ className,
20
+ defaultMonth = startOfMonth(new Date()).getTime(),
21
+ minDate,
22
+ maxDate,
23
+ valueFrom = '',
24
+ valueTo = '',
25
+ onDateFromChange = () => null,
26
+ onDateToChange = () => null,
27
+ onChange = () => null,
28
+ onError,
29
+ inputFromProps = {},
30
+ inputToProps = {},
31
+ offDays,
32
+ events,
33
+ returnInvalidDates = false,
34
+ dataTestId,
35
+ }) => {
36
+ const [inputFromValue, setInputFromValue] = useState<string>(valueFrom);
37
+ const [inputToValue, setInputToValue] = useState<string>(valueTo);
38
+
39
+ /**
40
+ * Ключ для сброса календарей
41
+ * Пользователь открыл календарь, изменил месяц, но ничего не выбрал
42
+ * — при следующем открытии в календаре будет установлен начальный месяц
43
+ */
44
+ const [resetKey, setResetKey] = useState<number>(0);
45
+
46
+ const dateFrom = isValidInputValue(inputFromValue, minDate, maxDate, offDays)
47
+ ? parseDateString(inputFromValue).getTime()
48
+ : null;
49
+
50
+ const dateTo = isValidInputValue(inputToValue, dateFrom || minDate, maxDate, offDays)
51
+ ? parseDateString(inputToValue).getTime()
52
+ : null;
53
+
54
+ const [inputFromInvalid, setInputFromInvalid] = useState<boolean>(
55
+ isCompleteDateInput(inputFromValue) && dateFrom === null,
56
+ );
57
+ const [inputToInvalid, setInputToInvalid] = useState<boolean>(
58
+ isCompleteDateInput(inputToValue) && dateTo === null,
59
+ );
60
+
61
+ const bothInvalid =
62
+ isCompleteDateInput(inputFromValue) &&
63
+ isCompleteDateInput(inputToValue) &&
64
+ parseDateString(inputFromValue).getTime() > parseDateString(inputToValue).getTime();
65
+
66
+ const hasValidateError = inputFromInvalid || inputToInvalid || bothInvalid;
67
+
68
+ const { monthFrom, monthTo, handleMonthFromChange, handleMonthToChange } =
69
+ usePopoverViewMonthes({
70
+ dateFrom,
71
+ dateTo,
72
+ defaultMonth,
73
+ resetKey,
74
+ });
75
+
76
+ const handleValidInputFrom = useCallback(() => {
77
+ setInputFromInvalid(
78
+ inputFromValue !== '' && !isValidInputValue(inputFromValue, minDate, maxDate, offDays),
79
+ );
80
+ }, [inputFromValue, maxDate, minDate, offDays]);
81
+
82
+ const handleValidInputTo = useCallback(() => {
83
+ setInputToInvalid(
84
+ inputToValue !== '' &&
85
+ !isValidInputValue(inputToValue, dateFrom || minDate, maxDate, offDays),
86
+ );
87
+ }, [dateFrom, inputToValue, maxDate, minDate, offDays]);
88
+
89
+ const handleInputFromChange: Required<CalendarInputProps>['onInputChange'] = (
90
+ event,
91
+ payload,
92
+ ) => {
93
+ setInputFromValue(payload.value);
94
+ inputFromProps.onInputChange?.(event, payload);
95
+ };
96
+
97
+ const handleInputToChange: Required<CalendarInputProps>['onInputChange'] = (event, payload) => {
98
+ setInputToValue(payload.value);
99
+ inputToProps.onInputChange?.(event, payload);
100
+ };
101
+
102
+ const handleInputFromBlur = useCallback(() => {
103
+ handleValidInputFrom();
104
+ setResetKey(+new Date());
105
+ }, [handleValidInputFrom]);
106
+
107
+ const handleInputToBlur = useCallback(() => {
108
+ handleValidInputTo();
109
+ setResetKey(+new Date());
110
+ }, [handleValidInputTo]);
111
+
112
+ const handleFromChange: Required<CalendarInputProps>['onChange'] = useCallback((_, payload) => {
113
+ setInputFromValue(payload.value);
114
+ }, []);
115
+
116
+ const handleToChange: Required<CalendarInputProps>['onChange'] = useCallback((_, payload) => {
117
+ setInputToValue(payload.value);
118
+ }, []);
119
+
120
+ useEffect(() => {
121
+ setInputFromValue(valueFrom);
122
+ }, [valueFrom]);
123
+
124
+ useEffect(() => {
125
+ setInputToValue(valueTo);
126
+ }, [valueTo]);
127
+
128
+ useDidUpdateEffect(() => {
129
+ onDateFromChange({ value: inputFromValue, date: dateFrom });
130
+
131
+ onChange({
132
+ valueFrom: inputFromValue,
133
+ valueTo: inputToValue,
134
+ dateFrom,
135
+ dateTo,
136
+ });
137
+
138
+ if (!inputFromValue || isCompleteDateInput(inputFromValue)) {
139
+ handleValidInputFrom();
140
+ }
141
+ // eslint-disable-next-line react-hooks/exhaustive-deps
142
+ }, [inputFromValue]);
143
+
144
+ useDidUpdateEffect(() => {
145
+ onDateToChange({ value: inputToValue, date: dateTo });
146
+
147
+ // eslint-disable-next-line no-nested-ternary
148
+ const inputDateTo = returnInvalidDates
149
+ ? isCompleteDateInput(inputToValue)
150
+ ? parseDateString(inputToValue).getTime()
151
+ : null
152
+ : dateTo;
153
+
154
+ onChange({
155
+ valueFrom: inputFromValue,
156
+ valueTo: inputToValue,
157
+ dateFrom,
158
+ dateTo: inputDateTo,
159
+ });
160
+
161
+ if (!inputToValue || isCompleteDateInput(inputToValue)) {
162
+ handleValidInputTo();
163
+ }
164
+ // eslint-disable-next-line react-hooks/exhaustive-deps
165
+ }, [inputToValue]);
166
+
167
+ useEffect(() => {
168
+ if (onError) {
169
+ onError(hasValidateError);
170
+ }
171
+ // eslint-disable-next-line react-hooks/exhaustive-deps
172
+ }, [hasValidateError]);
173
+
174
+ return (
175
+ <div className={cn(styles.component, className)} data-test-id={dataTestId}>
176
+ <CalendarInput
177
+ {...inputFromProps}
178
+ useAnchorWidth={false}
179
+ calendarPosition='popover'
180
+ popoverPosition='bottom-start'
181
+ error={inputFromInvalid || bothInvalid || inputFromProps.error}
182
+ onChange={handleFromChange}
183
+ onInputChange={handleInputFromChange}
184
+ onBlur={handleInputFromBlur}
185
+ value={inputFromValue}
186
+ minDate={minDate}
187
+ maxDate={maxDate}
188
+ offDays={offDays}
189
+ events={events}
190
+ calendarProps={{
191
+ ...inputFromProps.calendarProps,
192
+ month: monthFrom,
193
+ onMonthChange: handleMonthFromChange,
194
+ selectorView: 'full',
195
+ }}
196
+ />
197
+
198
+ <Divider inputFromProps={inputFromProps} inputToProps={inputToProps} />
199
+
200
+ <CalendarInput
201
+ {...inputToProps}
202
+ useAnchorWidth={false}
203
+ calendarPosition='popover'
204
+ popoverPosition='bottom-end'
205
+ error={inputToInvalid || bothInvalid || inputToProps.error}
206
+ onChange={handleToChange}
207
+ onInputChange={handleInputToChange}
208
+ onBlur={handleInputToBlur}
209
+ value={inputToValue}
210
+ minDate={dateFrom || minDate}
211
+ maxDate={maxDate}
212
+ offDays={offDays}
213
+ events={events}
214
+ calendarProps={{
215
+ ...inputToProps.calendarProps,
216
+ month: monthTo,
217
+ onMonthChange: handleMonthToChange,
218
+ selectorView: 'full',
219
+ }}
220
+ />
221
+ </div>
222
+ );
223
+ };