react-native-molecules 0.5.0-beta.18 → 0.5.0-beta.19
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/DatePicker/utils.ts +1 -0
- package/components/DatePickerInline/HeaderItem.tsx +1 -1
- package/components/TimePicker/TimeInput.tsx +87 -37
- package/components/TimePicker/TimeInputs.tsx +131 -49
- package/components/TimePicker/TimePicker.tsx +6 -1
- package/components/TimePicker/utils.ts +43 -0
- package/package.json +1 -1
|
@@ -171,6 +171,7 @@ const datePickerModalEditStylesDefault = StyleSheet.create(theme => ({
|
|
|
171
171
|
const datePickerPopoverHeaderStylesDefault = StyleSheet.create(theme => ({
|
|
172
172
|
buttonContainer: {
|
|
173
173
|
height: 46,
|
|
174
|
+
gap: theme.spacings['2'],
|
|
174
175
|
// width: '50%',
|
|
175
176
|
flexDirection: 'row',
|
|
176
177
|
alignItems: 'center',
|
|
@@ -1,24 +1,28 @@
|
|
|
1
|
-
import { forwardRef, memo, useCallback, useMemo, useState } from 'react';
|
|
2
|
-
import {
|
|
1
|
+
import { forwardRef, memo, useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
type NativeSyntheticEvent,
|
|
4
|
+
StyleSheet,
|
|
5
|
+
TextInput as NativeTextInput,
|
|
6
|
+
type TextInputProps as NativeTextInputProps,
|
|
7
|
+
type TextInputSelectionChangeEventData,
|
|
8
|
+
View,
|
|
9
|
+
} from 'react-native';
|
|
3
10
|
|
|
4
11
|
import { useTheme } from '../../hooks';
|
|
5
12
|
import { resolveStateVariant } from '../../utils';
|
|
6
|
-
import { TextInput, type TextInputProps } from '../TextInput';
|
|
7
13
|
import { TouchableRipple } from '../TouchableRipple';
|
|
8
14
|
import { inputTypes, type PossibleClockTypes, type PossibleInputTypes } from './timeUtils';
|
|
9
15
|
import { timePickerInputStyles } from './utils';
|
|
10
16
|
|
|
11
|
-
interface TimeInputProps
|
|
12
|
-
extends Omit<
|
|
13
|
-
Omit<TextInputProps, 'value' | 'variant' | 'onChangeText' | 'onPress'>,
|
|
14
|
-
'onFocus'
|
|
15
|
-
> {
|
|
17
|
+
interface TimeInputProps extends Omit<NativeTextInputProps, 'value' | 'onChangeText' | 'onPress'> {
|
|
16
18
|
value: number;
|
|
17
19
|
clockType: PossibleClockTypes;
|
|
18
20
|
onPress?: (type: PossibleClockTypes) => any;
|
|
19
21
|
pressed: boolean;
|
|
20
|
-
onChanged: (n: number) => any;
|
|
22
|
+
onChanged: (n: number, text: string) => any;
|
|
21
23
|
inputType: PossibleInputTypes;
|
|
24
|
+
error?: boolean;
|
|
25
|
+
inputStyle?: NativeTextInputProps['style'];
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
function TimeInput(
|
|
@@ -29,18 +33,22 @@ function TimeInput(
|
|
|
29
33
|
onPress,
|
|
30
34
|
onChanged,
|
|
31
35
|
inputType,
|
|
36
|
+
error = false,
|
|
32
37
|
inputStyle,
|
|
33
38
|
style,
|
|
34
39
|
...rest
|
|
35
40
|
}: TimeInputProps,
|
|
36
41
|
ref: any,
|
|
37
42
|
) {
|
|
38
|
-
const onInnerChange = (text: string) => {
|
|
39
|
-
onChanged(Number(text));
|
|
40
|
-
};
|
|
41
|
-
|
|
42
43
|
const theme = useTheme();
|
|
43
44
|
const [inputFocused, setInputFocused] = useState<boolean>(false);
|
|
45
|
+
const [rawText, setRawText] = useState<string | null>(null);
|
|
46
|
+
const [selection, setSelection] = useState<{ start: number; end: number } | undefined>();
|
|
47
|
+
|
|
48
|
+
const onInnerChange = (text: string) => {
|
|
49
|
+
setRawText(text);
|
|
50
|
+
onChanged(Number(text), text);
|
|
51
|
+
};
|
|
44
52
|
|
|
45
53
|
const highlighted = inputType === inputTypes.picker ? pressed : inputFocused;
|
|
46
54
|
|
|
@@ -52,46 +60,88 @@ function TimeInput(
|
|
|
52
60
|
});
|
|
53
61
|
|
|
54
62
|
const formattedValue = useMemo(() => {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (!inputFocused) {
|
|
58
|
-
_formattedValue = `${value}`.length === 1 ? `0${value}` : `${value}`;
|
|
59
|
-
}
|
|
63
|
+
if (rawText !== null && (inputFocused || error)) return rawText;
|
|
60
64
|
|
|
61
|
-
|
|
62
|
-
|
|
65
|
+
const str = `${value}`;
|
|
66
|
+
return str.length === 1 ? `0${str}` : str;
|
|
67
|
+
}, [value, inputFocused, rawText, error]);
|
|
63
68
|
|
|
64
|
-
const { rippleColor, containerStyle,
|
|
65
|
-
|
|
66
|
-
|
|
69
|
+
const { rippleColor, containerStyle, textInputStyle, buttonStyle } = useMemo(() => {
|
|
70
|
+
const {
|
|
71
|
+
container,
|
|
72
|
+
input,
|
|
73
|
+
keyboardInput,
|
|
74
|
+
keyboardInputHighlighted,
|
|
75
|
+
inputError,
|
|
76
|
+
keyboardInputError,
|
|
77
|
+
button,
|
|
78
|
+
} = timePickerInputStyles;
|
|
79
|
+
const isKeyboardInput = inputType === inputTypes.keyboard;
|
|
67
80
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
81
|
+
return {
|
|
82
|
+
rippleColor: timePickerInputStyles.root?._rippleColor,
|
|
83
|
+
containerStyle: container,
|
|
84
|
+
textInputStyle: [
|
|
85
|
+
input,
|
|
86
|
+
isKeyboardInput ? keyboardInput : null,
|
|
87
|
+
isKeyboardInput && highlighted ? keyboardInputHighlighted : null,
|
|
88
|
+
error ? inputError : null,
|
|
89
|
+
isKeyboardInput && error ? keyboardInputError : null,
|
|
90
|
+
style,
|
|
91
|
+
inputStyle,
|
|
92
|
+
],
|
|
93
|
+
buttonStyle: [StyleSheet.absoluteFill, button],
|
|
94
|
+
};
|
|
95
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
96
|
+
}, [error, highlighted, inputStyle, inputType, style, state]);
|
|
77
97
|
|
|
78
98
|
const onFocus = useCallback(() => setInputFocused(true), []);
|
|
79
|
-
|
|
99
|
+
|
|
100
|
+
const onBlur = useCallback(() => {
|
|
101
|
+
setInputFocused(false);
|
|
102
|
+
setSelection(undefined);
|
|
103
|
+
if (!error) {
|
|
104
|
+
setRawText(null);
|
|
105
|
+
}
|
|
106
|
+
}, [error]);
|
|
107
|
+
|
|
80
108
|
const onPressInput = useCallback(() => onPress?.(clockType), [clockType, onPress]);
|
|
81
109
|
|
|
110
|
+
const onSelectionChange = useCallback(
|
|
111
|
+
(e: NativeSyntheticEvent<TextInputSelectionChangeEventData>) => {
|
|
112
|
+
if (selection) {
|
|
113
|
+
setSelection(undefined);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
rest.onSelectionChange?.(e);
|
|
117
|
+
},
|
|
118
|
+
[rest, selection],
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
useEffect(() => {
|
|
122
|
+
if (error && inputFocused && rawText?.length) {
|
|
123
|
+
setSelection({ start: 0, end: rawText.length });
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
setSelection(undefined);
|
|
128
|
+
}, [error, inputFocused, rawText]);
|
|
129
|
+
|
|
82
130
|
return (
|
|
83
131
|
<View style={containerStyle}>
|
|
84
|
-
<
|
|
85
|
-
variant="plain"
|
|
132
|
+
<NativeTextInput
|
|
86
133
|
ref={ref}
|
|
87
|
-
inputStyle={textInputStyle}
|
|
88
|
-
style={textInputContainerStyle}
|
|
89
134
|
onFocus={onFocus}
|
|
90
135
|
onBlur={onBlur}
|
|
91
136
|
keyboardAppearance={theme.dark ? 'dark' : 'default'}
|
|
92
137
|
value={formattedValue}
|
|
93
138
|
maxLength={2}
|
|
139
|
+
placeholderTextColor={theme.colors.onSurfaceVariant}
|
|
140
|
+
selectTextOnFocus={inputType === inputTypes.picker || error}
|
|
141
|
+
selection={selection}
|
|
142
|
+
onSelectionChange={onSelectionChange}
|
|
94
143
|
onChangeText={onInnerChange}
|
|
144
|
+
style={textInputStyle}
|
|
95
145
|
{...rest}
|
|
96
146
|
/>
|
|
97
147
|
<>
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// @typescript-eslint/no-unused-vars
|
|
2
2
|
// WORK IN PROGRESS
|
|
3
3
|
|
|
4
|
-
import { memo, useCallback, useRef } from 'react';
|
|
4
|
+
import { memo, useCallback, useEffect, useRef, useState } from 'react';
|
|
5
5
|
import { TextInput as TextInputNative, useWindowDimensions, View } from 'react-native';
|
|
6
6
|
|
|
7
7
|
import { useLatest } from '../../hooks';
|
|
8
8
|
import { resolveStateVariant } from '../../utils';
|
|
9
|
+
import { Text } from '../Text';
|
|
9
10
|
import AmPmSwitcher from './AmPmSwitcher';
|
|
10
11
|
import TimeInput from './TimeInput';
|
|
11
12
|
import {
|
|
@@ -41,6 +42,8 @@ function TimeInputs({
|
|
|
41
42
|
}: Props) {
|
|
42
43
|
const dimensions = useWindowDimensions();
|
|
43
44
|
const isLandscape = dimensions.width > dimensions.height;
|
|
45
|
+
const [hourError, setHourError] = useState(false);
|
|
46
|
+
const [minuteError, setMinuteError] = useState(false);
|
|
44
47
|
|
|
45
48
|
timePickerInputsStyles.useVariants({
|
|
46
49
|
state: resolveStateVariant({
|
|
@@ -50,6 +53,17 @@ function TimeInputs({
|
|
|
50
53
|
const startInput = useRef<TextInputNative | null>(null);
|
|
51
54
|
const endInput = useRef<TextInputNative | null>(null);
|
|
52
55
|
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (inputType !== 'keyboard') {
|
|
58
|
+
setHourError(false);
|
|
59
|
+
setMinuteError(false);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const id = setTimeout(() => startInput.current?.focus(), 0);
|
|
64
|
+
return () => clearTimeout(id);
|
|
65
|
+
}, [inputType]);
|
|
66
|
+
|
|
53
67
|
const onSubmitStartInput = useCallback(() => {
|
|
54
68
|
if (endInput.current) {
|
|
55
69
|
endInput.current.focus();
|
|
@@ -61,6 +75,9 @@ function TimeInputs({
|
|
|
61
75
|
}, []);
|
|
62
76
|
|
|
63
77
|
const minutesRef = useLatest(minutes);
|
|
78
|
+
const isPm = hours >= 12;
|
|
79
|
+
const hourErrorText = is24Hour ? 'Hour must be 0-23' : 'Hour must be 1-12';
|
|
80
|
+
const minuteErrorText = 'Minute must be 0-59';
|
|
64
81
|
const onChangeHours = useCallback(
|
|
65
82
|
(newHours: number) => {
|
|
66
83
|
onChange({
|
|
@@ -73,74 +90,139 @@ function TimeInputs({
|
|
|
73
90
|
);
|
|
74
91
|
|
|
75
92
|
const onHourChange = useCallback(
|
|
76
|
-
(newHoursFromInput: number) => {
|
|
93
|
+
(newHoursFromInput: number, text: string) => {
|
|
94
|
+
if (text.length === 0) {
|
|
95
|
+
setHourError(false);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const isNumeric = /^\d+$/.test(text);
|
|
100
|
+
const minHours = is24Hour ? 0 : 1;
|
|
101
|
+
const maxHours = is24Hour ? 23 : 12;
|
|
102
|
+
const isValid =
|
|
103
|
+
isNumeric && newHoursFromInput >= minHours && newHoursFromInput <= maxHours;
|
|
104
|
+
|
|
105
|
+
setHourError(!isValid);
|
|
106
|
+
|
|
107
|
+
if (!isValid) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
77
111
|
let newHours = newHoursFromInput;
|
|
78
|
-
if (
|
|
79
|
-
|
|
112
|
+
if (!is24Hour) {
|
|
113
|
+
if (isPm) {
|
|
114
|
+
newHours = newHoursFromInput === 12 ? 12 : newHoursFromInput + 12;
|
|
115
|
+
} else {
|
|
116
|
+
newHours = newHoursFromInput === 12 ? 0 : newHoursFromInput;
|
|
117
|
+
}
|
|
80
118
|
}
|
|
119
|
+
|
|
81
120
|
onChange({
|
|
82
121
|
hours: newHours,
|
|
83
|
-
minutes,
|
|
122
|
+
minutes: minutesRef.current,
|
|
84
123
|
});
|
|
124
|
+
|
|
125
|
+
const maxStartDigit = is24Hour ? 2 : 1;
|
|
126
|
+
const shouldAdvance = text.length >= 2 || newHoursFromInput > maxStartDigit;
|
|
127
|
+
if (shouldAdvance) endInput.current?.focus();
|
|
85
128
|
},
|
|
86
|
-
[
|
|
129
|
+
[is24Hour, isPm, minutesRef, onChange],
|
|
87
130
|
);
|
|
88
131
|
|
|
89
132
|
const onMinuteChange = useCallback(
|
|
90
|
-
(newMinutesFromInput: number) => {
|
|
91
|
-
|
|
133
|
+
(newMinutesFromInput: number, text: string) => {
|
|
134
|
+
if (text.length === 0) {
|
|
135
|
+
setMinuteError(false);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const isNumeric = /^\d+$/.test(text);
|
|
140
|
+
const isValid = isNumeric && newMinutesFromInput >= 0 && newMinutesFromInput <= 59;
|
|
92
141
|
|
|
93
|
-
|
|
94
|
-
|
|
142
|
+
setMinuteError(!isValid);
|
|
143
|
+
|
|
144
|
+
if (!isValid) {
|
|
145
|
+
return;
|
|
95
146
|
}
|
|
147
|
+
|
|
96
148
|
onChange({
|
|
97
149
|
hours: hours,
|
|
98
|
-
minutes:
|
|
150
|
+
minutes: newMinutesFromInput,
|
|
99
151
|
});
|
|
100
152
|
},
|
|
101
153
|
[hours, onChange],
|
|
102
154
|
);
|
|
103
155
|
|
|
104
156
|
return (
|
|
105
|
-
<View style={timePickerInputsStyles.
|
|
106
|
-
<
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
<View style={timePickerInputsStyles.
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
157
|
+
<View style={timePickerInputsStyles.wrapper}>
|
|
158
|
+
<View style={timePickerInputsStyles.inputContainer}>
|
|
159
|
+
<TimeInput
|
|
160
|
+
ref={startInput}
|
|
161
|
+
placeholder={''}
|
|
162
|
+
value={toHourInputFormat(hours, is24Hour)}
|
|
163
|
+
clockType={clockTypes.hours}
|
|
164
|
+
pressed={focused === clockTypes.hours}
|
|
165
|
+
onPress={onFocusInput}
|
|
166
|
+
inputType={inputType}
|
|
167
|
+
returnKeyType={'next'}
|
|
168
|
+
onSubmitEditing={onSubmitStartInput}
|
|
169
|
+
blurOnSubmit={false}
|
|
170
|
+
error={hourError}
|
|
171
|
+
onChanged={onHourChange}
|
|
172
|
+
// onChangeText={onChangeStartInput}
|
|
173
|
+
/>
|
|
174
|
+
<View style={timePickerInputsStyles.hoursAndMinutesSeparator}>
|
|
175
|
+
<View style={timePickerInputsStyles.spaceDot} />
|
|
176
|
+
<View style={timePickerInputsStyles.dot} />
|
|
177
|
+
<View style={timePickerInputsStyles.betweenDot} />
|
|
178
|
+
<View style={timePickerInputsStyles.dot} />
|
|
179
|
+
<View style={timePickerInputsStyles.spaceDot} />
|
|
180
|
+
</View>
|
|
181
|
+
<TimeInput
|
|
182
|
+
ref={endInput}
|
|
183
|
+
placeholder={'00'}
|
|
184
|
+
value={minutes}
|
|
185
|
+
clockType={clockTypes.minutes}
|
|
186
|
+
pressed={focused === clockTypes.minutes}
|
|
187
|
+
onPress={onFocusInput}
|
|
188
|
+
inputType={inputType}
|
|
189
|
+
error={minuteError}
|
|
190
|
+
onSubmitEditing={onSubmitEndInput}
|
|
191
|
+
onChanged={onMinuteChange}
|
|
192
|
+
/>
|
|
193
|
+
{!is24Hour && (
|
|
194
|
+
<>
|
|
195
|
+
<View style={timePickerInputsStyles.spaceBetweenInputsAndSwitcher} />
|
|
196
|
+
<AmPmSwitcher hours={hours} onChange={onChangeHours} />
|
|
197
|
+
</>
|
|
198
|
+
)}
|
|
126
199
|
</View>
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
200
|
+
{inputType === 'keyboard' ? (
|
|
201
|
+
<View style={timePickerInputsStyles.supportingRow}>
|
|
202
|
+
<View style={timePickerInputsStyles.supportingSlot}>
|
|
203
|
+
<Text
|
|
204
|
+
style={[
|
|
205
|
+
timePickerInputsStyles.supportingText,
|
|
206
|
+
hourError ? timePickerInputsStyles.supportingTextError : null,
|
|
207
|
+
]}>
|
|
208
|
+
{hourError ? hourErrorText : 'Hour'}
|
|
209
|
+
</Text>
|
|
210
|
+
</View>
|
|
211
|
+
<View style={timePickerInputsStyles.hoursAndMinutesSeparator} />
|
|
212
|
+
<View style={timePickerInputsStyles.supportingSlot}>
|
|
213
|
+
<Text
|
|
214
|
+
style={[
|
|
215
|
+
timePickerInputsStyles.supportingText,
|
|
216
|
+
minuteError ? timePickerInputsStyles.supportingTextError : null,
|
|
217
|
+
]}>
|
|
218
|
+
{minuteError ? minuteErrorText : 'Minute'}
|
|
219
|
+
</Text>
|
|
220
|
+
</View>
|
|
221
|
+
{!is24Hour && (
|
|
222
|
+
<View style={timePickerInputsStyles.spaceBetweenInputsAndSwitcher} />
|
|
223
|
+
)}
|
|
224
|
+
</View>
|
|
225
|
+
) : null}
|
|
144
226
|
</View>
|
|
145
227
|
);
|
|
146
228
|
}
|
|
@@ -121,6 +121,11 @@ function TimePicker({
|
|
|
121
121
|
|
|
122
122
|
if (newDisplayMode !== displayMode) setDisplayMode(newDisplayMode);
|
|
123
123
|
|
|
124
|
+
if (params.focused) {
|
|
125
|
+
const nextFocused = params.focused;
|
|
126
|
+
setTimeout(() => onFocusInput(nextFocused), 300);
|
|
127
|
+
}
|
|
128
|
+
|
|
124
129
|
onTimeChange?.({
|
|
125
130
|
time: `${`${params.hours}`.padStart(2, '0')}:${`${params.minutes}`.padStart(
|
|
126
131
|
2,
|
|
@@ -129,7 +134,7 @@ function TimePicker({
|
|
|
129
134
|
focused: params.focused,
|
|
130
135
|
});
|
|
131
136
|
},
|
|
132
|
-
[displayMode, onTimeChange],
|
|
137
|
+
[displayMode, onFocusInput, onTimeChange],
|
|
133
138
|
);
|
|
134
139
|
|
|
135
140
|
const memoizedValue = useMemo(
|
|
@@ -41,6 +41,9 @@ const timePickerStylesDefault = StyleSheet.create(theme => ({
|
|
|
41
41
|
|
|
42
42
|
const timePickerInputsStylesDefault = StyleSheet.create(theme => ({
|
|
43
43
|
spaceBetweenInputsAndSwitcher: { width: 12 },
|
|
44
|
+
wrapper: {
|
|
45
|
+
alignItems: 'center',
|
|
46
|
+
},
|
|
44
47
|
inputContainer: {
|
|
45
48
|
flexDirection: 'row',
|
|
46
49
|
alignItems: 'center',
|
|
@@ -70,6 +73,27 @@ const timePickerInputsStylesDefault = StyleSheet.create(theme => ({
|
|
|
70
73
|
betweenDot: {
|
|
71
74
|
height: 12,
|
|
72
75
|
},
|
|
76
|
+
supportingRow: {
|
|
77
|
+
flexDirection: 'row',
|
|
78
|
+
alignItems: 'flex-start',
|
|
79
|
+
width: '100%',
|
|
80
|
+
marginTop: 2,
|
|
81
|
+
},
|
|
82
|
+
supportingSlot: {
|
|
83
|
+
width: 96,
|
|
84
|
+
minHeight: theme.typescale.bodyMedium.lineHeight * 2,
|
|
85
|
+
},
|
|
86
|
+
supportingText: {
|
|
87
|
+
...theme.typescale.bodyMedium,
|
|
88
|
+
fontSize: 12,
|
|
89
|
+
lineHeight: 16,
|
|
90
|
+
color: theme.colors.onSurfaceVariant,
|
|
91
|
+
textAlign: 'left',
|
|
92
|
+
paddingHorizontal: theme.spacings['1'],
|
|
93
|
+
},
|
|
94
|
+
supportingTextError: {
|
|
95
|
+
color: theme.colors.error,
|
|
96
|
+
},
|
|
73
97
|
}));
|
|
74
98
|
|
|
75
99
|
const timePickerInputStylesDefault = StyleSheet.create(theme => ({
|
|
@@ -91,6 +115,10 @@ const timePickerInputStylesDefault = StyleSheet.create(theme => ({
|
|
|
91
115
|
color: theme.colors.onSurface,
|
|
92
116
|
borderRadius: theme.shapes.corner.small,
|
|
93
117
|
|
|
118
|
+
_web: {
|
|
119
|
+
outline: 'none',
|
|
120
|
+
},
|
|
121
|
+
|
|
94
122
|
variants: {
|
|
95
123
|
state: {
|
|
96
124
|
highlighted: {
|
|
@@ -100,6 +128,20 @@ const timePickerInputStylesDefault = StyleSheet.create(theme => ({
|
|
|
100
128
|
},
|
|
101
129
|
},
|
|
102
130
|
},
|
|
131
|
+
keyboardInput: {
|
|
132
|
+
borderWidth: 2,
|
|
133
|
+
borderColor: 'transparent',
|
|
134
|
+
},
|
|
135
|
+
keyboardInputHighlighted: {
|
|
136
|
+
borderColor: theme.colors.primary,
|
|
137
|
+
},
|
|
138
|
+
inputError: {
|
|
139
|
+
backgroundColor: theme.colors.errorContainer,
|
|
140
|
+
color: theme.colors.onErrorContainer,
|
|
141
|
+
},
|
|
142
|
+
keyboardInputError: {
|
|
143
|
+
borderColor: theme.colors.error,
|
|
144
|
+
},
|
|
103
145
|
button: {
|
|
104
146
|
overflow: 'hidden',
|
|
105
147
|
borderRadius: theme.shapes.corner.small,
|
|
@@ -253,6 +295,7 @@ const timePickerModalStylesDefault = StyleSheet.create(theme => ({
|
|
|
253
295
|
timePickerContainer: {
|
|
254
296
|
padding: theme.spacings['6'],
|
|
255
297
|
paddingTop: theme.spacings['2'],
|
|
298
|
+
paddingBottom: 0,
|
|
256
299
|
},
|
|
257
300
|
footer: {
|
|
258
301
|
flexDirection: 'row',
|