-
Notifications
You must be signed in to change notification settings - Fork 833
/
usePickerState.ts
113 lines (95 loc) · 3.27 KB
/
usePickerState.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import { useUtils } from './useUtils';
import { IUtils } from '@date-io/core/IUtils';
import { MaterialUiPickersDate } from '../..';
import { useOpenState } from './useOpenState';
import { BasePickerProps } from '../../typings/BasePicker';
import { getDisplayDate, validate } from '../../_helpers/text-field-helper';
import { useCallback, useDebugValue, useEffect, useMemo, useState, useRef } from 'react';
export interface StateHookOptions {
getDefaultFormat: () => string;
}
const useValueToDate = (
utils: IUtils<MaterialUiPickersDate>,
{ value, initialFocusedDate }: BasePickerProps
) => {
const nowRef = useRef(utils.date());
const date = utils.date(value || initialFocusedDate || nowRef.current);
return date && utils.isValid(date) ? date : nowRef.current;
};
function useDateValues(props: BasePickerProps, options: StateHookOptions) {
const utils = useUtils();
const date = useValueToDate(utils, props);
const format = props.format || options.getDefaultFormat();
return { date, format };
}
export function usePickerState(props: BasePickerProps, options: StateHookOptions) {
const { autoOk, disabled, onAccept, onChange, onError, value, variant } = props;
const utils = useUtils();
const { isOpen, setIsOpen } = useOpenState(props);
const { date, format } = useDateValues(props, options);
const [pickerDate, setPickerDate] = useState(date);
useEffect(() => {
// if value was changed in closed state - treat it as accepted
if (!isOpen && !utils.isEqual(pickerDate, date)) {
setPickerDate(date);
}
}, [date, isOpen, pickerDate, utils]);
const acceptDate = useCallback(
(acceptedDate: MaterialUiPickersDate) => {
setIsOpen(false);
onChange(acceptedDate);
if (onAccept) {
onAccept(acceptedDate);
}
},
[onAccept, onChange, setIsOpen]
);
const wrapperProps = useMemo(
() => ({
format,
open: isOpen,
onClear: () => acceptDate(null),
onAccept: () => acceptDate(pickerDate),
onSetToday: () => setPickerDate(utils.date()),
onDismiss: () => {
setIsOpen(false);
},
}),
[acceptDate, format, isOpen, pickerDate, setIsOpen, utils]
);
const pickerProps = useMemo(
() => ({
date: pickerDate,
onChange: (newDate: MaterialUiPickersDate, isFinish = true) => {
setPickerDate(newDate);
if (variant === 'inline' || variant === 'static') {
onChange(newDate);
onAccept && onAccept(newDate);
return; // simulate autoOk, but do not close the mod
}
if (isFinish && autoOk) {
acceptDate(newDate);
}
},
}),
[acceptDate, autoOk, onAccept, onChange, pickerDate, variant]
);
const validationError = validate(value, utils, props);
useEffect(() => {
if (validationError && onError) {
onError(validationError, value);
}
}, [onError, validationError, value]);
const inputValue = getDisplayDate(date, format, utils, value === null, props);
const inputProps = useMemo(
() => ({
inputValue,
validationError,
onClick: () => !disabled && setIsOpen(true),
}),
[disabled, inputValue, setIsOpen, validationError]
);
const pickerState = { pickerProps, inputProps, wrapperProps };
useDebugValue(pickerState);
return pickerState;
}