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