@draftbit/core 44.2.1-e53c90.0 → 44.2.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.
@@ -1,11 +1,35 @@
1
1
  import * as React from "react";
2
- import { PickerComponentProps, PickerOption } from "./PickerTypes";
3
- declare type Props = PickerComponentProps & {
2
+ import { ViewStyle, StyleProp } from "react-native";
3
+ import type { Theme } from "../../styles/DefaultTheme";
4
+ import type { IconSlot } from "../../interfaces/Icon";
5
+ export interface PickerOption {
6
+ value: string;
7
+ label: string;
8
+ }
9
+ export declare type PickerProps = {
10
+ error?: any;
4
11
  placeholder?: string;
12
+ disabled?: boolean;
13
+ style?: StyleProp<ViewStyle> & {
14
+ height?: number;
15
+ };
5
16
  value?: string;
6
17
  options: PickerOption[] | string[];
18
+ onValueChange: (value: string, index: number) => void;
19
+ defaultValue?: string;
20
+ assistiveText?: string;
21
+ label?: string;
22
+ iconColor?: string;
23
+ iconSize?: number;
24
+ leftIconMode?: "inset" | "outset";
25
+ leftIconName?: string;
26
+ placeholderTextColor?: string;
27
+ rightIconName?: string;
28
+ type?: "solid" | "underline";
29
+ theme: Theme;
30
+ Icon: IconSlot["Icon"];
7
31
  };
8
- declare const _default: React.ComponentType<import("@draftbit/react-theme-provider").$Without<Props, "theme"> & {
32
+ declare const _default: React.ComponentType<import("@draftbit/react-theme-provider").$Without<PickerProps, "theme"> & {
9
33
  theme?: import("@draftbit/react-theme-provider").$DeepPartial<any> | undefined;
10
- }> & import("@draftbit/react-theme-provider/typings/hoist-non-react-statics").NonReactStatics<React.ComponentType<Props> & React.FC<Props>, {}>;
34
+ }> & import("@draftbit/react-theme-provider/typings/hoist-non-react-statics").NonReactStatics<React.ComponentType<PickerProps> & React.FC<PickerProps>, {}>;
11
35
  export default _default;
@@ -18,6 +18,27 @@ export declare const SEED_DATA: {
18
18
  required: boolean;
19
19
  group: string;
20
20
  };
21
+ iconSize: {
22
+ group: string;
23
+ label: string;
24
+ description: string;
25
+ editable: boolean;
26
+ required: boolean;
27
+ formType: string;
28
+ propType: string;
29
+ defaultValue: number;
30
+ options: number[];
31
+ };
32
+ iconColor: {
33
+ group: string;
34
+ label: string;
35
+ description: string;
36
+ editable: boolean;
37
+ required: boolean;
38
+ defaultValue: null;
39
+ formType: string;
40
+ propType: string;
41
+ };
21
42
  label: {
22
43
  group: string;
23
44
  label: string;
@@ -1,8 +1,15 @@
1
+ /// <reference types="lodash" />
1
2
  import { StyleProp, TextStyle } from "react-native";
2
3
  export declare function extractStyles(style: StyleProp<any>): {
3
4
  viewStyles: any;
4
5
  textStyles: TextStyle;
5
6
  };
7
+ export declare const borderStyleNames: string[];
8
+ export declare const marginStyleNames: string[];
9
+ export declare function extractBorderAndMarginStyles(style: StyleProp<any>, additionalBorderStyles?: string[], additionalMarginStyles?: string[]): {
10
+ borderStyles: import("lodash").Dictionary<any>;
11
+ marginStyles: import("lodash").Dictionary<any>;
12
+ };
6
13
  /**
7
14
  * Merges a style object on top of another style object. In React Native,
8
15
  * keys with undefined values in a style object will still override styles
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@draftbit/core",
3
- "version": "44.2.1-e53c90.0+e53c90f0",
3
+ "version": "44.2.2",
4
4
  "description": "Core (non-native) Components",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -45,7 +45,7 @@
45
45
  "@material-ui/core": "^4.11.0",
46
46
  "@material-ui/pickers": "^3.2.10",
47
47
  "@react-native-community/slider": "4.1.12",
48
- "@react-native-picker/picker": "2.2.1",
48
+ "@react-native-picker/picker": "2.4.1",
49
49
  "color": "^3.1.2",
50
50
  "date-fns": "^2.16.1",
51
51
  "dateformat": "^3.0.3",
@@ -78,5 +78,5 @@
78
78
  ]
79
79
  ]
80
80
  },
81
- "gitHead": "e53c90f036fa70a877f267a4bca32c37b3cf3b42"
81
+ "gitHead": "277c7239f03d659053b557456bc5970792bd51ca"
82
82
  }
@@ -1,29 +1,47 @@
1
1
  import * as React from "react";
2
+ import { View, StyleSheet, Text, Platform, Dimensions, } from "react-native";
3
+ import { omit, pickBy, identity, isObject } 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, extractBorderAndMarginStyles, borderStyleNames, marginStyleNames, } 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 (isObject(options[0]) &&
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 { width: deviceWidth, height: deviceHeight } = Dimensions.get("screen");
34
+ const isIos = Platform.OS === "ios";
35
+ const unstyledColor = "rgba(165, 173, 183, 1)";
36
+ const disabledColor = "rgb(240, 240, 240)";
37
+ const errorColor = "rgba(255, 69, 100, 1)";
38
+ 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", }) => {
39
+ const androidPickerRef = React.useRef(undefined);
26
40
  const [internalValue, setInternalValue] = React.useState(value || defaultValue);
41
+ const [pickerVisible, setPickerVisible] = React.useState(false);
42
+ const togglePickerVisible = () => {
43
+ setPickerVisible(!pickerVisible);
44
+ };
27
45
  React.useEffect(() => {
28
46
  if (value != null) {
29
47
  setInternalValue(value);
@@ -34,23 +52,215 @@ const Picker = ({ options = [], placeholder, onValueChange: onValueChangeOverrid
34
52
  setInternalValue(defaultValue);
35
53
  }
36
54
  }, [defaultValue]);
37
- const onValueChange = React.useCallback((itemValue, itemIndex) => {
38
- if (placeholder && itemIndex === 0) {
39
- return;
55
+ React.useEffect(() => {
56
+ if (pickerVisible && androidPickerRef.current) {
57
+ androidPickerRef?.current?.focus();
40
58
  }
41
- onValueChangeOverride &&
42
- onValueChangeOverride(String(itemValue), itemIndex);
43
- }, [placeholder, onValueChangeOverride]);
59
+ }, [pickerVisible, androidPickerRef]);
44
60
  const normalizedOptions = normalizeOptions(options);
45
61
  const pickerOptions = placeholder
46
62
  ? [{ value: placeholder, label: placeholder }, ...normalizedOptions]
47
63
  : normalizedOptions;
64
+ const { colors } = theme;
65
+ const { viewStyles, textStyles } = extractStyles(style);
66
+ const additionalBorderStyles = ["backgroundColor"];
67
+ const additionalMarginStyles = [
68
+ "bottom",
69
+ "height",
70
+ "left",
71
+ "maxHeight",
72
+ "maxWidth",
73
+ "minHeight",
74
+ "minWidth",
75
+ "overflow",
76
+ "position",
77
+ "right",
78
+ "top",
79
+ "width",
80
+ "zIndex",
81
+ ];
82
+ const { borderStyles: extractedBorderStyles, marginStyles: extractedMarginStyles, } = extractBorderAndMarginStyles(viewStyles, additionalBorderStyles, additionalMarginStyles);
83
+ const borderStyles = {
84
+ ...{
85
+ ...(type === "solid"
86
+ ? {
87
+ borderTopLeftRadius: 5,
88
+ borderTopRightRadius: 5,
89
+ borderBottomRightRadius: 5,
90
+ borderBottomLeftRadius: 5,
91
+ borderTopWidth: 1,
92
+ borderRightWidth: 1,
93
+ borderLeftWidth: 1,
94
+ }
95
+ : {}),
96
+ borderBottomWidth: 1,
97
+ borderColor: unstyledColor,
98
+ borderStyle: "solid",
99
+ },
100
+ ...extractedBorderStyles,
101
+ ...(error ? { borderColor: errorColor } : {}),
102
+ ...(disabled
103
+ ? { borderColor: "transparent", backgroundColor: disabledColor }
104
+ : {}),
105
+ };
106
+ const marginStyles = {
107
+ height: 60,
108
+ ...extractedMarginStyles,
109
+ };
110
+ const stylesWithoutBordersAndMargins = omit(viewStyles, [
111
+ ...borderStyleNames,
112
+ ...marginStyleNames,
113
+ ...additionalBorderStyles,
114
+ ...additionalMarginStyles,
115
+ ]);
116
+ const selectedLabel = internalValue &&
117
+ (pickerOptions.find((option) => option.value === internalValue)?.label ??
118
+ internalValue);
119
+ const labelText = label ? (React.createElement(Text, { style: {
120
+ textAlign: textStyles.textAlign,
121
+ color: unstyledColor,
122
+ fontSize: 12,
123
+ paddingBottom: 4,
124
+ } }, label)) : null;
125
+ const leftIconOutset = leftIconMode === "outset";
126
+ const leftIcon = leftIconName ? (React.createElement(Icon, { name: leftIconName, color: disabled ? unstyledColor : iconColor, size: iconSize, style: {
127
+ marginRight: 4,
128
+ marginLeft: 4,
129
+ } })) : null;
130
+ const rightIcon = rightIconName ? (React.createElement(Icon, { name: rightIconName, color: disabled ? unstyledColor : iconColor, size: iconSize, style: {
131
+ marginRight: -10,
132
+ marginLeft: 8,
133
+ } })) : null;
134
+ const textAlign = textStyles?.textAlign;
135
+ const calculateLeftPadding = () => {
136
+ if (leftIconOutset) {
137
+ if (textAlign === "center") {
138
+ return iconSize - Math.abs(8 - iconSize);
139
+ }
140
+ return iconSize + 8;
141
+ }
142
+ return 0;
143
+ };
144
+ const assistiveTextLabel = assistiveText ? (React.createElement(Text, { style: {
145
+ textAlign,
146
+ width: "100%",
147
+ paddingLeft: calculateLeftPadding(),
148
+ color: unstyledColor,
149
+ fontSize: 12,
150
+ paddingTop: 4,
151
+ } }, assistiveText)) : null;
152
+ const primaryTextStyle = {
153
+ color: unstyledColor,
154
+ fontSize: 14,
155
+ ...pickBy(textStyles, identity),
156
+ ...(placeholder === internalValue ? { color: placeholderTextColor } : {}),
157
+ ...(disabled ? { color: unstyledColor } : {}),
158
+ };
48
159
  const handleValueChange = (newValue, itemIndex) => {
49
- setInternalValue(newValue);
50
- if (onValueChange) {
51
- onValueChange(newValue, itemIndex);
160
+ if (!placeholder || itemIndex > 0) {
161
+ onValueChange?.(newValue, itemIndex);
52
162
  }
163
+ setInternalValue(newValue);
53
164
  };
54
- return (React.createElement(PickerComponent, { ...props, selectedValue: String(internalValue), placeholder: placeholder, options: pickerOptions, onValueChange: handleValueChange }));
165
+ return (
166
+ /* marginsContainer */
167
+ React.createElement(View, { style: [styles.marginsContainer, marginStyles] },
168
+ React.createElement(Touchable, { disabled: disabled, onPress: togglePickerVisible, style: styles.touchableContainer },
169
+ React.createElement(View, { pointerEvents: "none", style: [
170
+ styles.outsetContainer,
171
+ stylesWithoutBordersAndMargins,
172
+ !leftIconOutset ? borderStyles : {},
173
+ ] },
174
+ leftIcon,
175
+ React.createElement(View, { style: [
176
+ styles.insetContainer,
177
+ leftIconOutset ? borderStyles : {},
178
+ ] },
179
+ React.createElement(View, { style: styles.primaryTextContainer },
180
+ labelText,
181
+ React.createElement(Text, { style: primaryTextStyle }, String(selectedLabel ?? placeholder))),
182
+ rightIcon)),
183
+ assistiveTextLabel),
184
+ isIos && pickerVisible ? (React.createElement(Portal, null,
185
+ React.createElement(View, { style: [
186
+ styles.iosPicker,
187
+ {
188
+ backgroundColor: colors.divider,
189
+ },
190
+ ] },
191
+ React.createElement(SafeAreaView, { style: styles.iosSafeArea },
192
+ React.createElement(Button, { Icon: Icon, type: "text", onPress: togglePickerVisible, style: styles.iosButton }, "Close"),
193
+ 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,
194
+ !isIos && pickerVisible ? (React.createElement(NativePicker, { enabled: pickerVisible, selectedValue: internalValue, onValueChange: handleValueChange, style: styles.nonIosPicker, ref: androidPickerRef, onBlur: () => setPickerVisible(false) }, pickerOptions.map((option) => (React.createElement(NativePicker.Item, { label: option.label, value: option.value, key: option.value }))))) : null));
55
195
  };
56
196
  export default withTheme(Picker);
197
+ const styles = StyleSheet.create({
198
+ marginsContainer: {
199
+ alignSelf: "stretch",
200
+ alignItems: "center",
201
+ width: "100%",
202
+ maxWidth: deviceWidth,
203
+ },
204
+ touchableContainer: {
205
+ flex: 1,
206
+ height: "100%",
207
+ width: "100%",
208
+ alignSelf: "stretch",
209
+ alignItems: "center",
210
+ },
211
+ outsetContainer: {
212
+ flex: 1,
213
+ height: "100%",
214
+ width: "100%",
215
+ flexDirection: "row",
216
+ alignItems: "center",
217
+ justifyContent: "space-between",
218
+ },
219
+ insetContainer: {
220
+ flex: 1,
221
+ height: "100%",
222
+ width: "100%",
223
+ flexDirection: "row",
224
+ alignItems: "center",
225
+ justifyContent: "space-between",
226
+ paddingLeft: 12,
227
+ paddingRight: 12,
228
+ },
229
+ primaryTextContainer: {
230
+ flex: 1,
231
+ },
232
+ iosPicker: {
233
+ position: "absolute",
234
+ bottom: 0,
235
+ left: 0,
236
+ right: 0,
237
+ flexDirection: "row",
238
+ justifyContent: "center",
239
+ width: "100%",
240
+ maxWidth: deviceWidth,
241
+ maxHeight: deviceHeight,
242
+ },
243
+ iosSafeArea: {
244
+ backgroundColor: "white",
245
+ flexDirection: "column",
246
+ width: "100%",
247
+ maxWidth: deviceWidth,
248
+ },
249
+ iosButton: {
250
+ alignSelf: "flex-end",
251
+ },
252
+ iosNativePicker: {
253
+ backgroundColor: "white",
254
+ },
255
+ nonIosPicker: {
256
+ opacity: 0,
257
+ position: "absolute",
258
+ top: 0,
259
+ left: 0,
260
+ right: 0,
261
+ bottom: 0,
262
+ width: "100%",
263
+ maxWidth: deviceWidth,
264
+ maxHeight: deviceHeight,
265
+ },
266
+ });