@alfalab/core-components-date-time-input 3.2.0 → 4.0.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 (151) hide show
  1. package/Component-63dec22f.d.ts +167 -0
  2. package/Component-89a3cf4c.d.ts +6 -0
  3. package/Component-8b5756fe.d.ts +380 -0
  4. package/Component.desktop-2e2b2125.d.ts +6 -0
  5. package/Component.desktop-8b5756fe.d.ts +197 -0
  6. package/Component.desktop.d.ts +1 -1
  7. package/Component.desktop.js +4 -3
  8. package/Component.mobile-755fbaa3.d.ts +6 -0
  9. package/Component.mobile-ebda875c.d.ts +6 -0
  10. package/Component.mobile.d.ts +1 -1
  11. package/Component.mobile.js +4 -3
  12. package/Component.responsive-2e2b2125.d.ts +66 -0
  13. package/Component.responsive.d.ts +2 -2
  14. package/Component.responsive.js +5 -2
  15. package/components/date-time-input/Component.d.ts +19 -8
  16. package/components/date-time-input/Component.js +14 -13
  17. package/components/date-time-input/index.css +7 -7
  18. package/components/date-time-input/index.js +1 -2
  19. package/cssm/Component-63dec22f.d.ts +167 -0
  20. package/cssm/Component-89a3cf4c.d.ts +6 -0
  21. package/cssm/Component-8b5756fe.d.ts +380 -0
  22. package/cssm/Component.desktop-2e2b2125.d.ts +6 -0
  23. package/cssm/Component.desktop-8b5756fe.d.ts +197 -0
  24. package/cssm/Component.desktop.d.ts +1 -1
  25. package/cssm/Component.desktop.js +4 -3
  26. package/cssm/Component.mobile-755fbaa3.d.ts +6 -0
  27. package/cssm/Component.mobile-ebda875c.d.ts +6 -0
  28. package/cssm/Component.mobile.d.ts +1 -1
  29. package/cssm/Component.mobile.js +4 -3
  30. package/cssm/Component.responsive-2e2b2125.d.ts +66 -0
  31. package/cssm/Component.responsive.d.ts +2 -2
  32. package/cssm/Component.responsive.js +5 -2
  33. package/cssm/components/date-time-input/Component.d.ts +19 -8
  34. package/cssm/components/date-time-input/Component.js +13 -12
  35. package/cssm/components/date-time-input/index.js +1 -2
  36. package/cssm/desktop-63dec22f.d.ts +2 -0
  37. package/cssm/desktop.js +3 -2
  38. package/cssm/index-89a3cf4c.d.ts +3 -0
  39. package/cssm/index-9211a437.d.ts +2 -0
  40. package/cssm/index-ebda875c.d.ts +35 -0
  41. package/cssm/index-f034f741.d.ts +80 -0
  42. package/cssm/index.d.ts +3 -2
  43. package/cssm/index.js +5 -2
  44. package/cssm/mobile-c219f8ca.d.ts +1 -0
  45. package/cssm/mobile.js +3 -2
  46. package/cssm/types-ebda875c.d.ts +113 -0
  47. package/cssm/typings-5684a67d.d.ts +23 -0
  48. package/cssm/typings-9211a437.d.ts +95 -0
  49. package/cssm/useCalendar-5684a67d.d.ts +97 -0
  50. package/cssm/utils-5684a67d.d.ts +88 -0
  51. package/desktop-63dec22f.d.ts +2 -0
  52. package/desktop.js +3 -2
  53. package/esm/Component-63dec22f.d.ts +167 -0
  54. package/esm/Component-89a3cf4c.d.ts +6 -0
  55. package/esm/Component-8b5756fe.d.ts +380 -0
  56. package/esm/Component.desktop-2e2b2125.d.ts +6 -0
  57. package/esm/Component.desktop-8b5756fe.d.ts +197 -0
  58. package/esm/Component.desktop.d.ts +1 -1
  59. package/esm/Component.desktop.js +4 -3
  60. package/esm/Component.mobile-755fbaa3.d.ts +6 -0
  61. package/esm/Component.mobile-ebda875c.d.ts +6 -0
  62. package/esm/Component.mobile.d.ts +1 -1
  63. package/esm/Component.mobile.js +4 -3
  64. package/esm/Component.responsive-2e2b2125.d.ts +66 -0
  65. package/esm/Component.responsive.d.ts +2 -2
  66. package/esm/Component.responsive.js +5 -2
  67. package/esm/components/date-time-input/Component.d.ts +19 -8
  68. package/esm/components/date-time-input/Component.js +13 -12
  69. package/esm/components/date-time-input/index.css +7 -7
  70. package/esm/components/date-time-input/index.js +1 -2
  71. package/esm/desktop-63dec22f.d.ts +2 -0
  72. package/esm/desktop.js +3 -2
  73. package/esm/index-89a3cf4c.d.ts +3 -0
  74. package/esm/index-9211a437.d.ts +2 -0
  75. package/esm/index-ebda875c.d.ts +35 -0
  76. package/esm/index-f034f741.d.ts +80 -0
  77. package/esm/index.d.ts +3 -2
  78. package/esm/index.js +5 -2
  79. package/esm/mobile-c219f8ca.d.ts +1 -0
  80. package/esm/mobile.js +3 -2
  81. package/esm/types-ebda875c.d.ts +113 -0
  82. package/esm/typings-5684a67d.d.ts +23 -0
  83. package/esm/typings-9211a437.d.ts +95 -0
  84. package/esm/useCalendar-5684a67d.d.ts +97 -0
  85. package/esm/utils-5684a67d.d.ts +88 -0
  86. package/index-89a3cf4c.d.ts +3 -0
  87. package/index-9211a437.d.ts +2 -0
  88. package/index-ebda875c.d.ts +35 -0
  89. package/index-f034f741.d.ts +80 -0
  90. package/index.d.ts +3 -2
  91. package/index.js +5 -2
  92. package/mobile-c219f8ca.d.ts +1 -0
  93. package/mobile.js +3 -2
  94. package/modern/Component-63dec22f.d.ts +167 -0
  95. package/modern/Component-89a3cf4c.d.ts +6 -0
  96. package/modern/Component-8b5756fe.d.ts +380 -0
  97. package/modern/Component.desktop-2e2b2125.d.ts +6 -0
  98. package/modern/Component.desktop-8b5756fe.d.ts +197 -0
  99. package/modern/Component.desktop.d.ts +1 -1
  100. package/modern/Component.desktop.js +4 -3
  101. package/modern/Component.mobile-755fbaa3.d.ts +6 -0
  102. package/modern/Component.mobile-ebda875c.d.ts +6 -0
  103. package/modern/Component.mobile.d.ts +1 -1
  104. package/modern/Component.mobile.js +4 -3
  105. package/modern/Component.responsive-2e2b2125.d.ts +66 -0
  106. package/modern/Component.responsive.d.ts +2 -2
  107. package/modern/Component.responsive.js +5 -2
  108. package/modern/components/date-time-input/Component.d.ts +19 -8
  109. package/modern/components/date-time-input/Component.js +7 -8
  110. package/modern/components/date-time-input/index.css +7 -7
  111. package/modern/components/date-time-input/index.js +1 -2
  112. package/modern/desktop-63dec22f.d.ts +2 -0
  113. package/modern/desktop.js +3 -2
  114. package/modern/index-89a3cf4c.d.ts +3 -0
  115. package/modern/index-9211a437.d.ts +2 -0
  116. package/modern/index-ebda875c.d.ts +35 -0
  117. package/modern/index-f034f741.d.ts +80 -0
  118. package/modern/index.d.ts +3 -2
  119. package/modern/index.js +5 -2
  120. package/modern/mobile-c219f8ca.d.ts +1 -0
  121. package/modern/mobile.js +3 -2
  122. package/modern/types-ebda875c.d.ts +113 -0
  123. package/modern/typings-5684a67d.d.ts +23 -0
  124. package/modern/typings-9211a437.d.ts +95 -0
  125. package/modern/useCalendar-5684a67d.d.ts +97 -0
  126. package/modern/utils-5684a67d.d.ts +88 -0
  127. package/package.json +25 -5
  128. package/src/Component.desktop.tsx +21 -0
  129. package/src/Component.mobile.tsx +22 -0
  130. package/src/Component.responsive.tsx +37 -0
  131. package/src/components/date-time-input/Component.tsx +423 -0
  132. package/src/components/date-time-input/index.module.css +37 -0
  133. package/src/components/date-time-input/index.ts +1 -0
  134. package/src/desktop.ts +1 -0
  135. package/src/index.ts +2 -0
  136. package/src/mobile.ts +1 -0
  137. package/src/utils/format.ts +165 -0
  138. package/src/utils/index.ts +1 -0
  139. package/types-ebda875c.d.ts +113 -0
  140. package/typings-5684a67d.d.ts +23 -0
  141. package/typings-9211a437.d.ts +95 -0
  142. package/useCalendar-5684a67d.d.ts +97 -0
  143. package/utils-5684a67d.d.ts +88 -0
  144. package/cssm/responsive.d.ts +0 -2
  145. package/cssm/responsive.js +0 -26
  146. package/esm/responsive.d.ts +0 -2
  147. package/esm/responsive.js +0 -17
  148. package/modern/responsive.d.ts +0 -2
  149. package/modern/responsive.js +0 -16
  150. package/responsive.d.ts +0 -2
  151. package/responsive.js +0 -25
@@ -0,0 +1,423 @@
1
+ /* eslint-disable no-useless-escape, jsx-a11y/click-events-have-key-events */
2
+
3
+ import React, {
4
+ ChangeEvent,
5
+ ElementType,
6
+ FocusEvent,
7
+ KeyboardEvent,
8
+ MouseEvent,
9
+ useEffect,
10
+ useRef,
11
+ useState,
12
+ } from 'react';
13
+ import mergeRefs from 'react-merge-refs';
14
+ import cn from 'classnames';
15
+
16
+ import type { CalendarDesktopProps } from '@alfalab/core-components-calendar/desktop';
17
+ import type { CalendarMobileProps } from '@alfalab/core-components-calendar/mobile';
18
+ import { dateInLimits } from '@alfalab/core-components-calendar/shared';
19
+ import { IconButton } from '@alfalab/core-components-icon-button';
20
+ import { InputProps } from '@alfalab/core-components-input';
21
+ import { Popover, PopoverProps } from '@alfalab/core-components-popover';
22
+ import { useDidUpdateEffect } from '@alfalab/hooks';
23
+ import { CalendarMIcon } from '@alfalab/icons-glyph/CalendarMIcon';
24
+
25
+ import {
26
+ addTimeToDate,
27
+ DATE_WITH_TIME_LENGTH,
28
+ format,
29
+ getDateWithoutTime,
30
+ getFullDateTime,
31
+ isCompleteDateInput,
32
+ isValid,
33
+ parseTimestampToDate,
34
+ } from '../../utils';
35
+
36
+ import styles from './index.module.css';
37
+
38
+ export type DateTimeInputProps = Omit<InputProps, 'onChange'> & {
39
+ /**
40
+ * Дополнительный класс
41
+ */
42
+ className?: string;
43
+
44
+ /**
45
+ * Дополнительный класс для инпута
46
+ */
47
+ inputClassName?: string;
48
+
49
+ /**
50
+ * Дополнительный класс для поповера
51
+ */
52
+ popoverClassName?: string;
53
+
54
+ /**
55
+ * Обработчик изменения значения
56
+ */
57
+ picker?: boolean;
58
+
59
+ /**
60
+ * Обработчик изменения значения
61
+ */
62
+ onChange?: (
63
+ event: ChangeEvent<HTMLInputElement> | null,
64
+ payload: { date: Date; value: string },
65
+ ) => void;
66
+
67
+ /**
68
+ * Обработчик окончания ввода
69
+ */
70
+ onComplete?: (
71
+ event: ChangeEvent<HTMLInputElement> | null,
72
+ payload: { date: Date; value: string },
73
+ ) => void;
74
+
75
+ /**
76
+ * Компонент календаря
77
+ */
78
+ Calendar?: ElementType;
79
+
80
+ /**
81
+ * Доп. пропсы для календаря
82
+ */
83
+ calendarProps?:
84
+ | (CalendarDesktopProps & Record<string, unknown>)
85
+ | (CalendarMobileProps & Record<string, unknown>);
86
+
87
+ /**
88
+ * Месяц в календаре по умолчанию (timestamp)
89
+ */
90
+ defaultMonth?: number;
91
+
92
+ /**
93
+ * Минимальная дата, доступная для выбора (timestamp)
94
+ */
95
+ minDate?: number;
96
+
97
+ /**
98
+ * Максимальная дата, доступная для выбора (timestamp)
99
+ */
100
+ maxDate?: number;
101
+
102
+ /**
103
+ * Список событий
104
+ */
105
+ events?: Array<Date | number>;
106
+
107
+ /**
108
+ * Список выходных
109
+ */
110
+ offDays?: Array<Date | number>;
111
+
112
+ /**
113
+ * Состояние открытия по умолчанию
114
+ */
115
+ defaultOpen?: boolean;
116
+
117
+ /**
118
+ * Позиционирование поповера с календарем
119
+ */
120
+ popoverPosition?: PopoverProps['position'];
121
+
122
+ /**
123
+ * z-index Popover
124
+ */
125
+ zIndexPopover?: PopoverProps['zIndex'];
126
+
127
+ /**
128
+ * Запрещает поповеру менять свою позицию.
129
+ * Например, если места снизу недостаточно,то он все равно будет показан снизу
130
+ */
131
+ preventFlip?: boolean;
132
+
133
+ /**
134
+ * Календарь будет принимать ширину инпута
135
+ */
136
+ useAnchorWidth?: boolean;
137
+
138
+ /**
139
+ * Растягивает компонент на ширину контейнера
140
+ */
141
+ block?: boolean;
142
+
143
+ /**
144
+ * Отображение компонента в мобильном или десктопном виде
145
+ */
146
+ view?: 'desktop' | 'mobile';
147
+
148
+ /**
149
+ * Компонент инпута
150
+ */
151
+ InputComponent?: ElementType;
152
+
153
+ /**
154
+ * Запретить ввод с клавиатуры
155
+ */
156
+ disableUserInput?: boolean;
157
+ };
158
+
159
+ export const DateTimeInput = React.forwardRef<HTMLInputElement, DateTimeInputProps>(
160
+ (
161
+ {
162
+ className,
163
+ inputClassName,
164
+ popoverClassName,
165
+ disabled,
166
+ readOnly,
167
+ disableUserInput = false,
168
+ picker,
169
+ defaultValue = '',
170
+ value: propValue,
171
+ onChange,
172
+ onComplete,
173
+ rightAddons,
174
+ useAnchorWidth,
175
+ block,
176
+ popoverPosition = 'bottom-start',
177
+ zIndexPopover,
178
+ preventFlip,
179
+ InputComponent,
180
+ Calendar,
181
+ calendarProps = {},
182
+ defaultMonth,
183
+ minDate = calendarProps.minDate,
184
+ maxDate = calendarProps.maxDate,
185
+ offDays = calendarProps.offDays || [],
186
+ events = calendarProps.events || [],
187
+ defaultOpen = false,
188
+ error,
189
+ view = 'desktop',
190
+ ...restProps
191
+ },
192
+ ref,
193
+ ) => {
194
+ const inputRef = useRef<HTMLInputElement>(null);
195
+ const calendarRef = useRef<HTMLDivElement>(null);
196
+
197
+ const [value, setValue] = useState(propValue || defaultValue);
198
+ const [open, setOpen] = useState(false);
199
+
200
+ const calendarValue = value ? getDateWithoutTime(value).getTime() : undefined;
201
+
202
+ const inputDisabled = disabled || readOnly;
203
+
204
+ const calendarResponsive = calendarProps?.responsive ?? true;
205
+
206
+ useEffect(() => {
207
+ setOpen(defaultOpen);
208
+ }, [defaultOpen]);
209
+
210
+ useDidUpdateEffect(() => {
211
+ const newPropValue = propValue || '';
212
+
213
+ setValue((prevValue) => (prevValue === propValue ? prevValue : newPropValue));
214
+ }, [propValue]);
215
+
216
+ const checkInputValueIsValid = (newInputValue?: string) => {
217
+ if (!newInputValue || error) return false;
218
+
219
+ const dateValue = getDateWithoutTime(newInputValue).getTime();
220
+
221
+ return (
222
+ dateValue &&
223
+ dateInLimits(dateValue, minDate, maxDate) &&
224
+ !offDays.includes(dateValue)
225
+ );
226
+ };
227
+
228
+ const setTimeToDate = () => {
229
+ setValue((prevValue) => {
230
+ const dateWithTime = addTimeToDate(prevValue);
231
+
232
+ if (dateWithTime !== prevValue && dateWithTime.length === DATE_WITH_TIME_LENGTH) {
233
+ onComplete?.(null, {
234
+ date: getFullDateTime(dateWithTime),
235
+ value: dateWithTime,
236
+ });
237
+ }
238
+
239
+ return dateWithTime;
240
+ });
241
+ };
242
+
243
+ const handleInputWrapperFocus = (event: FocusEvent<HTMLDivElement>) => {
244
+ if (view === 'desktop') {
245
+ if (picker) {
246
+ setOpen(true);
247
+ }
248
+ if (!open && event.target.tagName !== 'INPUT' && calendarRef.current) {
249
+ calendarRef.current.focus();
250
+ }
251
+ }
252
+ };
253
+
254
+ const handleBlur = (event: FocusEvent<HTMLDivElement>) => {
255
+ if (view === 'desktop') {
256
+ const target = (event.relatedTarget || document.activeElement) as HTMLElement;
257
+
258
+ if (calendarRef.current && calendarRef.current.contains(target) === false) {
259
+ setOpen(false);
260
+ setTimeToDate();
261
+ }
262
+ }
263
+ };
264
+
265
+ const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
266
+ const { value: newValue } = event.target;
267
+
268
+ if (newValue.length > DATE_WITH_TIME_LENGTH) return;
269
+
270
+ // Позволяем вводить только цифры, точки, запятую, двоеточие и пробел
271
+ if (/[^\d., :]/.test(newValue)) {
272
+ return;
273
+ }
274
+
275
+ const dots = newValue.match(/\./g);
276
+ const colon = newValue.match(/:/g);
277
+ const comma = newValue.match(/,/g);
278
+
279
+ // Не даем вводить больше, чем 2 точки, 1 двоеточие и 1 запятую
280
+ if (
281
+ (dots && dots.length > 2) ||
282
+ (colon && colon.length > 1) ||
283
+ (comma && comma.length > 1)
284
+ ) {
285
+ return;
286
+ }
287
+
288
+ const formattedValue = format(newValue);
289
+ const date = getFullDateTime(formattedValue);
290
+
291
+ setValue(formattedValue);
292
+
293
+ if (onChange) onChange(event, { date, value: formattedValue });
294
+
295
+ if (isCompleteDateInput(formattedValue)) {
296
+ const valid = isValid(formattedValue);
297
+
298
+ if (!valid) return;
299
+
300
+ if (onComplete) {
301
+ onComplete(event, { date, value: formattedValue });
302
+ }
303
+ }
304
+ };
305
+
306
+ const handleMobileCalendarClose = () => {
307
+ setOpen(false);
308
+ setTimeToDate();
309
+ };
310
+
311
+ const handleClear = () => {
312
+ setValue('');
313
+ };
314
+
315
+ const handleInputKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
316
+ const isCopy = (event.metaKey || event.ctrlKey) && event.key === 'c';
317
+
318
+ if (disableUserInput && !isCopy) {
319
+ event.preventDefault();
320
+ }
321
+ };
322
+
323
+ const handleCalendarChange = (date?: number) => {
324
+ if (date) {
325
+ const newValue = parseTimestampToDate(date);
326
+
327
+ setValue(newValue);
328
+ onChange?.(null, { date: getFullDateTime(newValue), value: newValue });
329
+ }
330
+ };
331
+
332
+ const handleCalendarWrapperMouseDown = (event: MouseEvent<HTMLDivElement>) => {
333
+ // Не дает инпуту терять фокус при выборе даты
334
+ event.preventDefault();
335
+ };
336
+
337
+ const handleIconButtonClick = () => {
338
+ if (!open) setOpen(true);
339
+
340
+ if (view === 'desktop' && inputRef.current) {
341
+ inputRef.current.focus();
342
+ }
343
+ };
344
+
345
+ const renderCalendar = () =>
346
+ Calendar ? (
347
+ // eslint-disable-next-line jsx-a11y/no-static-element-interactions
348
+ <div onMouseDown={handleCalendarWrapperMouseDown}>
349
+ <Calendar
350
+ {...calendarProps}
351
+ responsive={calendarResponsive}
352
+ open={open}
353
+ onClose={handleMobileCalendarClose}
354
+ ref={calendarRef}
355
+ defaultMonth={defaultMonth}
356
+ value={checkInputValueIsValid(value) ? calendarValue : undefined}
357
+ onChange={handleCalendarChange}
358
+ minDate={minDate}
359
+ maxDate={maxDate}
360
+ offDays={offDays}
361
+ events={events}
362
+ />
363
+ </div>
364
+ ) : null;
365
+
366
+ return (
367
+ <div
368
+ className={cn(styles.component, className, {
369
+ [styles.block]: block,
370
+ })}
371
+ onFocus={inputDisabled ? undefined : handleInputWrapperFocus}
372
+ onBlur={handleBlur}
373
+ >
374
+ {InputComponent ? (
375
+ <InputComponent
376
+ {...restProps}
377
+ block={block}
378
+ ref={mergeRefs([ref, inputRef])}
379
+ value={value}
380
+ onChange={handleChange}
381
+ disabled={disabled}
382
+ readOnly={readOnly}
383
+ className={inputClassName}
384
+ onClear={handleClear}
385
+ onKeyDown={handleInputKeyDown}
386
+ error={error}
387
+ rightAddons={
388
+ <React.Fragment>
389
+ {rightAddons}
390
+ {picker && (
391
+ <IconButton
392
+ className={styles.calendarIcon}
393
+ onClick={inputDisabled ? undefined : handleIconButtonClick}
394
+ icon={CalendarMIcon}
395
+ size='s'
396
+ />
397
+ )}
398
+ </React.Fragment>
399
+ }
400
+ />
401
+ ) : null}
402
+ {picker && (
403
+ <Popover
404
+ open={open}
405
+ useAnchorWidth={useAnchorWidth}
406
+ anchorElement={inputRef.current as HTMLElement}
407
+ popperClassName={cn(styles.calendarContainer, {
408
+ [styles.calendarResponsive]: calendarResponsive,
409
+ })}
410
+ className={popoverClassName}
411
+ position={popoverPosition}
412
+ offset={[0, 8]}
413
+ withTransition={false}
414
+ preventFlip={preventFlip}
415
+ zIndex={zIndexPopover}
416
+ >
417
+ {renderCalendar()}
418
+ </Popover>
419
+ )}
420
+ </div>
421
+ );
422
+ },
423
+ );
@@ -0,0 +1,37 @@
1
+ @import '@alfalab/core-components-themes/src/default.css';
2
+ @import '@alfalab/core-components-calendar/src/vars.css';
3
+
4
+ :root {
5
+ --calendar-popover-border-radius: var(--border-radius-m);
6
+ }
7
+
8
+ .component {
9
+ display: inline-block;
10
+ outline: none;
11
+ position: relative;
12
+ }
13
+
14
+ .calendarContainer {
15
+ display: inline-block;
16
+ box-sizing: border-box;
17
+ border-radius: var(--calendar-popover-border-radius);
18
+ border: 1px solid var(--color-light-border-secondary);
19
+
20
+ @media (max-width: 374px) {
21
+ width: 100%;
22
+ min-width: 288px;
23
+ }
24
+ }
25
+
26
+ .calendarResponsive {
27
+ width: var(--calendar-width);
28
+ }
29
+
30
+ .block {
31
+ width: 100%;
32
+ }
33
+
34
+ .calendarIcon {
35
+ margin-right: var(--gap-s-neg);
36
+ height: 100%;
37
+ }
@@ -0,0 +1 @@
1
+ export * from './Component';
package/src/desktop.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './Component.desktop';
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { DateTimeInputResponsive as DateTimeInput } from './Component.responsive';
2
+ export type { DateTimeInputResponsiveProps as DateTimeInputProps } from './Component.responsive';
package/src/mobile.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './Component.mobile';
@@ -0,0 +1,165 @@
1
+ /* eslint-disable no-useless-escape */
2
+
3
+ import dateFnsIsValid from 'date-fns/isValid';
4
+ import parse from 'date-fns/parse';
5
+
6
+ export const DATE_FORMAT = 'dd.MM.yyyy';
7
+ export const DATE_MASK = [
8
+ /\d/,
9
+ /\d/,
10
+ '.',
11
+ /\d/,
12
+ /\d/,
13
+ '.',
14
+ /\d/,
15
+ /\d/,
16
+ /\d/,
17
+ /\d/,
18
+ ',',
19
+ ' ',
20
+ /\d/,
21
+ /\d/,
22
+ ':',
23
+ /\d/,
24
+ /\d/,
25
+ ];
26
+
27
+ export const DATE_WITH_TIME_LENGTH = DATE_MASK.length;
28
+ export const isCompleteDateInput = (input: string) => input.length === DATE_WITH_TIME_LENGTH;
29
+ export const parseDateString = (value: string, dateFormat = DATE_FORMAT) =>
30
+ parse(value, dateFormat, new Date());
31
+ export const isValidTimeFormat = (value: string): boolean => {
32
+ const timeArr = value.split(':');
33
+ const hours = timeArr[0];
34
+ const mins = timeArr[1];
35
+
36
+ if (hours.length !== 2 || Number(hours) > 23) {
37
+ return false;
38
+ }
39
+
40
+ if (mins.length !== 2 || Number(mins) > 59) {
41
+ return false;
42
+ }
43
+
44
+ return true;
45
+ };
46
+
47
+ export const isValid = (inputValue: string) => {
48
+ const inputValueArr = inputValue.split(', ');
49
+ const date = inputValueArr[0];
50
+ const time = inputValueArr[1];
51
+
52
+ return (
53
+ !inputValue ||
54
+ (isCompleteDateInput(inputValue) &&
55
+ dateFnsIsValid(parseDateString(date)) &&
56
+ isValidTimeFormat(time))
57
+ );
58
+ };
59
+
60
+ export const format = (value: string): string =>
61
+ value
62
+ .replace(/^(\d\d)(\d)$/, '$1.$2') // 121 => 12.1
63
+ .replace(/^(\d\d)\.(\d\d)(\d)$/, '$1.$2.$3') // 12.122 => 12.12.2
64
+ .replace(/^(\d\d)\d\.(.*)/, '$1.$2') // 123.12.2005 => 12.12.2005
65
+ .replace(/^(\d\d\.\d\d)\d\.(.*)/, '$1.$2') // 12.123.2005 => 12.12.2005
66
+ .replace(/\.$/, '') // 12. => 12
67
+ .replace(/\ $/, '') // 1 2 => 12
68
+ .replace(/\:$/, '') // 1:2 => 12
69
+ .replace(/^(\d\d)(\d.*)/, '$1.$2') // 1212 => 12.12
70
+ .replace(/^(\d\d.\d\d)(\d.*)/, '$1.$2') // 12.122 => 12.12.2
71
+ .replace(/^(\d\d\.\d\d)(\d\d\d\d)/, '$1.$2') // 12.122005 => 12.12.2005
72
+ .replace(/^(\d\d)(\d\d\.\d\d\d\d)/, '$1.$2') // 1212.2005 => 12.12.2005
73
+ .replace(/^(\d\d.\d\d\.\d\d\d\d),/, '$1') // 12.12.2005 => 12.12.2005
74
+ .replace(/^(\d\d.\d\d\.\d\d\d\d)(\d)/, '$1, $2') // 12.12.20050 => 12.12.2005, 0
75
+ .replace(/^(\d\d.\d\d\.\d\d\d\d),(\d.*)/, '$1, $2') // 12.12.2005,00:00 => 12.12.2005, 00:00
76
+ .replace(/^(\d\d.\d\d\.\d\d\d\d) (\d.*)/, '$1, $2') // 12.12.2005 00:00 => 12.12.2005, 00:00
77
+ .replace(/^(\d\d.\d\d\.\d\d\d\d)(\d.*)/, '$1, $2') // 12.12.200500:00=> 12.12.2005, 00:00
78
+ .replace(/^(\d\d.\d\d\.\d\d\d\d), (\d\d):/, '$1, $2') // 12.12.2005, 00: => 12.12.2005, 00
79
+ .replace(/^(\d\d.\d\d\.\d\d\d\d), (\d\d)(\d)/, '$1, $2:$3') // 12.12.2005, 000 => 12.12.2005, 00:0
80
+ .replace(/^(\d\.\d\d\.\d\d\d\d)([0-9]*)/, '$1') // 1.12.2005123123 => 1.12.2005
81
+ .replace(/^(\d\d\.\d\.\d\d\d\d)([0-9]*)/, '$1') // 01.2.20055125125 => 01.2.2005
82
+ .replace(/^(\d)\.(\d\d)([0-9]*)\.(\d\d\d\d)/, '$1.$2.$4') // 1.123123.2005 => 1.12.2005
83
+ .replace(/^(\d\.\d\.\d\d\d\d)([0-9]*)/, '$1') // 1.2.20055125125 => 1.2.2005
84
+ .replace(/^(\d\d)\.()\.(\d\d\d\d)([0-9]*)/, '$1.$2.$3') // 01..2005123123 => 01..2005
85
+ .replace(/^(\d)\.()\.(\d\d\d\d)([0-9]*)/, '$1.$2.$3') // 1..2005123123 => 1..2005
86
+ .replace(/^()\.()\.(\d\d\d\d)([0-9]*)/, '$1.$2.$3') // ..2005123123 => ..2005
87
+ .replace(/^()\.(\d)\.(\d\d\d\d)([0-9]*)/, '$1.$2.$3'); // .2.2005123123 => .2.2005
88
+
89
+ export const parseTimestampToDate = (timestamp: number): string => {
90
+ const date = new Date(timestamp);
91
+ const year = date.getFullYear();
92
+
93
+ let month: number | string = date.getMonth() + 1;
94
+ let day: number | string = date.getDate();
95
+
96
+ if (month < 10) {
97
+ month = `0${month}`;
98
+ }
99
+ if (day < 10) {
100
+ day = `0${day}`;
101
+ }
102
+
103
+ return `${day}.${month}.${year}`;
104
+ };
105
+
106
+ export const getDateWithoutTime = (value: string): Date => {
107
+ const valueArr = value.split(', ');
108
+
109
+ let day;
110
+ let month;
111
+ let year;
112
+
113
+ if (valueArr[0]) {
114
+ const date = valueArr[0].split('.');
115
+
116
+ [day, month, year] = date;
117
+ }
118
+
119
+ const date = new Date();
120
+
121
+ date.setFullYear(Number(year), Number(month) - 1, Number(day));
122
+ date.setHours(0, 0, 0, 0);
123
+
124
+ return date;
125
+ };
126
+
127
+ export const getFullDateTime = (value: string): Date => {
128
+ const valueArr = value.split(', ');
129
+
130
+ let day;
131
+ let month;
132
+ let year;
133
+ let hours;
134
+ let mins;
135
+
136
+ if (valueArr[0]) {
137
+ const date = valueArr[0].split('.');
138
+
139
+ [day, month, year] = date;
140
+ }
141
+ if (valueArr[1]) {
142
+ const time = valueArr[1].split(':');
143
+
144
+ hours = Number(time[0]);
145
+ mins = Number(time[1]);
146
+ }
147
+
148
+ const fullDate = new Date();
149
+
150
+ fullDate.setFullYear(Number(year), Number(month) - 1, Number(day));
151
+ fullDate.setHours(Number(hours) || 0);
152
+ fullDate.setMinutes(Number(mins) || 0);
153
+ fullDate.setSeconds(0);
154
+ fullDate.setMilliseconds(0);
155
+
156
+ return fullDate;
157
+ };
158
+
159
+ export const addTimeToDate = (value: string): string => {
160
+ if (value.length === 10 && dateFnsIsValid(parseDateString(value))) {
161
+ return `${value}, 00:00`;
162
+ }
163
+
164
+ return value;
165
+ };
@@ -0,0 +1 @@
1
+ export * from './format';