@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,338 @@
1
+ /* eslint-disable complexity */
2
+ import React, { FC, MouseEvent, useCallback, useEffect, useState } from 'react';
3
+ import cn from 'classnames';
4
+ import addMonths from 'date-fns/addMonths';
5
+ import endOfMonth from 'date-fns/endOfMonth';
6
+ import isSameMonth from 'date-fns/isSameMonth';
7
+ import max from 'date-fns/max';
8
+ import startOfMonth from 'date-fns/startOfMonth';
9
+ import subMonths from 'date-fns/subMonths';
10
+
11
+ import { CalendarDesktop } from '@alfalab/core-components-calendar/desktop';
12
+ import { usePeriodWithReset } from '@alfalab/core-components-calendar/shared';
13
+ import {
14
+ formatDate,
15
+ isValidInputValue,
16
+ parseDateString,
17
+ } from '@alfalab/core-components-calendar-input/shared';
18
+ import {
19
+ DateInput,
20
+ DateInputProps,
21
+ isCompleteDateInput,
22
+ } from '@alfalab/core-components-date-input';
23
+
24
+ import { CalendarRangeProps } from '../Component';
25
+ import { Divider } from '../components/divider';
26
+ import { useSelectionProps, useStaticViewMonthes } from '../hooks';
27
+ import { isDayButton } from '../utils';
28
+
29
+ import styles from './index.module.css';
30
+
31
+ export type CalendarRangeStaticProps = Omit<CalendarRangeProps, 'calendarPosition'> & {
32
+ /**
33
+ * Отображать начальный месяц слева или справа (влияет только на начальный рендер)
34
+ */
35
+ defaultMonthPosition?: 'left' | 'right';
36
+ };
37
+
38
+ export const CalendarRangeStatic: FC<CalendarRangeStaticProps> = ({
39
+ className,
40
+ defaultMonth = startOfMonth(new Date()).getTime(),
41
+ defaultMonthPosition = 'left',
42
+ minDate,
43
+ maxDate,
44
+ valueFrom = '',
45
+ valueTo = '',
46
+ onDateFromChange = () => null,
47
+ onDateToChange = () => null,
48
+ onChange = () => null,
49
+ onError,
50
+ inputFromProps = {},
51
+ inputToProps = {},
52
+ offDays,
53
+ events,
54
+ returnInvalidDates = false,
55
+ dataTestId,
56
+ }) => {
57
+ const [inputFromValue, setInputFromValue] = useState<string>(valueFrom);
58
+ const [inputToValue, setInputToValue] = useState<string>(valueTo);
59
+
60
+ let dateFrom = isValidInputValue(inputFromValue, minDate, maxDate, offDays)
61
+ ? parseDateString(inputFromValue).getTime()
62
+ : null;
63
+
64
+ const dateTo = isValidInputValue(inputToValue, dateFrom || minDate, maxDate, offDays)
65
+ ? parseDateString(inputToValue).getTime()
66
+ : null;
67
+
68
+ if (isCompleteDateInput(inputToValue) && !dateTo && !returnInvalidDates) {
69
+ dateFrom = null;
70
+ }
71
+
72
+ const bothInvalid =
73
+ isCompleteDateInput(inputFromValue) &&
74
+ isCompleteDateInput(inputToValue) &&
75
+ parseDateString(inputFromValue).getTime() > parseDateString(inputToValue).getTime();
76
+
77
+ const [highlightedDate, setHighlightedDate] = useState<number | undefined>(undefined);
78
+
79
+ const period = usePeriodWithReset({
80
+ initialSelectedFrom: dateFrom ? parseDateString(inputFromValue).getTime() : undefined,
81
+ initialSelectedTo: dateTo ? parseDateString(inputToValue).getTime() : undefined,
82
+ });
83
+
84
+ const validateInputFromValue = useCallback(
85
+ (value: string) => isValidInputValue(value, minDate, dateFrom || maxDate, offDays),
86
+ [dateFrom, maxDate, minDate, offDays],
87
+ );
88
+
89
+ const validateInputToValue = useCallback(
90
+ (value: string) => isValidInputValue(value, dateFrom || minDate, maxDate, offDays),
91
+
92
+ [dateFrom, minDate, maxDate, offDays],
93
+ );
94
+
95
+ const [inputFromInvalid, setInputFromInvalid] = useState<boolean>(
96
+ isCompleteDateInput(inputFromValue) && dateFrom === null,
97
+ );
98
+
99
+ const [inputToInvalid, setInputToInvalid] = useState<boolean>(
100
+ isCompleteDateInput(inputToValue) && dateTo === null,
101
+ );
102
+
103
+ const hasValidateError = bothInvalid || inputFromInvalid || inputToInvalid;
104
+ const {
105
+ calendarProps: calendarFromProps,
106
+ onInputChange: onInputChangeFrom,
107
+ ...dateInputFromProps
108
+ } = inputFromProps;
109
+ const {
110
+ calendarProps: calendarToProps,
111
+ onInputChange: onInputChangeTo,
112
+ ...dateInputToProps
113
+ } = inputToProps;
114
+
115
+ const { monthFrom, monthTo, handleMonthFromChange, handleMonthToChange } = useStaticViewMonthes(
116
+ {
117
+ selectedFrom: period.selectedFrom,
118
+ selectedTo: period.selectedTo,
119
+ defaultMonth,
120
+ defaultMonthPosition,
121
+ },
122
+ );
123
+
124
+ const handleValidInputFrom = useCallback(() => {
125
+ setInputFromInvalid(inputFromValue !== '' && !validateInputFromValue(inputFromValue));
126
+ }, [inputFromValue, validateInputFromValue]);
127
+
128
+ const handleValidInputTo = useCallback(() => {
129
+ setInputToInvalid(inputToValue !== '' && !validateInputToValue(inputToValue));
130
+ }, [inputToValue, validateInputToValue]);
131
+
132
+ const handleInputFromChange: Required<DateInputProps>['onChange'] = (event, payload) => {
133
+ setInputFromValue(payload.value);
134
+ onInputChangeFrom?.(event, payload);
135
+ };
136
+
137
+ const handleInputToChange: Required<DateInputProps>['onChange'] = (event, payload) => {
138
+ setInputToValue(payload.value);
139
+ onInputChangeTo?.(event, payload);
140
+ };
141
+
142
+ const handleMouseOver = useCallback((event: MouseEvent<HTMLDivElement>) => {
143
+ const target = event.target as HTMLElement;
144
+
145
+ const mouseOverDayButton = isDayButton(target) || isDayButton(target.parentElement);
146
+
147
+ let date;
148
+
149
+ if (mouseOverDayButton) {
150
+ const button =
151
+ target.tagName === 'BUTTON' ? target : (target.parentElement as HTMLButtonElement);
152
+
153
+ if (button.dataset.date) {
154
+ date = +button.dataset.date;
155
+ }
156
+ }
157
+
158
+ setHighlightedDate(date);
159
+ }, []);
160
+
161
+ const handleClearFrom = useCallback(() => {
162
+ setInputFromValue('');
163
+ }, []);
164
+
165
+ const handleClearTo = useCallback(() => {
166
+ setInputToValue('');
167
+ }, []);
168
+
169
+ useEffect(() => {
170
+ setInputFromValue(period.selectedFrom ? formatDate(period.selectedFrom) : '');
171
+ }, [period.selectedFrom]);
172
+
173
+ useEffect(() => {
174
+ setInputToValue(period.selectedTo ? formatDate(period.selectedTo) : '');
175
+ }, [period.selectedTo]);
176
+
177
+ useEffect(() => {
178
+ setInputFromValue(valueFrom);
179
+ }, [valueFrom]);
180
+
181
+ useEffect(() => {
182
+ setInputToValue(valueTo);
183
+ }, [valueTo]);
184
+
185
+ useEffect(() => {
186
+ if (!inputFromValue || isCompleteDateInput(inputFromValue)) {
187
+ handleValidInputFrom();
188
+ }
189
+
190
+ period.setStart(dateFrom || undefined);
191
+ if (dateTo) {
192
+ period.setEnd(dateTo);
193
+ }
194
+
195
+ if (inputFromValue !== valueFrom) {
196
+ onDateFromChange({
197
+ value: inputFromValue,
198
+ date: dateFrom,
199
+ });
200
+
201
+ onChange({
202
+ valueFrom: inputFromValue,
203
+ valueTo: inputToValue,
204
+ dateFrom,
205
+ dateTo,
206
+ });
207
+ }
208
+ // eslint-disable-next-line react-hooks/exhaustive-deps
209
+ }, [inputFromValue]);
210
+
211
+ useEffect(() => {
212
+ if (!inputToValue || isCompleteDateInput(inputToValue)) {
213
+ handleValidInputTo();
214
+ }
215
+
216
+ period.setEnd(dateTo || undefined);
217
+ if (dateFrom) {
218
+ period.setStart(dateFrom);
219
+ }
220
+
221
+ if (inputToValue !== valueTo) {
222
+ // eslint-disable-next-line no-nested-ternary
223
+ const inputDateTo = returnInvalidDates
224
+ ? isCompleteDateInput(inputToValue)
225
+ ? parseDateString(inputToValue).getTime()
226
+ : null
227
+ : dateTo;
228
+
229
+ onDateToChange({
230
+ value: inputToValue,
231
+ date: inputDateTo,
232
+ });
233
+
234
+ onChange({
235
+ valueFrom: inputFromValue,
236
+ valueTo: inputToValue,
237
+ dateFrom,
238
+ dateTo: inputDateTo,
239
+ });
240
+ }
241
+ // eslint-disable-next-line react-hooks/exhaustive-deps
242
+ }, [inputToValue]);
243
+
244
+ useEffect(() => {
245
+ if (onError) {
246
+ onError(hasValidateError);
247
+ }
248
+ // eslint-disable-next-line react-hooks/exhaustive-deps
249
+ }, [hasValidateError]);
250
+
251
+ const rangeProps = useSelectionProps(period.selectedFrom, period.selectedTo, highlightedDate);
252
+
253
+ const CalendarFromComponent = dateInputFromProps.Calendar || CalendarDesktop;
254
+ const CalendarToComponent = dateInputToProps.Calendar || CalendarDesktop;
255
+
256
+ const minMaxInSameMonth = minDate && maxDate && isSameMonth(minDate, maxDate);
257
+
258
+ return (
259
+ // eslint-disable-next-line jsx-a11y/mouse-events-have-key-events
260
+ <div
261
+ className={cn(styles.component, styles.static, className)}
262
+ onMouseOver={handleMouseOver}
263
+ data-test-id={dataTestId}
264
+ >
265
+ <div>
266
+ <DateInput
267
+ {...dateInputFromProps}
268
+ mobileMode={
269
+ dateInputFromProps.mobileMode === 'popover'
270
+ ? 'input'
271
+ : dateInputFromProps.mobileMode
272
+ }
273
+ value={inputFromValue}
274
+ onChange={handleInputFromChange}
275
+ onClear={handleClearFrom}
276
+ onBlur={handleValidInputFrom}
277
+ error={bothInvalid || inputFromInvalid || dateInputFromProps.error}
278
+ clear={true}
279
+ block={true}
280
+ />
281
+ <CalendarFromComponent
282
+ {...calendarFromProps}
283
+ className={cn(styles.calendar, calendarFromProps?.className)}
284
+ month={monthFrom}
285
+ selectorView='month-only'
286
+ offDays={offDays}
287
+ events={events}
288
+ onChange={period.updatePeriod}
289
+ onMonthChange={handleMonthFromChange}
290
+ minDate={minDate}
291
+ maxDate={
292
+ minMaxInSameMonth
293
+ ? maxDate
294
+ : maxDate && max([maxDate, endOfMonth(subMonths(maxDate, 1))]).getTime()
295
+ }
296
+ {...rangeProps}
297
+ />
298
+ </div>
299
+
300
+ <Divider inputFromProps={inputFromProps} inputToProps={inputToProps} />
301
+
302
+ <div>
303
+ <DateInput
304
+ {...dateInputToProps}
305
+ mobileMode={
306
+ dateInputToProps.mobileMode === 'popover'
307
+ ? 'input'
308
+ : dateInputToProps.mobileMode
309
+ }
310
+ value={inputToValue}
311
+ onChange={handleInputToChange}
312
+ onClear={handleClearTo}
313
+ onBlur={handleValidInputTo}
314
+ error={bothInvalid || inputToInvalid}
315
+ clear={true}
316
+ block={true}
317
+ />
318
+ <CalendarToComponent
319
+ {...calendarToProps}
320
+ className={cn(styles.calendar, calendarToProps?.className)}
321
+ month={monthTo}
322
+ selectorView='month-only'
323
+ offDays={offDays}
324
+ events={events}
325
+ onChange={period.updatePeriod}
326
+ onMonthChange={handleMonthToChange}
327
+ minDate={
328
+ minMaxInSameMonth
329
+ ? minDate
330
+ : minDate && startOfMonth(addMonths(minDate, 1)).getTime()
331
+ }
332
+ maxDate={maxDate}
333
+ {...rangeProps}
334
+ />
335
+ </div>
336
+ </div>
337
+ );
338
+ };
@@ -0,0 +1,23 @@
1
+ import { ReactNode } from 'react';
2
+ type SpecialDays = Record<number, boolean>;
3
+ type DayAddons = {
4
+ date: Date | number;
5
+ addon: ReactNode;
6
+ };
7
+ type SpecialDaysAddon = Record<number, ReactNode>;
8
+ type Day = {
9
+ date: Date;
10
+ disabled?: boolean;
11
+ event?: boolean;
12
+ selected?: boolean;
13
+ holiday?: boolean;
14
+ dayAddon?: ReactNode;
15
+ };
16
+ type Month = {
17
+ date: Date;
18
+ disabled?: boolean;
19
+ };
20
+ type DateShift = 'prev' | 'prevWeek' | 'prevMonth' | 'startOfWeek' | 'next' | 'nextWeek' | 'nextMonth' | 'endOfWeek';
21
+ type View = 'years' | 'months' | 'days';
22
+ type SelectorView = 'month-only' | 'full';
23
+ export { SpecialDays, DayAddons, SpecialDaysAddon, Day, Month, DateShift, View, SelectorView };
@@ -0,0 +1,95 @@
1
+ import { AnchorHTMLAttributes, ButtonHTMLAttributes, ElementType, ReactNode } from 'react';
2
+ type StyleColors = {
3
+ default: {
4
+ [key: string]: string;
5
+ };
6
+ inverted: {
7
+ [key: string]: string;
8
+ };
9
+ };
10
+ type ComponentProps = {
11
+ /**
12
+ * Тип кнопки
13
+ * @default secondary
14
+ */
15
+ view?: 'accent' | 'primary' | 'secondary' | 'tertiary' | 'outlined' | 'filled' | 'transparent' | 'link' | 'ghost';
16
+ /**
17
+ * Слот слева
18
+ */
19
+ leftAddons?: ReactNode;
20
+ /**
21
+ * Слот справа
22
+ */
23
+ rightAddons?: ReactNode;
24
+ /**
25
+ * Размер компонента
26
+ * @default m
27
+ */
28
+ size?: 'xxs' | 'xs' | 's' | 'm' | 'l' | 'xl';
29
+ /**
30
+ * Растягивает компонент на ширину контейнера
31
+ * @default false
32
+ */
33
+ block?: boolean;
34
+ /**
35
+ * Дополнительный класс
36
+ */
37
+ className?: string;
38
+ /**
39
+ * Дополнительный класс для спиннера
40
+ */
41
+ spinnerClassName?: string;
42
+ /**
43
+ * Выводит ссылку в виде кнопки
44
+ */
45
+ href?: string;
46
+ /**
47
+ * Позволяет использовать кастомный компонент для кнопки (например Link из роутера)
48
+ */
49
+ Component?: ElementType;
50
+ /**
51
+ * Идентификатор для систем автоматизированного тестирования
52
+ */
53
+ dataTestId?: string;
54
+ /**
55
+ * Показать лоадер
56
+ * @default false
57
+ */
58
+ loading?: boolean;
59
+ /**
60
+ * Не переносить текст кнопки на новую строку
61
+ * @default false
62
+ */
63
+ nowrap?: boolean;
64
+ /**
65
+ * Набор цветов для компонента
66
+ */
67
+ colors?: 'default' | 'inverted';
68
+ /**
69
+ * Дочерние элементы.
70
+ */
71
+ children?: ReactNode;
72
+ /**
73
+ * Основные стили компонента.
74
+ */
75
+ styles: {
76
+ [key: string]: string;
77
+ };
78
+ /**
79
+ * Стили компонента для default и inverted режима.
80
+ */
81
+ colorStylesMap: StyleColors;
82
+ };
83
+ type AnchorBaseButtonProps = ComponentProps & AnchorHTMLAttributes<HTMLAnchorElement>;
84
+ type NativeBaseButtonProps = ComponentProps & ButtonHTMLAttributes<HTMLButtonElement>;
85
+ type BaseButtonProps = Partial<AnchorBaseButtonProps | NativeBaseButtonProps>;
86
+ type AnchorButtonProps = Omit<BaseButtonProps, 'styles' | 'colorStylesMap'> & AnchorHTMLAttributes<HTMLAnchorElement>;
87
+ type NativeButtonProps = Omit<BaseButtonProps, 'styles' | 'colorStylesMap'> & ButtonHTMLAttributes<HTMLButtonElement>;
88
+ type ButtonProps = Partial<AnchorButtonProps | NativeButtonProps> & {
89
+ /**
90
+ * Контрольная точка, с нее начинается desktop версия
91
+ * @default 1024
92
+ */
93
+ breakpoint?: number;
94
+ };
95
+ export { StyleColors, ComponentProps, AnchorBaseButtonProps, NativeBaseButtonProps, BaseButtonProps, AnchorButtonProps, NativeButtonProps, ButtonProps };
@@ -0,0 +1,97 @@
1
+ /// <reference types="react" />
2
+ import { KeyboardEvent, MouseEvent, Ref } from 'react';
3
+ import { Day, DayAddons, Month, View } from "./typings-5684a67d";
4
+ type UseCalendarProps = {
5
+ /**
6
+ * Активный вид (выбор дней, месяцев, лет)
7
+ */
8
+ view?: View;
9
+ /**
10
+ * Выбранный месяц (controlled)
11
+ */
12
+ month?: Date;
13
+ /**
14
+ * Начальный месяц
15
+ */
16
+ defaultMonth: Date;
17
+ /**
18
+ * Минимальная дата, доступная для выбора
19
+ */
20
+ minDate?: Date;
21
+ /**
22
+ * Максимальная дата, доступная для выбора
23
+ */
24
+ maxDate?: Date;
25
+ /**
26
+ * Выбранная дата
27
+ */
28
+ selected?: Date;
29
+ /**
30
+ * Список событий
31
+ */
32
+ events?: Array<Date | number>;
33
+ /**
34
+ * Список отключенных для выбора дней
35
+ */
36
+ offDays?: Array<Date | number>;
37
+ /**
38
+ * Список выходных дней
39
+ */
40
+ holidays?: Array<Date | number>;
41
+ /**
42
+ * Обработчик изменения месяца (или года)
43
+ */
44
+ onMonthChange?: (month: number) => void;
45
+ /**
46
+ * Обработчик выбора даты
47
+ */
48
+ onChange?: (date: number) => void;
49
+ /**
50
+ * Дополнительный контент под числом
51
+ */
52
+ dayAddons?: DayAddons[];
53
+ };
54
+ declare function useCalendar({ defaultMonth, month, minDate, view, maxDate, selected, events, offDays, holidays, dayAddons, onMonthChange, onChange, }: UseCalendarProps): {
55
+ activeMonth: Date;
56
+ weeks: Day[][];
57
+ months: Month[];
58
+ years: Date[];
59
+ canSetPrevMonth: boolean;
60
+ canSetNextMonth: boolean;
61
+ highlighted: number | Date | undefined;
62
+ setPrevMonth: () => void;
63
+ setNextMonth: () => void;
64
+ setMonthByDate: (newMonth: Date) => void;
65
+ getDayProps: (day: Day) => {
66
+ 'data-date': number;
67
+ 'aria-selected': boolean | undefined;
68
+ ref: (node: HTMLTableDataCellElement) => void;
69
+ tabIndex: number;
70
+ onMouseEnter: (event: MouseEvent<HTMLTableDataCellElement>) => void;
71
+ onMouseLeave: () => void;
72
+ onClick: (event: MouseEvent<HTMLTableDataCellElement>) => void;
73
+ };
74
+ getMonthProps: (currMonth: Month) => {
75
+ 'data-date': number;
76
+ 'aria-selected': boolean;
77
+ ref: (node: HTMLButtonElement) => void;
78
+ tabIndex: number;
79
+ disabled: boolean | undefined;
80
+ onClick: (event: MouseEvent<HTMLButtonElement>) => void;
81
+ };
82
+ getYearProps: (year: Date) => {
83
+ 'data-date': number;
84
+ 'aria-selected': boolean;
85
+ ref: (node: HTMLButtonElement) => void;
86
+ tabIndex: number;
87
+ onClick: (event: MouseEvent<HTMLButtonElement>) => void;
88
+ };
89
+ getRootProps: ({ ref }: {
90
+ ref?: Ref<HTMLDivElement> | undefined;
91
+ }) => {
92
+ onKeyDown: (event: KeyboardEvent<HTMLDivElement>) => void;
93
+ ref: (instance: HTMLDivElement | null) => void;
94
+ tabIndex: number;
95
+ };
96
+ };
97
+ export { UseCalendarProps, useCalendar };
@@ -0,0 +1,88 @@
1
+ import { ReactNode } from 'react';
2
+ import { DateShift, Day, DayAddons, Month, SpecialDays, SpecialDaysAddon } from "./typings-5684a67d";
3
+ declare const DAYS_IN_WEEK = 7;
4
+ declare const MONTHS_IN_YEAR = 12;
5
+ declare const SUNDAY_INDEX = 6;
6
+ declare const DATE_FORMAT = "dd.MM.yyyy";
7
+ declare const NATIVE_DATE_FORMAT = "yyyy-MM-dd";
8
+ declare const WEEKDAYS: string[];
9
+ declare const MONTHS: string[];
10
+ /**
11
+ * Возвращает «правильный» индекс дня недели, 0 - пн, 1 - вт и так далее.
12
+ */
13
+ declare function russianWeekDay(date: Date): number;
14
+ /**
15
+ * Возвращает таблицу-календарь с заполненными датами для переданного месяца
16
+ */
17
+ declare function generateWeeks(month: Date, options: {
18
+ minDate?: Date;
19
+ maxDate?: Date;
20
+ selected?: Date;
21
+ eventsMap?: SpecialDays;
22
+ offDaysMap?: SpecialDays;
23
+ holidaysMap?: SpecialDays;
24
+ dayAddonsMap?: SpecialDaysAddon;
25
+ }): Day[][];
26
+ /**
27
+ * Возвращает массив с месяцами для переданного года
28
+ */
29
+ declare function generateMonths(year: Date, options: {
30
+ minMonth?: Date;
31
+ maxMonth?: Date;
32
+ }): Month[];
33
+ /**
34
+ * Возвращает массив лет от minYear до maxYear
35
+ */
36
+ declare function generateYears(minYear: Date, maxYear: Date): Date[];
37
+ /**
38
+ * Добавляет метаданные для переданного дня
39
+ */
40
+ declare function buildDay(day: Date, options: {
41
+ minDate?: Date;
42
+ maxDate?: Date;
43
+ selected?: Date;
44
+ eventsMap?: SpecialDays;
45
+ offDaysMap?: SpecialDays;
46
+ holidaysMap?: SpecialDays;
47
+ dayAddonsMap?: SpecialDaysAddon;
48
+ }): Day;
49
+ /**
50
+ * Добавляет метаданные для переданного месяца
51
+ */
52
+ declare function buildMonth(month: Date, options: {
53
+ minMonth?: Date;
54
+ maxMonth?: Date;
55
+ }): Month;
56
+ /**
57
+ * Ограничивает дату на отрезке [minDate, maxDate]
58
+ */
59
+ declare function limitDate(date: Date | number, minDate?: Date | number, maxDate?: Date | number): Date;
60
+ /**
61
+ * Проверяет, находится ли переданная дата в указанных границах
62
+ */
63
+ declare function dateInLimits(date?: Date | number | null, minDate?: Date | number, maxDate?: Date | number): boolean | 0 | null | undefined;
64
+ /**
65
+ * Возвращает русское название месяца с большой буквы
66
+ */
67
+ declare function monthName(month: Date): string;
68
+ /**
69
+ * Превращает массив в объект, у которого ключи составляются из элементов массива
70
+ */
71
+ declare function dateArrayToHashTable(arr: Array<Date | number>): Record<number, boolean>;
72
+ declare function addonArrayToHashTable(arr: DayAddons[]): Record<number, ReactNode>;
73
+ /**
74
+ * Возвращает корректный отрезок дат для выделения
75
+ */
76
+ declare function getSelectionRange(from?: Date | number, to?: Date | number, highlighted?: Date | number): {
77
+ start: Date;
78
+ end: Date;
79
+ } | null;
80
+ declare function modifyDateByShift(shift: DateShift, date: Date, minDate?: Date, maxDate?: Date, offDaysMap?: Record<number, boolean>): Date;
81
+ /**
82
+ * Если дата была выбрана мышкой — фокусную обводку не видно
83
+ * TODO: добавить в useFocus возможность переключать метод ввода программно
84
+ */
85
+ declare function simulateTab(node: HTMLElement): void;
86
+ declare const formatDate: (date: Date | number, dateFormat?: string) => string;
87
+ declare const parseDateString: (value: string, dateFormat?: string) => Date;
88
+ export { DAYS_IN_WEEK, MONTHS_IN_YEAR, SUNDAY_INDEX, DATE_FORMAT, NATIVE_DATE_FORMAT, WEEKDAYS, MONTHS, russianWeekDay, generateWeeks, generateMonths, generateYears, buildDay, buildMonth, limitDate, dateInLimits, monthName, dateArrayToHashTable, addonArrayToHashTable, getSelectionRange, modifyDateByShift, simulateTab, formatDate, parseDateString };
@@ -0,0 +1,8 @@
1
+ import { PeriodType } from "./index-f034f741";
2
+ declare const formatPeriod: (valueFrom: Date, valueTo: Date, periodType: PeriodType, showCurrentYear?: boolean) => string;
3
+ declare const getYearSelectorValue: (valueFrom: Date | undefined, showCurrentYear: boolean) => number | "";
4
+ declare const shiftValues: (valueFrom: Date, valueTo: Date, periodType: PeriodType, direction: 'prev' | 'next') => {
5
+ valueFrom: Date;
6
+ valueTo: Date;
7
+ };
8
+ export { formatPeriod, getYearSelectorValue, shiftValues };
package/views/index.css CHANGED
@@ -1,4 +1,4 @@
1
- /* hash: hthb6 */
1
+ /* hash: 1gokg */
2
2
  :root {
3
3
  } /* deprecated */ :root { /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */
4
4
  } :root { /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */
@@ -38,16 +38,16 @@
38
38
  /* disabled */
39
39
 
40
40
  /* marker */
41
- } .calendar-range__component_11yhf {
41
+ } .calendar-range__component_hnnqf {
42
42
  display: flex
43
- } .calendar-range__component_11yhf button[aria-selected='true'] {
43
+ } .calendar-range__component_hnnqf button[aria-selected='true'] {
44
44
  cursor: pointer;
45
- } .calendar-range__component_11yhf *[class*='errorIcon_'] {
45
+ } .calendar-range__component_hnnqf *[class*='errorIcon_'] {
46
46
  display: none;
47
- } .calendar-range__component_11yhf *[class*='calendarIcon_'] {
47
+ } .calendar-range__component_hnnqf *[class*='calendarIcon_'] {
48
48
  margin-right: 0;
49
- } .calendar-range__static_11yhf .calendar-range__calendar_11yhf {
49
+ } .calendar-range__static_hnnqf .calendar-range__calendar_hnnqf {
50
50
  width: var(--calendar-inner-width)
51
- } .calendar-range__static_11yhf .calendar-range__calendar_11yhf > div:first-child {
51
+ } .calendar-range__static_hnnqf .calendar-range__calendar_hnnqf > div:first-child {
52
52
  padding: var(--gap-m) 0 var(--gap-s);
53
53
  }