react-native-molecules 0.5.0-beta.16 → 0.5.0-beta.17
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/components/DateField/DateField.tsx +110 -0
- package/components/DateField/index.tsx +6 -0
- package/components/{DatePickerInput/inputUtils.ts → DateField/useDateFieldState.ts} +17 -49
- package/components/DatePicker/DateCalendar.tsx +83 -0
- package/components/DatePicker/DatePickerActions.tsx +73 -0
- package/components/DatePicker/DatePickerModal.tsx +234 -0
- package/components/DatePicker/DatePickerPopover.tsx +79 -0
- package/components/DatePicker/DatePickerProvider.tsx +152 -0
- package/components/DatePicker/DatePickerTrigger.tsx +23 -0
- package/components/DatePicker/context.tsx +82 -0
- package/components/DatePicker/index.tsx +44 -0
- package/components/DatePicker/utils.ts +292 -0
- package/components/DatePickerInline/DatePickerContext.tsx +1 -0
- package/components/DatePickerInline/DatePickerDockedHeader.tsx +113 -0
- package/components/DatePickerInline/DatePickerInline.tsx +16 -15
- package/components/DatePickerInline/DatePickerInlineBase.tsx +7 -1
- package/components/DatePickerInline/Day.tsx +25 -1
- package/components/DatePickerInline/DayRange.tsx +2 -4
- package/components/DatePickerInline/HeaderItem.tsx +42 -27
- package/components/DatePickerInline/Month.tsx +45 -65
- package/components/DatePickerInline/MonthPicker.tsx +25 -41
- package/components/DatePickerInline/Swiper.native.tsx +21 -4
- package/components/DatePickerInline/Swiper.tsx +168 -13
- package/components/DatePickerInline/Week.tsx +6 -1
- package/components/DatePickerInline/YearPicker.tsx +206 -53
- package/components/DatePickerInline/dateUtils.tsx +17 -12
- package/components/DatePickerInline/types.ts +3 -0
- package/components/DatePickerInline/utils.ts +66 -29
- package/components/ListItem/ListItem.tsx +3 -1
- package/components/ListItem/utils.ts +1 -1
- package/components/LoadingIndicator/index.tsx +1 -1
- package/components/Popover/Popover.native.tsx +4 -25
- package/components/Popover/Popover.tsx +4 -26
- package/components/Popover/utils.ts +41 -0
- package/components/Select/Select.tsx +7 -8
- package/components/Select/context.tsx +72 -0
- package/components/Select/index.ts +1 -0
- package/components/Select/utils.ts +0 -71
- package/components/Slot/compose-refs.tsx +2 -0
- package/components/TimeField/TimeField.tsx +75 -0
- package/components/TimeField/index.tsx +6 -0
- package/components/TimeField/useTimeFieldState.ts +70 -0
- package/components/{TimePickerField/sanitizeTime.ts → TimeField/utils.ts} +77 -10
- package/components/TimePicker/TimePicker.tsx +53 -9
- package/components/TimePicker/TimePickerModal.tsx +186 -0
- package/components/TimePicker/context.tsx +17 -0
- package/components/TimePicker/index.tsx +15 -3
- package/components/TimePicker/utils.ts +50 -0
- package/hooks/useActionState.tsx +19 -8
- package/package.json +6 -1
- package/components/DatePickerDocked/DatePickerDocked.tsx +0 -30
- package/components/DatePickerDocked/DatePickerDockedHeader.tsx +0 -129
- package/components/DatePickerDocked/index.tsx +0 -17
- package/components/DatePickerDocked/types.ts +0 -11
- package/components/DatePickerDocked/utils.ts +0 -157
- package/components/DatePickerInput/DatePickerInput.tsx +0 -130
- package/components/DatePickerInput/DatePickerInputModal.tsx +0 -48
- package/components/DatePickerInput/DatePickerInputWithoutModal.tsx +0 -73
- package/components/DatePickerInput/DateRangeInput.tsx +0 -88
- package/components/DatePickerInput/index.tsx +0 -11
- package/components/DatePickerInput/types.ts +0 -26
- package/components/DatePickerInput/utils.ts +0 -24
- package/components/DatePickerModal/AnimatedCrossView.tsx +0 -94
- package/components/DatePickerModal/CalendarEdit.tsx +0 -140
- package/components/DatePickerModal/DatePickerModal.tsx +0 -85
- package/components/DatePickerModal/DatePickerModalContent.tsx +0 -155
- package/components/DatePickerModal/DatePickerModalContentHeader.tsx +0 -213
- package/components/DatePickerModal/DatePickerModalHeader.tsx +0 -74
- package/components/DatePickerModal/DatePickerModalHeaderBackground.tsx +0 -13
- package/components/DatePickerModal/index.tsx +0 -16
- package/components/DatePickerModal/types.ts +0 -92
- package/components/DatePickerModal/utils.ts +0 -122
- package/components/DateTimePicker/DateTimePicker.tsx +0 -172
- package/components/DateTimePicker/index.tsx +0 -10
- package/components/DateTimePicker/utils.ts +0 -12
- package/components/TimePickerField/TimePickerField.tsx +0 -154
- package/components/TimePickerField/index.tsx +0 -10
- package/components/TimePickerField/utils.ts +0 -94
- package/components/TimePickerModal/TimePickerModal.tsx +0 -119
- package/components/TimePickerModal/index.tsx +0 -10
- package/components/TimePickerModal/utils.ts +0 -47
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import type { ViewStyle } from 'react-native';
|
|
2
|
-
|
|
3
|
-
import type {
|
|
4
|
-
BaseDatePickerProps,
|
|
5
|
-
CalendarDate,
|
|
6
|
-
CalendarDates,
|
|
7
|
-
MultiChange,
|
|
8
|
-
MultiConfirm,
|
|
9
|
-
RangeChange,
|
|
10
|
-
SingleChange,
|
|
11
|
-
} from '../DatePickerInline';
|
|
12
|
-
import type { HeaderPickProps } from './DatePickerModalContentHeader';
|
|
13
|
-
|
|
14
|
-
export type LocalState = LocalStateSingle | LocalStateMultiple | LocalStateRange;
|
|
15
|
-
|
|
16
|
-
export type LocalStateSingle = {
|
|
17
|
-
date: CalendarDate;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export type LocalStateMultiple = {
|
|
21
|
-
dates: CalendarDates;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export type LocalStateRange = {
|
|
25
|
-
startDate: CalendarDate;
|
|
26
|
-
endDate: CalendarDate;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
interface DatePickerModalContentBaseProps {
|
|
30
|
-
inputFormat?: string;
|
|
31
|
-
locale?: string;
|
|
32
|
-
onClose: () => any;
|
|
33
|
-
disableSafeTop?: boolean;
|
|
34
|
-
saveLabelDisabled?: boolean;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface DatePickerModalContentRangeProps
|
|
38
|
-
extends HeaderPickProps,
|
|
39
|
-
BaseDatePickerProps,
|
|
40
|
-
DatePickerModalContentBaseProps {
|
|
41
|
-
mode?: 'range';
|
|
42
|
-
startDate?: CalendarDate;
|
|
43
|
-
endDate?: CalendarDate;
|
|
44
|
-
onChange?: RangeChange;
|
|
45
|
-
onConfirm?: RangeChange;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export interface DatePickerModalContentSingleProps
|
|
49
|
-
extends HeaderPickProps,
|
|
50
|
-
BaseDatePickerProps,
|
|
51
|
-
DatePickerModalContentBaseProps {
|
|
52
|
-
mode?: 'single';
|
|
53
|
-
date?: CalendarDate;
|
|
54
|
-
onChange?: SingleChange;
|
|
55
|
-
onConfirm?: SingleChange;
|
|
56
|
-
dateMode?: 'start' | 'end';
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export interface DatePickerModalContentMultiProps
|
|
60
|
-
extends HeaderPickProps,
|
|
61
|
-
BaseDatePickerProps,
|
|
62
|
-
DatePickerModalContentBaseProps {
|
|
63
|
-
mode?: 'multiple';
|
|
64
|
-
dates?: CalendarDates;
|
|
65
|
-
onChange?: MultiChange;
|
|
66
|
-
onConfirm?: MultiConfirm;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
interface BaseDatePickerModalProps {
|
|
70
|
-
isOpen: boolean;
|
|
71
|
-
animationType?: 'slide' | 'fade' | 'none';
|
|
72
|
-
disableStatusBar?: boolean;
|
|
73
|
-
disableStatusBarPadding?: boolean;
|
|
74
|
-
style?: ViewStyle;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export interface DatePickerModalSingleProps
|
|
78
|
-
extends DatePickerModalContentSingleProps,
|
|
79
|
-
BaseDatePickerModalProps {}
|
|
80
|
-
|
|
81
|
-
export interface DatePickerModalMultiProps
|
|
82
|
-
extends DatePickerModalContentMultiProps,
|
|
83
|
-
BaseDatePickerModalProps {}
|
|
84
|
-
|
|
85
|
-
export interface DatePickerModalRangeProps
|
|
86
|
-
extends DatePickerModalContentRangeProps,
|
|
87
|
-
BaseDatePickerModalProps {}
|
|
88
|
-
|
|
89
|
-
export type DatePickerModalProps =
|
|
90
|
-
| DatePickerModalRangeProps
|
|
91
|
-
| DatePickerModalSingleProps
|
|
92
|
-
| DatePickerModalMultiProps;
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import { StyleSheet } from 'react-native-unistyles';
|
|
2
|
-
|
|
3
|
-
import { getRegisteredComponentStylesWithFallback } from '../../core';
|
|
4
|
-
|
|
5
|
-
const datePickerModalStylesDefault = StyleSheet.create(theme => ({
|
|
6
|
-
header: {
|
|
7
|
-
backgroundColor: theme.colors.primary,
|
|
8
|
-
},
|
|
9
|
-
}));
|
|
10
|
-
|
|
11
|
-
const datePickerModalHeaderStylesDefault = StyleSheet.create(theme => ({
|
|
12
|
-
root: {
|
|
13
|
-
color: theme.colors.onPrimary,
|
|
14
|
-
},
|
|
15
|
-
animated: {
|
|
16
|
-
paddingBottom: theme.spacings['0'],
|
|
17
|
-
elevation: 4,
|
|
18
|
-
},
|
|
19
|
-
safeContent: {
|
|
20
|
-
paddingBottom: theme.spacings['0'],
|
|
21
|
-
|
|
22
|
-
variants: {
|
|
23
|
-
state: {
|
|
24
|
-
disableSafeTop: {
|
|
25
|
-
paddingTop: 0,
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
},
|
|
30
|
-
safeContentNoTop: {
|
|
31
|
-
paddingTop: theme.spacings['0'],
|
|
32
|
-
},
|
|
33
|
-
appbarHeader: {
|
|
34
|
-
flexDirection: 'row',
|
|
35
|
-
alignItems: 'center',
|
|
36
|
-
justifyContent: 'space-between',
|
|
37
|
-
paddingHorizontal: theme.spacings['2'],
|
|
38
|
-
paddingVertical: theme.spacings['2'],
|
|
39
|
-
elevation: 0,
|
|
40
|
-
backgroundColor: 'transparent',
|
|
41
|
-
},
|
|
42
|
-
}));
|
|
43
|
-
|
|
44
|
-
const datePickerModalContentHeaderStylesDefault = StyleSheet.create(theme => ({
|
|
45
|
-
root: {
|
|
46
|
-
color: theme.colors.onPrimary,
|
|
47
|
-
},
|
|
48
|
-
|
|
49
|
-
fill: {
|
|
50
|
-
flex: 1,
|
|
51
|
-
},
|
|
52
|
-
header: {
|
|
53
|
-
height: 75,
|
|
54
|
-
alignItems: 'center',
|
|
55
|
-
flexDirection: 'row',
|
|
56
|
-
paddingLeft: theme.spacings['6'],
|
|
57
|
-
paddingRight: theme.spacings['3'],
|
|
58
|
-
},
|
|
59
|
-
headerContentContainer: {
|
|
60
|
-
marginTop: theme.spacings['1'],
|
|
61
|
-
flexDirection: 'row',
|
|
62
|
-
alignItems: 'center',
|
|
63
|
-
},
|
|
64
|
-
label: {
|
|
65
|
-
color: theme.colors.onPrimary,
|
|
66
|
-
letterSpacing: 1,
|
|
67
|
-
fontSize: theme.typescale.bodyMedium.fontSize,
|
|
68
|
-
},
|
|
69
|
-
headerText: {
|
|
70
|
-
fontSize: theme.typescale.bodyMedium.fontSize,
|
|
71
|
-
color: theme.colors.onPrimary,
|
|
72
|
-
},
|
|
73
|
-
headerSeparator: {
|
|
74
|
-
fontSize: theme.typescale.bodyMedium.fontSize,
|
|
75
|
-
paddingLeft: theme.spacings['2'],
|
|
76
|
-
paddingRight: theme.spacings['2'],
|
|
77
|
-
color: theme.colors.onPrimary,
|
|
78
|
-
},
|
|
79
|
-
icon: {
|
|
80
|
-
color: theme.colors.onPrimary,
|
|
81
|
-
},
|
|
82
|
-
}));
|
|
83
|
-
|
|
84
|
-
const datePickerModalHeaderBackgroundStylesDefault = StyleSheet.create(theme => ({
|
|
85
|
-
header: {
|
|
86
|
-
backgroundColor: theme.colors.primary,
|
|
87
|
-
paddingBottom: theme.spacings['0'],
|
|
88
|
-
elevation: 4,
|
|
89
|
-
},
|
|
90
|
-
safeContent: {
|
|
91
|
-
paddingBottom: theme.spacings['0'],
|
|
92
|
-
},
|
|
93
|
-
}));
|
|
94
|
-
|
|
95
|
-
const datePickerModalEditStylesDefault = StyleSheet.create(theme => ({
|
|
96
|
-
container: { padding: theme.spacings['3'] },
|
|
97
|
-
inner: { flexDirection: 'row' },
|
|
98
|
-
inputContainer: { flex: 1 },
|
|
99
|
-
input: { flex: 1 },
|
|
100
|
-
separator: { width: 12 },
|
|
101
|
-
}));
|
|
102
|
-
|
|
103
|
-
export const datePickerModalStyles = getRegisteredComponentStylesWithFallback(
|
|
104
|
-
'DatePickerModal',
|
|
105
|
-
datePickerModalStylesDefault,
|
|
106
|
-
);
|
|
107
|
-
export const datePickerModalHeaderStyles = getRegisteredComponentStylesWithFallback(
|
|
108
|
-
'DatePickerModal_Header',
|
|
109
|
-
datePickerModalHeaderStylesDefault,
|
|
110
|
-
);
|
|
111
|
-
export const datePickerModalContentHeaderStyles = getRegisteredComponentStylesWithFallback(
|
|
112
|
-
'DatePickerModal_ContentHeader',
|
|
113
|
-
datePickerModalContentHeaderStylesDefault,
|
|
114
|
-
);
|
|
115
|
-
export const datePickerModalHeaderBackgroundStyles = getRegisteredComponentStylesWithFallback(
|
|
116
|
-
'DatePickerModal_HeaderBackground',
|
|
117
|
-
datePickerModalHeaderBackgroundStylesDefault,
|
|
118
|
-
);
|
|
119
|
-
export const datePickerModalEditStyles = getRegisteredComponentStylesWithFallback(
|
|
120
|
-
'DatePickerModal_Edit',
|
|
121
|
-
datePickerModalEditStylesDefault,
|
|
122
|
-
);
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import { format, parse, set } from 'date-fns';
|
|
2
|
-
import {
|
|
3
|
-
type ComponentType,
|
|
4
|
-
forwardRef,
|
|
5
|
-
memo,
|
|
6
|
-
type RefObject,
|
|
7
|
-
useCallback,
|
|
8
|
-
useEffect,
|
|
9
|
-
useImperativeHandle,
|
|
10
|
-
useMemo,
|
|
11
|
-
useRef,
|
|
12
|
-
} from 'react';
|
|
13
|
-
import type { ViewProps, ViewStyle } from 'react-native';
|
|
14
|
-
|
|
15
|
-
import { useControlledValue } from '../../hooks';
|
|
16
|
-
import { isValid } from '../../utils/date-fns';
|
|
17
|
-
import { DatePickerInput, type DatePickerInputProps } from '../DatePickerInput';
|
|
18
|
-
import { ElementGroup } from '../ElementGroup';
|
|
19
|
-
import type { TextInputHandles } from '../TextInput/TextInput';
|
|
20
|
-
import { sanitizeTimeString, TimePickerField, type TimePickerFieldProps } from '../TimePickerField';
|
|
21
|
-
|
|
22
|
-
export type Props = Omit<ViewProps, 'style'> & {
|
|
23
|
-
is24Hour?: boolean;
|
|
24
|
-
date?: Date | null;
|
|
25
|
-
onChange?: (date: Date | null) => void;
|
|
26
|
-
defaultValue?: Date | null;
|
|
27
|
-
timePickerFieldProps?: Omit<
|
|
28
|
-
Partial<TimePickerFieldProps>,
|
|
29
|
-
'value' | 'onChangeText' | 'date' | 'onTimeChange'
|
|
30
|
-
>;
|
|
31
|
-
datePickerInputProps?: Omit<Partial<DatePickerInputProps>, 'value' | 'onChange'>;
|
|
32
|
-
datePickerInputRef?: RefObject<TextInputHandles | null>;
|
|
33
|
-
timePickerInputRef?: RefObject<TextInputHandles | null>;
|
|
34
|
-
Wrapper?: ComponentType<any>;
|
|
35
|
-
style?: ViewStyle;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const emptyObj = {};
|
|
39
|
-
|
|
40
|
-
const normalizeDateWithCurrentTime = (specificDate: Date) => {
|
|
41
|
-
const date = new Date();
|
|
42
|
-
|
|
43
|
-
return set(specificDate, {
|
|
44
|
-
hours: date.getHours(),
|
|
45
|
-
minutes: date.getHours(),
|
|
46
|
-
seconds: date.getSeconds(),
|
|
47
|
-
});
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const DateTimePicker = (
|
|
51
|
-
{
|
|
52
|
-
is24Hour = false,
|
|
53
|
-
date: dateProp,
|
|
54
|
-
onChange: onChangeProp,
|
|
55
|
-
defaultValue,
|
|
56
|
-
datePickerInputProps = emptyObj,
|
|
57
|
-
timePickerFieldProps = emptyObj,
|
|
58
|
-
style,
|
|
59
|
-
testID,
|
|
60
|
-
datePickerInputRef: _datePickerInputRef,
|
|
61
|
-
timePickerInputRef: _timePickerInputRef,
|
|
62
|
-
Wrapper: _WrapperProp,
|
|
63
|
-
...rest
|
|
64
|
-
}: Props,
|
|
65
|
-
ref: any,
|
|
66
|
-
) => {
|
|
67
|
-
const Wrapper = _WrapperProp ?? ElementGroup;
|
|
68
|
-
|
|
69
|
-
const containerRef = useRef(null);
|
|
70
|
-
const datePickerInputRef = useRef<TextInputHandles>(null);
|
|
71
|
-
const timePickerInputRef = useRef<TextInputHandles>(null);
|
|
72
|
-
|
|
73
|
-
const [date, onChange] = useControlledValue<Date | null>({
|
|
74
|
-
value: dateProp,
|
|
75
|
-
defaultValue,
|
|
76
|
-
onChange: onChangeProp,
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
const timeString = useMemo(() => (date && isValid(date) ? format(date, 'HH:mm') : ''), [date]);
|
|
80
|
-
|
|
81
|
-
const timeStringRef = useRef(timeString);
|
|
82
|
-
|
|
83
|
-
const onDateChange = useCallback(
|
|
84
|
-
(newDate: Date | null) => {
|
|
85
|
-
if (newDate === date || (!isValid(newDate) && !isValid(date))) return;
|
|
86
|
-
|
|
87
|
-
if (!newDate) {
|
|
88
|
-
onChange(null);
|
|
89
|
-
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const addTimeString = (_date: Date) =>
|
|
94
|
-
timeStringRef.current
|
|
95
|
-
? parse(timeStringRef.current ?? '00:00', 'HH:mm', _date)
|
|
96
|
-
: _date;
|
|
97
|
-
|
|
98
|
-
if (!date) {
|
|
99
|
-
onChange(addTimeString(normalizeDateWithCurrentTime(newDate)));
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (!isValid(newDate)) {
|
|
104
|
-
onChange(date);
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const [day, month, year] = format(newDate, 'dd/MM/yyyy').split('/');
|
|
109
|
-
|
|
110
|
-
onChange(addTimeString(set(date, { date: +day, month: +month - 1, year: +year })));
|
|
111
|
-
},
|
|
112
|
-
[date, onChange],
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
const onTimeChange = useCallback(
|
|
116
|
-
(time: string) => {
|
|
117
|
-
if (!time) return;
|
|
118
|
-
|
|
119
|
-
const newTime = sanitizeTimeString(time);
|
|
120
|
-
|
|
121
|
-
timeStringRef.current = newTime;
|
|
122
|
-
|
|
123
|
-
onChange(date ? parse(newTime, 'HH:mm', date) : null);
|
|
124
|
-
},
|
|
125
|
-
[date, onChange],
|
|
126
|
-
);
|
|
127
|
-
|
|
128
|
-
useEffect(() => {
|
|
129
|
-
if (isValid(date)) return;
|
|
130
|
-
|
|
131
|
-
onChange(null);
|
|
132
|
-
}, [date, onChange]);
|
|
133
|
-
|
|
134
|
-
useImperativeHandle(_datePickerInputRef, () => datePickerInputRef.current as TextInputHandles);
|
|
135
|
-
useImperativeHandle(_timePickerInputRef, () => timePickerInputRef.current as TextInputHandles);
|
|
136
|
-
|
|
137
|
-
useImperativeHandle(ref, () =>
|
|
138
|
-
Object.assign(containerRef.current || {}, {
|
|
139
|
-
blur: () => {
|
|
140
|
-
datePickerInputRef.current?.blur?.();
|
|
141
|
-
timePickerInputRef.current?.blur?.();
|
|
142
|
-
},
|
|
143
|
-
}),
|
|
144
|
-
);
|
|
145
|
-
|
|
146
|
-
return (
|
|
147
|
-
<>
|
|
148
|
-
<Wrapper style={style} testID={testID} {...rest} ref={containerRef}>
|
|
149
|
-
<DatePickerInput
|
|
150
|
-
ref={datePickerInputRef}
|
|
151
|
-
inputMode="start"
|
|
152
|
-
variant="outlined"
|
|
153
|
-
testID={testID ? `${testID}--datepickerinput` : undefined}
|
|
154
|
-
{...datePickerInputProps}
|
|
155
|
-
value={date}
|
|
156
|
-
onChange={onDateChange}
|
|
157
|
-
/>
|
|
158
|
-
<TimePickerField
|
|
159
|
-
ref={timePickerInputRef}
|
|
160
|
-
variant="outlined"
|
|
161
|
-
testID={testID ? `${testID}--timepickerinput` : undefined}
|
|
162
|
-
is24Hour={is24Hour}
|
|
163
|
-
{...timePickerFieldProps}
|
|
164
|
-
time={timeString}
|
|
165
|
-
onTimeChange={onTimeChange}
|
|
166
|
-
/>
|
|
167
|
-
</Wrapper>
|
|
168
|
-
</>
|
|
169
|
-
);
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
export default memo(forwardRef(DateTimePicker));
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { getRegisteredComponentWithFallback } from '../../core';
|
|
2
|
-
import DateTimePickerDefault from './DateTimePicker';
|
|
3
|
-
|
|
4
|
-
export const DateTimePicker = getRegisteredComponentWithFallback(
|
|
5
|
-
'DateTimePicker',
|
|
6
|
-
DateTimePickerDefault,
|
|
7
|
-
);
|
|
8
|
-
|
|
9
|
-
export type { Props as DateTimePickerProps } from './DateTimePicker';
|
|
10
|
-
export { dateTimePickerStyles } from './utils';
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { StyleSheet } from 'react-native-unistyles';
|
|
2
|
-
|
|
3
|
-
import { getRegisteredComponentStylesWithFallback } from '../../core';
|
|
4
|
-
|
|
5
|
-
const dateTimePickerStylesDefault = StyleSheet.create({
|
|
6
|
-
container: {},
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
export const dateTimePickerStyles = getRegisteredComponentStylesWithFallback(
|
|
10
|
-
'DateTimePicker',
|
|
11
|
-
dateTimePickerStylesDefault,
|
|
12
|
-
);
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
import { forwardRef, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
-
import type { BlurEvent, FocusEvent } from 'react-native';
|
|
3
|
-
|
|
4
|
-
import { useToggle } from '../../hooks';
|
|
5
|
-
import { IconButton, type IconButtonProps } from '../IconButton';
|
|
6
|
-
import { TextInput, type TextInputProps } from '../TextInput';
|
|
7
|
-
import type { TimePickerModalProps } from '../TimePickerModal';
|
|
8
|
-
import { TimePickerModal } from '../TimePickerModal/TimePickerModal';
|
|
9
|
-
import { sanitizeTime } from './sanitizeTime';
|
|
10
|
-
import { getFormattedTime, getOutputTime, styles, timeFormat } from './utils';
|
|
11
|
-
|
|
12
|
-
export type Props = TextInputProps & {
|
|
13
|
-
time: string;
|
|
14
|
-
onTimeChange: (time: string) => void;
|
|
15
|
-
is24Hour?: boolean;
|
|
16
|
-
withModal?: boolean;
|
|
17
|
-
modalProps?: Omit<TimePickerModalProps, 'time' | 'onConfirm' | 'isOpen' | 'onClose' | 'ref'>;
|
|
18
|
-
iconButtonProps?: Omit<Partial<IconButtonProps>, 'onPress' | 'ref'>;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const TimePickerField = (
|
|
22
|
-
{
|
|
23
|
-
time,
|
|
24
|
-
onTimeChange: onTimeChangeProp,
|
|
25
|
-
is24Hour = false,
|
|
26
|
-
withModal = true,
|
|
27
|
-
style,
|
|
28
|
-
onBlur: onBlurProp,
|
|
29
|
-
modalProps,
|
|
30
|
-
iconButtonProps,
|
|
31
|
-
disabled,
|
|
32
|
-
onFocus: onFocusProp,
|
|
33
|
-
children,
|
|
34
|
-
...rest
|
|
35
|
-
}: Props,
|
|
36
|
-
ref: any,
|
|
37
|
-
) => {
|
|
38
|
-
const componentStyles = useMemo(() => [styles.root, style], [style]);
|
|
39
|
-
|
|
40
|
-
const [timeString, setTimeString] = useState(() => getFormattedTime({ time, is24Hour }));
|
|
41
|
-
const isBlurredRef = useRef(true);
|
|
42
|
-
|
|
43
|
-
const currentTimeFormat = useMemo(() => timeFormat[!is24Hour ? '12' : '24'], [is24Hour]);
|
|
44
|
-
|
|
45
|
-
const { state: isOpen, handleOpen: onOpenModal, handleClose: onCloseModal } = useToggle(false);
|
|
46
|
-
|
|
47
|
-
const onChangeText = useCallback(
|
|
48
|
-
(_text: string) => {
|
|
49
|
-
const text = sanitizeTime(_text, is24Hour);
|
|
50
|
-
setTimeString(_text);
|
|
51
|
-
|
|
52
|
-
if (disabled || !text) return;
|
|
53
|
-
|
|
54
|
-
const outputTime = getOutputTime({ time: text || time, is24Hour });
|
|
55
|
-
|
|
56
|
-
onTimeChangeProp(outputTime);
|
|
57
|
-
},
|
|
58
|
-
[disabled, is24Hour, onTimeChangeProp, time],
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
const onConfirmTime = useCallback(
|
|
62
|
-
(newTime: string) => {
|
|
63
|
-
onCloseModal();
|
|
64
|
-
|
|
65
|
-
onTimeChangeProp(newTime);
|
|
66
|
-
},
|
|
67
|
-
[onTimeChangeProp, onCloseModal],
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
const onBlur = useCallback(
|
|
71
|
-
(e: BlurEvent) => {
|
|
72
|
-
isBlurredRef.current = true;
|
|
73
|
-
onBlurProp?.(e);
|
|
74
|
-
|
|
75
|
-
if (disabled) return;
|
|
76
|
-
|
|
77
|
-
// const outputTime = getOutputTime({ time: timeString || time, is24Hour });
|
|
78
|
-
// onTimeChangeProp(outputTime);
|
|
79
|
-
|
|
80
|
-
// if (time === outputTime) {
|
|
81
|
-
setTimeString(sanitizeTime(getFormattedTime({ time, is24Hour }), is24Hour));
|
|
82
|
-
// }
|
|
83
|
-
},
|
|
84
|
-
[disabled, is24Hour, onBlurProp, time],
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
const onFocus = useCallback(
|
|
88
|
-
(e: FocusEvent) => {
|
|
89
|
-
isBlurredRef.current = false;
|
|
90
|
-
|
|
91
|
-
onFocusProp?.(e);
|
|
92
|
-
},
|
|
93
|
-
[onFocusProp],
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
const rightElement = useMemo(() => {
|
|
97
|
-
if (!withModal) return null;
|
|
98
|
-
|
|
99
|
-
return (
|
|
100
|
-
<>
|
|
101
|
-
<IconButton
|
|
102
|
-
name="clock-outline"
|
|
103
|
-
onPress={onOpenModal}
|
|
104
|
-
disabled={disabled}
|
|
105
|
-
{...iconButtonProps}
|
|
106
|
-
/>
|
|
107
|
-
<TimePickerModal
|
|
108
|
-
{...modalProps}
|
|
109
|
-
time={getFormattedTime({ time: time, is24Hour: true })}
|
|
110
|
-
isOpen={isOpen}
|
|
111
|
-
onClose={onCloseModal}
|
|
112
|
-
onConfirm={onConfirmTime}
|
|
113
|
-
is24Hour={is24Hour}
|
|
114
|
-
/>
|
|
115
|
-
</>
|
|
116
|
-
);
|
|
117
|
-
}, [
|
|
118
|
-
disabled,
|
|
119
|
-
iconButtonProps,
|
|
120
|
-
is24Hour,
|
|
121
|
-
isOpen,
|
|
122
|
-
modalProps,
|
|
123
|
-
onCloseModal,
|
|
124
|
-
onConfirmTime,
|
|
125
|
-
onOpenModal,
|
|
126
|
-
time,
|
|
127
|
-
withModal,
|
|
128
|
-
]);
|
|
129
|
-
|
|
130
|
-
// only change masked string when the input is not focus so as to not interrup the user
|
|
131
|
-
useEffect(() => {
|
|
132
|
-
if (!isBlurredRef.current) return;
|
|
133
|
-
|
|
134
|
-
setTimeString(getFormattedTime({ time, is24Hour }));
|
|
135
|
-
}, [is24Hour, time]);
|
|
136
|
-
|
|
137
|
-
return (
|
|
138
|
-
<TextInput
|
|
139
|
-
ref={ref}
|
|
140
|
-
placeholder={currentTimeFormat.format}
|
|
141
|
-
{...rest}
|
|
142
|
-
disabled={disabled}
|
|
143
|
-
value={timeString}
|
|
144
|
-
onFocus={onFocus}
|
|
145
|
-
onChangeText={onChangeText}
|
|
146
|
-
style={componentStyles}
|
|
147
|
-
onBlur={onBlur}>
|
|
148
|
-
<TextInput.Right>{rightElement}</TextInput.Right>
|
|
149
|
-
{children}
|
|
150
|
-
</TextInput>
|
|
151
|
-
);
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
export default memo(forwardRef(TimePickerField));
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { getRegisteredComponentWithFallback } from '../../core';
|
|
2
|
-
import TimePickerFieldDefault from './TimePickerField';
|
|
3
|
-
|
|
4
|
-
export const TimePickerField = getRegisteredComponentWithFallback(
|
|
5
|
-
'TimePickerField',
|
|
6
|
-
TimePickerFieldDefault,
|
|
7
|
-
);
|
|
8
|
-
|
|
9
|
-
export { type Props as TimePickerFieldProps } from './TimePickerField';
|
|
10
|
-
export { sanitizeTimeString, styles } from './utils';
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { format, parse, set } from 'date-fns';
|
|
2
|
-
import { StyleSheet } from 'react-native-unistyles';
|
|
3
|
-
|
|
4
|
-
export declare type MaskItem = string | RegExp | [RegExp];
|
|
5
|
-
export declare type MaskArray = Array<MaskItem>;
|
|
6
|
-
export declare type Mask = MaskArray | ((value?: string) => MaskArray);
|
|
7
|
-
|
|
8
|
-
import { getRegisteredComponentStylesWithFallback } from '../../core';
|
|
9
|
-
|
|
10
|
-
const timepickerFieldStylesDefault = StyleSheet.create({
|
|
11
|
-
root: {},
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
export const styles = getRegisteredComponentStylesWithFallback(
|
|
15
|
-
'TimePickerField',
|
|
16
|
-
timepickerFieldStylesDefault,
|
|
17
|
-
);
|
|
18
|
-
|
|
19
|
-
export const timeMask24Hour: Mask = (text: string = '') => {
|
|
20
|
-
const cleanTime = text.replace(/\D+/g, '');
|
|
21
|
-
|
|
22
|
-
const hourFirstDigit = /[012]/; // only 0,1 or 2
|
|
23
|
-
let hourSecondDigit = /\d/; // any number
|
|
24
|
-
|
|
25
|
-
if (cleanTime.charAt(0) === '2') {
|
|
26
|
-
hourSecondDigit = /[0123]/; // only 0,1,2 or 3
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const minuteFirstDigit = /[012345]/; // only 0,1,2,3,4 or 5
|
|
30
|
-
const minuteSecondDigit = /\d/; // any number
|
|
31
|
-
|
|
32
|
-
return [hourFirstDigit, hourSecondDigit, ':', minuteFirstDigit, minuteSecondDigit];
|
|
33
|
-
};
|
|
34
|
-
export const timeMask12Hour: Mask = (text: string = '') => {
|
|
35
|
-
const cleanTime = text.replace(/\D+/g, '');
|
|
36
|
-
|
|
37
|
-
const hourFirstDigit = /[01]/; // only 0,1 or 2
|
|
38
|
-
let hourSecondDigit = /\d/; // any number
|
|
39
|
-
|
|
40
|
-
if (cleanTime.charAt(0) === '1') {
|
|
41
|
-
hourSecondDigit = /[012]/; // only 0,1,2 or 3
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const minuteFirstDigit = /[012345]/; // only 0,1,2,3,4 or 5
|
|
45
|
-
const minuteSecondDigit = /\d/; // any number
|
|
46
|
-
|
|
47
|
-
return [hourFirstDigit, hourSecondDigit, ':', minuteFirstDigit, minuteSecondDigit, /[ap]/, 'm'];
|
|
48
|
-
};
|
|
49
|
-
export const timeFormat = {
|
|
50
|
-
'24': {
|
|
51
|
-
format: 'HH:mm',
|
|
52
|
-
mask: timeMask24Hour,
|
|
53
|
-
},
|
|
54
|
-
'12': {
|
|
55
|
-
format: 'hh:mmaaa',
|
|
56
|
-
mask: timeMask12Hour,
|
|
57
|
-
},
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
const referenceDate = new Date('2022-01-01T00:00:00.000Z');
|
|
61
|
-
|
|
62
|
-
export const sanitizeTimeString = (time: string): string => time.replace(/[^\d:]/g, '');
|
|
63
|
-
|
|
64
|
-
export const getFormattedTime = ({ time, is24Hour }: { time: string; is24Hour: boolean }) => {
|
|
65
|
-
if (!time) {
|
|
66
|
-
return '';
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const [hour = '0', minute = '0'] = sanitizeTimeString(time).split(':');
|
|
70
|
-
|
|
71
|
-
const newHour = hour.padStart(2, '0');
|
|
72
|
-
const newMinute = minute.padStart(2, '0');
|
|
73
|
-
|
|
74
|
-
return format(
|
|
75
|
-
set(referenceDate, { hours: +newHour, minutes: +newMinute }),
|
|
76
|
-
timeFormat[is24Hour ? '24' : '12'].format,
|
|
77
|
-
);
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
export const getOutputTime = ({ time, is24Hour }: { time: string; is24Hour: boolean }) => {
|
|
81
|
-
if (!time) return '';
|
|
82
|
-
|
|
83
|
-
const formattedTime = sanitizeTimeString(getFormattedTime({ time, is24Hour }));
|
|
84
|
-
const isPM = time.replace(/[\d:]/g, '').includes('p');
|
|
85
|
-
|
|
86
|
-
return format(
|
|
87
|
-
parse(
|
|
88
|
-
formattedTime + (is24Hour ? '' : isPM ? 'pm' : 'am'),
|
|
89
|
-
timeFormat[is24Hour ? '24' : '12'].format,
|
|
90
|
-
referenceDate,
|
|
91
|
-
),
|
|
92
|
-
'HH:mm',
|
|
93
|
-
);
|
|
94
|
-
};
|