@draftbit/core 44.1.8 → 44.1.9-222859.1

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.
Files changed (58) hide show
  1. package/lib/commonjs/components/ActionSheet/ActionSheetItem.js.map +1 -1
  2. package/lib/commonjs/components/Picker/Picker.js +254 -27
  3. package/lib/commonjs/components/Picker/Picker.js.map +1 -1
  4. package/lib/commonjs/components/StepIndicator.js.map +1 -1
  5. package/lib/commonjs/components/Stepper.js.map +1 -1
  6. package/lib/commonjs/hooks.js.map +1 -1
  7. package/lib/commonjs/mappings/AvatarEdit.js.map +1 -1
  8. package/lib/commonjs/mappings/Image.js.map +1 -1
  9. package/lib/commonjs/mappings/Picker.js +3 -1
  10. package/lib/commonjs/mappings/Picker.js.map +1 -1
  11. package/lib/commonjs/mappings/RadioButtonRow.js.map +1 -1
  12. package/lib/commonjs/mappings/RowBodyIcon.js.map +1 -1
  13. package/lib/commonjs/mappings/RowHeadlineImageCaption.js.map +1 -1
  14. package/lib/commonjs/mappings/ScrollView.js.map +1 -1
  15. package/lib/commonjs/mappings/Swiper.js.map +1 -1
  16. package/lib/commonjs/mappings/WebView.js.map +1 -1
  17. package/lib/commonjs/styles/overlay.js.map +1 -1
  18. package/lib/commonjs/styles/shadow.js.map +1 -1
  19. package/lib/module/components/Picker/Picker.js +241 -29
  20. package/lib/module/components/Picker/Picker.js.map +1 -1
  21. package/lib/module/mappings/AudioPlayer.js.map +1 -1
  22. package/lib/module/mappings/Picker.js +4 -2
  23. package/lib/module/mappings/Picker.js.map +1 -1
  24. package/lib/typescript/src/components/Picker/Picker.d.ts +28 -4
  25. package/lib/typescript/src/mappings/Picker.d.ts +21 -0
  26. package/package.json +2 -2
  27. package/src/components/Picker/Picker.js +188 -18
  28. package/src/components/Picker/Picker.tsx +364 -35
  29. package/src/mappings/Picker.js +3 -1
  30. package/src/mappings/Picker.ts +4 -0
  31. package/lib/commonjs/components/Picker/PickerComponent.android.js +0 -135
  32. package/lib/commonjs/components/Picker/PickerComponent.android.js.map +0 -1
  33. package/lib/commonjs/components/Picker/PickerComponent.ios.js +0 -161
  34. package/lib/commonjs/components/Picker/PickerComponent.ios.js.map +0 -1
  35. package/lib/commonjs/components/Picker/PickerComponent.web.js +0 -136
  36. package/lib/commonjs/components/Picker/PickerComponent.web.js.map +0 -1
  37. package/lib/commonjs/components/Picker/PickerTypes.js +0 -6
  38. package/lib/commonjs/components/Picker/PickerTypes.js.map +0 -1
  39. package/lib/module/components/Picker/PickerComponent.android.js +0 -112
  40. package/lib/module/components/Picker/PickerComponent.android.js.map +0 -1
  41. package/lib/module/components/Picker/PickerComponent.ios.js +0 -135
  42. package/lib/module/components/Picker/PickerComponent.ios.js.map +0 -1
  43. package/lib/module/components/Picker/PickerComponent.web.js +0 -113
  44. package/lib/module/components/Picker/PickerComponent.web.js.map +0 -1
  45. package/lib/module/components/Picker/PickerTypes.js +0 -2
  46. package/lib/module/components/Picker/PickerTypes.js.map +0 -1
  47. package/lib/typescript/src/components/Picker/PickerComponent.android.d.ts +0 -6
  48. package/lib/typescript/src/components/Picker/PickerComponent.ios.d.ts +0 -7
  49. package/lib/typescript/src/components/Picker/PickerComponent.web.d.ts +0 -6
  50. package/lib/typescript/src/components/Picker/PickerTypes.d.ts +0 -18
  51. package/src/components/Picker/PickerComponent.android.js +0 -68
  52. package/src/components/Picker/PickerComponent.android.tsx +0 -116
  53. package/src/components/Picker/PickerComponent.ios.js +0 -78
  54. package/src/components/Picker/PickerComponent.ios.tsx +0 -142
  55. package/src/components/Picker/PickerComponent.web.js +0 -69
  56. package/src/components/Picker/PickerComponent.web.tsx +0 -117
  57. package/src/components/Picker/PickerTypes.js +0 -1
  58. package/src/components/Picker/PickerTypes.ts +0 -18
@@ -1,29 +1,41 @@
1
1
  import * as React from "react";
2
+ import { View, StyleSheet, Text, Platform, Dimensions, } from "react-native";
3
+ import { omit, pick, pickBy, identity } from "lodash";
4
+ import { SafeAreaView } from "react-native-safe-area-context";
5
+ import { Picker as NativePicker } from "@react-native-picker/picker";
2
6
  import { withTheme } from "../../theming";
3
- //@ts-ignore
4
- import PickerComponent from "./PickerComponent"; //unable to find file due to using .android/.web/.ios
7
+ import Portal from "../Portal/Portal";
8
+ import Button from "../DeprecatedButton";
9
+ import Touchable from "../Touchable";
10
+ import { extractStyles } from "../../utilities";
5
11
  function normalizeOptions(options) {
6
12
  if (options.length === 0) {
7
13
  return [];
8
14
  }
9
- if (typeof options[0] === "string") {
15
+ if (typeof options[0] === ("string" || "number")) {
10
16
  return options.map((option) => ({
11
- label: option,
17
+ label: String(option),
12
18
  value: String(option),
13
19
  }));
14
20
  }
15
- if (options[0].label && options[0].value) {
21
+ if (typeof options[0] === "object" &&
22
+ options[0].value !== null &&
23
+ options[0].label !== null) {
16
24
  return options.map((option) => {
17
25
  return {
18
- label: option.label,
26
+ label: String(option.label),
19
27
  value: String(option.value),
20
28
  };
21
29
  });
22
30
  }
23
31
  throw new Error('Picker options must be either an array of strings or array of { "label": string; "value": string; } objects.');
24
32
  }
25
- const Picker = ({ options = [], placeholder, onValueChange: onValueChangeOverride, value, defaultValue, ...props }) => {
33
+ const unstyledColor = "rgba(165, 173, 183, 1)";
34
+ const disabledColor = "rgb(240, 240, 240)";
35
+ const errorColor = "rgba(255, 69, 100, 1)";
36
+ const Picker = ({ error, options = [], onValueChange, defaultValue, Icon, style, placeholder, value, disabled = false, theme, assistiveText, label, iconColor = unstyledColor, iconSize = 24, leftIconMode = "inset", leftIconName, placeholderTextColor = unstyledColor, rightIconName, type = "solid", }) => {
26
37
  const [internalValue, setInternalValue] = React.useState(value || defaultValue);
38
+ const [pickerVisible, togglePickerVisible] = React.useReducer((state) => !state, false);
27
39
  React.useEffect(() => {
28
40
  if (value != null) {
29
41
  setInternalValue(value);
@@ -34,23 +46,181 @@ const Picker = ({ options = [], placeholder, onValueChange: onValueChangeOverrid
34
46
  setInternalValue(defaultValue);
35
47
  }
36
48
  }, [defaultValue]);
37
- const onValueChange = React.useCallback((itemValue, itemIndex) => {
38
- if (placeholder && itemIndex === 0) {
39
- return;
40
- }
41
- onValueChangeOverride &&
42
- onValueChangeOverride(String(itemValue), itemIndex);
43
- }, [placeholder, onValueChangeOverride]);
44
49
  const normalizedOptions = normalizeOptions(options);
45
50
  const pickerOptions = placeholder
46
51
  ? [{ value: placeholder, label: placeholder }, ...normalizedOptions]
47
52
  : normalizedOptions;
53
+ const { viewStyles, textStyles } = extractStyles(style);
54
+ const { colors } = theme;
55
+ const borders = [
56
+ "borderRadius",
57
+ "borderTopLeftRadius",
58
+ "borderTopRightRadius",
59
+ "borderBottomRightRadius",
60
+ "borderBottomLeftRadius",
61
+ "borderTopWidth",
62
+ "borderRightWidth",
63
+ "borderBottomWidth",
64
+ "borderLeftWidth",
65
+ "borderColor",
66
+ "borderStyle",
67
+ "backgroundColor",
68
+ ];
69
+ const borderStyles = {
70
+ ...{
71
+ ...(type === "solid"
72
+ ? {
73
+ borderTopLeftRadius: 5,
74
+ borderTopRightRadius: 5,
75
+ borderBottomRightRadius: 5,
76
+ borderBottomLeftRadius: 5,
77
+ borderTopWidth: 1,
78
+ borderRightWidth: 1,
79
+ borderLeftWidth: 1,
80
+ }
81
+ : {}),
82
+ borderBottomWidth: 1,
83
+ borderColor: unstyledColor,
84
+ borderStyle: "solid",
85
+ },
86
+ ...pick(viewStyles, borders),
87
+ ...(error ? { borderColor: errorColor } : {}),
88
+ ...(disabled
89
+ ? { borderColor: "transparent", backgroundColor: disabledColor }
90
+ : {}),
91
+ };
92
+ const margins = ["marginLeft", "marginRight", "marginTop", "marginBottom"];
93
+ const marginStyles = pick(viewStyles, margins);
94
+ const maxHeight = viewStyles?.maxHeight && viewStyles.maxHeight !== "100%"
95
+ ? viewStyles.maxHeight
96
+ : Dimensions.get("window").height;
97
+ const stylesWithoutBordersAndMargins = {
98
+ ...{
99
+ height: 60,
100
+ width: "100%",
101
+ },
102
+ ...omit(viewStyles, [...borders, ...margins]),
103
+ ...{ maxHeight },
104
+ };
105
+ const selectedLabel = internalValue &&
106
+ (pickerOptions.find((option) => option.value === internalValue)?.label ??
107
+ internalValue);
108
+ const labelText = label ? (React.createElement(Text, { style: {
109
+ textAlign: textStyles.textAlign,
110
+ color: unstyledColor,
111
+ fontSize: 12,
112
+ paddingBottom: 4,
113
+ } }, label)) : null;
114
+ const leftIconOutset = leftIconMode === "outset";
115
+ const leftIcon = leftIconName ? (React.createElement(Icon, { name: leftIconName, color: disabled ? unstyledColor : iconColor, size: iconSize, style: {
116
+ marginRight: 4,
117
+ marginLeft: 4,
118
+ } })) : null;
119
+ const rightIcon = rightIconName ? (React.createElement(Icon, { name: rightIconName, color: disabled ? unstyledColor : iconColor, size: iconSize, style: {
120
+ marginRight: -10,
121
+ marginLeft: 8,
122
+ } })) : null;
123
+ const width = stylesWithoutBordersAndMargins?.width ?? undefined;
124
+ const textAlign = textStyles?.textAlign;
125
+ const paddingLeft = leftIconOutset &&
126
+ (!textAlign || textAlign === "left" || textAlign === "justify")
127
+ ? iconSize + 4
128
+ : 0;
129
+ const assistiveTextLabel = assistiveText ? (React.createElement(Text, { style: {
130
+ textAlign,
131
+ width,
132
+ paddingLeft,
133
+ color: unstyledColor,
134
+ fontSize: 12,
135
+ paddingTop: 4,
136
+ } }, assistiveText)) : null;
137
+ const primaryTextStyle = {
138
+ color: unstyledColor,
139
+ fontSize: 14,
140
+ ...pickBy(textStyles, identity),
141
+ ...(placeholder === internalValue ? { color: placeholderTextColor } : {}),
142
+ ...(disabled ? { color: unstyledColor } : {}),
143
+ };
48
144
  const handleValueChange = (newValue, itemIndex) => {
49
- setInternalValue(newValue);
50
- if (onValueChange) {
51
- onValueChange(newValue, itemIndex);
145
+ if (!placeholder || itemIndex > 0) {
146
+ onValueChange?.(newValue, itemIndex);
52
147
  }
148
+ setInternalValue(newValue);
53
149
  };
54
- return (React.createElement(PickerComponent, { ...props, selectedValue: String(internalValue), placeholder: placeholder, options: pickerOptions, onValueChange: handleValueChange }));
150
+ return (
151
+ /* marginsContainer */
152
+ React.createElement(View, { style: [styles.marginsContainer, marginStyles] },
153
+ React.createElement(Touchable, { disabled: disabled, onPress: togglePickerVisible, style: styles.touchableContainer },
154
+ React.createElement(View, { pointerEvents: "none", style: [
155
+ styles.outsetContainer,
156
+ stylesWithoutBordersAndMargins,
157
+ // @ts-expect-error ... rejects border-related { key: undefined }
158
+ !leftIconOutset && borderStyles, // set border if Icon is inset
159
+ ] },
160
+ leftIcon,
161
+ React.createElement(View, { style: [
162
+ styles.insetContainer,
163
+ // @ts-expect-error ... rejects border-related { key: undefined }
164
+ leftIconOutset && borderStyles, // set border if Icon is outset
165
+ ] },
166
+ React.createElement(View, { style: styles.primaryTextContainer },
167
+ labelText,
168
+ React.createElement(Text, { style: primaryTextStyle }, String(selectedLabel ?? placeholder))),
169
+ rightIcon)),
170
+ assistiveTextLabel),
171
+ Platform.OS === "ios" && pickerVisible ? (React.createElement(Portal, null,
172
+ React.createElement(View, { style: [
173
+ styles.iosPicker,
174
+ {
175
+ backgroundColor: colors.divider,
176
+ },
177
+ ] },
178
+ React.createElement(SafeAreaView, { style: styles.iosSafeArea },
179
+ React.createElement(Button, { Icon: Icon, type: "text", onPress: togglePickerVisible, style: styles.iosButton }, "Close"),
180
+ React.createElement(NativePicker, { style: styles.iosNativePicker, selectedValue: internalValue, onValueChange: handleValueChange }, pickerOptions.map((option) => (React.createElement(NativePicker.Item, { label: option.label, value: option.value, key: option.value })))))))) : null,
181
+ Platform.OS !== "ios" ? (React.createElement(NativePicker, { enabled: !disabled, selectedValue: internalValue, onValueChange: handleValueChange, style: styles.nonIosPicker }, pickerOptions.map((option) => (React.createElement(NativePicker.Item, { label: option.label, value: option.value, key: option.value }))))) : null));
55
182
  };
56
183
  export default withTheme(Picker);
184
+ const styles = StyleSheet.create({
185
+ marginsContainer: { alignSelf: "stretch" },
186
+ touchableContainer: { alignSelf: "stretch", alignItems: "center" },
187
+ outsetContainer: {
188
+ flexDirection: "row",
189
+ alignItems: "center",
190
+ justifyContent: "space-between",
191
+ },
192
+ insetContainer: {
193
+ flex: 1,
194
+ height: "100%",
195
+ flexDirection: "row",
196
+ alignItems: "center",
197
+ justifyContent: "space-between",
198
+ paddingLeft: 12,
199
+ paddingRight: 12,
200
+ },
201
+ primaryTextContainer: { flex: 1 },
202
+ iosPicker: {
203
+ position: "absolute",
204
+ bottom: 0,
205
+ left: 0,
206
+ right: 0,
207
+ flexDirection: "row",
208
+ justifyContent: "center",
209
+ },
210
+ iosSafeArea: {
211
+ backgroundColor: "white",
212
+ flexDirection: "column",
213
+ width: "100%",
214
+ },
215
+ iosButton: { alignSelf: "flex-end" },
216
+ iosNativePicker: { backgroundColor: "white" },
217
+ nonIosPicker: {
218
+ opacity: 0,
219
+ position: "absolute",
220
+ top: 0,
221
+ left: 0,
222
+ right: 0,
223
+ bottom: 0,
224
+ width: "100%",
225
+ },
226
+ });
@@ -1,31 +1,72 @@
1
1
  import * as React from "react";
2
+ import {
3
+ View,
4
+ StyleSheet,
5
+ Text,
6
+ Platform,
7
+ ViewStyle,
8
+ StyleProp,
9
+ Dimensions,
10
+ } from "react-native";
11
+ import { omit, pick, pickBy, identity } from "lodash";
12
+ import { SafeAreaView } from "react-native-safe-area-context";
13
+ import { Picker as NativePicker } from "@react-native-picker/picker";
14
+
2
15
  import { withTheme } from "../../theming";
3
- //@ts-ignore
4
- import PickerComponent from "./PickerComponent"; //unable to find file due to using .android/.web/.ios
5
- import { PickerComponentProps, PickerOption } from "./PickerTypes";
16
+ import Portal from "../Portal/Portal";
17
+ import Button from "../DeprecatedButton";
18
+ import Touchable from "../Touchable";
19
+ import type { Theme } from "../../styles/DefaultTheme";
20
+ import type { IconSlot } from "../../interfaces/Icon";
21
+ import { extractStyles } from "../../utilities";
22
+
23
+ export interface PickerOption {
24
+ value: string;
25
+ label: string;
26
+ }
6
27
 
7
- type Props = PickerComponentProps & {
28
+ export type PickerProps = {
29
+ error?: any;
8
30
  placeholder?: string;
31
+ disabled?: boolean;
32
+ style?: StyleProp<ViewStyle> & { height?: number };
9
33
  value?: string;
10
34
  options: PickerOption[] | string[];
35
+ onValueChange: (value: string, index: number) => void;
36
+ defaultValue?: string;
37
+ assistiveText?: string;
38
+ label?: string;
39
+ iconColor?: string;
40
+ iconSize?: number;
41
+ leftIconMode?: "inset" | "outset";
42
+ leftIconName?: string;
43
+ placeholderTextColor?: string;
44
+ rightIconName?: string;
45
+ type?: "solid" | "underline";
46
+ theme: Theme;
47
+ Icon: IconSlot["Icon"];
11
48
  };
12
49
 
13
- function normalizeOptions(options: Props["options"]): PickerOption[] {
50
+ function normalizeOptions(options: PickerProps["options"]): PickerOption[] {
14
51
  if (options.length === 0) {
15
52
  return [];
16
53
  }
17
54
 
18
- if (typeof options[0] === "string") {
55
+ if (typeof options[0] === ("string" || "number")) {
19
56
  return (options as string[]).map((option) => ({
20
- label: option,
57
+ label: String(option),
21
58
  value: String(option),
22
59
  }));
23
60
  }
24
61
 
25
- if (options[0].label && options[0].value) {
26
- return options.map((option) => {
62
+ if (
63
+ typeof options[0] === "object" &&
64
+ options[0].value !== null &&
65
+ options[0].label !== null
66
+ ) {
67
+ return (options as PickerOption[]).map((option) => {
27
68
  return {
28
- label: option.label,
69
+ label: String(option.label),
29
70
  value: String(option.value),
30
71
  };
31
72
  });
@@ -36,18 +77,40 @@ function normalizeOptions(options: Props["options"]): PickerOption[] {
36
77
  );
37
78
  }
38
79
 
39
- const Picker: React.FC<Props> = ({
80
+ const unstyledColor = "rgba(165, 173, 183, 1)";
81
+ const disabledColor = "rgb(240, 240, 240)";
82
+ const errorColor = "rgba(255, 69, 100, 1)";
83
+
84
+ const Picker: React.FC<PickerProps> = ({
85
+ error,
40
86
  options = [],
87
+ onValueChange,
88
+ defaultValue,
89
+ Icon,
90
+ style,
41
91
  placeholder,
42
- onValueChange: onValueChangeOverride,
43
92
  value,
44
- defaultValue,
45
- ...props
93
+ disabled = false,
94
+ theme,
95
+ assistiveText,
96
+ label,
97
+ iconColor = unstyledColor,
98
+ iconSize = 24,
99
+ leftIconMode = "inset",
100
+ leftIconName,
101
+ placeholderTextColor = unstyledColor,
102
+ rightIconName,
103
+ type = "solid",
46
104
  }) => {
47
105
  const [internalValue, setInternalValue] = React.useState<string | undefined>(
48
106
  value || defaultValue
49
107
  );
50
108
 
109
+ const [pickerVisible, togglePickerVisible] = React.useReducer(
110
+ (state) => !state,
111
+ false
112
+ );
113
+
51
114
  React.useEffect(() => {
52
115
  if (value != null) {
53
116
  setInternalValue(value);
@@ -60,39 +123,305 @@ const Picker: React.FC<Props> = ({
60
123
  }
61
124
  }, [defaultValue]);
62
125
 
63
- const onValueChange = React.useCallback(
64
- (itemValue: string, itemIndex: number) => {
65
- if (placeholder && itemIndex === 0) {
66
- return;
67
- }
68
- onValueChangeOverride &&
69
- onValueChangeOverride(String(itemValue), itemIndex);
70
- },
71
- [placeholder, onValueChangeOverride]
72
- );
73
-
74
126
  const normalizedOptions = normalizeOptions(options);
75
127
 
76
128
  const pickerOptions = placeholder
77
129
  ? [{ value: placeholder, label: placeholder }, ...normalizedOptions]
78
130
  : normalizedOptions;
79
131
 
132
+ const { viewStyles, textStyles } = extractStyles(style);
133
+
134
+ const { colors } = theme;
135
+
136
+ const borders = [
137
+ "borderRadius",
138
+ "borderTopLeftRadius",
139
+ "borderTopRightRadius",
140
+ "borderBottomRightRadius",
141
+ "borderBottomLeftRadius",
142
+ "borderTopWidth",
143
+ "borderRightWidth",
144
+ "borderBottomWidth",
145
+ "borderLeftWidth",
146
+ "borderColor",
147
+ "borderStyle",
148
+ "backgroundColor",
149
+ ];
150
+
151
+ const borderStyles = {
152
+ ...{
153
+ ...(type === "solid"
154
+ ? {
155
+ borderTopLeftRadius: 5,
156
+ borderTopRightRadius: 5,
157
+ borderBottomRightRadius: 5,
158
+ borderBottomLeftRadius: 5,
159
+ borderTopWidth: 1,
160
+ borderRightWidth: 1,
161
+ borderLeftWidth: 1,
162
+ }
163
+ : {}),
164
+ borderBottomWidth: 1,
165
+ borderColor: unstyledColor,
166
+ borderStyle: "solid",
167
+ },
168
+ ...pick(viewStyles, borders),
169
+ ...(error ? { borderColor: errorColor } : {}),
170
+ ...(disabled
171
+ ? { borderColor: "transparent", backgroundColor: disabledColor }
172
+ : {}),
173
+ };
174
+
175
+ const margins = ["marginLeft", "marginRight", "marginTop", "marginBottom"];
176
+
177
+ const marginStyles = pick(viewStyles, margins);
178
+
179
+ const maxHeight =
180
+ viewStyles?.maxHeight && viewStyles.maxHeight !== "100%"
181
+ ? viewStyles.maxHeight
182
+ : Dimensions.get("window").height;
183
+
184
+ const stylesWithoutBordersAndMargins = {
185
+ ...{
186
+ height: 60,
187
+ width: "100%",
188
+ },
189
+ ...omit(viewStyles, [...borders, ...margins]),
190
+ ...{ maxHeight },
191
+ };
192
+
193
+ const selectedLabel =
194
+ internalValue &&
195
+ ((pickerOptions as unknown as PickerOption[]).find(
196
+ (option) => option.value === internalValue
197
+ )?.label ??
198
+ internalValue);
199
+
200
+ const labelText = label ? (
201
+ <Text
202
+ style={{
203
+ textAlign: textStyles.textAlign,
204
+ color: unstyledColor,
205
+ fontSize: 12,
206
+ paddingBottom: 4,
207
+ }}
208
+ >
209
+ {label}
210
+ </Text>
211
+ ) : null;
212
+
213
+ const leftIconOutset = leftIconMode === "outset";
214
+
215
+ const leftIcon = leftIconName ? (
216
+ <Icon
217
+ name={leftIconName}
218
+ color={disabled ? unstyledColor : iconColor}
219
+ size={iconSize}
220
+ style={{
221
+ marginRight: 4,
222
+ marginLeft: 4,
223
+ }}
224
+ />
225
+ ) : null;
226
+
227
+ const rightIcon = rightIconName ? (
228
+ <Icon
229
+ name={rightIconName}
230
+ color={disabled ? unstyledColor : iconColor}
231
+ size={iconSize}
232
+ style={{
233
+ marginRight: -10,
234
+ marginLeft: 8,
235
+ }}
236
+ />
237
+ ) : null;
238
+
239
+ const width = stylesWithoutBordersAndMargins?.width ?? undefined;
240
+
241
+ const textAlign = textStyles?.textAlign;
242
+
243
+ const paddingLeft =
244
+ leftIconOutset &&
245
+ (!textAlign || textAlign === "left" || textAlign === "justify")
246
+ ? iconSize + 4
247
+ : 0;
248
+
249
+ const assistiveTextLabel = assistiveText ? (
250
+ <Text
251
+ style={{
252
+ textAlign,
253
+ width,
254
+ paddingLeft,
255
+ color: unstyledColor,
256
+ fontSize: 12,
257
+ paddingTop: 4,
258
+ }}
259
+ >
260
+ {assistiveText}
261
+ </Text>
262
+ ) : null;
263
+
264
+ const primaryTextStyle = {
265
+ color: unstyledColor,
266
+ fontSize: 14,
267
+ ...pickBy(textStyles, identity),
268
+ ...(placeholder === internalValue ? { color: placeholderTextColor } : {}),
269
+ ...(disabled ? { color: unstyledColor } : {}),
270
+ };
271
+
80
272
  const handleValueChange = (newValue: string, itemIndex: number) => {
81
- setInternalValue(newValue);
82
- if (onValueChange) {
83
- onValueChange(newValue, itemIndex);
273
+ if (!placeholder || itemIndex > 0) {
274
+ onValueChange?.(newValue, itemIndex);
84
275
  }
276
+ setInternalValue(newValue);
85
277
  };
86
278
 
87
279
  return (
88
- <PickerComponent
89
- {...props}
90
- selectedValue={String(internalValue)}
91
- placeholder={placeholder}
92
- options={pickerOptions}
93
- onValueChange={handleValueChange}
94
- />
280
+ /* marginsContainer */
281
+ <View style={[styles.marginsContainer, marginStyles]}>
282
+ {/* touchableContainer */}
283
+ <Touchable
284
+ disabled={disabled}
285
+ onPress={togglePickerVisible}
286
+ style={styles.touchableContainer}
287
+ >
288
+ {/* outsetContainer */}
289
+ <View
290
+ pointerEvents="none"
291
+ style={[
292
+ styles.outsetContainer,
293
+ stylesWithoutBordersAndMargins,
294
+ // @ts-expect-error ... rejects border-related { key: undefined }
295
+ !leftIconOutset && borderStyles, // set border if Icon is inset
296
+ ]}
297
+ >
298
+ {leftIcon}
299
+
300
+ {/* insetContainer */}
301
+ <View
302
+ style={[
303
+ styles.insetContainer,
304
+ // @ts-expect-error ... rejects border-related { key: undefined }
305
+ leftIconOutset && borderStyles, // set border if Icon is outset
306
+ ]}
307
+ >
308
+ {/* primaryTextContainer */}
309
+ <View style={styles.primaryTextContainer}>
310
+ {labelText}
311
+
312
+ <Text style={primaryTextStyle}>
313
+ {String(selectedLabel ?? placeholder)}
314
+ </Text>
315
+ </View>
316
+
317
+ {rightIcon}
318
+ </View>
319
+ </View>
320
+ {assistiveTextLabel}
321
+ </Touchable>
322
+
323
+ {/* iosPicker */}
324
+ {Platform.OS === "ios" && pickerVisible ? (
325
+ <Portal>
326
+ <View
327
+ style={[
328
+ styles.iosPicker,
329
+ {
330
+ backgroundColor: colors.divider,
331
+ },
332
+ ]}
333
+ >
334
+ <SafeAreaView style={styles.iosSafeArea}>
335
+ <Button
336
+ Icon={Icon}
337
+ type="text"
338
+ onPress={togglePickerVisible}
339
+ style={styles.iosButton}
340
+ >
341
+ {"Close"}
342
+ </Button>
343
+
344
+ <NativePicker
345
+ style={styles.iosNativePicker}
346
+ selectedValue={internalValue}
347
+ onValueChange={handleValueChange}
348
+ >
349
+ {(pickerOptions as unknown as PickerOption[]).map((option) => (
350
+ <NativePicker.Item
351
+ label={option.label}
352
+ value={option.value}
353
+ key={option.value}
354
+ />
355
+ ))}
356
+ </NativePicker>
357
+ </SafeAreaView>
358
+ </View>
359
+ </Portal>
360
+ ) : null}
361
+
362
+ {/* nonIosPicker */}
363
+ {Platform.OS !== "ios" ? (
364
+ <NativePicker
365
+ enabled={!disabled}
366
+ selectedValue={internalValue}
367
+ onValueChange={handleValueChange}
368
+ style={styles.nonIosPicker}
369
+ >
370
+ {(pickerOptions as unknown as PickerOption[]).map((option) => (
371
+ <NativePicker.Item
372
+ label={option.label}
373
+ value={option.value}
374
+ key={option.value}
375
+ />
376
+ ))}
377
+ </NativePicker>
378
+ ) : null}
379
+ </View>
95
380
  );
96
381
  };
97
382
 
98
383
  export default withTheme(Picker);
384
+
385
+ const styles = StyleSheet.create({
386
+ marginsContainer: { alignSelf: "stretch" },
387
+ touchableContainer: { alignSelf: "stretch", alignItems: "center" },
388
+ outsetContainer: {
389
+ flexDirection: "row",
390
+ alignItems: "center",
391
+ justifyContent: "space-between",
392
+ },
393
+ insetContainer: {
394
+ flex: 1,
395
+ height: "100%",
396
+ flexDirection: "row",
397
+ alignItems: "center",
398
+ justifyContent: "space-between",
399
+ paddingLeft: 12,
400
+ paddingRight: 12,
401
+ },
402
+ primaryTextContainer: { flex: 1 },
403
+ iosPicker: {
404
+ position: "absolute",
405
+ bottom: 0,
406
+ left: 0,
407
+ right: 0,
408
+ flexDirection: "row",
409
+ justifyContent: "center",
410
+ },
411
+ iosSafeArea: {
412
+ backgroundColor: "white",
413
+ flexDirection: "column",
414
+ width: "100%",
415
+ },
416
+ iosButton: { alignSelf: "flex-end" },
417
+ iosNativePicker: { backgroundColor: "white" },
418
+ nonIosPicker: {
419
+ opacity: 0,
420
+ position: "absolute",
421
+ top: 0,
422
+ left: 0,
423
+ right: 0,
424
+ bottom: 0,
425
+ width: "100%",
426
+ },
427
+ });