@teamnhz/rn-ui-toolkit 1.0.1 → 1.0.3
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/README.md +3 -2
- package/dist/assets/images/ic_calendar.png +0 -0
- package/dist/assets/images/ic_time.png +0 -0
- package/dist/components/BottomSheet/index.js +58 -2
- package/dist/components/Buttons/index.d.ts +2 -2
- package/dist/components/Buttons/index.js +102 -11
- package/dist/components/CheckBox/index.d.ts +2 -2
- package/dist/components/CheckBox/index.js +112 -15
- package/dist/components/DateTimePicker/index.d.ts +25 -3
- package/dist/components/DateTimePicker/index.js +248 -22
- package/dist/components/Dividers/index.d.ts +3 -3
- package/dist/components/Dividers/index.js +41 -5
- package/dist/components/HorizontalFlatList/index.d.ts +2 -2
- package/dist/components/HorizontalFlatList/index.js +47 -8
- package/dist/components/Image/index.d.ts +2 -4
- package/dist/components/Image/index.js +22 -4
- package/dist/components/ImagePicker/index.d.ts +8 -1
- package/dist/components/ImagePicker/index.js +154 -18
- package/dist/components/Input/index.d.ts +17 -3
- package/dist/components/Input/index.js +302 -19
- package/dist/components/KeyboardScroll/index.d.ts +3 -0
- package/dist/components/KeyboardScroll/index.js +76 -0
- package/dist/components/Modal/index.d.ts +2 -2
- package/dist/components/Modal/index.js +31 -3
- package/dist/components/Switch/index.d.ts +13 -3
- package/dist/components/Switch/index.js +93 -12
- package/dist/components/T/index.d.ts +5 -4
- package/dist/components/T/index.js +69 -10
- package/dist/components/Toast/index.js +123 -3
- package/dist/components/VerticalFlatList/index.d.ts +2 -2
- package/dist/components/VerticalFlatList/index.js +22 -5
- package/dist/components/index.d.ts +29 -29
- package/dist/components/index.js +29 -29
- package/dist/styles/colors.d.ts +1 -0
- package/dist/styles/colors.js +30 -29
- package/dist/styles/images.d.ts +2 -0
- package/dist/styles/images.js +5 -1
- package/package.json +20 -16
- package/dist/components/ScrolledContainer/index.d.ts +0 -13
- package/dist/components/ScrolledContainer/index.js +0 -30
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React, { useCallback } from "react";
|
|
2
|
-
import { View, Text, TouchableOpacity, StyleSheet, Image, Alert } from "react-native";
|
|
2
|
+
import { View, Text, TouchableOpacity, StyleSheet, Image, Alert, } from "react-native";
|
|
3
3
|
import { BottomSheet, Dividers } from "../index";
|
|
4
4
|
import { launchCamera, launchImageLibrary } from "react-native-image-picker";
|
|
5
5
|
import ImageCropPicker from "react-native-image-crop-picker";
|
|
6
6
|
import { Colors, Images, Scale, Typography } from "../../styles";
|
|
7
|
-
const ImagePicker = ({ mediaType, isMultiSelect = false, onSuccess, visible, onClose, }) => {
|
|
7
|
+
const ImagePicker = ({ mediaType, isMultiSelect = false, onSuccess, visible, onClose, containerStyle, rowStyle, textStyle, iconStyle, }) => {
|
|
8
8
|
const onComplete = useCallback((data) => {
|
|
9
9
|
onSuccess(data);
|
|
10
10
|
onClose();
|
|
@@ -42,7 +42,11 @@ const ImagePicker = ({ mediaType, isMultiSelect = false, onSuccess, visible, onC
|
|
|
42
42
|
const onGallery = () => {
|
|
43
43
|
if (mediaType === "photo") {
|
|
44
44
|
if (isMultiSelect) {
|
|
45
|
-
ImageCropPicker.openPicker({
|
|
45
|
+
ImageCropPicker.openPicker({
|
|
46
|
+
mediaType: "photo",
|
|
47
|
+
multiple: true,
|
|
48
|
+
maxFiles: 5,
|
|
49
|
+
})
|
|
46
50
|
.then((images) => {
|
|
47
51
|
if (images.length > 5) {
|
|
48
52
|
Alert.alert("Limit Exceeded", "You can only select up to 5 images.");
|
|
@@ -76,19 +80,19 @@ const ImagePicker = ({ mediaType, isMultiSelect = false, onSuccess, visible, onC
|
|
|
76
80
|
});
|
|
77
81
|
}
|
|
78
82
|
};
|
|
79
|
-
return (React.createElement(BottomSheet, { visible: visible, onClose: onClose, height:
|
|
80
|
-
React.createElement(View, { style: styles.container },
|
|
81
|
-
React.createElement(TouchableOpacity, { style: styles.row, onPress: onCamera },
|
|
82
|
-
React.createElement(Image, { source: Images.video_icon, style: styles.icon }),
|
|
83
|
-
React.createElement(Text, { style: styles.text }, "Camera")),
|
|
83
|
+
return (React.createElement(BottomSheet, { visible: visible, onClose: onClose, height: 230 },
|
|
84
|
+
React.createElement(View, { style: [styles.container, containerStyle] },
|
|
85
|
+
React.createElement(TouchableOpacity, { style: [styles.row, rowStyle], onPress: onCamera },
|
|
86
|
+
React.createElement(Image, { source: Images.video_icon, style: [styles.icon, iconStyle] }),
|
|
87
|
+
React.createElement(Text, { style: [styles.text, textStyle] }, "Camera")),
|
|
84
88
|
React.createElement(Dividers, { small: true }),
|
|
85
|
-
React.createElement(TouchableOpacity, { style: styles.row, onPress: onGallery },
|
|
86
|
-
React.createElement(Image, { source: Images.image_icon, style: styles.icon }),
|
|
87
|
-
React.createElement(Text, { style: styles.text }, "Gallery")),
|
|
89
|
+
React.createElement(TouchableOpacity, { style: [styles.row, rowStyle], onPress: onGallery },
|
|
90
|
+
React.createElement(Image, { source: Images.image_icon, style: [styles.icon, iconStyle] }),
|
|
91
|
+
React.createElement(Text, { style: [styles.text, textStyle] }, "Gallery")),
|
|
88
92
|
React.createElement(Dividers, { small: true }),
|
|
89
|
-
React.createElement(TouchableOpacity, { style: styles.row, onPress: onClose },
|
|
90
|
-
React.createElement(Image, { source: Images.
|
|
91
|
-
React.createElement(Text, { style: styles.text }, "Cancel")))));
|
|
93
|
+
React.createElement(TouchableOpacity, { style: [styles.row, rowStyle], onPress: onClose },
|
|
94
|
+
React.createElement(Image, { source: Images.cancel, style: [styles.icon, iconStyle] }),
|
|
95
|
+
React.createElement(Text, { style: [styles.text, textStyle] }, "Cancel")))));
|
|
92
96
|
};
|
|
93
97
|
export default ImagePicker;
|
|
94
98
|
const styles = StyleSheet.create({
|
|
@@ -96,14 +100,146 @@ const styles = StyleSheet.create({
|
|
|
96
100
|
row: {
|
|
97
101
|
flexDirection: "row",
|
|
98
102
|
alignItems: "center",
|
|
99
|
-
// paddingVertical: 12,
|
|
100
103
|
},
|
|
101
|
-
text: { ...Typography.style.standardU(), color: Colors.
|
|
102
|
-
separator: { height: 1, backgroundColor: Colors.borderGrey, marginVertical: 8 },
|
|
104
|
+
text: { ...Typography.style.standardU(), color: Colors.white },
|
|
103
105
|
icon: {
|
|
104
106
|
width: Scale.moderateScale(20),
|
|
105
107
|
height: Scale.moderateScale(20),
|
|
106
108
|
marginRight: 10,
|
|
107
|
-
tintColor: Colors.
|
|
109
|
+
tintColor: Colors.white,
|
|
108
110
|
},
|
|
109
111
|
});
|
|
112
|
+
// import React, { useCallback } from "react";
|
|
113
|
+
// import { View, Text, TouchableOpacity, StyleSheet, Image, Alert } from "react-native";
|
|
114
|
+
// import { BottomSheet, Dividers } from "../index";
|
|
115
|
+
// import { launchCamera, launchImageLibrary } from "react-native-image-picker";
|
|
116
|
+
// import ImageCropPicker from "react-native-image-crop-picker";
|
|
117
|
+
// import { Colors, Images, Scale, Typography } from "../../styles";
|
|
118
|
+
// type Props = {
|
|
119
|
+
// mediaType: "photo" | "video";
|
|
120
|
+
// isMultiSelect?: boolean;
|
|
121
|
+
// onSuccess: (data: any) => void;
|
|
122
|
+
// visible: boolean;
|
|
123
|
+
// onClose: () => void;
|
|
124
|
+
// };
|
|
125
|
+
// const ImagePicker: React.FC<Props> = ({
|
|
126
|
+
// mediaType,
|
|
127
|
+
// isMultiSelect = false,
|
|
128
|
+
// onSuccess,
|
|
129
|
+
// visible,
|
|
130
|
+
// onClose,
|
|
131
|
+
// }) => {
|
|
132
|
+
// const onComplete = useCallback(
|
|
133
|
+
// (data: any) => {
|
|
134
|
+
// onSuccess(data);
|
|
135
|
+
// onClose();
|
|
136
|
+
// },
|
|
137
|
+
// [onSuccess, onClose]
|
|
138
|
+
// );
|
|
139
|
+
// const onCamera = () => {
|
|
140
|
+
// if (mediaType === "photo") {
|
|
141
|
+
// if (isMultiSelect) {
|
|
142
|
+
// ImageCropPicker.openCamera({ mediaType: "photo" })
|
|
143
|
+
// .then((response) => onComplete([response]))
|
|
144
|
+
// .catch(() => {});
|
|
145
|
+
// } else {
|
|
146
|
+
// ImageCropPicker.openCamera({ mediaType: "photo" })
|
|
147
|
+
// .then((response) =>
|
|
148
|
+
// ImageCropPicker.openCropper({
|
|
149
|
+
// path: response?.path,
|
|
150
|
+
// width: response?.width,
|
|
151
|
+
// height: response?.height,
|
|
152
|
+
// mediaType: "photo",
|
|
153
|
+
// freeStyleCropEnabled: true,
|
|
154
|
+
// }).then(onComplete)
|
|
155
|
+
// )
|
|
156
|
+
// .catch(() => {});
|
|
157
|
+
// }
|
|
158
|
+
// } else {
|
|
159
|
+
// launchCamera({ mediaType: "video" }, (response) => {
|
|
160
|
+
// if (response?.assets) {
|
|
161
|
+
// onComplete({
|
|
162
|
+
// path: response.assets[0]?.uri,
|
|
163
|
+
// duration: response.assets[0]?.duration,
|
|
164
|
+
// });
|
|
165
|
+
// }
|
|
166
|
+
// });
|
|
167
|
+
// }
|
|
168
|
+
// };
|
|
169
|
+
// const onGallery = () => {
|
|
170
|
+
// if (mediaType === "photo") {
|
|
171
|
+
// if (isMultiSelect) {
|
|
172
|
+
// ImageCropPicker.openPicker({ mediaType: "photo", multiple: true, maxFiles: 5 })
|
|
173
|
+
// .then((images) => {
|
|
174
|
+
// if (images.length > 5) {
|
|
175
|
+
// Alert.alert("Limit Exceeded", "You can only select up to 5 images.");
|
|
176
|
+
// } else {
|
|
177
|
+
// onComplete(images);
|
|
178
|
+
// }
|
|
179
|
+
// })
|
|
180
|
+
// .catch(() => {});
|
|
181
|
+
// } else {
|
|
182
|
+
// ImageCropPicker.openPicker({ mediaType: "photo" })
|
|
183
|
+
// .then((response) =>
|
|
184
|
+
// ImageCropPicker.openCropper({
|
|
185
|
+
// path: response?.path,
|
|
186
|
+
// width: response?.width,
|
|
187
|
+
// height: response?.height,
|
|
188
|
+
// mediaType: "photo",
|
|
189
|
+
// freeStyleCropEnabled: true,
|
|
190
|
+
// }).then(onComplete)
|
|
191
|
+
// )
|
|
192
|
+
// .catch(() => {});
|
|
193
|
+
// }
|
|
194
|
+
// } else {
|
|
195
|
+
// launchImageLibrary({ mediaType: "video" }, (result) => {
|
|
196
|
+
// if (result?.assets) {
|
|
197
|
+
// onComplete({
|
|
198
|
+
// path: result.assets[0]?.uri,
|
|
199
|
+
// duration: result.assets[0]?.duration,
|
|
200
|
+
// });
|
|
201
|
+
// }
|
|
202
|
+
// });
|
|
203
|
+
// }
|
|
204
|
+
// };
|
|
205
|
+
// return (
|
|
206
|
+
// <BottomSheet visible={visible} onClose={onClose} height={210}>
|
|
207
|
+
// <View style={styles.container}>
|
|
208
|
+
// {/* Camera */}
|
|
209
|
+
// <TouchableOpacity style={styles.row} onPress={onCamera}>
|
|
210
|
+
// <Image source={Images.video_icon} style={styles.icon} />
|
|
211
|
+
// <Text style={styles.text}>Camera</Text>
|
|
212
|
+
// </TouchableOpacity>
|
|
213
|
+
// <Dividers small/>
|
|
214
|
+
// {/* Gallery */}
|
|
215
|
+
// <TouchableOpacity style={styles.row} onPress={onGallery}>
|
|
216
|
+
// <Image source={Images.image_icon} style={styles.icon} />
|
|
217
|
+
// <Text style={styles.text}>Gallery</Text>
|
|
218
|
+
// </TouchableOpacity>
|
|
219
|
+
// <Dividers small/>
|
|
220
|
+
// {/* Cancel */}
|
|
221
|
+
// <TouchableOpacity style={styles.row} onPress={onClose}>
|
|
222
|
+
// <Image source={Images.image_icon} style={styles.icon} />
|
|
223
|
+
// <Text style={styles.text}>Cancel</Text>
|
|
224
|
+
// </TouchableOpacity>
|
|
225
|
+
// </View>
|
|
226
|
+
// </BottomSheet>
|
|
227
|
+
// );
|
|
228
|
+
// };
|
|
229
|
+
// export default ImagePicker;
|
|
230
|
+
// const styles = StyleSheet.create({
|
|
231
|
+
// container: { flex: 1, padding: 16 },
|
|
232
|
+
// row: {
|
|
233
|
+
// flexDirection: "row",
|
|
234
|
+
// alignItems: "center",
|
|
235
|
+
// // paddingVertical: 12,
|
|
236
|
+
// },
|
|
237
|
+
// text: { ...Typography.style.standardU(), color: Colors.black },
|
|
238
|
+
// separator: { height: 1, backgroundColor: Colors.borderGrey, marginVertical: 8 },
|
|
239
|
+
// icon: {
|
|
240
|
+
// width: Scale.moderateScale(20),
|
|
241
|
+
// height: Scale.moderateScale(20),
|
|
242
|
+
// marginRight: 10,
|
|
243
|
+
// tintColor: Colors.darkBlue,
|
|
244
|
+
// },
|
|
245
|
+
// });
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { TextInputProps, ImageSourcePropType } from "react-native";
|
|
2
|
+
import { TextInputProps, ImageSourcePropType, ReturnKeyTypeOptions } from "react-native";
|
|
3
3
|
import { InputType } from "../../utils/regex";
|
|
4
4
|
interface InputProps extends TextInputProps {
|
|
5
5
|
intlType?: string;
|
|
@@ -9,8 +9,7 @@ interface InputProps extends TextInputProps {
|
|
|
9
9
|
onLeftIconPress?: () => void;
|
|
10
10
|
onRightIconPress?: () => void;
|
|
11
11
|
type?: InputType;
|
|
12
|
-
|
|
13
|
-
/** error message from parent (Formik, RHF, Zod, etc.) */
|
|
12
|
+
editable?: boolean;
|
|
14
13
|
error?: string | boolean;
|
|
15
14
|
value?: string;
|
|
16
15
|
customRegex?: RegExp;
|
|
@@ -21,6 +20,21 @@ interface InputProps extends TextInputProps {
|
|
|
21
20
|
hasError: boolean;
|
|
22
21
|
message?: string;
|
|
23
22
|
}) => void;
|
|
23
|
+
containerStyle?: object;
|
|
24
|
+
inputStyle?: object;
|
|
25
|
+
errorTextStyle?: object;
|
|
26
|
+
leftIconStyle?: object;
|
|
27
|
+
rightIconStyle?: object;
|
|
28
|
+
leftIconWrapperStyle?: object;
|
|
29
|
+
rightIconWrapperStyle?: object;
|
|
30
|
+
maxLength?: number;
|
|
31
|
+
placeholder?: string;
|
|
32
|
+
inputPlaceholderTextColor?: string;
|
|
33
|
+
returnKeyType?: ReturnKeyTypeOptions | undefined;
|
|
34
|
+
countryCode?: string;
|
|
35
|
+
onPressCountryCode?: () => void;
|
|
36
|
+
countryCodeWrapperStyle?: object;
|
|
37
|
+
countryCodeTextStyle?: object;
|
|
24
38
|
}
|
|
25
39
|
declare const Input: React.FC<InputProps>;
|
|
26
40
|
export default Input;
|
|
@@ -4,17 +4,22 @@ import { useTranslation } from "react-i18next";
|
|
|
4
4
|
import { Colors, Typography, Scale, Images } from "../../styles";
|
|
5
5
|
import { defaultRegex } from "../../utils/regex";
|
|
6
6
|
import { messages } from "../../constants/messages";
|
|
7
|
-
const Input = ({ intlType, textKey, placeholder, leftIcon, rightIcon, onLeftIconPress, onRightIconPress, style, type = "text",
|
|
7
|
+
const Input = ({ intlType, textKey, placeholder, inputPlaceholderTextColor, leftIcon, rightIcon, onLeftIconPress, onRightIconPress, style, containerStyle, inputStyle, errorTextStyle, leftIconStyle, rightIconStyle, leftIconWrapperStyle, rightIconWrapperStyle, type = "text", editable = true, error, value = "", customRegex, customErrorMessage, onChangeText, onValidation, onBlur: restOnBlur, onFocus: restOnFocus, multiline = false, maxLength, returnKeyType, countryCode, onPressCountryCode, countryCodeTextStyle, countryCodeWrapperStyle, ...rest }) => {
|
|
8
8
|
const { t } = useTranslation();
|
|
9
9
|
const [secureText, setSecureText] = useState(type === "password");
|
|
10
10
|
const [internalError, setInternalError] = useState(null);
|
|
11
11
|
const [wasBlurred, setWasBlurred] = useState(false);
|
|
12
12
|
const [isFocused, setIsFocused] = useState(false);
|
|
13
|
-
const translatedPlaceholder = intlType && textKey
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
const translatedPlaceholder = intlType && textKey
|
|
14
|
+
? String(t(textKey, { ns: intlType, value }))
|
|
15
|
+
: placeholder;
|
|
16
|
+
const keyboardType = type === "email"
|
|
17
|
+
? "email-address"
|
|
18
|
+
: type === "number"
|
|
19
|
+
? "numeric"
|
|
20
|
+
: "default";
|
|
16
21
|
const validateInternal = useCallback((text) => {
|
|
17
|
-
if (!wasBlurred)
|
|
22
|
+
if (!wasBlurred || !editable)
|
|
18
23
|
return;
|
|
19
24
|
const regexToUse = customRegex ?? defaultRegex[type];
|
|
20
25
|
const fallbackMsg = messages.invalid[type] || "Invalid input";
|
|
@@ -27,7 +32,7 @@ const Input = ({ intlType, textKey, placeholder, leftIcon, rightIcon, onLeftIcon
|
|
|
27
32
|
setInternalError(null);
|
|
28
33
|
onValidation?.({ type, hasError: false });
|
|
29
34
|
}
|
|
30
|
-
}, [wasBlurred, type, customRegex, customErrorMessage, onValidation]);
|
|
35
|
+
}, [wasBlurred, editable, type, customRegex, customErrorMessage, onValidation]);
|
|
31
36
|
useEffect(() => {
|
|
32
37
|
if (!customRegex)
|
|
33
38
|
return;
|
|
@@ -49,31 +54,50 @@ const Input = ({ intlType, textKey, placeholder, leftIcon, rightIcon, onLeftIcon
|
|
|
49
54
|
setIsFocused(false);
|
|
50
55
|
if (!wasBlurred)
|
|
51
56
|
setWasBlurred(true);
|
|
52
|
-
|
|
57
|
+
if (editable)
|
|
58
|
+
validateInternal(value || "");
|
|
53
59
|
restOnBlur?.(e);
|
|
54
60
|
};
|
|
55
|
-
// Decide which error to show: external error (Formik/RHF/etc) > internal error
|
|
56
61
|
const rawError = (typeof error === "string" ? error : undefined) ?? internalError ?? null;
|
|
62
|
+
// const showError = (() => {
|
|
63
|
+
// if (!rawError || !editable) return null;
|
|
64
|
+
// return wasBlurred && !isFocused ? rawError : null;
|
|
65
|
+
// })();
|
|
57
66
|
const showError = (() => {
|
|
58
|
-
if (!rawError)
|
|
67
|
+
if (!rawError || !editable)
|
|
59
68
|
return null;
|
|
69
|
+
// If error comes from parent, show it directly
|
|
70
|
+
if (typeof error === "string" && error.length > 0) {
|
|
71
|
+
return rawError;
|
|
72
|
+
}
|
|
60
73
|
return wasBlurred && !isFocused ? rawError : null;
|
|
61
74
|
})();
|
|
62
|
-
return (React.createElement(View,
|
|
75
|
+
return (React.createElement(View, null,
|
|
63
76
|
React.createElement(View, { style: [
|
|
64
77
|
styles.container,
|
|
65
|
-
|
|
78
|
+
!editable && styles.disabled,
|
|
66
79
|
!!showError && styles.errorBorder,
|
|
67
80
|
isFocused && styles.focusedBorder,
|
|
68
81
|
style,
|
|
82
|
+
containerStyle,
|
|
83
|
+
multiline && styles.multilineContainer,
|
|
69
84
|
] },
|
|
70
|
-
leftIcon && (React.createElement(TouchableOpacity, { onPress: onLeftIconPress, disabled: !onLeftIconPress, style: styles.iconWrapper },
|
|
71
|
-
React.createElement(Image, { source: leftIcon, style: styles.icon, resizeMode: "contain" }))),
|
|
72
|
-
React.createElement(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
85
|
+
leftIcon && (React.createElement(TouchableOpacity, { onPress: onLeftIconPress, disabled: !onLeftIconPress, style: [styles.iconWrapper, leftIconWrapperStyle] },
|
|
86
|
+
React.createElement(Image, { source: leftIcon, style: [styles.icon, leftIconStyle], resizeMode: "contain" }))),
|
|
87
|
+
countryCode && (React.createElement(TouchableOpacity, { onPress: onPressCountryCode, disabled: !onPressCountryCode, style: [styles.countryCodeWrapper, countryCodeWrapperStyle] },
|
|
88
|
+
React.createElement(Text, { style: [styles.countryCodeText, countryCodeTextStyle] }, countryCode))),
|
|
89
|
+
React.createElement(TextInput, { style: [
|
|
90
|
+
styles.input,
|
|
91
|
+
!editable && styles.disabledText,
|
|
92
|
+
multiline && styles.multilineInput,
|
|
93
|
+
inputStyle,
|
|
94
|
+
], placeholder: translatedPlaceholder, placeholderTextColor: inputPlaceholderTextColor
|
|
95
|
+
? inputPlaceholderTextColor
|
|
96
|
+
: Colors.textGrey, editable: editable, secureTextEntry: secureText, keyboardType: keyboardType, value: value, onChangeText: handleChangeText, onFocus: handleFocus, onBlur: handleBlur, multiline: multiline, maxLength: maxLength, returnKeyType: returnKeyType, ...rest }),
|
|
97
|
+
type === "password" ? (React.createElement(TouchableOpacity, { onPress: () => setSecureText(!secureText), style: [styles.iconWrapper, rightIconWrapperStyle] },
|
|
98
|
+
React.createElement(Image, { source: secureText ? Images.Eyeon : Images.Eyeoff, style: [styles.icon, rightIconStyle], resizeMode: "contain" }))) : (rightIcon && (React.createElement(TouchableOpacity, { onPress: onRightIconPress, disabled: !onRightIconPress, style: [styles.iconWrapper, rightIconWrapperStyle] },
|
|
99
|
+
React.createElement(Image, { source: rightIcon, style: [styles.icon, rightIconStyle], resizeMode: "contain" }))))),
|
|
100
|
+
showError && (React.createElement(Text, { style: [styles.errorText, errorTextStyle] }, showError))));
|
|
77
101
|
};
|
|
78
102
|
export default Input;
|
|
79
103
|
const styles = StyleSheet.create({
|
|
@@ -85,7 +109,13 @@ const styles = StyleSheet.create({
|
|
|
85
109
|
borderColor: Colors.primaryColor,
|
|
86
110
|
backgroundColor: Colors.white,
|
|
87
111
|
height: Scale.moderateScale(50),
|
|
88
|
-
paddingHorizontal: Scale.moderateScale(
|
|
112
|
+
paddingHorizontal: Scale.moderateScale(4),
|
|
113
|
+
},
|
|
114
|
+
multilineContainer: {
|
|
115
|
+
height: "auto",
|
|
116
|
+
minHeight: Scale.moderateScale(80),
|
|
117
|
+
alignItems: "flex-start",
|
|
118
|
+
paddingVertical: Scale.moderateScale(8),
|
|
89
119
|
},
|
|
90
120
|
focusedBorder: {
|
|
91
121
|
borderColor: Colors.primaryColor,
|
|
@@ -96,6 +126,10 @@ const styles = StyleSheet.create({
|
|
|
96
126
|
textTransform: "none",
|
|
97
127
|
color: Colors.textColor,
|
|
98
128
|
},
|
|
129
|
+
multilineInput: {
|
|
130
|
+
textAlignVertical: "top",
|
|
131
|
+
paddingTop: Scale.moderateScale(5),
|
|
132
|
+
},
|
|
99
133
|
iconWrapper: {
|
|
100
134
|
padding: Scale.moderateScale(5),
|
|
101
135
|
},
|
|
@@ -119,4 +153,253 @@ const styles = StyleSheet.create({
|
|
|
119
153
|
fontSize: Scale.moderateScale(12),
|
|
120
154
|
marginTop: 3,
|
|
121
155
|
},
|
|
156
|
+
countryCodeWrapper: {
|
|
157
|
+
paddingHorizontal: Scale.moderateScale(6),
|
|
158
|
+
justifyContent: "center",
|
|
159
|
+
alignItems: "center",
|
|
160
|
+
borderRightWidth: 1,
|
|
161
|
+
borderRightColor: Colors.borderGrey,
|
|
162
|
+
marginRight: Scale.moderateScale(6),
|
|
163
|
+
},
|
|
164
|
+
countryCodeText: {
|
|
165
|
+
...Typography.style.standardU(),
|
|
166
|
+
fontSize: Scale.moderateScale(14),
|
|
167
|
+
color: Colors.textColor,
|
|
168
|
+
},
|
|
122
169
|
});
|
|
170
|
+
// import React, { useState, useCallback, useEffect } from "react";
|
|
171
|
+
// import {
|
|
172
|
+
// View,
|
|
173
|
+
// TextInput,
|
|
174
|
+
// TextInputProps,
|
|
175
|
+
// StyleSheet,
|
|
176
|
+
// Image,
|
|
177
|
+
// ImageSourcePropType,
|
|
178
|
+
// TouchableOpacity,
|
|
179
|
+
// Text,
|
|
180
|
+
// NativeSyntheticEvent,
|
|
181
|
+
// TextInputFocusEventData,
|
|
182
|
+
// } from "react-native";
|
|
183
|
+
// import { useTranslation } from "react-i18next";
|
|
184
|
+
// import { Colors, Typography, Scale, Images } from "../../styles";
|
|
185
|
+
// import { defaultRegex, InputType } from "../../utils/regex";
|
|
186
|
+
// import { messages } from "../../constants/messages";
|
|
187
|
+
// interface InputProps extends TextInputProps {
|
|
188
|
+
// intlType?: string;
|
|
189
|
+
// textKey?: string;
|
|
190
|
+
// leftIcon?: ImageSourcePropType;
|
|
191
|
+
// rightIcon?: ImageSourcePropType;
|
|
192
|
+
// onLeftIconPress?: () => void;
|
|
193
|
+
// onRightIconPress?: () => void;
|
|
194
|
+
// type?: InputType;
|
|
195
|
+
// editable?: boolean;
|
|
196
|
+
// error?: string | boolean;
|
|
197
|
+
// value?: string;
|
|
198
|
+
// customRegex?: RegExp;
|
|
199
|
+
// customErrorMessage?: string;
|
|
200
|
+
// onChangeText?: (text: string) => void;
|
|
201
|
+
// onValidation?: (errorObj: { type: InputType; hasError: boolean; message?: string }) => void;
|
|
202
|
+
// containerStyle?: object;
|
|
203
|
+
// inputStyle?: object;
|
|
204
|
+
// errorTextStyle?: object;
|
|
205
|
+
// leftIconStyle?: object;
|
|
206
|
+
// rightIconStyle?: object;
|
|
207
|
+
// }
|
|
208
|
+
// const Input: React.FC<InputProps> = ({
|
|
209
|
+
// intlType,
|
|
210
|
+
// textKey,
|
|
211
|
+
// placeholder,
|
|
212
|
+
// leftIcon,
|
|
213
|
+
// rightIcon,
|
|
214
|
+
// onLeftIconPress,
|
|
215
|
+
// onRightIconPress,
|
|
216
|
+
// style,
|
|
217
|
+
// containerStyle,
|
|
218
|
+
// inputStyle,
|
|
219
|
+
// errorTextStyle,
|
|
220
|
+
// leftIconStyle,
|
|
221
|
+
// rightIconStyle,
|
|
222
|
+
// type = "text",
|
|
223
|
+
// editable = true,
|
|
224
|
+
// error,
|
|
225
|
+
// value = "",
|
|
226
|
+
// customRegex,
|
|
227
|
+
// customErrorMessage,
|
|
228
|
+
// onChangeText,
|
|
229
|
+
// onValidation,
|
|
230
|
+
// onBlur: restOnBlur,
|
|
231
|
+
// onFocus: restOnFocus,
|
|
232
|
+
// multiline = false,
|
|
233
|
+
// ...rest
|
|
234
|
+
// }) => {
|
|
235
|
+
// const { t } = useTranslation();
|
|
236
|
+
// const [secureText, setSecureText] = useState(type === "password");
|
|
237
|
+
// const [internalError, setInternalError] = useState<string | null>(null);
|
|
238
|
+
// const [wasBlurred, setWasBlurred] = useState(false);
|
|
239
|
+
// const [isFocused, setIsFocused] = useState(false);
|
|
240
|
+
// const translatedPlaceholder =
|
|
241
|
+
// intlType && textKey ? String(t(textKey, { ns: intlType, value })) : placeholder;
|
|
242
|
+
// const keyboardType: TextInputProps["keyboardType"] =
|
|
243
|
+
// type === "email" ? "email-address" : type === "number" ? "numeric" : "default";
|
|
244
|
+
// const validateInternal = useCallback(
|
|
245
|
+
// (text: string) => {
|
|
246
|
+
// if (!wasBlurred || !editable) return;
|
|
247
|
+
// const regexToUse = customRegex ?? defaultRegex[type];
|
|
248
|
+
// const fallbackMsg = messages.invalid[type] || "Invalid input";
|
|
249
|
+
// const msg = customErrorMessage || fallbackMsg;
|
|
250
|
+
// if (text === "" || !regexToUse.test(text)) {
|
|
251
|
+
// setInternalError(msg);
|
|
252
|
+
// onValidation?.({ type, hasError: true, message: msg });
|
|
253
|
+
// } else {
|
|
254
|
+
// setInternalError(null);
|
|
255
|
+
// onValidation?.({ type, hasError: false });
|
|
256
|
+
// }
|
|
257
|
+
// },
|
|
258
|
+
// [wasBlurred, editable, type, customRegex, customErrorMessage, onValidation]
|
|
259
|
+
// );
|
|
260
|
+
// useEffect(() => {
|
|
261
|
+
// if (!customRegex) return;
|
|
262
|
+
// if (internalError && value && customRegex.test(value)) {
|
|
263
|
+
// setInternalError(null);
|
|
264
|
+
// onValidation?.({ type, hasError: false });
|
|
265
|
+
// }
|
|
266
|
+
// }, [value]);
|
|
267
|
+
// const handleChangeText = (text: string) => {
|
|
268
|
+
// onChangeText?.(text);
|
|
269
|
+
// if (wasBlurred) validateInternal(text);
|
|
270
|
+
// };
|
|
271
|
+
// const handleFocus = (e?: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
272
|
+
// setIsFocused(true);
|
|
273
|
+
// restOnFocus?.(e as any);
|
|
274
|
+
// };
|
|
275
|
+
// const handleBlur = (e?: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
276
|
+
// setIsFocused(false);
|
|
277
|
+
// if (!wasBlurred) setWasBlurred(true);
|
|
278
|
+
// if (editable) validateInternal(value || "");
|
|
279
|
+
// restOnBlur?.(e as any);
|
|
280
|
+
// };
|
|
281
|
+
// const rawError = (typeof error === "string" ? error : undefined) ?? internalError ?? null;
|
|
282
|
+
// const showError = (() => {
|
|
283
|
+
// if (!rawError || !editable) return null;
|
|
284
|
+
// return wasBlurred && !isFocused ? rawError : null;
|
|
285
|
+
// })();
|
|
286
|
+
// return (
|
|
287
|
+
// <View style={{ marginBottom: 10 }}>
|
|
288
|
+
// <View
|
|
289
|
+
// style={[
|
|
290
|
+
// styles.container,
|
|
291
|
+
// !editable && styles.disabled,
|
|
292
|
+
// !!showError && styles.errorBorder,
|
|
293
|
+
// isFocused && styles.focusedBorder,
|
|
294
|
+
// style,
|
|
295
|
+
// containerStyle,
|
|
296
|
+
// multiline && styles.multilineContainer,
|
|
297
|
+
// ]}
|
|
298
|
+
// >
|
|
299
|
+
// {leftIcon && (
|
|
300
|
+
// <TouchableOpacity
|
|
301
|
+
// onPress={onLeftIconPress}
|
|
302
|
+
// disabled={!onLeftIconPress}
|
|
303
|
+
// style={styles.iconWrapper}
|
|
304
|
+
// >
|
|
305
|
+
// <Image source={leftIcon} style={[styles.icon, leftIconStyle]} resizeMode="contain" />
|
|
306
|
+
// </TouchableOpacity>
|
|
307
|
+
// )}
|
|
308
|
+
// <TextInput
|
|
309
|
+
// style={[
|
|
310
|
+
// styles.input,
|
|
311
|
+
// !editable && styles.disabledText,
|
|
312
|
+
// multiline && styles.multilineInput,
|
|
313
|
+
// inputStyle,
|
|
314
|
+
// ]}
|
|
315
|
+
// placeholder={translatedPlaceholder}
|
|
316
|
+
// placeholderTextColor={Colors.textGrey}
|
|
317
|
+
// editable={editable}
|
|
318
|
+
// secureTextEntry={secureText}
|
|
319
|
+
// keyboardType={keyboardType}
|
|
320
|
+
// value={value}
|
|
321
|
+
// onChangeText={handleChangeText}
|
|
322
|
+
// onFocus={handleFocus}
|
|
323
|
+
// onBlur={handleBlur}
|
|
324
|
+
// multiline={multiline}
|
|
325
|
+
// {...rest}
|
|
326
|
+
// />
|
|
327
|
+
// {type === "password" ? (
|
|
328
|
+
// <TouchableOpacity onPress={() => setSecureText(!secureText)} style={styles.iconWrapper}>
|
|
329
|
+
// <Image
|
|
330
|
+
// source={secureText ? Images.Eyeoff : Images.Eyeon}
|
|
331
|
+
// style={[styles.icon, rightIconStyle]}
|
|
332
|
+
// resizeMode="contain"
|
|
333
|
+
// />
|
|
334
|
+
// </TouchableOpacity>
|
|
335
|
+
// ) : (
|
|
336
|
+
// rightIcon && (
|
|
337
|
+
// <TouchableOpacity
|
|
338
|
+
// onPress={onRightIconPress}
|
|
339
|
+
// disabled={!onRightIconPress}
|
|
340
|
+
// style={styles.iconWrapper}
|
|
341
|
+
// >
|
|
342
|
+
// <Image source={rightIcon} style={[styles.icon, rightIconStyle]} resizeMode="contain" />
|
|
343
|
+
// </TouchableOpacity>
|
|
344
|
+
// )
|
|
345
|
+
// )}
|
|
346
|
+
// </View>
|
|
347
|
+
// {showError && <Text style={[styles.errorText, errorTextStyle]}>{showError}</Text>}
|
|
348
|
+
// </View>
|
|
349
|
+
// );
|
|
350
|
+
// };
|
|
351
|
+
// export default Input;
|
|
352
|
+
// const styles = StyleSheet.create({
|
|
353
|
+
// container: {
|
|
354
|
+
// flexDirection: "row",
|
|
355
|
+
// alignItems: "center",
|
|
356
|
+
// borderRadius: 5,
|
|
357
|
+
// borderWidth: 1,
|
|
358
|
+
// borderColor: Colors.primaryColor,
|
|
359
|
+
// backgroundColor: Colors.white,
|
|
360
|
+
// height: Scale.moderateScale(50),
|
|
361
|
+
// paddingHorizontal: Scale.moderateScale(4),
|
|
362
|
+
// },
|
|
363
|
+
// multilineContainer: {
|
|
364
|
+
// height: "auto",
|
|
365
|
+
// minHeight: Scale.moderateScale(80),
|
|
366
|
+
// alignItems: "flex-start",
|
|
367
|
+
// paddingVertical: Scale.moderateScale(8),
|
|
368
|
+
// },
|
|
369
|
+
// focusedBorder: {
|
|
370
|
+
// borderColor: Colors.primaryColor,
|
|
371
|
+
// },
|
|
372
|
+
// input: {
|
|
373
|
+
// flex: 1,
|
|
374
|
+
// ...Typography.style.standardU(),
|
|
375
|
+
// textTransform: "none",
|
|
376
|
+
// color: Colors.textColor,
|
|
377
|
+
// },
|
|
378
|
+
// multilineInput: {
|
|
379
|
+
// textAlignVertical: "top",
|
|
380
|
+
// paddingTop: Scale.moderateScale(5),
|
|
381
|
+
// },
|
|
382
|
+
// iconWrapper: {
|
|
383
|
+
// padding: Scale.moderateScale(5),
|
|
384
|
+
// },
|
|
385
|
+
// icon: {
|
|
386
|
+
// width: Scale.moderateScale(20),
|
|
387
|
+
// height: Scale.moderateScale(20),
|
|
388
|
+
// tintColor: Colors.primaryColor,
|
|
389
|
+
// },
|
|
390
|
+
// disabled: {
|
|
391
|
+
// backgroundColor: Colors.lightGrey,
|
|
392
|
+
// borderColor: Colors.borderGrey,
|
|
393
|
+
// },
|
|
394
|
+
// disabledText: {
|
|
395
|
+
// color: Colors.disabledGrey,
|
|
396
|
+
// },
|
|
397
|
+
// errorBorder: {
|
|
398
|
+
// borderColor: Colors.dangerRed,
|
|
399
|
+
// },
|
|
400
|
+
// errorText: {
|
|
401
|
+
// color: Colors.dangerRed,
|
|
402
|
+
// fontSize: Scale.moderateScale(12),
|
|
403
|
+
// marginTop: 3,
|
|
404
|
+
// },
|
|
405
|
+
// });
|