@draftbit/core 48.4.8-fb2b2b.2 → 48.4.9-3aa6b7.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/Picker/Picker.js +1 -1
- package/lib/commonjs/components/Picker/PickerInputContainer.js +1 -0
- package/lib/commonjs/components/PinInput/PinInput.js +1 -1
- package/lib/commonjs/components/SectionList/SectionList.js +1 -1
- package/lib/commonjs/components/TextField.js +1 -1
- package/lib/commonjs/utilities.js +1 -1
- package/lib/typescript/src/components/Picker/Picker.d.ts +3 -35
- package/lib/typescript/src/components/Picker/Picker.js +69 -244
- package/lib/typescript/src/components/Picker/Picker.js.map +1 -1
- package/lib/typescript/src/components/Picker/PickerCommon.d.ts +27 -0
- package/lib/typescript/src/components/Picker/PickerCommon.js +2 -0
- package/lib/typescript/src/components/Picker/PickerCommon.js.map +1 -0
- package/lib/typescript/src/components/Picker/PickerInputContainer.d.ts +9 -0
- package/lib/typescript/src/components/Picker/PickerInputContainer.js +26 -0
- package/lib/typescript/src/components/Picker/PickerInputContainer.js.map +1 -0
- package/lib/typescript/src/components/PinInput/PinInput.d.ts +2 -6
- package/lib/typescript/src/components/PinInput/PinInput.js +16 -15
- package/lib/typescript/src/components/PinInput/PinInput.js.map +1 -1
- package/lib/typescript/src/components/SectionList/SectionList.d.ts +2 -1
- package/lib/typescript/src/components/SectionList/SectionList.js +13 -3
- package/lib/typescript/src/components/SectionList/SectionList.js.map +1 -1
- package/lib/typescript/src/components/TextField.d.ts +3 -3
- package/lib/typescript/src/components/TextField.js +9 -6
- package/lib/typescript/src/components/TextField.js.map +1 -1
- package/lib/typescript/src/utilities.d.ts +4 -0
- package/lib/typescript/src/utilities.js +15 -1
- package/lib/typescript/src/utilities.js.map +1 -1
- package/lib/typescript/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -3
- package/src/components/Picker/Picker.js +69 -244
- package/src/components/Picker/Picker.js.map +1 -1
- package/src/components/Picker/Picker.tsx +111 -441
- package/src/components/Picker/PickerCommon.js +2 -0
- package/src/components/Picker/PickerCommon.js.map +1 -0
- package/src/components/Picker/PickerCommon.ts +30 -0
- package/src/components/Picker/PickerInputContainer.js +26 -0
- package/src/components/Picker/PickerInputContainer.js.map +1 -0
- package/src/components/Picker/PickerInputContainer.tsx +74 -0
- package/src/components/PinInput/PinInput.js +16 -15
- package/src/components/PinInput/PinInput.js.map +1 -1
- package/src/components/PinInput/PinInput.tsx +20 -26
- package/src/components/SectionList/SectionList.js +13 -3
- package/src/components/SectionList/SectionList.js.map +1 -1
- package/src/components/SectionList/SectionList.tsx +15 -0
- package/src/components/TextField.js +9 -6
- package/src/components/TextField.js.map +1 -1
- package/src/components/TextField.tsx +14 -8
- package/src/utilities.js +15 -1
- package/src/utilities.js.map +1 -1
- package/src/utilities.ts +22 -1
- package/lib/commonjs/components/Picker/PickerComponent.android.js +0 -1
- package/lib/commonjs/components/Picker/PickerComponent.ios.js +0 -1
- package/lib/commonjs/components/Picker/PickerComponent.web.js +0 -1
- package/lib/typescript/src/components/Picker/PickerComponent.android.d.ts +0 -6
- package/lib/typescript/src/components/Picker/PickerComponent.android.js +0 -70
- package/lib/typescript/src/components/Picker/PickerComponent.android.js.map +0 -1
- package/lib/typescript/src/components/Picker/PickerComponent.ios.d.ts +0 -7
- package/lib/typescript/src/components/Picker/PickerComponent.ios.js +0 -80
- package/lib/typescript/src/components/Picker/PickerComponent.ios.js.map +0 -1
- package/lib/typescript/src/components/Picker/PickerComponent.web.d.ts +0 -6
- package/lib/typescript/src/components/Picker/PickerComponent.web.js +0 -71
- package/lib/typescript/src/components/Picker/PickerComponent.web.js.map +0 -1
- package/lib/typescript/src/components/Picker/PickerTypes.d.ts +0 -18
- package/lib/typescript/src/components/Picker/PickerTypes.js +0 -2
- package/lib/typescript/src/components/Picker/PickerTypes.js.map +0 -1
- package/src/components/Picker/PickerComponent.android.js +0 -70
- package/src/components/Picker/PickerComponent.android.js.map +0 -1
- package/src/components/Picker/PickerComponent.android.tsx +0 -116
- package/src/components/Picker/PickerComponent.ios.js +0 -80
- package/src/components/Picker/PickerComponent.ios.js.map +0 -1
- package/src/components/Picker/PickerComponent.ios.tsx +0 -142
- package/src/components/Picker/PickerComponent.web.js +0 -71
- package/src/components/Picker/PickerComponent.web.js.map +0 -1
- package/src/components/Picker/PickerComponent.web.tsx +0 -117
- package/src/components/Picker/PickerTypes.js +0 -2
- package/src/components/Picker/PickerTypes.js.map +0 -1
- package/src/components/Picker/PickerTypes.ts +0 -18
- /package/lib/commonjs/components/Picker/{PickerTypes.js → PickerCommon.js} +0 -0
|
@@ -1,476 +1,127 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
StyleSheet,
|
|
5
|
-
Text,
|
|
6
|
-
Platform,
|
|
7
|
-
ViewStyle,
|
|
8
|
-
StyleProp,
|
|
9
|
-
Dimensions,
|
|
10
|
-
Keyboard,
|
|
11
|
-
} from "react-native";
|
|
12
|
-
import { omit, pickBy, identity, isObject } from "lodash";
|
|
2
|
+
import { View, StyleSheet, Platform, Keyboard } from "react-native";
|
|
3
|
+
import { isObject } from "lodash";
|
|
13
4
|
import { SafeAreaView } from "react-native-safe-area-context";
|
|
14
5
|
import { Picker as NativePicker } from "@react-native-picker/picker";
|
|
15
|
-
|
|
16
|
-
import { withTheme } from "../../theming";
|
|
17
6
|
import Portal from "../Portal/Portal";
|
|
18
|
-
import Button from "
|
|
19
|
-
import
|
|
20
|
-
import
|
|
21
|
-
import
|
|
22
|
-
import {
|
|
23
|
-
extractStyles,
|
|
24
|
-
extractBorderAndMarginStyles,
|
|
25
|
-
borderStyleNames,
|
|
26
|
-
marginStyleNames,
|
|
27
|
-
} from "../../utilities";
|
|
28
|
-
|
|
29
|
-
export interface PickerOption {
|
|
30
|
-
value: string;
|
|
31
|
-
label: string;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export type PickerProps = {
|
|
35
|
-
error?: any;
|
|
36
|
-
placeholder?: string;
|
|
37
|
-
disabled?: boolean;
|
|
38
|
-
style?: StyleProp<ViewStyle> & { height?: number };
|
|
39
|
-
value?: string;
|
|
40
|
-
options: PickerOption[] | string[];
|
|
41
|
-
onValueChange: (value: string, index: number) => void;
|
|
42
|
-
defaultValue?: string;
|
|
43
|
-
assistiveText?: string;
|
|
44
|
-
label?: string;
|
|
45
|
-
iconColor?: string;
|
|
46
|
-
iconSize?: number;
|
|
47
|
-
leftIconMode?: "inset" | "outset";
|
|
48
|
-
leftIconName?: string;
|
|
49
|
-
placeholderTextColor?: string;
|
|
50
|
-
rightIconName?: string;
|
|
51
|
-
type?: "solid" | "underline";
|
|
52
|
-
autoDismissKeyboard?: boolean;
|
|
53
|
-
theme: Theme;
|
|
54
|
-
Icon: IconSlot["Icon"];
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
function normalizeOptions(options: PickerProps["options"]): PickerOption[] {
|
|
58
|
-
if (options.length === 0) {
|
|
59
|
-
return [];
|
|
60
|
-
}
|
|
7
|
+
import { Button } from "../Button";
|
|
8
|
+
import { useDeepCompareMemo } from "../../utilities";
|
|
9
|
+
import { PickerOption, PickerProps } from "./PickerCommon";
|
|
10
|
+
import PickerInputContainer from "./PickerInputContainer";
|
|
61
11
|
|
|
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
|
-
}
|
|
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");
|
|
88
12
|
const isIos = Platform.OS === "ios";
|
|
89
13
|
const isWeb = Platform.OS === "web";
|
|
90
14
|
|
|
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*/
|
|
97
15
|
const Picker: React.FC<PickerProps> = ({
|
|
98
|
-
|
|
99
|
-
options = [],
|
|
16
|
+
options: optionsProp = [],
|
|
100
17
|
onValueChange,
|
|
101
|
-
defaultValue,
|
|
102
18
|
Icon,
|
|
103
|
-
style,
|
|
104
19
|
placeholder,
|
|
105
20
|
value,
|
|
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",
|
|
116
21
|
autoDismissKeyboard = true,
|
|
22
|
+
...rest
|
|
117
23
|
}) => {
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
const [internalValue, setInternalValue] = React.useState<string | undefined>(
|
|
121
|
-
value || defaultValue
|
|
122
|
-
);
|
|
24
|
+
const pickerRef = React.useRef<NativePicker<string | number>>(null);
|
|
123
25
|
|
|
124
26
|
const [pickerVisible, setPickerVisible] = React.useState(false);
|
|
125
27
|
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
React.useEffect(() => {
|
|
131
|
-
if (value != null && value !== "") {
|
|
132
|
-
setInternalValue(value);
|
|
133
|
-
} else if (value === "") {
|
|
134
|
-
setInternalValue(undefined);
|
|
135
|
-
}
|
|
136
|
-
}, [value]);
|
|
28
|
+
const options = useDeepCompareMemo(() => {
|
|
29
|
+
const normalizedOptions = normalizeToPickerOptions(optionsProp);
|
|
137
30
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
React.useEffect(() => {
|
|
145
|
-
if (pickerVisible && androidPickerRef.current) {
|
|
146
|
-
androidPickerRef?.current?.focus();
|
|
31
|
+
// Underlying Picker component defaults selection to first element when value is not provided (or undefined)
|
|
32
|
+
// Placholder must be the 1st option in order to allow selection of the 'actual' 1st option
|
|
33
|
+
if (placeholder) {
|
|
34
|
+
return [{ label: placeholder, value: placeholder }, ...normalizedOptions];
|
|
35
|
+
} else {
|
|
36
|
+
return normalizedOptions;
|
|
147
37
|
}
|
|
148
|
-
}, [
|
|
38
|
+
}, [placeholder, optionsProp]);
|
|
149
39
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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);
|
|
40
|
+
// When no placeholder is provided then first item should be marked selected to reflect underlying Picker internal state
|
|
41
|
+
if (!placeholder && options.length && !value && value !== options[0].value) {
|
|
42
|
+
onValueChange?.(options[0].value);
|
|
180
43
|
}
|
|
181
44
|
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
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,
|
|
245
|
-
]);
|
|
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,
|
|
45
|
+
const renderNativePicker = () => (
|
|
46
|
+
<NativePicker
|
|
47
|
+
ref={pickerRef}
|
|
48
|
+
selectedValue={value}
|
|
49
|
+
onValueChange={(newValue) => {
|
|
50
|
+
if (newValue !== placeholder) {
|
|
51
|
+
onValueChange?.(newValue);
|
|
52
|
+
} else if (newValue === placeholder) {
|
|
53
|
+
onValueChange?.("");
|
|
54
|
+
}
|
|
261
55
|
}}
|
|
56
|
+
style={[
|
|
57
|
+
styles.nativePicker,
|
|
58
|
+
isIos ? styles.iosNativePicker : styles.nonIosPicker,
|
|
59
|
+
]}
|
|
60
|
+
onBlur={() => setPickerVisible(false)}
|
|
262
61
|
>
|
|
263
|
-
{
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
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;
|
|
321
|
-
|
|
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>
|
|
62
|
+
{options.map((option) => (
|
|
63
|
+
<NativePicker.Item
|
|
64
|
+
label={option.label.toString()}
|
|
65
|
+
value={option.value}
|
|
66
|
+
key={option.value}
|
|
67
|
+
/>
|
|
68
|
+
))}
|
|
69
|
+
</NativePicker>
|
|
70
|
+
);
|
|
381
71
|
|
|
382
|
-
|
|
383
|
-
|
|
72
|
+
const renderPicker = () => {
|
|
73
|
+
if (isIos) {
|
|
74
|
+
return (
|
|
384
75
|
<Portal>
|
|
385
|
-
<SafeAreaView style={styles.
|
|
76
|
+
<SafeAreaView style={styles.nativePicker}>
|
|
386
77
|
<View style={styles.iosPickerContent}>
|
|
387
78
|
<Button
|
|
388
79
|
Icon={Icon}
|
|
389
80
|
type="text"
|
|
390
|
-
onPress={
|
|
81
|
+
onPress={() => setPickerVisible(!pickerVisible)}
|
|
391
82
|
style={styles.iosButton}
|
|
392
83
|
>
|
|
393
84
|
{"Close"}
|
|
394
85
|
</Button>
|
|
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>
|
|
86
|
+
{renderNativePicker()}
|
|
409
87
|
</View>
|
|
410
88
|
</SafeAreaView>
|
|
411
89
|
</Portal>
|
|
412
|
-
)
|
|
90
|
+
);
|
|
91
|
+
} else {
|
|
92
|
+
return renderNativePicker();
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
React.useEffect(() => {
|
|
97
|
+
if (pickerVisible && pickerRef.current) {
|
|
98
|
+
pickerRef?.current?.focus();
|
|
99
|
+
}
|
|
100
|
+
}, [pickerVisible, pickerRef]);
|
|
101
|
+
|
|
102
|
+
React.useEffect(() => {
|
|
103
|
+
if (pickerVisible && autoDismissKeyboard) {
|
|
104
|
+
Keyboard.dismiss();
|
|
105
|
+
}
|
|
106
|
+
}, [pickerVisible, autoDismissKeyboard]);
|
|
413
107
|
|
|
414
|
-
|
|
108
|
+
return (
|
|
109
|
+
<PickerInputContainer
|
|
110
|
+
Icon={Icon}
|
|
111
|
+
placeholder={placeholder}
|
|
112
|
+
selectedValue={value}
|
|
113
|
+
options={options}
|
|
114
|
+
onPress={() => setPickerVisible(!pickerVisible)}
|
|
115
|
+
{...rest}
|
|
116
|
+
>
|
|
415
117
|
{/* Web version is collapsed by default, always show to allow direct expand */}
|
|
416
|
-
{
|
|
417
|
-
|
|
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}
|
|
434
|
-
</View>
|
|
118
|
+
{(pickerVisible || isWeb) && renderPicker()}
|
|
119
|
+
</PickerInputContainer>
|
|
435
120
|
);
|
|
436
121
|
};
|
|
437
122
|
|
|
438
123
|
const styles = StyleSheet.create({
|
|
439
|
-
|
|
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: {
|
|
124
|
+
nativePicker: {
|
|
474
125
|
position: "absolute",
|
|
475
126
|
bottom: 0,
|
|
476
127
|
left: 0,
|
|
@@ -478,14 +129,11 @@ const styles = StyleSheet.create({
|
|
|
478
129
|
flexDirection: "row",
|
|
479
130
|
justifyContent: "center",
|
|
480
131
|
width: "100%",
|
|
481
|
-
maxWidth: deviceWidth,
|
|
482
|
-
maxHeight: deviceHeight,
|
|
483
132
|
backgroundColor: "white",
|
|
484
133
|
},
|
|
485
134
|
iosPickerContent: {
|
|
486
135
|
flexDirection: "column",
|
|
487
136
|
width: "100%",
|
|
488
|
-
maxWidth: deviceWidth,
|
|
489
137
|
},
|
|
490
138
|
iosButton: {
|
|
491
139
|
alignSelf: "flex-end",
|
|
@@ -495,15 +143,37 @@ const styles = StyleSheet.create({
|
|
|
495
143
|
},
|
|
496
144
|
nonIosPicker: {
|
|
497
145
|
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,
|
|
506
146
|
},
|
|
507
147
|
});
|
|
508
148
|
|
|
509
|
-
|
|
149
|
+
function normalizeToPickerOptions(
|
|
150
|
+
options: PickerOption[] | string[] | number[]
|
|
151
|
+
): PickerOption[] {
|
|
152
|
+
if (options.length === 0) {
|
|
153
|
+
return [];
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const firstOption = options[0];
|
|
157
|
+
|
|
158
|
+
if (typeof firstOption === ("string" || "number")) {
|
|
159
|
+
return options.map((option) => ({
|
|
160
|
+
label: option as string | number,
|
|
161
|
+
value: option as string | number,
|
|
162
|
+
}));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (isObject(firstOption) && firstOption.value && firstOption.label) {
|
|
166
|
+
return (options as PickerOption[]).map((option) => {
|
|
167
|
+
return {
|
|
168
|
+
label: option.label,
|
|
169
|
+
value: option.value,
|
|
170
|
+
};
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
throw new Error(
|
|
175
|
+
'Picker options must be either an array of strings, numbers, or an array of { "label": string | number; "value": string | number; } objects.'
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export default Picker;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PickerCommon.js","sourceRoot":"","sources":["PickerCommon.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { StyleProp, ViewStyle } from "react-native";
|
|
2
|
+
import { IconSlot } from "../../interfaces/Icon";
|
|
3
|
+
|
|
4
|
+
export interface PickerOption {
|
|
5
|
+
value: string | number;
|
|
6
|
+
label: string | number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface PickerInputContainerProps extends IconSlot {
|
|
10
|
+
error?: any;
|
|
11
|
+
placeholder?: string;
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
style?: StyleProp<ViewStyle>;
|
|
14
|
+
label?: string;
|
|
15
|
+
assistiveText?: string;
|
|
16
|
+
iconColor?: string;
|
|
17
|
+
iconSize?: number;
|
|
18
|
+
leftIconMode?: "inset" | "outset";
|
|
19
|
+
leftIconName?: string;
|
|
20
|
+
placeholderTextColor?: string;
|
|
21
|
+
rightIconName?: string;
|
|
22
|
+
type?: "solid" | "underline";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface PickerProps extends PickerInputContainerProps {
|
|
26
|
+
value?: string | number;
|
|
27
|
+
options: PickerOption[] | string[] | number[];
|
|
28
|
+
onValueChange: (value: string | number) => void;
|
|
29
|
+
autoDismissKeyboard?: boolean;
|
|
30
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { View, StyleSheet } from "react-native";
|
|
3
|
+
import omit from "lodash.omit";
|
|
4
|
+
import { extractSizeStyles, extractPositionStyles, extractFlexItemStyles, extractBorderAndMarginStyles, } from "../../utilities";
|
|
5
|
+
import TextField from "../TextField";
|
|
6
|
+
import Touchable from "../Touchable";
|
|
7
|
+
const PickerInputContainer = ({ options = [], onPress, Icon, style, placeholder, selectedValue, disabled = false, children, ...rest }) => {
|
|
8
|
+
var _a;
|
|
9
|
+
const containerStyle = StyleSheet.flatten([
|
|
10
|
+
extractSizeStyles(style),
|
|
11
|
+
extractPositionStyles(style),
|
|
12
|
+
extractFlexItemStyles(style),
|
|
13
|
+
extractBorderAndMarginStyles(style).marginStyles,
|
|
14
|
+
]);
|
|
15
|
+
const textFieldStyle = omit(StyleSheet.flatten(style), Object.keys(containerStyle));
|
|
16
|
+
const selectedLabel = ((_a = options
|
|
17
|
+
.find((option) => option.value === selectedValue)) === null || _a === void 0 ? void 0 : _a.label.toString()) ||
|
|
18
|
+
selectedValue ||
|
|
19
|
+
placeholder;
|
|
20
|
+
return (React.createElement(View, { style: containerStyle },
|
|
21
|
+
React.createElement(Touchable, { disabled: disabled, onPress: onPress },
|
|
22
|
+
React.createElement(TextField, { Icon: Icon, numberOfLines: 1, onChangeText: () => { }, value: selectedLabel === null || selectedLabel === void 0 ? void 0 : selectedLabel.toString(), editable: false, disabled: disabled, style: textFieldStyle, ...rest })),
|
|
23
|
+
children));
|
|
24
|
+
};
|
|
25
|
+
export default PickerInputContainer;
|
|
26
|
+
//# sourceMappingURL=PickerInputContainer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PickerInputContainer.js","sourceRoot":"","sources":["PickerInputContainer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,IAAI,MAAM,aAAa,CAAC;AAC/B,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,4BAA4B,GAC7B,MAAM,iBAAiB,CAAC;AACzB,OAAO,SAAS,MAAM,cAAc,CAAC;AACrC,OAAO,SAAS,MAAM,cAAc,CAAC;AAYrC,MAAM,oBAAoB,GAEtB,CAAC,EACH,OAAO,GAAG,EAAE,EACZ,OAAO,EACP,IAAI,EACJ,KAAK,EACL,WAAW,EACX,aAAa,EACb,QAAQ,GAAG,KAAK,EAChB,QAAQ,EACR,GAAG,IAAI,EACR,EAAE,EAAE;;IACH,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,CAAC;QACxC,iBAAiB,CAAC,KAAK,CAAC;QACxB,qBAAqB,CAAC,KAAK,CAAC;QAC5B,qBAAqB,CAAC,KAAK,CAAC;QAC5B,4BAA4B,CAAC,KAAK,CAAC,CAAC,YAAY;KACjD,CAAC,CAAC;IAEH,MAAM,cAAc,GAAG,IAAI,CACzB,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,EACzB,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAC5B,CAAC;IAEF,MAAM,aAAa,GACjB,CAAA,MAAA,OAAO;SACJ,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,KAAK,aAAa,CAAC,0CAC/C,KAAK,CAAC,QAAQ,EAAE;QACpB,aAAa;QACb,WAAW,CAAC;IAEd,OAAO,CACL,oBAAC,IAAI,IAAC,KAAK,EAAE,cAAc;QACzB,oBAAC,SAAS,IAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO;YAC7C,oBAAC,SAAS,IACR,IAAI,EAAE,IAAI,EACV,aAAa,EAAE,CAAC,EAChB,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC,EACtB,KAAK,EAAE,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAE,QAAQ,EAAE,EAChC,QAAQ,EAAE,KAAK,EACf,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,cAAc,KACjB,IAAI,GACR,CACQ;QACX,QAAQ,CACJ,CACR,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
|