@draftbit/core 48.4.5-facee4.2 → 48.4.6-959edf.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/lib/commonjs/components/BottomSheet/BottomSheet.js +1 -1
- package/lib/commonjs/components/Picker/Picker.js +1 -1
- package/lib/commonjs/components/Picker/PickerComponent.android.js +1 -0
- package/lib/commonjs/components/Picker/PickerComponent.ios.js +1 -0
- package/lib/commonjs/components/Picker/PickerComponent.web.js +1 -0
- package/lib/commonjs/components/TextField.js +1 -1
- package/lib/typescript/src/components/BottomSheet/BottomSheet.d.ts +3 -2
- package/lib/typescript/src/components/BottomSheet/BottomSheet.js +3 -3
- package/lib/typescript/src/components/BottomSheet/BottomSheet.js.map +1 -1
- package/lib/typescript/src/components/Picker/Picker.d.ts +10 -4
- package/lib/typescript/src/components/Picker/Picker.js +243 -84
- package/lib/typescript/src/components/Picker/Picker.js.map +1 -1
- package/lib/typescript/src/components/Picker/PickerComponent.android.d.ts +6 -0
- package/lib/typescript/src/components/Picker/PickerComponent.android.js +70 -0
- package/lib/typescript/src/components/Picker/PickerComponent.android.js.map +1 -0
- package/lib/typescript/src/components/Picker/PickerComponent.ios.d.ts +7 -0
- package/lib/typescript/src/components/Picker/PickerComponent.ios.js +80 -0
- package/lib/typescript/src/components/Picker/PickerComponent.ios.js.map +1 -0
- package/lib/typescript/src/components/Picker/PickerComponent.web.d.ts +6 -0
- package/lib/typescript/src/components/Picker/PickerComponent.web.js +71 -0
- package/lib/typescript/src/components/Picker/PickerComponent.web.js.map +1 -0
- package/lib/typescript/src/components/TextField.d.ts +3 -3
- package/lib/typescript/src/components/TextField.js +6 -9
- package/lib/typescript/src/components/TextField.js.map +1 -1
- package/lib/typescript/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/components/BottomSheet/BottomSheet.js +3 -3
- package/src/components/BottomSheet/BottomSheet.js.map +1 -1
- package/src/components/BottomSheet/BottomSheet.tsx +90 -81
- package/src/components/Picker/Picker.js +243 -84
- package/src/components/Picker/Picker.js.map +1 -1
- package/src/components/Picker/Picker.tsx +401 -134
- package/src/components/Picker/PickerComponent.android.js +70 -0
- package/src/components/Picker/PickerComponent.android.js.map +1 -0
- package/src/components/Picker/PickerComponent.android.tsx +116 -0
- package/src/components/Picker/PickerComponent.ios.js +80 -0
- package/src/components/Picker/PickerComponent.ios.js.map +1 -0
- package/src/components/Picker/PickerComponent.ios.tsx +142 -0
- package/src/components/Picker/PickerComponent.web.js +71 -0
- package/src/components/Picker/PickerComponent.web.js.map +1 -0
- package/src/components/Picker/PickerComponent.web.tsx +117 -0
- package/src/components/TextField.js +6 -9
- package/src/components/TextField.js.map +1 -1
- package/src/components/TextField.tsx +8 -14
|
@@ -2,26 +2,29 @@ import * as React from "react";
|
|
|
2
2
|
import {
|
|
3
3
|
View,
|
|
4
4
|
StyleSheet,
|
|
5
|
+
Text,
|
|
5
6
|
Platform,
|
|
6
7
|
ViewStyle,
|
|
7
8
|
StyleProp,
|
|
9
|
+
Dimensions,
|
|
8
10
|
Keyboard,
|
|
9
11
|
} from "react-native";
|
|
10
|
-
import { isObject } from "lodash";
|
|
12
|
+
import { omit, pickBy, identity, isObject } from "lodash";
|
|
11
13
|
import { SafeAreaView } from "react-native-safe-area-context";
|
|
12
14
|
import { Picker as NativePicker } from "@react-native-picker/picker";
|
|
15
|
+
|
|
16
|
+
import { withTheme } from "../../theming";
|
|
13
17
|
import Portal from "../Portal/Portal";
|
|
14
|
-
import
|
|
18
|
+
import Button from "../../deprecated-components/DeprecatedButton";
|
|
15
19
|
import Touchable from "../Touchable";
|
|
20
|
+
import type { Theme } from "../../styles/DefaultTheme";
|
|
16
21
|
import type { IconSlot } from "../../interfaces/Icon";
|
|
17
22
|
import {
|
|
23
|
+
extractStyles,
|
|
18
24
|
extractBorderAndMarginStyles,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
extractPositionStyles,
|
|
25
|
+
borderStyleNames,
|
|
26
|
+
marginStyleNames,
|
|
22
27
|
} from "../../utilities";
|
|
23
|
-
import TextField from "../TextField";
|
|
24
|
-
import omit from "lodash.omit";
|
|
25
28
|
|
|
26
29
|
export interface PickerOption {
|
|
27
30
|
value: string;
|
|
@@ -35,7 +38,8 @@ export type PickerProps = {
|
|
|
35
38
|
style?: StyleProp<ViewStyle> & { height?: number };
|
|
36
39
|
value?: string;
|
|
37
40
|
options: PickerOption[] | string[];
|
|
38
|
-
onValueChange: (value: string) => void;
|
|
41
|
+
onValueChange: (value: string, index: number) => void;
|
|
42
|
+
defaultValue?: string;
|
|
39
43
|
assistiveText?: string;
|
|
40
44
|
label?: string;
|
|
41
45
|
iconColor?: string;
|
|
@@ -46,145 +50,427 @@ export type PickerProps = {
|
|
|
46
50
|
rightIconName?: string;
|
|
47
51
|
type?: "solid" | "underline";
|
|
48
52
|
autoDismissKeyboard?: boolean;
|
|
49
|
-
|
|
53
|
+
theme: Theme;
|
|
54
|
+
Icon: IconSlot["Icon"];
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
function normalizeOptions(options: PickerProps["options"]): PickerOption[] {
|
|
58
|
+
if (options.length === 0) {
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (typeof options[0] === ("string" || "number")) {
|
|
63
|
+
return (options as string[]).map((option) => ({
|
|
64
|
+
label: String(option),
|
|
65
|
+
value: String(option),
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (
|
|
70
|
+
isObject(options[0]) &&
|
|
71
|
+
options[0].value !== null &&
|
|
72
|
+
options[0].label !== null
|
|
73
|
+
) {
|
|
74
|
+
return (options as PickerOption[]).map((option) => {
|
|
75
|
+
return {
|
|
76
|
+
label: String(option.label),
|
|
77
|
+
value: String(option.value),
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
}
|
|
50
81
|
|
|
82
|
+
throw new Error(
|
|
83
|
+
'Picker options must be either an array of strings or array of { "label": string; "value": string; } objects.'
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const { width: deviceWidth, height: deviceHeight } = Dimensions.get("screen");
|
|
51
88
|
const isIos = Platform.OS === "ios";
|
|
52
89
|
const isWeb = Platform.OS === "web";
|
|
53
90
|
|
|
91
|
+
const unstyledColor = "rgba(165, 173, 183, 1)";
|
|
92
|
+
const disabledColor = "rgb(240, 240, 240)";
|
|
93
|
+
const errorColor = "rgba(255, 69, 100, 1)";
|
|
94
|
+
|
|
95
|
+
//Empty string for 'value' is treated as a non-value
|
|
96
|
+
//reason: Draftbit uses empty string as initial value for string state*/
|
|
54
97
|
const Picker: React.FC<PickerProps> = ({
|
|
55
|
-
|
|
98
|
+
error,
|
|
99
|
+
options = [],
|
|
56
100
|
onValueChange,
|
|
101
|
+
defaultValue,
|
|
57
102
|
Icon,
|
|
58
103
|
style,
|
|
59
104
|
placeholder,
|
|
60
105
|
value,
|
|
61
106
|
disabled = false,
|
|
107
|
+
assistiveText,
|
|
108
|
+
label,
|
|
109
|
+
iconColor = unstyledColor,
|
|
110
|
+
iconSize = 24,
|
|
111
|
+
leftIconMode = "inset",
|
|
112
|
+
leftIconName,
|
|
113
|
+
placeholderTextColor = unstyledColor,
|
|
114
|
+
rightIconName,
|
|
115
|
+
type = "solid",
|
|
62
116
|
autoDismissKeyboard = true,
|
|
63
|
-
...rest
|
|
64
117
|
}) => {
|
|
65
|
-
const
|
|
118
|
+
const androidPickerRef = React.useRef<any | undefined>(undefined);
|
|
119
|
+
|
|
120
|
+
const [internalValue, setInternalValue] = React.useState<string | undefined>(
|
|
121
|
+
value || defaultValue
|
|
122
|
+
);
|
|
66
123
|
|
|
67
124
|
const [pickerVisible, setPickerVisible] = React.useState(false);
|
|
68
125
|
|
|
69
|
-
const
|
|
70
|
-
|
|
126
|
+
const togglePickerVisible = () => {
|
|
127
|
+
setPickerVisible(!pickerVisible);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
React.useEffect(() => {
|
|
131
|
+
if (value != null && value !== "") {
|
|
132
|
+
setInternalValue(value);
|
|
133
|
+
} else if (value === "") {
|
|
134
|
+
setInternalValue(undefined);
|
|
135
|
+
}
|
|
136
|
+
}, [value]);
|
|
71
137
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
return [{ label: placeholder, value: placeholder }, ...normalizedOptions];
|
|
76
|
-
} else {
|
|
77
|
-
return normalizedOptions;
|
|
138
|
+
React.useEffect(() => {
|
|
139
|
+
if (defaultValue != null && defaultValue !== "") {
|
|
140
|
+
setInternalValue(defaultValue);
|
|
78
141
|
}
|
|
79
|
-
}, [
|
|
142
|
+
}, [defaultValue]);
|
|
80
143
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
144
|
+
React.useEffect(() => {
|
|
145
|
+
if (pickerVisible && androidPickerRef.current) {
|
|
146
|
+
androidPickerRef?.current?.focus();
|
|
147
|
+
}
|
|
148
|
+
}, [pickerVisible, androidPickerRef]);
|
|
149
|
+
|
|
150
|
+
React.useEffect(() => {
|
|
151
|
+
if (pickerVisible && autoDismissKeyboard) {
|
|
152
|
+
Keyboard.dismiss();
|
|
153
|
+
}
|
|
154
|
+
}, [pickerVisible, autoDismissKeyboard]);
|
|
155
|
+
|
|
156
|
+
const normalizedOptions = React.useMemo(
|
|
157
|
+
() => normalizeOptions(options),
|
|
158
|
+
[options]
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
//Underlying Picker component defaults selection to first element when value is not provided (or undefined)
|
|
162
|
+
//Placholder must be the 1st option in order to allow selection of the 'actual' 1st option
|
|
163
|
+
const pickerOptions = React.useMemo(
|
|
164
|
+
() =>
|
|
165
|
+
placeholder
|
|
166
|
+
? [{ label: placeholder, value: placeholder }, ...normalizedOptions]
|
|
167
|
+
: normalizedOptions,
|
|
168
|
+
[placeholder, normalizedOptions]
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
//When no placeholder is provided then first item should be marked selected to reflect underlying Picker internal state
|
|
172
|
+
if (
|
|
173
|
+
!placeholder &&
|
|
174
|
+
pickerOptions.length &&
|
|
175
|
+
!internalValue &&
|
|
176
|
+
internalValue !== pickerOptions[0].value //Prevent infinite state changes incase first value is falsy
|
|
177
|
+
) {
|
|
178
|
+
onValueChange?.(pickerOptions[0].value, 0);
|
|
179
|
+
setInternalValue(pickerOptions[0].value);
|
|
84
180
|
}
|
|
85
181
|
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
182
|
+
const { viewStyles, textStyles } = extractStyles(style);
|
|
183
|
+
|
|
184
|
+
const additionalBorderStyles = ["backgroundColor"];
|
|
185
|
+
|
|
186
|
+
const additionalMarginStyles = [
|
|
187
|
+
"bottom",
|
|
188
|
+
"height",
|
|
189
|
+
"left",
|
|
190
|
+
"maxHeight",
|
|
191
|
+
"maxWidth",
|
|
192
|
+
"minHeight",
|
|
193
|
+
"minWidth",
|
|
194
|
+
"overflow",
|
|
195
|
+
"position",
|
|
196
|
+
"right",
|
|
197
|
+
"top",
|
|
198
|
+
"width",
|
|
199
|
+
"zIndex",
|
|
200
|
+
];
|
|
201
|
+
|
|
202
|
+
const {
|
|
203
|
+
borderStyles: extractedBorderStyles,
|
|
204
|
+
marginStyles: extractedMarginStyles,
|
|
205
|
+
} = extractBorderAndMarginStyles(
|
|
206
|
+
viewStyles,
|
|
207
|
+
additionalBorderStyles,
|
|
208
|
+
additionalMarginStyles
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
const borderStyles = {
|
|
212
|
+
...{
|
|
213
|
+
...(type === "solid"
|
|
214
|
+
? {
|
|
215
|
+
borderTopLeftRadius: 5,
|
|
216
|
+
borderTopRightRadius: 5,
|
|
217
|
+
borderBottomRightRadius: 5,
|
|
218
|
+
borderBottomLeftRadius: 5,
|
|
219
|
+
borderTopWidth: 1,
|
|
220
|
+
borderRightWidth: 1,
|
|
221
|
+
borderLeftWidth: 1,
|
|
222
|
+
}
|
|
223
|
+
: {}),
|
|
224
|
+
borderBottomWidth: 1,
|
|
225
|
+
borderColor: unstyledColor,
|
|
226
|
+
borderStyle: "solid",
|
|
227
|
+
},
|
|
228
|
+
...extractedBorderStyles,
|
|
229
|
+
...(error ? { borderColor: errorColor } : {}),
|
|
230
|
+
...(disabled
|
|
231
|
+
? { borderColor: "transparent", backgroundColor: disabledColor }
|
|
232
|
+
: {}),
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
const marginStyles = {
|
|
236
|
+
height: 60,
|
|
237
|
+
...extractedMarginStyles,
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
const stylesWithoutBordersAndMargins = omit(viewStyles, [
|
|
241
|
+
...borderStyleNames,
|
|
242
|
+
...marginStyleNames,
|
|
243
|
+
...additionalBorderStyles,
|
|
244
|
+
...additionalMarginStyles,
|
|
96
245
|
]);
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
246
|
+
|
|
247
|
+
const selectedLabel =
|
|
248
|
+
internalValue &&
|
|
249
|
+
((pickerOptions as unknown as PickerOption[]).find(
|
|
250
|
+
(option) => option.value === internalValue
|
|
251
|
+
)?.label ??
|
|
252
|
+
internalValue);
|
|
253
|
+
|
|
254
|
+
const labelText = label ? (
|
|
255
|
+
<Text
|
|
256
|
+
style={{
|
|
257
|
+
textAlign: textStyles.textAlign,
|
|
258
|
+
color: unstyledColor,
|
|
259
|
+
fontSize: 12,
|
|
260
|
+
paddingBottom: 4,
|
|
109
261
|
}}
|
|
110
|
-
style={[
|
|
111
|
-
styles.nativePicker,
|
|
112
|
-
isIos ? styles.iosNativePicker : styles.nonIosPicker,
|
|
113
|
-
]}
|
|
114
|
-
onBlur={() => setPickerVisible(false)}
|
|
115
262
|
>
|
|
116
|
-
{
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
263
|
+
{label}
|
|
264
|
+
</Text>
|
|
265
|
+
) : null;
|
|
266
|
+
|
|
267
|
+
const leftIconOutset = leftIconMode === "outset";
|
|
268
|
+
|
|
269
|
+
const leftIcon = leftIconName ? (
|
|
270
|
+
<Icon
|
|
271
|
+
name={leftIconName}
|
|
272
|
+
color={disabled ? unstyledColor : iconColor}
|
|
273
|
+
size={iconSize}
|
|
274
|
+
style={{
|
|
275
|
+
marginRight: 4,
|
|
276
|
+
marginLeft: 4,
|
|
277
|
+
}}
|
|
278
|
+
/>
|
|
279
|
+
) : null;
|
|
280
|
+
|
|
281
|
+
const rightIcon = rightIconName ? (
|
|
282
|
+
<Icon
|
|
283
|
+
name={rightIconName}
|
|
284
|
+
color={disabled ? unstyledColor : iconColor}
|
|
285
|
+
size={iconSize}
|
|
286
|
+
style={{
|
|
287
|
+
marginRight: -10,
|
|
288
|
+
marginLeft: 8,
|
|
289
|
+
}}
|
|
290
|
+
/>
|
|
291
|
+
) : null;
|
|
292
|
+
|
|
293
|
+
const textAlign = textStyles?.textAlign;
|
|
294
|
+
|
|
295
|
+
const calculateLeftPadding = () => {
|
|
296
|
+
if (leftIconOutset) {
|
|
297
|
+
if (textAlign === "center") {
|
|
298
|
+
return iconSize - Math.abs(8 - iconSize);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return iconSize + 8;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return 0;
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
const assistiveTextLabel = assistiveText ? (
|
|
308
|
+
<Text
|
|
309
|
+
style={{
|
|
310
|
+
textAlign,
|
|
311
|
+
width: "100%",
|
|
312
|
+
paddingLeft: calculateLeftPadding(),
|
|
313
|
+
color: unstyledColor,
|
|
314
|
+
fontSize: 12,
|
|
315
|
+
paddingTop: 4,
|
|
316
|
+
}}
|
|
317
|
+
>
|
|
318
|
+
{assistiveText}
|
|
319
|
+
</Text>
|
|
320
|
+
) : null;
|
|
125
321
|
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
322
|
+
const primaryTextStyle = {
|
|
323
|
+
color: unstyledColor,
|
|
324
|
+
fontSize: 14,
|
|
325
|
+
...pickBy(textStyles, identity),
|
|
326
|
+
...(placeholder === internalValue ? { color: placeholderTextColor } : {}),
|
|
327
|
+
...(disabled ? { color: unstyledColor } : {}),
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
const handleValueChange = (newValue: string, itemIndex: number) => {
|
|
331
|
+
if (newValue !== "" && newValue !== placeholder) {
|
|
332
|
+
onValueChange?.(newValue, itemIndex);
|
|
333
|
+
setInternalValue(newValue);
|
|
334
|
+
} else if (newValue === placeholder) {
|
|
335
|
+
onValueChange?.("", 0);
|
|
336
|
+
setInternalValue(undefined);
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
return (
|
|
341
|
+
/* marginsContainer */
|
|
342
|
+
<View style={[styles.marginsContainer, marginStyles]}>
|
|
343
|
+
{/* touchableContainer */}
|
|
344
|
+
<Touchable
|
|
345
|
+
disabled={disabled}
|
|
346
|
+
onPress={togglePickerVisible}
|
|
347
|
+
style={styles.touchableContainer}
|
|
348
|
+
>
|
|
349
|
+
{/* outsetContainer */}
|
|
350
|
+
<View
|
|
351
|
+
pointerEvents="none"
|
|
352
|
+
style={[
|
|
353
|
+
styles.outsetContainer,
|
|
354
|
+
stylesWithoutBordersAndMargins,
|
|
355
|
+
!leftIconOutset ? (borderStyles as PickerProps["style"]) : {},
|
|
356
|
+
]}
|
|
357
|
+
>
|
|
358
|
+
{leftIcon}
|
|
359
|
+
|
|
360
|
+
{/* insetContainer */}
|
|
361
|
+
<View
|
|
362
|
+
style={[
|
|
363
|
+
styles.insetContainer,
|
|
364
|
+
leftIconOutset ? (borderStyles as PickerProps["style"]) : {},
|
|
365
|
+
]}
|
|
366
|
+
>
|
|
367
|
+
{/* primaryTextContainer */}
|
|
368
|
+
<View style={styles.primaryTextContainer}>
|
|
369
|
+
{labelText}
|
|
370
|
+
|
|
371
|
+
<Text style={primaryTextStyle}>
|
|
372
|
+
{String(selectedLabel ?? placeholder)}
|
|
373
|
+
</Text>
|
|
374
|
+
</View>
|
|
375
|
+
|
|
376
|
+
{rightIcon}
|
|
377
|
+
</View>
|
|
378
|
+
</View>
|
|
379
|
+
{assistiveTextLabel}
|
|
380
|
+
</Touchable>
|
|
381
|
+
|
|
382
|
+
{/* iosPicker */}
|
|
383
|
+
{isIos && pickerVisible ? (
|
|
129
384
|
<Portal>
|
|
130
|
-
<SafeAreaView style={styles.
|
|
385
|
+
<SafeAreaView style={styles.iosPicker}>
|
|
131
386
|
<View style={styles.iosPickerContent}>
|
|
132
387
|
<Button
|
|
133
388
|
Icon={Icon}
|
|
134
389
|
type="text"
|
|
135
|
-
onPress={
|
|
390
|
+
onPress={togglePickerVisible}
|
|
136
391
|
style={styles.iosButton}
|
|
137
392
|
>
|
|
138
393
|
{"Close"}
|
|
139
394
|
</Button>
|
|
140
|
-
|
|
395
|
+
|
|
396
|
+
<NativePicker
|
|
397
|
+
style={styles.iosNativePicker}
|
|
398
|
+
selectedValue={internalValue}
|
|
399
|
+
onValueChange={handleValueChange}
|
|
400
|
+
>
|
|
401
|
+
{(pickerOptions as unknown as PickerOption[]).map((option) => (
|
|
402
|
+
<NativePicker.Item
|
|
403
|
+
label={option.label}
|
|
404
|
+
value={option.value}
|
|
405
|
+
key={option.value}
|
|
406
|
+
/>
|
|
407
|
+
))}
|
|
408
|
+
</NativePicker>
|
|
141
409
|
</View>
|
|
142
410
|
</SafeAreaView>
|
|
143
411
|
</Portal>
|
|
144
|
-
)
|
|
145
|
-
} else {
|
|
146
|
-
return renderNativePicker();
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
React.useEffect(() => {
|
|
151
|
-
if (pickerVisible && pickerRef.current) {
|
|
152
|
-
pickerRef?.current?.focus();
|
|
153
|
-
}
|
|
154
|
-
}, [pickerVisible, pickerRef]);
|
|
155
|
-
|
|
156
|
-
React.useEffect(() => {
|
|
157
|
-
if (pickerVisible && autoDismissKeyboard) {
|
|
158
|
-
Keyboard.dismiss();
|
|
159
|
-
}
|
|
160
|
-
}, [pickerVisible, autoDismissKeyboard]);
|
|
161
|
-
|
|
162
|
-
return (
|
|
163
|
-
<View style={containerStyle}>
|
|
164
|
-
<Touchable
|
|
165
|
-
disabled={disabled}
|
|
166
|
-
onPress={() => setPickerVisible(!pickerVisible)}
|
|
167
|
-
>
|
|
168
|
-
<TextField
|
|
169
|
-
Icon={Icon}
|
|
170
|
-
numberOfLines={1}
|
|
171
|
-
onChangeText={() => {}}
|
|
172
|
-
value={String(selectedLabel ?? placeholder)}
|
|
173
|
-
editable={false}
|
|
174
|
-
disabled={disabled}
|
|
175
|
-
style={textFieldStyle}
|
|
176
|
-
{...rest}
|
|
177
|
-
/>
|
|
178
|
-
</Touchable>
|
|
412
|
+
) : null}
|
|
179
413
|
|
|
414
|
+
{/* nonIosPicker */}
|
|
180
415
|
{/* Web version is collapsed by default, always show to allow direct expand */}
|
|
181
|
-
{(pickerVisible || isWeb)
|
|
416
|
+
{!isIos && (pickerVisible || isWeb) ? (
|
|
417
|
+
<NativePicker
|
|
418
|
+
enabled={!disabled}
|
|
419
|
+
selectedValue={internalValue}
|
|
420
|
+
onValueChange={handleValueChange}
|
|
421
|
+
style={styles.nonIosPicker}
|
|
422
|
+
ref={androidPickerRef}
|
|
423
|
+
onBlur={() => setPickerVisible(false)}
|
|
424
|
+
>
|
|
425
|
+
{(pickerOptions as unknown as PickerOption[]).map((option) => (
|
|
426
|
+
<NativePicker.Item
|
|
427
|
+
label={option.label}
|
|
428
|
+
value={option.value}
|
|
429
|
+
key={option.value}
|
|
430
|
+
/>
|
|
431
|
+
))}
|
|
432
|
+
</NativePicker>
|
|
433
|
+
) : null}
|
|
182
434
|
</View>
|
|
183
435
|
);
|
|
184
436
|
};
|
|
185
437
|
|
|
186
438
|
const styles = StyleSheet.create({
|
|
187
|
-
|
|
439
|
+
marginsContainer: {
|
|
440
|
+
alignSelf: "stretch",
|
|
441
|
+
alignItems: "center",
|
|
442
|
+
width: "100%",
|
|
443
|
+
maxWidth: deviceWidth,
|
|
444
|
+
},
|
|
445
|
+
touchableContainer: {
|
|
446
|
+
flex: 1,
|
|
447
|
+
height: "100%",
|
|
448
|
+
width: "100%",
|
|
449
|
+
alignSelf: "stretch",
|
|
450
|
+
alignItems: "center",
|
|
451
|
+
},
|
|
452
|
+
outsetContainer: {
|
|
453
|
+
flex: 1,
|
|
454
|
+
height: "100%",
|
|
455
|
+
width: "100%",
|
|
456
|
+
flexDirection: "row",
|
|
457
|
+
alignItems: "center",
|
|
458
|
+
justifyContent: "space-between",
|
|
459
|
+
},
|
|
460
|
+
insetContainer: {
|
|
461
|
+
flex: 1,
|
|
462
|
+
height: "100%",
|
|
463
|
+
width: "100%",
|
|
464
|
+
flexDirection: "row",
|
|
465
|
+
alignItems: "center",
|
|
466
|
+
justifyContent: "space-between",
|
|
467
|
+
paddingLeft: 12,
|
|
468
|
+
paddingRight: 12,
|
|
469
|
+
},
|
|
470
|
+
primaryTextContainer: {
|
|
471
|
+
flex: 1,
|
|
472
|
+
},
|
|
473
|
+
iosPicker: {
|
|
188
474
|
position: "absolute",
|
|
189
475
|
bottom: 0,
|
|
190
476
|
left: 0,
|
|
@@ -192,11 +478,14 @@ const styles = StyleSheet.create({
|
|
|
192
478
|
flexDirection: "row",
|
|
193
479
|
justifyContent: "center",
|
|
194
480
|
width: "100%",
|
|
481
|
+
maxWidth: deviceWidth,
|
|
482
|
+
maxHeight: deviceHeight,
|
|
195
483
|
backgroundColor: "white",
|
|
196
484
|
},
|
|
197
485
|
iosPickerContent: {
|
|
198
486
|
flexDirection: "column",
|
|
199
487
|
width: "100%",
|
|
488
|
+
maxWidth: deviceWidth,
|
|
200
489
|
},
|
|
201
490
|
iosButton: {
|
|
202
491
|
alignSelf: "flex-end",
|
|
@@ -206,37 +495,15 @@ const styles = StyleSheet.create({
|
|
|
206
495
|
},
|
|
207
496
|
nonIosPicker: {
|
|
208
497
|
opacity: 0,
|
|
498
|
+
position: "absolute",
|
|
499
|
+
top: 0,
|
|
500
|
+
left: 0,
|
|
501
|
+
right: 0,
|
|
502
|
+
bottom: 0,
|
|
503
|
+
width: "100%",
|
|
504
|
+
maxWidth: deviceWidth,
|
|
505
|
+
maxHeight: deviceHeight,
|
|
209
506
|
},
|
|
210
507
|
});
|
|
211
508
|
|
|
212
|
-
|
|
213
|
-
options: PickerOption[] | string[] | number[]
|
|
214
|
-
): PickerOption[] {
|
|
215
|
-
if (options.length === 0) {
|
|
216
|
-
return [];
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
const firstOption = options[0];
|
|
220
|
-
|
|
221
|
-
if (typeof firstOption === ("string" || "number")) {
|
|
222
|
-
return options.map((option) => ({
|
|
223
|
-
label: String(option),
|
|
224
|
-
value: String(option),
|
|
225
|
-
}));
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
if (isObject(firstOption) && firstOption.value && firstOption.label) {
|
|
229
|
-
return (options as PickerOption[]).map((option) => {
|
|
230
|
-
return {
|
|
231
|
-
label: String(option.label),
|
|
232
|
-
value: String(option.value),
|
|
233
|
-
};
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
throw new Error(
|
|
238
|
-
'Picker options must be either an array of strings or array of { "label": string; "value": string; } objects.'
|
|
239
|
-
);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
export default Picker;
|
|
509
|
+
export default withTheme(Picker);
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { View, StyleSheet } from "react-native";
|
|
3
|
+
import omit from "lodash.omit";
|
|
4
|
+
import { withTheme } from "../../theming";
|
|
5
|
+
import { Picker as NativePicker } from "@react-native-picker/picker";
|
|
6
|
+
import { extractStyles } from "../../utilities";
|
|
7
|
+
import TextField from "../TextField";
|
|
8
|
+
import Touchable from "../Touchable";
|
|
9
|
+
const Picker = ({ style, options, placeholder, selectedValue, disabled = false, onValueChange: onValueChangeOverride = () => { }, ...props }) => {
|
|
10
|
+
var _a, _b;
|
|
11
|
+
const { viewStyles: { borderRadius, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
12
|
+
borderWidth, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
13
|
+
borderTopWidth, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
14
|
+
borderRightWidth, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
15
|
+
borderBottomWidth, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
16
|
+
borderLeftWidth, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
17
|
+
borderColor, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
18
|
+
backgroundColor, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
19
|
+
padding, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
20
|
+
paddingTop, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
21
|
+
paddingRight, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
22
|
+
paddingBottom, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
23
|
+
paddingLeft, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
24
|
+
...viewStyles }, } = extractStyles(style);
|
|
25
|
+
const textField = React.useRef(undefined);
|
|
26
|
+
const onValueChange = (itemValue, itemIndex) => {
|
|
27
|
+
toggleFocus();
|
|
28
|
+
onValueChangeOverride(itemValue, itemIndex);
|
|
29
|
+
};
|
|
30
|
+
const toggleFocus = () => {
|
|
31
|
+
if (!disabled) {
|
|
32
|
+
// @ts-ignore
|
|
33
|
+
textField.current.toggleFocus(); // cannot determine if method exists due to component being wrapped in a withTheme()
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const stylesWithoutMargin = style &&
|
|
37
|
+
omit(StyleSheet.flatten(style), [
|
|
38
|
+
"margin",
|
|
39
|
+
"marginTop",
|
|
40
|
+
"marginRight",
|
|
41
|
+
"marginBottom",
|
|
42
|
+
"marginLeft",
|
|
43
|
+
]);
|
|
44
|
+
const selectedLabel = selectedValue &&
|
|
45
|
+
((_b = (_a = options.find((o) => o.value === selectedValue)) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : selectedValue);
|
|
46
|
+
return (React.createElement(Touchable, { disabled: disabled, onPress: toggleFocus, style: [styles.container, viewStyles] },
|
|
47
|
+
React.createElement(View, null,
|
|
48
|
+
React.createElement(NativePicker, { enabled: !disabled, selectedValue: selectedValue, onValueChange: onValueChange, style: {
|
|
49
|
+
opacity: 0,
|
|
50
|
+
position: "absolute",
|
|
51
|
+
top: 0,
|
|
52
|
+
left: 0,
|
|
53
|
+
right: 0,
|
|
54
|
+
bottom: 0,
|
|
55
|
+
width: "100%",
|
|
56
|
+
} }, options.map((o) => (React.createElement(NativePicker.Item, { label: o.label, value: o.value, key: o.value })))),
|
|
57
|
+
React.createElement(View, { pointerEvents: "none" },
|
|
58
|
+
React.createElement(TextField, { ...props, value: selectedLabel, placeholder: placeholder,
|
|
59
|
+
// @ts-ignore
|
|
60
|
+
ref: textField, disabled: disabled,
|
|
61
|
+
// @ts-expect-error
|
|
62
|
+
style: stylesWithoutMargin })))));
|
|
63
|
+
};
|
|
64
|
+
const styles = StyleSheet.create({
|
|
65
|
+
container: {
|
|
66
|
+
alignSelf: "stretch",
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
export default withTheme(Picker);
|
|
70
|
+
//# sourceMappingURL=PickerComponent.android.js.map
|