react-native-molecules 0.5.0-beta.16 → 0.5.0-beta.18
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/Menu/Menu.tsx +3 -18
- package/components/Popover/Popover.tsx +122 -145
- package/components/Popover/PopoverRoot.tsx +74 -0
- package/components/Popover/common.ts +50 -34
- package/components/Popover/index.ts +18 -1
- package/components/Popover/usePlatformMeasure.native.ts +90 -0
- package/components/Popover/usePlatformMeasure.ts +118 -0
- package/components/Popover/utils.ts +34 -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/Popover/Popover.native.tsx +0 -185
- 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,213 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
|
-
import { type TextStyle, View } from 'react-native';
|
|
3
|
-
|
|
4
|
-
import { format } from '../../utils/date-fns';
|
|
5
|
-
import type { ModeType } from '../DatePickerInline';
|
|
6
|
-
import { IconButton } from '../IconButton';
|
|
7
|
-
import { Text } from '../Text';
|
|
8
|
-
import type { LocalState, LocalStateMultiple, LocalStateRange, LocalStateSingle } from './types';
|
|
9
|
-
import { datePickerModalContentHeaderStyles } from './utils';
|
|
10
|
-
|
|
11
|
-
export interface HeaderPickProps {
|
|
12
|
-
moreLabel?: string;
|
|
13
|
-
label?: string;
|
|
14
|
-
emptyLabel?: string;
|
|
15
|
-
saveLabel?: string;
|
|
16
|
-
uppercase?: boolean;
|
|
17
|
-
headerSeparator?: string;
|
|
18
|
-
startLabel?: string;
|
|
19
|
-
endLabel?: string;
|
|
20
|
-
editIcon?: string;
|
|
21
|
-
calendarIcon?: string;
|
|
22
|
-
closeIcon?: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface HeaderContentProps extends HeaderPickProps {
|
|
26
|
-
state: LocalState;
|
|
27
|
-
mode: ModeType;
|
|
28
|
-
collapsed: boolean;
|
|
29
|
-
onToggle: () => any;
|
|
30
|
-
// locale: string | undefined;
|
|
31
|
-
textStyle?: TextStyle;
|
|
32
|
-
separatorStyle?: TextStyle;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function getLabel(mode: ModeType, configuredLabel?: string) {
|
|
36
|
-
if (configuredLabel) {
|
|
37
|
-
return configuredLabel;
|
|
38
|
-
}
|
|
39
|
-
if (mode === 'range') {
|
|
40
|
-
return 'Select period';
|
|
41
|
-
}
|
|
42
|
-
if (mode === 'multiple') {
|
|
43
|
-
return 'Select dates';
|
|
44
|
-
}
|
|
45
|
-
if (mode === 'single') {
|
|
46
|
-
return 'Select date';
|
|
47
|
-
}
|
|
48
|
-
return '...';
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export default function DatePickerModalContentHeader(props: HeaderContentProps) {
|
|
52
|
-
const {
|
|
53
|
-
onToggle,
|
|
54
|
-
collapsed,
|
|
55
|
-
mode,
|
|
56
|
-
moreLabel,
|
|
57
|
-
uppercase,
|
|
58
|
-
editIcon = 'pencil',
|
|
59
|
-
calendarIcon = 'calendar',
|
|
60
|
-
} = props;
|
|
61
|
-
|
|
62
|
-
const label = getLabel(props.mode, props.label);
|
|
63
|
-
const allowEditing = mode !== 'multiple';
|
|
64
|
-
|
|
65
|
-
const {
|
|
66
|
-
fillContainerStyle,
|
|
67
|
-
headerContentContainerStyle,
|
|
68
|
-
headerStyle,
|
|
69
|
-
labelStyle,
|
|
70
|
-
headerTextStyle,
|
|
71
|
-
separatorStyle,
|
|
72
|
-
iconButtonStyle,
|
|
73
|
-
} = useMemo(() => {
|
|
74
|
-
const {
|
|
75
|
-
fill,
|
|
76
|
-
headerContentContainer,
|
|
77
|
-
header,
|
|
78
|
-
label: _labelStyle,
|
|
79
|
-
headerText,
|
|
80
|
-
headerSeparator,
|
|
81
|
-
icon,
|
|
82
|
-
} = datePickerModalContentHeaderStyles;
|
|
83
|
-
|
|
84
|
-
return {
|
|
85
|
-
fillContainerStyle: fill,
|
|
86
|
-
headerContentContainerStyle: headerContentContainer,
|
|
87
|
-
headerStyle: header,
|
|
88
|
-
labelStyle: _labelStyle,
|
|
89
|
-
headerTextStyle: headerText,
|
|
90
|
-
separatorStyle: headerSeparator,
|
|
91
|
-
iconButtonStyle: icon,
|
|
92
|
-
};
|
|
93
|
-
}, []);
|
|
94
|
-
|
|
95
|
-
return (
|
|
96
|
-
<View style={headerStyle}>
|
|
97
|
-
<View>
|
|
98
|
-
<Text style={labelStyle}>{uppercase ? label.toUpperCase() : label}</Text>
|
|
99
|
-
<View style={headerContentContainerStyle}>
|
|
100
|
-
<>
|
|
101
|
-
{mode === 'range' ? (
|
|
102
|
-
<HeaderContentRange
|
|
103
|
-
{...props}
|
|
104
|
-
textStyle={headerTextStyle}
|
|
105
|
-
separatorStyle={separatorStyle}
|
|
106
|
-
/>
|
|
107
|
-
) : null}
|
|
108
|
-
</>
|
|
109
|
-
<>
|
|
110
|
-
{mode === 'single' ? (
|
|
111
|
-
<HeaderContentSingle {...props} textStyle={headerTextStyle} />
|
|
112
|
-
) : null}
|
|
113
|
-
</>
|
|
114
|
-
<>
|
|
115
|
-
{mode === 'multiple' ? (
|
|
116
|
-
<HeaderContentMulti
|
|
117
|
-
{...props}
|
|
118
|
-
moreLabel={moreLabel}
|
|
119
|
-
textStyle={headerTextStyle}
|
|
120
|
-
/>
|
|
121
|
-
) : null}
|
|
122
|
-
</>
|
|
123
|
-
</View>
|
|
124
|
-
</View>
|
|
125
|
-
<View style={fillContainerStyle} />
|
|
126
|
-
<>
|
|
127
|
-
{allowEditing ? (
|
|
128
|
-
<IconButton
|
|
129
|
-
name={collapsed ? editIcon : calendarIcon}
|
|
130
|
-
accessibilityLabel={collapsed ? 'Type in date' : 'Pick date from calendar'}
|
|
131
|
-
style={iconButtonStyle}
|
|
132
|
-
onPress={onToggle}
|
|
133
|
-
/>
|
|
134
|
-
) : null}
|
|
135
|
-
</>
|
|
136
|
-
</View>
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// TODO add translations
|
|
141
|
-
export function HeaderContentSingle({
|
|
142
|
-
state,
|
|
143
|
-
emptyLabel = ' ',
|
|
144
|
-
// locale,
|
|
145
|
-
textStyle,
|
|
146
|
-
}: HeaderContentProps) {
|
|
147
|
-
const singleState = state as LocalStateSingle;
|
|
148
|
-
|
|
149
|
-
const label = useMemo(
|
|
150
|
-
() => (singleState.date ? format(singleState.date, 'LLL dd') : emptyLabel),
|
|
151
|
-
[emptyLabel, singleState.date],
|
|
152
|
-
);
|
|
153
|
-
|
|
154
|
-
return <Text style={textStyle}>{label}</Text>;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// TODO add translations
|
|
158
|
-
export function HeaderContentMulti({
|
|
159
|
-
state,
|
|
160
|
-
emptyLabel = ' ',
|
|
161
|
-
moreLabel = 'more',
|
|
162
|
-
textStyle,
|
|
163
|
-
}: // locale = 'en',
|
|
164
|
-
HeaderContentProps & { moreLabel: string | undefined }) {
|
|
165
|
-
const multiState = state as LocalStateMultiple;
|
|
166
|
-
|
|
167
|
-
const label = useMemo(() => {
|
|
168
|
-
let _label = emptyLabel;
|
|
169
|
-
const dateCount = multiState.dates?.length || 0;
|
|
170
|
-
|
|
171
|
-
if (dateCount) {
|
|
172
|
-
if (dateCount <= 2) {
|
|
173
|
-
_label = multiState.dates!.map(date => format(date, 'LLL dd')).join(', ');
|
|
174
|
-
} else {
|
|
175
|
-
_label =
|
|
176
|
-
format(multiState.dates![0], 'LLL dd') + ` (+ ${dateCount - 1} ${moreLabel})`;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
return _label;
|
|
180
|
-
}, [emptyLabel, moreLabel, multiState.dates]);
|
|
181
|
-
|
|
182
|
-
return <Text style={textStyle}>{label}</Text>;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// TODO add translations
|
|
186
|
-
export function HeaderContentRange({
|
|
187
|
-
// locale,
|
|
188
|
-
state,
|
|
189
|
-
headerSeparator = '-',
|
|
190
|
-
startLabel = 'Start',
|
|
191
|
-
endLabel = 'End',
|
|
192
|
-
textStyle,
|
|
193
|
-
separatorStyle,
|
|
194
|
-
}: HeaderContentProps) {
|
|
195
|
-
const rangeState = state as LocalStateRange;
|
|
196
|
-
|
|
197
|
-
const startDateLabel = useMemo(
|
|
198
|
-
() => (rangeState.startDate ? format(rangeState.startDate, 'LLL dd') : startLabel),
|
|
199
|
-
[rangeState.startDate, startLabel],
|
|
200
|
-
);
|
|
201
|
-
const endDateLabel = useMemo(
|
|
202
|
-
() => (rangeState.endDate ? format(rangeState.endDate, 'LLL dd') : endLabel),
|
|
203
|
-
[endLabel, rangeState.endDate],
|
|
204
|
-
);
|
|
205
|
-
|
|
206
|
-
return (
|
|
207
|
-
<>
|
|
208
|
-
<Text style={textStyle}>{startDateLabel}</Text>
|
|
209
|
-
<Text style={separatorStyle}>{headerSeparator}</Text>
|
|
210
|
-
<Text style={textStyle}>{endDateLabel}</Text>
|
|
211
|
-
</>
|
|
212
|
-
);
|
|
213
|
-
}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
|
-
import { Animated, SafeAreaView, View } from 'react-native';
|
|
3
|
-
|
|
4
|
-
import { resolveStateVariant } from '../../utils';
|
|
5
|
-
import { Button } from '../Button';
|
|
6
|
-
import { IconButton } from '../IconButton';
|
|
7
|
-
import { datePickerModalHeaderStyles } from './utils';
|
|
8
|
-
|
|
9
|
-
export interface DatePickerModalHeaderProps {
|
|
10
|
-
disableSafeTop?: boolean;
|
|
11
|
-
saveLabel?: string;
|
|
12
|
-
saveLabelDisabled?: boolean;
|
|
13
|
-
onClose: () => void;
|
|
14
|
-
onSave: () => void;
|
|
15
|
-
closeIcon?: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export default function DatePickerModalHeader(props: DatePickerModalHeaderProps) {
|
|
19
|
-
const { disableSafeTop, closeIcon = 'close' } = props;
|
|
20
|
-
|
|
21
|
-
const state = resolveStateVariant({
|
|
22
|
-
disableSafeTop: !!disableSafeTop,
|
|
23
|
-
});
|
|
24
|
-
datePickerModalHeaderStyles.useVariants({
|
|
25
|
-
state: state as any,
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
const saveLabel = props.saveLabel || 'Save';
|
|
29
|
-
|
|
30
|
-
const {
|
|
31
|
-
animatedContainerStyle,
|
|
32
|
-
safeContentStyle,
|
|
33
|
-
appBarHeaderStyle,
|
|
34
|
-
iconButtonStyle,
|
|
35
|
-
buttonStyle,
|
|
36
|
-
} = useMemo(() => {
|
|
37
|
-
const { animated, safeContent, appbarHeader } = datePickerModalHeaderStyles;
|
|
38
|
-
|
|
39
|
-
return {
|
|
40
|
-
iconButtonStyle: { color: datePickerModalHeaderStyles.root.color },
|
|
41
|
-
buttonStyle: { color: datePickerModalHeaderStyles.root.color },
|
|
42
|
-
animatedContainerStyle: animated,
|
|
43
|
-
safeContentStyle: safeContent,
|
|
44
|
-
appBarHeaderStyle: appbarHeader,
|
|
45
|
-
};
|
|
46
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
47
|
-
}, [state]);
|
|
48
|
-
|
|
49
|
-
return (
|
|
50
|
-
<>
|
|
51
|
-
<Animated.View style={animatedContainerStyle}>
|
|
52
|
-
<SafeAreaView style={safeContentStyle}>
|
|
53
|
-
<View style={appBarHeaderStyle}>
|
|
54
|
-
<IconButton
|
|
55
|
-
name={closeIcon}
|
|
56
|
-
accessibilityLabel={'Close'}
|
|
57
|
-
onPress={props.onClose}
|
|
58
|
-
style={iconButtonStyle}
|
|
59
|
-
testID="date-picker-close"
|
|
60
|
-
/>
|
|
61
|
-
<Button
|
|
62
|
-
variant="contained"
|
|
63
|
-
style={buttonStyle}
|
|
64
|
-
onPress={props.onSave}
|
|
65
|
-
disabled={props.saveLabelDisabled || false}
|
|
66
|
-
testID="dates-save">
|
|
67
|
-
<Button.Text>{saveLabel}</Button.Text>
|
|
68
|
-
</Button>
|
|
69
|
-
</View>
|
|
70
|
-
</SafeAreaView>
|
|
71
|
-
</Animated.View>
|
|
72
|
-
</>
|
|
73
|
-
);
|
|
74
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { Animated, SafeAreaView } from 'react-native';
|
|
2
|
-
|
|
3
|
-
import { datePickerModalHeaderBackgroundStyles } from './utils';
|
|
4
|
-
|
|
5
|
-
export default function DatePickerModalHeaderBackground({ children }: { children: any }) {
|
|
6
|
-
return (
|
|
7
|
-
<Animated.View style={datePickerModalHeaderBackgroundStyles.header}>
|
|
8
|
-
<SafeAreaView style={datePickerModalHeaderBackgroundStyles.safeContent}>
|
|
9
|
-
{children}
|
|
10
|
-
</SafeAreaView>
|
|
11
|
-
</Animated.View>
|
|
12
|
-
);
|
|
13
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { getRegisteredComponentWithFallback } from '../../core';
|
|
2
|
-
import DatePickerModalDefault from './DatePickerModal';
|
|
3
|
-
|
|
4
|
-
export const DatePickerModal = getRegisteredComponentWithFallback(
|
|
5
|
-
'DatePickerModal',
|
|
6
|
-
DatePickerModalDefault,
|
|
7
|
-
);
|
|
8
|
-
|
|
9
|
-
export type { DatePickerModalProps } from './types';
|
|
10
|
-
export {
|
|
11
|
-
datePickerModalContentHeaderStyles,
|
|
12
|
-
datePickerModalEditStyles,
|
|
13
|
-
datePickerModalHeaderBackgroundStyles,
|
|
14
|
-
datePickerModalHeaderStyles,
|
|
15
|
-
datePickerModalStyles,
|
|
16
|
-
} from './utils';
|
|
@@ -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));
|