@snack-uikit/fields 0.29.2-preview-eb3592d8.0 → 0.29.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README.md +2 -8
- package/dist/components/FieldDate/FieldDate.d.ts +3 -10
- package/dist/components/FieldDate/FieldDate.js +15 -15
- package/dist/components/FieldDate/constants.d.ts +5 -12
- package/dist/components/FieldDate/constants.js +11 -36
- package/dist/components/FieldDate/hooks/useDateField.d.ts +3 -5
- package/dist/components/FieldDate/hooks/useDateField.js +23 -34
- package/dist/components/FieldDate/hooks/useDateFieldHelpers.js +5 -5
- package/dist/components/FieldDate/types.d.ts +0 -3
- package/dist/components/FieldDate/utils.d.ts +4 -9
- package/dist/components/FieldDate/utils.js +8 -70
- package/package.json +4 -4
- package/src/components/FieldDate/FieldDate.tsx +17 -25
- package/src/components/FieldDate/constants.ts +15 -59
- package/src/components/FieldDate/hooks/useDateField.ts +28 -51
- package/src/components/FieldDate/hooks/useDateFieldHelpers.ts +5 -5
- package/src/components/FieldDate/types.ts +0 -6
- package/src/components/FieldDate/utils.ts +10 -80
- package/dist/components/FieldDate/hooks/useDateTimeFieldHelpers.d.ts +0 -10
- package/dist/components/FieldDate/hooks/useDateTimeFieldHelpers.js +0 -75
- package/src/components/FieldDate/hooks/useDateTimeFieldHelpers.ts +0 -109
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## 0.29.2 (2024-10-14)
|
|
7
|
+
|
|
8
|
+
### Only dependencies have been changed
|
|
9
|
+
* [@snack-uikit/list@0.17.1](https://github.com/cloud-ru-tech/snack-uikit/blob/master/packages/list/CHANGELOG.md)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
6
15
|
## 0.29.1 (2024-10-08)
|
|
7
16
|
|
|
8
17
|
### Only dependencies have been changed
|
package/README.md
CHANGED
|
@@ -161,11 +161,6 @@ const [isOpen, setIsOpen] = useState(false);
|
|
|
161
161
|
enableFuzzySearch={true}
|
|
162
162
|
/>;
|
|
163
163
|
```
|
|
164
|
-
## Особенности работы FieldSlider-a
|
|
165
|
-
|
|
166
|
-
Для корректной работы компонента, свойство `marks` должно быть либо **константой**, либо **мемоизировано**,
|
|
167
|
-
т.к. это на этой свойство завязана логика обновления ui.
|
|
168
|
-
|
|
169
164
|
## Особенности работы FieldStepper-a
|
|
170
165
|
|
|
171
166
|
FieldStepper в основном предназначен для работы с небольшими числами,
|
|
@@ -321,11 +316,10 @@ FieldStepper в основном предназначен для работы с
|
|
|
321
316
|
### Props
|
|
322
317
|
| name | type | default value | description |
|
|
323
318
|
|------|------|---------------|-------------|
|
|
324
|
-
|
|
|
319
|
+
| value* | `string` | - | Значение input |
|
|
325
320
|
| open | `boolean` | - | Открыт date-picker |
|
|
326
321
|
| onOpenChange | `(value: boolean) => void` | - | Колбек открытия пикера |
|
|
327
|
-
|
|
|
328
|
-
| onChange | `(value: Date) => void` | - | Колбек смены значения |
|
|
322
|
+
| onChange | `(value: string) => void` | - | Колбек смены значения |
|
|
329
323
|
| showCopyButton | `boolean` | - | Отображение кнопки копирования |
|
|
330
324
|
| showClearButton | `boolean` | true | Отображение кнопки Очистки поля |
|
|
331
325
|
| locale | `Locale` | new Intl.Locale('ru-RU') | Текущая локаль календаря |
|
|
@@ -2,18 +2,15 @@ import { CalendarProps } from '@snack-uikit/calendar';
|
|
|
2
2
|
import { InputPrivateProps } from '@snack-uikit/input-private';
|
|
3
3
|
import { WithSupportProps } from '@snack-uikit/utils';
|
|
4
4
|
import { FieldDecoratorProps } from '../FieldDecorator';
|
|
5
|
-
|
|
6
|
-
type InputProps = Pick<InputPrivateProps, 'id' | 'name' | 'disabled' | 'readonly' | 'onFocus' | 'onBlur'>;
|
|
5
|
+
type InputProps = Pick<InputPrivateProps, 'id' | 'name' | 'value' | 'disabled' | 'readonly' | 'onFocus' | 'onBlur'>;
|
|
7
6
|
type WrapperProps = Pick<FieldDecoratorProps, 'className' | 'label' | 'labelTooltip' | 'required' | 'caption' | 'hint' | 'showHintIcon' | 'size' | 'validationState' | 'labelTooltipPlacement' | 'error'>;
|
|
8
7
|
type FieldDateOwnProps = {
|
|
9
8
|
/** Открыт date-picker */
|
|
10
9
|
open?: boolean;
|
|
11
10
|
/** Колбек открытия пикера */
|
|
12
11
|
onOpenChange?(value: boolean): void;
|
|
13
|
-
/** Значение поля */
|
|
14
|
-
value?: Date;
|
|
15
12
|
/** Колбек смены значения */
|
|
16
|
-
onChange?(value:
|
|
13
|
+
onChange?(value: string): void;
|
|
17
14
|
/** Отображение кнопки копирования */
|
|
18
15
|
showCopyButton?: boolean;
|
|
19
16
|
/**
|
|
@@ -23,7 +20,6 @@ type FieldDateOwnProps = {
|
|
|
23
20
|
showClearButton?: boolean;
|
|
24
21
|
/** Текущая локаль календаря */
|
|
25
22
|
locale?: Intl.Locale;
|
|
26
|
-
mode: Mode;
|
|
27
23
|
} & Pick<CalendarProps, 'buildCellProps'>;
|
|
28
24
|
export type FieldDateProps = WithSupportProps<FieldDateOwnProps & InputProps & WrapperProps>;
|
|
29
25
|
export declare const FieldDate: import("react").ForwardRefExoticComponent<{
|
|
@@ -33,10 +29,8 @@ export declare const FieldDate: import("react").ForwardRefExoticComponent<{
|
|
|
33
29
|
open?: boolean;
|
|
34
30
|
/** Колбек открытия пикера */
|
|
35
31
|
onOpenChange?(value: boolean): void;
|
|
36
|
-
/** Значение поля */
|
|
37
|
-
value?: Date;
|
|
38
32
|
/** Колбек смены значения */
|
|
39
|
-
onChange?(value:
|
|
33
|
+
onChange?(value: string): void;
|
|
40
34
|
/** Отображение кнопки копирования */
|
|
41
35
|
showCopyButton?: boolean;
|
|
42
36
|
/**
|
|
@@ -46,6 +40,5 @@ export declare const FieldDate: import("react").ForwardRefExoticComponent<{
|
|
|
46
40
|
showClearButton?: boolean;
|
|
47
41
|
/** Текущая локаль календаря */
|
|
48
42
|
locale?: Intl.Locale;
|
|
49
|
-
mode: Mode;
|
|
50
43
|
} & Pick<CalendarProps, "buildCellProps"> & InputProps & WrapperProps & import("react").RefAttributes<HTMLInputElement>>;
|
|
51
44
|
export {};
|
|
@@ -28,14 +28,14 @@ import { useDateField } from './hooks';
|
|
|
28
28
|
import { useFocusHandlers } from './hooks/useFocusHandlers';
|
|
29
29
|
import { useHandlers } from './hooks/useHandlers';
|
|
30
30
|
import styles from './styles.module.css';
|
|
31
|
+
import { parseDate } from './utils';
|
|
31
32
|
const CALENDAR_SIZE_MAP = {
|
|
32
33
|
[SIZE.S]: 's',
|
|
33
34
|
[SIZE.M]: 'm',
|
|
34
|
-
[SIZE.L]: '
|
|
35
|
+
[SIZE.L]: 'm',
|
|
35
36
|
};
|
|
36
37
|
export const FieldDate = forwardRef((_a, ref) => {
|
|
37
|
-
var
|
|
38
|
-
var { id, name, value: valueProp, disabled = false, readonly = false, showCopyButton: showCopyButtonProp = true, showClearButton: showClearButtonProp = true, open, onOpenChange, onChange, onFocus, onBlur: onBlurProp, className, label, labelTooltip, labelTooltipPlacement, required = false, caption, hint, showHintIcon, size = SIZE.S, validationState = VALIDATION_STATE.Default, locale = DEFAULT_LOCALE, buildCellProps, error, mode } = _a, rest = __rest(_a, ["id", "name", "value", "disabled", "readonly", "showCopyButton", "showClearButton", "open", "onOpenChange", "onChange", "onFocus", "onBlur", "className", "label", "labelTooltip", "labelTooltipPlacement", "required", "caption", "hint", "showHintIcon", "size", "validationState", "locale", "buildCellProps", "error", "mode"]);
|
|
38
|
+
var { id, name, value: valueProp, disabled = false, readonly = false, showCopyButton: showCopyButtonProp = true, showClearButton: showClearButtonProp = true, open, onOpenChange, onChange, onFocus, onBlur: onBlurProp, className, label, labelTooltip, labelTooltipPlacement, required = false, caption, hint, showHintIcon, size = SIZE.S, validationState = VALIDATION_STATE.Default, locale = DEFAULT_LOCALE, buildCellProps, error } = _a, rest = __rest(_a, ["id", "name", "value", "disabled", "readonly", "showCopyButton", "showClearButton", "open", "onOpenChange", "onChange", "onFocus", "onBlur", "className", "label", "labelTooltip", "labelTooltipPlacement", "required", "caption", "hint", "showHintIcon", "size", "validationState", "locale", "buildCellProps", "error"]);
|
|
39
39
|
const [isOpen, setIsOpen] = useUncontrolledProp(open, false, onOpenChange);
|
|
40
40
|
const [pickerAutofocus, setPickerAutofocus] = useState(false);
|
|
41
41
|
const localRef = useRef(null);
|
|
@@ -55,7 +55,7 @@ export const FieldDate = forwardRef((_a, ref) => {
|
|
|
55
55
|
}, [setIsOpen]);
|
|
56
56
|
const handleClear = useCallback(() => {
|
|
57
57
|
var _a, _b, _c;
|
|
58
|
-
onChange && onChange(
|
|
58
|
+
onChange && onChange('');
|
|
59
59
|
if ((_a = localRef.current) === null || _a === void 0 ? void 0 : _a.value) {
|
|
60
60
|
localRef.current.value = '';
|
|
61
61
|
}
|
|
@@ -68,9 +68,8 @@ export const FieldDate = forwardRef((_a, ref) => {
|
|
|
68
68
|
setIsOpen(false);
|
|
69
69
|
}
|
|
70
70
|
}, [onChange, required, setIsOpen]);
|
|
71
|
-
const valueToCopy = (_b = (mode === 'date' ? valueProp === null || valueProp === void 0 ? void 0 : valueProp.toLocaleDateString() : valueProp === null || valueProp === void 0 ? void 0 : valueProp.toLocaleString())) !== null && _b !== void 0 ? _b : '';
|
|
72
71
|
const clearButtonSettings = useClearButton({ clearButtonRef, showClearButton, size, onClear: handleClear });
|
|
73
|
-
const copyButtonSettings = useCopyButton({ copyButtonRef, showCopyButton, size, valueToCopy });
|
|
72
|
+
const copyButtonSettings = useCopyButton({ copyButtonRef, showCopyButton, size, valueToCopy: valueProp || '' });
|
|
74
73
|
const calendarIcon = useMemo(() => ({
|
|
75
74
|
active: false,
|
|
76
75
|
show: true,
|
|
@@ -84,9 +83,8 @@ export const FieldDate = forwardRef((_a, ref) => {
|
|
|
84
83
|
readonly,
|
|
85
84
|
locale,
|
|
86
85
|
setIsOpen,
|
|
87
|
-
mode,
|
|
88
86
|
});
|
|
89
|
-
const setInputFocusFromButtons = useCallback(() => setInputFocus(
|
|
87
|
+
const setInputFocusFromButtons = useCallback(() => setInputFocus(SlotKey.Year), [setInputFocus]);
|
|
90
88
|
const { postfixButtons, inputTabIndex, onInputKeyDown: navigationInputKeyDownHandler, setInitialTabIndices, } = useButtonNavigation({
|
|
91
89
|
setInputFocus: setInputFocusFromButtons,
|
|
92
90
|
inputRef: localRef,
|
|
@@ -95,15 +93,12 @@ export const FieldDate = forwardRef((_a, ref) => {
|
|
|
95
93
|
readonly,
|
|
96
94
|
submitKeys: ['Enter', 'Space', 'Tab'],
|
|
97
95
|
});
|
|
96
|
+
// TODO: do not hardcode locale here
|
|
98
97
|
const handleSelectDate = (date) => {
|
|
99
98
|
var _a;
|
|
100
|
-
onChange && onChange(date);
|
|
99
|
+
onChange && onChange(date.toLocaleDateString(DEFAULT_LOCALE));
|
|
101
100
|
(_a = localRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
102
101
|
setIsOpen(false);
|
|
103
|
-
if (localRef.current) {
|
|
104
|
-
localRef.current.value =
|
|
105
|
-
mode === 'date' ? date.toLocaleDateString(DEFAULT_LOCALE) : date.toLocaleString(DEFAULT_LOCALE);
|
|
106
|
-
}
|
|
107
102
|
};
|
|
108
103
|
const handleCalendarFocusLeave = () => {
|
|
109
104
|
setInitialTabIndices();
|
|
@@ -125,6 +120,11 @@ export const FieldDate = forwardRef((_a, ref) => {
|
|
|
125
120
|
(_a = localRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
126
121
|
}
|
|
127
122
|
}, [open]);
|
|
123
|
+
useEffect(() => {
|
|
124
|
+
if (localRef.current) {
|
|
125
|
+
localRef.current.value = valueProp;
|
|
126
|
+
}
|
|
127
|
+
}, [valueProp]);
|
|
128
128
|
const onFocusByKeyboard = useCallback((e) => {
|
|
129
129
|
setInputFocus();
|
|
130
130
|
onFocus === null || onFocus === void 0 ? void 0 : onFocus(e);
|
|
@@ -146,10 +146,10 @@ export const FieldDate = forwardRef((_a, ref) => {
|
|
|
146
146
|
: {
|
|
147
147
|
open: showDropList,
|
|
148
148
|
onOpenChange: setIsOpen,
|
|
149
|
-
}), { content: _jsx("div", { className: styles.calendarWrapper, "data-size": size, children: _jsx(Calendar, { mode:
|
|
149
|
+
}), { content: _jsx("div", { className: styles.calendarWrapper, "data-size": size, children: _jsx(Calendar, { mode: 'date', size: CALENDAR_SIZE_MAP[size], value: valueProp ? parseDate(valueProp) : undefined, onChangeValue: handleSelectDate, buildCellProps: buildCellProps, navigationStartRef: element => {
|
|
150
150
|
if (pickerAutofocus) {
|
|
151
151
|
element === null || element === void 0 ? void 0 : element.focus();
|
|
152
152
|
setPickerAutofocus(false);
|
|
153
153
|
}
|
|
154
|
-
}, onFocusLeave: handleCalendarFocusLeave, locale: locale, "data-test-id": 'field-date__calendar'
|
|
154
|
+
}, onFocusLeave: handleCalendarFocusLeave, locale: locale, "data-test-id": 'field-date__calendar' }) }), children: _jsx(FieldContainerPrivate, { className: styles.container, size: size, validationState: fieldValidationState, disabled: disabled, readonly: readonly, variant: CONTAINER_VARIANT.SingleLine, focused: showDropList, inputRef: localRef, postfix: postfixButtons, children: _jsx(InputPrivate, { ref: mergeRefs(ref, localRef), "data-size": size, value: value || '', placeholder: mask, onChange: handleChange, onFocus: inputHandlers.onFocus, onMouseDown: inputHandlers.onMouseDown, onBlur: onBlur, onKeyDown: handleInputKeyDown, onClick: onClick, disabled: disabled, readonly: readonly, tabIndex: inputTabIndex, type: 'text', id: id, name: name, "data-test-id": 'field-date__input' }) }) })) })));
|
|
155
155
|
});
|
|
@@ -1,17 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Slot } from './types';
|
|
2
2
|
export declare enum SlotKey {
|
|
3
3
|
Day = "D",
|
|
4
4
|
Month = "M",
|
|
5
|
-
Year = "Y"
|
|
6
|
-
Hours = "h",
|
|
7
|
-
Minutes = "m",
|
|
8
|
-
Seconds = "s"
|
|
5
|
+
Year = "Y"
|
|
9
6
|
}
|
|
10
|
-
export declare const
|
|
11
|
-
readonly Date: "date";
|
|
12
|
-
readonly DateTime: "date-time";
|
|
13
|
-
};
|
|
14
|
-
export declare const MASK: Record<Mode, Record<string, string>>;
|
|
7
|
+
export declare const MASK: Record<string, string>;
|
|
15
8
|
export declare const DEFAULT_LOCALE: Intl.Locale;
|
|
16
|
-
export declare const SLOTS: Record<
|
|
17
|
-
export declare const SLOTS_PLACEHOLDER: Record<
|
|
9
|
+
export declare const SLOTS: Record<SlotKey | string, Slot>;
|
|
10
|
+
export declare const SLOTS_PLACEHOLDER: Record<string, Record<string, string>>;
|
|
@@ -3,51 +3,26 @@ export var SlotKey;
|
|
|
3
3
|
SlotKey["Day"] = "D";
|
|
4
4
|
SlotKey["Month"] = "M";
|
|
5
5
|
SlotKey["Year"] = "Y";
|
|
6
|
-
SlotKey["Hours"] = "h";
|
|
7
|
-
SlotKey["Minutes"] = "m";
|
|
8
|
-
SlotKey["Seconds"] = "s";
|
|
9
6
|
})(SlotKey || (SlotKey = {}));
|
|
10
|
-
export const MODES = {
|
|
11
|
-
Date: 'date',
|
|
12
|
-
DateTime: 'date-time',
|
|
13
|
-
};
|
|
14
7
|
export const MASK = {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
'en-US': 'DD.MM.YYYY',
|
|
18
|
-
},
|
|
19
|
-
[MODES.DateTime]: {
|
|
20
|
-
'ru-RU': 'ДД.ММ.ГГГГ, чч:мм:сс',
|
|
21
|
-
'en-US': 'DD.MM.YYYY, hh:mm:ss',
|
|
22
|
-
},
|
|
8
|
+
'ru-RU': 'ДД.ММ.ГГГГ',
|
|
9
|
+
'en-US': 'DD.MM.YYYY',
|
|
23
10
|
};
|
|
24
11
|
export const DEFAULT_LOCALE = new Intl.Locale('ru-RU');
|
|
25
|
-
const
|
|
12
|
+
export const SLOTS = {
|
|
26
13
|
[SlotKey.Day]: { start: 0, end: 2, max: 31, min: 1 },
|
|
27
14
|
[SlotKey.Month]: { start: 3, end: 5, max: 12, min: 1 },
|
|
28
15
|
[SlotKey.Year]: { start: 6, end: 10, max: 2100, min: 1900 },
|
|
29
16
|
};
|
|
30
|
-
export const SLOTS = {
|
|
31
|
-
[MODES.Date]: DATE_SLOTS,
|
|
32
|
-
[MODES.DateTime]: Object.assign(Object.assign({}, DATE_SLOTS), { [SlotKey.Hours]: { start: 12, end: 14, max: 23, min: 0 }, [SlotKey.Minutes]: { start: 15, end: 17, max: 59, min: 0 }, [SlotKey.Seconds]: { start: 18, end: 20, max: 59, min: 0 } }),
|
|
33
|
-
};
|
|
34
|
-
const RU_DATE_SLOTS_PLACEHOLDER = {
|
|
35
|
-
[SlotKey.Day]: 'ДД',
|
|
36
|
-
[SlotKey.Month]: 'ММ',
|
|
37
|
-
[SlotKey.Year]: 'ГГГГ',
|
|
38
|
-
};
|
|
39
|
-
const EN_DATE_SLOTS_PLACEHOLDER = {
|
|
40
|
-
[SlotKey.Day]: 'DD',
|
|
41
|
-
[SlotKey.Month]: 'MM',
|
|
42
|
-
[SlotKey.Year]: 'YYYY',
|
|
43
|
-
};
|
|
44
17
|
export const SLOTS_PLACEHOLDER = {
|
|
45
|
-
|
|
46
|
-
'
|
|
47
|
-
'
|
|
18
|
+
'ru-RU': {
|
|
19
|
+
[SlotKey.Day]: 'ДД',
|
|
20
|
+
[SlotKey.Month]: 'ММ',
|
|
21
|
+
[SlotKey.Year]: 'ГГГГ',
|
|
48
22
|
},
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
23
|
+
'en-US': {
|
|
24
|
+
[SlotKey.Day]: 'DD',
|
|
25
|
+
[SlotKey.Month]: 'MM',
|
|
26
|
+
[SlotKey.Year]: 'YYYY',
|
|
52
27
|
},
|
|
53
28
|
};
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { ChangeEvent, FocusEventHandler, KeyboardEvent, RefObject } from 'react';
|
|
2
2
|
import { SlotKey } from '../constants';
|
|
3
|
-
import { Mode } from '../types';
|
|
4
3
|
type UseDateFieldProps = {
|
|
5
4
|
inputRef: RefObject<HTMLInputElement>;
|
|
6
|
-
onChange?(value:
|
|
5
|
+
onChange?(value: string): void;
|
|
7
6
|
readonly?: boolean;
|
|
8
7
|
locale?: Intl.Locale;
|
|
9
8
|
setIsOpen(v: boolean): void;
|
|
10
|
-
mode: Mode;
|
|
11
9
|
};
|
|
12
|
-
type FocusSlot = SlotKey.Day | SlotKey.Year |
|
|
13
|
-
export declare function useDateField({ inputRef, onChange, readonly, locale, setIsOpen
|
|
10
|
+
type FocusSlot = SlotKey.Day | SlotKey.Year | 'auto';
|
|
11
|
+
export declare function useDateField({ inputRef, onChange, readonly, locale, setIsOpen }: UseDateFieldProps): {
|
|
14
12
|
handleKeyDown: (e: KeyboardEvent<HTMLInputElement>) => void;
|
|
15
13
|
handleChange: (value: string, e?: ChangeEvent<HTMLInputElement> | undefined) => void;
|
|
16
14
|
handleClick: () => void;
|
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
import { useCallback, useMemo, useRef } from 'react';
|
|
2
2
|
import { isBrowser } from '@snack-uikit/utils';
|
|
3
3
|
import { DEFAULT_LOCALE, MASK, SlotKey, SLOTS, SLOTS_PLACEHOLDER } from '../constants';
|
|
4
|
-
import { getNextSlotKey, getPrevSlotKey, getSlotKey
|
|
4
|
+
import { getNextSlotKey, getPrevSlotKey, getSlotKey } from '../utils';
|
|
5
5
|
import { useDateFieldHelpers } from './useDateFieldHelpers';
|
|
6
|
-
|
|
7
|
-
export function useDateField({ inputRef, onChange, readonly, locale = DEFAULT_LOCALE, setIsOpen, mode, }) {
|
|
6
|
+
export function useDateField({ inputRef, onChange, readonly, locale = DEFAULT_LOCALE, setIsOpen }) {
|
|
8
7
|
var _a;
|
|
9
|
-
const
|
|
10
|
-
const dateTimeHelpers = useDateTimeFieldHelpers(inputRef);
|
|
11
|
-
const { setFocus, updateSlot, getSlot, isLikeDate, isAllSelected, tryToCompleteInput, isValidInput } = mode === 'date' ? dateHelpers : dateTimeHelpers;
|
|
8
|
+
const { setFocus, updateSlot, getSlot, isLikeDate, isAllSelected, isValidInput, tryToCompleteInput } = useDateFieldHelpers(inputRef);
|
|
12
9
|
const focusSlotRef = useRef(SlotKey.Day);
|
|
13
|
-
const mask = useMemo(() => MASK[
|
|
14
|
-
const
|
|
15
|
-
const getPrevSlotKeyHandler = getPrevSlotKey(mode);
|
|
16
|
-
const slotsPlaceholder = useMemo(() => SLOTS_PLACEHOLDER[mode][locale.baseName] || SLOTS_PLACEHOLDER[mode][DEFAULT_LOCALE.baseName], [locale.baseName, mode]);
|
|
10
|
+
const mask = useMemo(() => MASK[locale.baseName] || MASK[DEFAULT_LOCALE.baseName], [locale]);
|
|
11
|
+
const slotsPlaceHolder = useMemo(() => SLOTS_PLACEHOLDER[locale.baseName] || SLOTS_PLACEHOLDER[DEFAULT_LOCALE.baseName], [locale.baseName]);
|
|
17
12
|
const setInputFocus = useCallback((focusSlot) => {
|
|
18
13
|
if (!inputRef.current || readonly) {
|
|
19
14
|
return;
|
|
@@ -36,44 +31,42 @@ export function useDateField({ inputRef, onChange, readonly, locale = DEFAULT_LO
|
|
|
36
31
|
setFocus(focusSlotValue);
|
|
37
32
|
return;
|
|
38
33
|
}
|
|
39
|
-
const slotKey = getSlotKey(inputRef.current.selectionStart
|
|
34
|
+
const slotKey = getSlotKey(inputRef.current.selectionStart);
|
|
40
35
|
if (slotKey) {
|
|
41
|
-
const { start, end } = SLOTS[
|
|
36
|
+
const { start, end } = SLOTS[slotKey];
|
|
42
37
|
inputRef.current.setSelectionRange(start, end);
|
|
43
38
|
}
|
|
44
|
-
}, [inputRef, isLikeDate, mask,
|
|
39
|
+
}, [inputRef, isLikeDate, mask, readonly, setFocus]);
|
|
45
40
|
const handleClick = useCallback(() => {
|
|
46
41
|
setInputFocus('auto');
|
|
47
42
|
}, [setInputFocus]);
|
|
48
43
|
const handleChange = () => {
|
|
49
44
|
var _a;
|
|
50
|
-
onChange && isLikeDate() && onChange(
|
|
45
|
+
onChange && isLikeDate() && onChange(((_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.value) || '');
|
|
51
46
|
};
|
|
52
47
|
const checkInputAndGoNext = useCallback((slotKey) => {
|
|
53
|
-
|
|
54
|
-
if (slotKey === (mode === 'date' ? SlotKey.Year : SlotKey.Seconds) && tryToCompleteInput()) {
|
|
48
|
+
if (slotKey === SlotKey.Year && tryToCompleteInput()) {
|
|
55
49
|
return;
|
|
56
50
|
}
|
|
57
51
|
if (isValidInput()) {
|
|
58
|
-
setFocus(
|
|
52
|
+
setFocus(getNextSlotKey(slotKey));
|
|
59
53
|
return;
|
|
60
54
|
}
|
|
61
55
|
switch (slotKey) {
|
|
62
56
|
case SlotKey.Day:
|
|
63
|
-
updateSlot(SlotKey.Month,
|
|
57
|
+
updateSlot(SlotKey.Month, slotsPlaceHolder[SlotKey.Month]);
|
|
64
58
|
setFocus(SlotKey.Month);
|
|
65
59
|
return;
|
|
66
60
|
case SlotKey.Year:
|
|
67
61
|
case SlotKey.Month:
|
|
68
|
-
updateSlot(SlotKey.Day,
|
|
62
|
+
updateSlot(SlotKey.Day, slotsPlaceHolder[SlotKey.Day]);
|
|
69
63
|
setFocus(SlotKey.Day);
|
|
70
64
|
return;
|
|
71
65
|
default:
|
|
72
|
-
setFocus(
|
|
66
|
+
setFocus(getNextSlotKey(slotKey));
|
|
73
67
|
}
|
|
74
|
-
}, [
|
|
68
|
+
}, [tryToCompleteInput, isValidInput, setFocus, slotsPlaceHolder, updateSlot]);
|
|
75
69
|
const handleKeyDown = useCallback((e) => {
|
|
76
|
-
var _a;
|
|
77
70
|
if (inputRef.current && !readonly) {
|
|
78
71
|
if (e.key !== 'Tab') {
|
|
79
72
|
e.preventDefault();
|
|
@@ -90,21 +83,21 @@ export function useDateField({ inputRef, onChange, readonly, locale = DEFAULT_LO
|
|
|
90
83
|
tryToCompleteInput();
|
|
91
84
|
}
|
|
92
85
|
const clickIndex = inputRef.current.selectionStart;
|
|
93
|
-
const slotKey = getSlotKey(clickIndex
|
|
86
|
+
const slotKey = getSlotKey(clickIndex);
|
|
94
87
|
if (slotKey) {
|
|
95
88
|
const value = getSlot(slotKey);
|
|
96
|
-
const { max } = SLOTS[
|
|
89
|
+
const { max } = SLOTS[slotKey];
|
|
97
90
|
const numberValue = Number(value) || 0;
|
|
98
91
|
if (e.key === 'ArrowRight') {
|
|
99
|
-
if (isAllSelected() || slotKey ===
|
|
92
|
+
if (isAllSelected() || slotKey === SlotKey.Year) {
|
|
100
93
|
inputRef.current.selectionStart = inputRef.current.value.length;
|
|
101
94
|
return;
|
|
102
95
|
}
|
|
103
|
-
setFocus(
|
|
96
|
+
setFocus(getNextSlotKey(slotKey));
|
|
104
97
|
return;
|
|
105
98
|
}
|
|
106
99
|
if (e.key === 'ArrowLeft') {
|
|
107
|
-
setFocus(
|
|
100
|
+
setFocus(getPrevSlotKey(slotKey));
|
|
108
101
|
return;
|
|
109
102
|
}
|
|
110
103
|
if (e.key === 'Backspace') {
|
|
@@ -113,7 +106,7 @@ export function useDateField({ inputRef, onChange, readonly, locale = DEFAULT_LO
|
|
|
113
106
|
setFocus(SlotKey.Day);
|
|
114
107
|
}
|
|
115
108
|
else {
|
|
116
|
-
updateSlot(slotKey,
|
|
109
|
+
updateSlot(slotKey, slotsPlaceHolder[slotKey]);
|
|
117
110
|
}
|
|
118
111
|
}
|
|
119
112
|
if (/^\d+$/.test(e.key)) {
|
|
@@ -151,25 +144,21 @@ export function useDateField({ inputRef, onChange, readonly, locale = DEFAULT_LO
|
|
|
151
144
|
}
|
|
152
145
|
}
|
|
153
146
|
}
|
|
154
|
-
|
|
155
|
-
onChange === null || onChange === void 0 ? void 0 : onChange(newDate);
|
|
147
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(isLikeDate() ? inputRef.current.value : '');
|
|
156
148
|
}
|
|
157
149
|
}
|
|
158
150
|
}, [
|
|
159
151
|
checkInputAndGoNext,
|
|
160
|
-
getNextSlotKeyHandler,
|
|
161
|
-
getPrevSlotKeyHandler,
|
|
162
152
|
getSlot,
|
|
163
153
|
inputRef,
|
|
164
154
|
isAllSelected,
|
|
165
155
|
isLikeDate,
|
|
166
156
|
mask,
|
|
167
|
-
mode,
|
|
168
157
|
onChange,
|
|
169
158
|
readonly,
|
|
170
159
|
setFocus,
|
|
171
160
|
setIsOpen,
|
|
172
|
-
|
|
161
|
+
slotsPlaceHolder,
|
|
173
162
|
tryToCompleteInput,
|
|
174
163
|
updateSlot,
|
|
175
164
|
]);
|
|
@@ -3,20 +3,20 @@ import { SlotKey, SLOTS } from '../constants';
|
|
|
3
3
|
export function useDateFieldHelpers(inputRef) {
|
|
4
4
|
const setFocus = useCallback((slotKey) => {
|
|
5
5
|
if (inputRef.current) {
|
|
6
|
-
const { start, end } = SLOTS
|
|
6
|
+
const { start, end } = SLOTS[slotKey];
|
|
7
7
|
inputRef.current.setSelectionRange(start, end);
|
|
8
8
|
}
|
|
9
9
|
}, [inputRef]);
|
|
10
10
|
const isAllSelected = useCallback(() => { var _a, _b, _c; return ((_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.value.length) === ((_b = inputRef.current) === null || _b === void 0 ? void 0 : _b.selectionEnd) && ((_c = inputRef.current) === null || _c === void 0 ? void 0 : _c.selectionStart) === 0; }, [inputRef]);
|
|
11
11
|
const getSlot = useCallback((slotKey) => {
|
|
12
12
|
if (inputRef.current) {
|
|
13
|
-
return inputRef.current.value.slice(SLOTS
|
|
13
|
+
return inputRef.current.value.slice(SLOTS[slotKey].start, SLOTS[slotKey].end);
|
|
14
14
|
}
|
|
15
15
|
return '';
|
|
16
16
|
}, [inputRef]);
|
|
17
17
|
const isLikeDate = useCallback(() => {
|
|
18
18
|
if (inputRef.current) {
|
|
19
|
-
return Object.keys(SLOTS
|
|
19
|
+
return Object.keys(SLOTS).every(slotKey => getSlot(slotKey) && Number.isInteger(Number(getSlot(slotKey))));
|
|
20
20
|
}
|
|
21
21
|
return false;
|
|
22
22
|
}, [getSlot, inputRef]);
|
|
@@ -35,7 +35,7 @@ export function useDateFieldHelpers(inputRef) {
|
|
|
35
35
|
const day = parseInt(getSlot(SlotKey.Day), 10);
|
|
36
36
|
const month = parseInt(getSlot(SlotKey.Month), 10);
|
|
37
37
|
const year = parseInt(getSlot(SlotKey.Year), 10);
|
|
38
|
-
const { min, max } = SLOTS
|
|
38
|
+
const { min, max } = SLOTS[SlotKey.Year];
|
|
39
39
|
const isCompleted = Boolean(day && month && year >= min && year <= max);
|
|
40
40
|
if (isCompleted && inputRef.current) {
|
|
41
41
|
const lastPosition = (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.value.length;
|
|
@@ -46,7 +46,7 @@ export function useDateFieldHelpers(inputRef) {
|
|
|
46
46
|
}, [getSlot, inputRef]);
|
|
47
47
|
const updateSlot = useCallback((slotKey, slotValue) => {
|
|
48
48
|
if (inputRef.current) {
|
|
49
|
-
const { start, end, max } = SLOTS
|
|
49
|
+
const { start, end, max } = SLOTS[slotKey];
|
|
50
50
|
inputRef.current.value =
|
|
51
51
|
inputRef.current.value.slice(0, start) +
|
|
52
52
|
slotValue.toString().padStart(max.toString().length, '0') +
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import { SlotKey } from './constants';
|
|
2
|
-
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function
|
|
5
|
-
export declare function getPrevSlotKeyWithDate(slotKey: string | null): SlotKey.Day | SlotKey.Month;
|
|
6
|
-
export declare function getNextSlotKeyWithTime(slotKey: string | null): SlotKey.Month | SlotKey.Year | SlotKey.Hours | SlotKey.Minutes | SlotKey.Seconds;
|
|
7
|
-
export declare function getPrevSlotKeyWithTime(slotKey: string | null): SlotKey.Day | SlotKey.Month | SlotKey.Year | SlotKey.Hours | SlotKey.Minutes;
|
|
8
|
-
export declare function getNextSlotKey(mode: Mode): typeof getNextSlotKeyWithTime;
|
|
9
|
-
export declare function getPrevSlotKey(mode: Mode): typeof getPrevSlotKeyWithTime;
|
|
2
|
+
export declare function getSlotKey(index: number | null): string | null;
|
|
3
|
+
export declare function getNextSlotKey(slotKey: string | null): SlotKey.Month | SlotKey.Year;
|
|
4
|
+
export declare function getPrevSlotKey(slotKey: string | null): SlotKey.Day | SlotKey.Month;
|
|
10
5
|
/**
|
|
11
6
|
* Преобразует строковое значение поля FieldDate в тип Date
|
|
12
7
|
* @function helper
|
|
13
8
|
*/
|
|
14
|
-
export declare function parseDate(
|
|
9
|
+
export declare function parseDate(date: string): Date;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { SlotKey, SLOTS } from './constants';
|
|
2
|
-
export function getSlotKey(index
|
|
2
|
+
export function getSlotKey(index) {
|
|
3
3
|
if (index !== null) {
|
|
4
|
-
for (const key in SLOTS
|
|
5
|
-
if (index >= SLOTS[
|
|
4
|
+
for (const key in SLOTS) {
|
|
5
|
+
if (index >= SLOTS[key].start && index <= SLOTS[key].end) {
|
|
6
6
|
return key;
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
return null;
|
|
11
11
|
}
|
|
12
|
-
export function
|
|
12
|
+
export function getNextSlotKey(slotKey) {
|
|
13
13
|
switch (slotKey) {
|
|
14
14
|
case SlotKey.Day: {
|
|
15
15
|
return SlotKey.Month;
|
|
@@ -21,7 +21,7 @@ export function getNextSlotKeyWithDate(slotKey) {
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
-
export function
|
|
24
|
+
export function getPrevSlotKey(slotKey) {
|
|
25
25
|
switch (slotKey) {
|
|
26
26
|
case SlotKey.Year: {
|
|
27
27
|
return SlotKey.Month;
|
|
@@ -33,73 +33,11 @@ export function getPrevSlotKeyWithDate(slotKey) {
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
-
export function getNextSlotKeyWithTime(slotKey) {
|
|
37
|
-
switch (slotKey) {
|
|
38
|
-
case SlotKey.Day: {
|
|
39
|
-
return SlotKey.Month;
|
|
40
|
-
}
|
|
41
|
-
case SlotKey.Month: {
|
|
42
|
-
return SlotKey.Year;
|
|
43
|
-
}
|
|
44
|
-
case SlotKey.Year: {
|
|
45
|
-
return SlotKey.Hours;
|
|
46
|
-
}
|
|
47
|
-
case SlotKey.Hours: {
|
|
48
|
-
return SlotKey.Minutes;
|
|
49
|
-
}
|
|
50
|
-
case SlotKey.Minutes:
|
|
51
|
-
case SlotKey.Seconds:
|
|
52
|
-
default: {
|
|
53
|
-
return SlotKey.Seconds;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
export function getPrevSlotKeyWithTime(slotKey) {
|
|
58
|
-
switch (slotKey) {
|
|
59
|
-
case SlotKey.Seconds: {
|
|
60
|
-
return SlotKey.Minutes;
|
|
61
|
-
}
|
|
62
|
-
case SlotKey.Minutes: {
|
|
63
|
-
return SlotKey.Hours;
|
|
64
|
-
}
|
|
65
|
-
case SlotKey.Hours: {
|
|
66
|
-
return SlotKey.Year;
|
|
67
|
-
}
|
|
68
|
-
case SlotKey.Year: {
|
|
69
|
-
return SlotKey.Month;
|
|
70
|
-
}
|
|
71
|
-
case SlotKey.Month:
|
|
72
|
-
case SlotKey.Day:
|
|
73
|
-
default: {
|
|
74
|
-
return SlotKey.Day;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
export function getNextSlotKey(mode) {
|
|
79
|
-
return mode === 'date' ? getNextSlotKeyWithDate : getNextSlotKeyWithTime;
|
|
80
|
-
}
|
|
81
|
-
export function getPrevSlotKey(mode) {
|
|
82
|
-
return mode === 'date' ? getPrevSlotKeyWithDate : getPrevSlotKeyWithTime;
|
|
83
|
-
}
|
|
84
36
|
/**
|
|
85
37
|
* Преобразует строковое значение поля FieldDate в тип Date
|
|
86
38
|
* @function helper
|
|
87
39
|
*/
|
|
88
|
-
export function parseDate(
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
const [date, time] = value.split(', ');
|
|
93
|
-
const dateValues = date.split('.');
|
|
94
|
-
const year = Number(dateValues[2]);
|
|
95
|
-
const month = Number(dateValues[1]) - 1;
|
|
96
|
-
const day = Number(dateValues[0]);
|
|
97
|
-
if (time) {
|
|
98
|
-
const timeValues = time.split(':');
|
|
99
|
-
const hours = timeValues[0] ? Number(timeValues[0]) : undefined;
|
|
100
|
-
const minutes = timeValues[1] ? Number(timeValues[1]) : undefined;
|
|
101
|
-
const seconds = timeValues[2] ? Number(timeValues[2]) : undefined;
|
|
102
|
-
return new Date(year, month, day, hours, minutes, seconds);
|
|
103
|
-
}
|
|
104
|
-
return new Date(year, month, day);
|
|
40
|
+
export function parseDate(date) {
|
|
41
|
+
const values = date.split('.');
|
|
42
|
+
return new Date(Number(values[2]), Number(values[1]) - 1, Number(values[0]));
|
|
105
43
|
}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
6
|
"title": "Fields",
|
|
7
|
-
"version": "0.29.2
|
|
7
|
+
"version": "0.29.2",
|
|
8
8
|
"sideEffects": [
|
|
9
9
|
"*.css",
|
|
10
10
|
"*.woff",
|
|
@@ -33,13 +33,13 @@
|
|
|
33
33
|
"scripts": {},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@snack-uikit/button": "0.17.5",
|
|
36
|
-
"@snack-uikit/calendar": "0.8.
|
|
36
|
+
"@snack-uikit/calendar": "0.8.0",
|
|
37
37
|
"@snack-uikit/color-picker": "0.1.1",
|
|
38
38
|
"@snack-uikit/divider": "3.0.4",
|
|
39
39
|
"@snack-uikit/dropdown": "0.2.7",
|
|
40
40
|
"@snack-uikit/icons": "0.22.1",
|
|
41
41
|
"@snack-uikit/input-private": "4.0.0",
|
|
42
|
-
"@snack-uikit/list": "0.17.1
|
|
42
|
+
"@snack-uikit/list": "0.17.1",
|
|
43
43
|
"@snack-uikit/scroll": "0.6.2",
|
|
44
44
|
"@snack-uikit/skeleton": "0.3.5",
|
|
45
45
|
"@snack-uikit/slider": "0.1.18",
|
|
@@ -61,5 +61,5 @@
|
|
|
61
61
|
"peerDependencies": {
|
|
62
62
|
"@snack-uikit/locale": "*"
|
|
63
63
|
},
|
|
64
|
-
"gitHead": "
|
|
64
|
+
"gitHead": "c2ae92f1626a256a9a0505c2cd74136cba9700bb"
|
|
65
65
|
}
|