@teamnhz/rn-ui-toolkit 1.0.4 → 1.0.6

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,2 +1,17 @@
1
- declare const AppHeader: (props: any) => any;
1
+ type AppHeaderProps = {
2
+ navigation: any;
3
+ headerTitle?: string;
4
+ titleStyle?: object;
5
+ leftImage?: any;
6
+ onPressLeft?: () => void;
7
+ leftIconStyle?: object;
8
+ rightImageOne?: any;
9
+ onPressRightOne?: () => void;
10
+ rightImageOneStyle?: object;
11
+ rightImageTwo?: any;
12
+ onPressRightTwo?: () => void;
13
+ rightImageTwoStyle?: object;
14
+ headerStyle?: object;
15
+ };
16
+ declare const AppHeader: (props: AppHeaderProps) => void;
2
17
  export default AppHeader;
@@ -1,58 +1,45 @@
1
1
  import { View, TouchableOpacity, StyleSheet } from "react-native";
2
2
  import React from "react";
3
3
  import { Colors } from "../../styles";
4
- import Image from "../Image";
5
- import T from "../T";
4
+ import { Image, T } from "../index";
6
5
  const AppHeader = (props) => {
7
- return props.navigation.setOptions({
8
- headerLeft: () => (React.createElement(TouchableOpacity, { style: {
9
- display: props.leftImage ? "flex" : "none",
10
- }, onPress: props.onPressLeft, activeOpacity: 0.8 },
11
- React.createElement(Image, { source: props.leftImage, resizeMode: "contain", style: styles.left_image_style }))),
12
- headerTitle: () => (React.createElement(T, { title: props.headerTitle, style: {
13
- ...styles.header_title_text,
14
- display: props.headerTitle ? "flex" : "none",
15
- } })),
16
- headerRight: () => (React.createElement(View, { style: styles.header_right_style },
17
- React.createElement(TouchableOpacity, { style: {
18
- display: props.rightImageOne ? "flex" : "none",
19
- }, onPress: props.onPressRightOne, activeOpacity: 0.8 },
20
- React.createElement(Image, { source: props.rightImageOne, resizeMode: "contain", style: styles.right_image_one_style })),
21
- React.createElement(TouchableOpacity, { style: {
22
- display: props.rightImageTwo ? "flex" : "none",
23
- }, onPress: props.onPressRightTwo, activeOpacity: 0.8 },
24
- React.createElement(Image, { source: props.rightImageTwo, resizeMode: "contain", style: styles.right_image_two_style })))),
25
- headerStyle: {
26
- height: 100,
27
- width: "100%",
28
- },
6
+ const { navigation, headerTitle, titleStyle, leftImage, onPressLeft, leftIconStyle, rightImageOne, onPressRightOne, rightImageOneStyle, rightImageTwo, onPressRightTwo, rightImageTwoStyle, headerStyle, } = props;
7
+ navigation.setOptions({
8
+ headerLeft: () => leftImage ? (React.createElement(TouchableOpacity, { onPress: onPressLeft, activeOpacity: 0.8 },
9
+ React.createElement(Image, { source: leftImage, resizeMode: "contain", style: [styles.leftImage, leftIconStyle] }))) : null,
10
+ headerTitle: () => headerTitle ? (React.createElement(T, { title: headerTitle, style: [styles.headerTitleText, titleStyle] })) : null,
11
+ headerRight: () => (React.createElement(View, { style: styles.headerRightWrapper },
12
+ rightImageOne ? (React.createElement(TouchableOpacity, { onPress: onPressRightOne, activeOpacity: 0.8 },
13
+ React.createElement(Image, { source: rightImageOne, resizeMode: "contain", style: [
14
+ styles.rightImage,
15
+ rightImageOneStyle,
16
+ { marginRight: 10 },
17
+ ] }))) : null,
18
+ rightImageTwo ? (React.createElement(TouchableOpacity, { onPress: onPressRightTwo, activeOpacity: 0.8 },
19
+ React.createElement(Image, { source: rightImageTwo, resizeMode: "contain", style: [styles.rightImage, rightImageTwoStyle] }))) : null)),
20
+ headerStyle: [styles.headerBase, headerStyle],
29
21
  });
30
22
  };
23
+ export default AppHeader;
31
24
  const styles = StyleSheet.create({
32
- left_image_style: {
33
- height: 44,
34
- width: 44,
25
+ headerBase: {
26
+ height: 100,
27
+ width: "100%",
35
28
  },
36
- right_image_one_style: {
29
+ leftImage: {
37
30
  height: 44,
38
31
  width: 44,
39
- marginRight: 10,
40
32
  },
41
- right_image_two_style: {
33
+ rightImage: {
42
34
  height: 44,
43
35
  width: 44,
44
36
  },
45
- header_right_style: {
37
+ headerRightWrapper: {
46
38
  flexDirection: "row",
47
39
  alignItems: "center",
48
40
  },
49
- header_title_text: {
41
+ headerTitleText: {
50
42
  color: Colors.black,
51
43
  textAlign: "center",
52
44
  },
53
- header_title_view: {
54
- justifyContent: "center",
55
- alignItems: "center",
56
- },
57
45
  });
58
- export default AppHeader;
@@ -1,17 +1,10 @@
1
1
  import React from "react";
2
- import { ViewStyle, TextStyle, ImageStyle } from "react-native";
3
- type StyleProps = {
4
- containerStyle?: ViewStyle;
5
- rowStyle?: ViewStyle;
6
- textStyle?: TextStyle;
7
- iconStyle?: ImageStyle;
8
- };
9
2
  type Props = {
10
3
  mediaType: "photo" | "video";
11
4
  isMultiSelect?: boolean;
12
5
  onSuccess: (data: any) => void;
13
6
  visible: boolean;
14
7
  onClose: () => void;
15
- } & StyleProps;
8
+ };
16
9
  declare const ImagePicker: React.FC<Props>;
17
10
  export default ImagePicker;
@@ -1,133 +1,42 @@
1
- import React, { useCallback } from "react";
2
- import { View, Text, TouchableOpacity, StyleSheet, Image, Alert, } from "react-native";
3
- import { BottomSheet, Dividers } from "../index";
4
- import { launchCamera, launchImageLibrary } from "react-native-image-picker";
5
- import ImageCropPicker from "react-native-image-crop-picker";
6
- import { Colors, Images, Scale, Typography } from "../../styles";
7
- const ImagePicker = ({ mediaType, isMultiSelect = false, onSuccess, visible, onClose, containerStyle, rowStyle, textStyle, iconStyle, }) => {
8
- const onComplete = useCallback((data) => {
9
- onSuccess(data);
10
- onClose();
11
- }, [onSuccess, onClose]);
12
- const onCamera = () => {
13
- if (mediaType === "photo") {
14
- if (isMultiSelect) {
15
- ImageCropPicker.openCamera({ mediaType: "photo" })
16
- .then((response) => onComplete([response]))
17
- .catch(() => { });
18
- }
19
- else {
20
- ImageCropPicker.openCamera({ mediaType: "photo" })
21
- .then((response) => ImageCropPicker.openCropper({
22
- path: response?.path,
23
- width: response?.width,
24
- height: response?.height,
25
- mediaType: "photo",
26
- freeStyleCropEnabled: true,
27
- }).then(onComplete))
28
- .catch(() => { });
29
- }
30
- }
31
- else {
32
- launchCamera({ mediaType: "video" }, (response) => {
33
- if (response?.assets) {
34
- onComplete({
35
- path: response.assets[0]?.uri,
36
- duration: response.assets[0]?.duration,
37
- });
38
- }
39
- });
40
- }
41
- };
42
- const onGallery = () => {
43
- if (mediaType === "photo") {
44
- if (isMultiSelect) {
45
- ImageCropPicker.openPicker({
46
- mediaType: "photo",
47
- multiple: true,
48
- maxFiles: 5,
49
- })
50
- .then((images) => {
51
- if (images.length > 5) {
52
- Alert.alert("Limit Exceeded", "You can only select up to 5 images.");
53
- }
54
- else {
55
- onComplete(images);
56
- }
57
- })
58
- .catch(() => { });
59
- }
60
- else {
61
- ImageCropPicker.openPicker({ mediaType: "photo" })
62
- .then((response) => ImageCropPicker.openCropper({
63
- path: response?.path,
64
- width: response?.width,
65
- height: response?.height,
66
- mediaType: "photo",
67
- freeStyleCropEnabled: true,
68
- }).then(onComplete))
69
- .catch(() => { });
70
- }
71
- }
72
- else {
73
- launchImageLibrary({ mediaType: "video" }, (result) => {
74
- if (result?.assets) {
75
- onComplete({
76
- path: result.assets[0]?.uri,
77
- duration: result.assets[0]?.duration,
78
- });
79
- }
80
- });
81
- }
82
- };
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")),
88
- React.createElement(Dividers, { small: true }),
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")),
92
- React.createElement(Dividers, { small: true }),
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")))));
96
- };
97
- export default ImagePicker;
98
- const styles = StyleSheet.create({
99
- container: { flex: 1, padding: 16 },
100
- row: {
101
- flexDirection: "row",
102
- alignItems: "center",
103
- },
104
- text: { ...Typography.style.standardU(), color: Colors.white },
105
- icon: {
106
- width: Scale.moderateScale(20),
107
- height: Scale.moderateScale(20),
108
- marginRight: 10,
109
- tintColor: Colors.white,
110
- },
111
- });
112
1
  // import React, { useCallback } from "react";
113
- // import { View, Text, TouchableOpacity, StyleSheet, Image, Alert } from "react-native";
2
+ // import {
3
+ // View,
4
+ // Text,
5
+ // TouchableOpacity,
6
+ // StyleSheet,
7
+ // Image,
8
+ // Alert,
9
+ // ViewStyle,
10
+ // TextStyle,
11
+ // ImageStyle,
12
+ // } from "react-native";
114
13
  // import { BottomSheet, Dividers } from "../index";
115
14
  // import { launchCamera, launchImageLibrary } from "react-native-image-picker";
116
15
  // import ImageCropPicker from "react-native-image-crop-picker";
117
16
  // import { Colors, Images, Scale, Typography } from "../../styles";
17
+ // type StyleProps = {
18
+ // containerStyle?: ViewStyle;
19
+ // rowStyle?: ViewStyle;
20
+ // textStyle?: TextStyle;
21
+ // iconStyle?: ImageStyle;
22
+ // };
118
23
  // type Props = {
119
24
  // mediaType: "photo" | "video";
120
25
  // isMultiSelect?: boolean;
121
26
  // onSuccess: (data: any) => void;
122
27
  // visible: boolean;
123
28
  // onClose: () => void;
124
- // };
29
+ // } & StyleProps;
125
30
  // const ImagePicker: React.FC<Props> = ({
126
31
  // mediaType,
127
32
  // isMultiSelect = false,
128
33
  // onSuccess,
129
34
  // visible,
130
35
  // onClose,
36
+ // containerStyle,
37
+ // rowStyle,
38
+ // textStyle,
39
+ // iconStyle,
131
40
  // }) => {
132
41
  // const onComplete = useCallback(
133
42
  // (data: any) => {
@@ -169,10 +78,17 @@ const styles = StyleSheet.create({
169
78
  // const onGallery = () => {
170
79
  // if (mediaType === "photo") {
171
80
  // if (isMultiSelect) {
172
- // ImageCropPicker.openPicker({ mediaType: "photo", multiple: true, maxFiles: 5 })
81
+ // ImageCropPicker.openPicker({
82
+ // mediaType: "photo",
83
+ // multiple: true,
84
+ // maxFiles: 5,
85
+ // })
173
86
  // .then((images) => {
174
87
  // if (images.length > 5) {
175
- // Alert.alert("Limit Exceeded", "You can only select up to 5 images.");
88
+ // Alert.alert(
89
+ // "Limit Exceeded",
90
+ // "You can only select up to 5 images."
91
+ // );
176
92
  // } else {
177
93
  // onComplete(images);
178
94
  // }
@@ -203,24 +119,24 @@ const styles = StyleSheet.create({
203
119
  // }
204
120
  // };
205
121
  // return (
206
- // <BottomSheet visible={visible} onClose={onClose} height={210}>
207
- // <View style={styles.container}>
122
+ // <BottomSheet visible={visible} onClose={onClose} height={230}>
123
+ // <View style={[styles.container, containerStyle]}>
208
124
  // {/* Camera */}
209
- // <TouchableOpacity style={styles.row} onPress={onCamera}>
210
- // <Image source={Images.video_icon} style={styles.icon} />
211
- // <Text style={styles.text}>Camera</Text>
125
+ // <TouchableOpacity style={[styles.row, rowStyle]} onPress={onCamera}>
126
+ // <Image source={Images.video_icon} style={[styles.icon, iconStyle]} />
127
+ // <Text style={[styles.text, textStyle]}>Camera</Text>
212
128
  // </TouchableOpacity>
213
- // <Dividers small/>
129
+ // <Dividers small />
214
130
  // {/* Gallery */}
215
- // <TouchableOpacity style={styles.row} onPress={onGallery}>
216
- // <Image source={Images.image_icon} style={styles.icon} />
217
- // <Text style={styles.text}>Gallery</Text>
131
+ // <TouchableOpacity style={[styles.row, rowStyle]} onPress={onGallery}>
132
+ // <Image source={Images.image_icon} style={[styles.icon, iconStyle]} />
133
+ // <Text style={[styles.text, textStyle]}>Gallery</Text>
218
134
  // </TouchableOpacity>
219
- // <Dividers small/>
135
+ // <Dividers small />
220
136
  // {/* Cancel */}
221
- // <TouchableOpacity style={styles.row} onPress={onClose}>
222
- // <Image source={Images.image_icon} style={styles.icon} />
223
- // <Text style={styles.text}>Cancel</Text>
137
+ // <TouchableOpacity style={[styles.row, rowStyle]} onPress={onClose}>
138
+ // <Image source={Images.cancel} style={[styles.icon, iconStyle]} />
139
+ // <Text style={[styles.text, textStyle]}>Cancel</Text>
224
140
  // </TouchableOpacity>
225
141
  // </View>
226
142
  // </BottomSheet>
@@ -232,14 +148,139 @@ const styles = StyleSheet.create({
232
148
  // row: {
233
149
  // flexDirection: "row",
234
150
  // alignItems: "center",
235
- // // paddingVertical: 12,
236
151
  // },
237
- // text: { ...Typography.style.standardU(), color: Colors.black },
238
- // separator: { height: 1, backgroundColor: Colors.borderGrey, marginVertical: 8 },
152
+ // text: { ...Typography.style.standardU(), color: Colors.white },
239
153
  // icon: {
240
154
  // width: Scale.moderateScale(20),
241
155
  // height: Scale.moderateScale(20),
242
156
  // marginRight: 10,
243
- // tintColor: Colors.darkBlue,
157
+ // tintColor: Colors.white,
244
158
  // },
245
159
  // });
160
+ import React, { useCallback } from "react";
161
+ import { View, Text, TouchableOpacity, StyleSheet, Image, Alert, } from "react-native";
162
+ import { BottomSheet, Dividers } from "../index";
163
+ import { launchCamera, launchImageLibrary } from "react-native-image-picker";
164
+ import ImageCropPicker from "react-native-image-crop-picker";
165
+ import { Colors, Images, Scale, Typography } from "../../styles";
166
+ // 👇 Import your permission utilities
167
+ import { cameraPermissions, galleryPermissions, } from "../../utils/permissions"; // ✅ Make sure path is correct
168
+ const ImagePicker = ({ mediaType, isMultiSelect = false, onSuccess, visible, onClose, }) => {
169
+ // ✅ Success handler
170
+ const onComplete = useCallback((data) => {
171
+ onSuccess(data);
172
+ onClose();
173
+ }, [onSuccess, onClose]);
174
+ // ✅ CAMERA HANDLER with permission check
175
+ const handleCamera = async () => {
176
+ await cameraPermissions(async (granted) => {
177
+ if (!granted)
178
+ return; // ❌ Permission denied, handled by your alert
179
+ if (mediaType === "photo") {
180
+ if (isMultiSelect) {
181
+ // single capture, multiple not supported directly from camera
182
+ ImageCropPicker.openCamera({ mediaType: "photo" })
183
+ .then((response) => onComplete([response]))
184
+ .catch(() => { });
185
+ }
186
+ else {
187
+ ImageCropPicker.openCamera({ mediaType: "photo" })
188
+ .then((response) => ImageCropPicker.openCropper({
189
+ path: response?.path,
190
+ width: response?.width,
191
+ height: response?.height,
192
+ mediaType: "photo",
193
+ freeStyleCropEnabled: true,
194
+ }).then(onComplete))
195
+ .catch(() => { });
196
+ }
197
+ }
198
+ else {
199
+ // 🎥 VIDEO CAPTURE
200
+ launchCamera({ mediaType: "video" }, (response) => {
201
+ if (response?.assets?.length) {
202
+ onComplete({
203
+ path: response.assets[0]?.uri,
204
+ duration: response.assets[0]?.duration,
205
+ });
206
+ }
207
+ });
208
+ }
209
+ });
210
+ };
211
+ // ✅ GALLERY HANDLER with permission check
212
+ const handleGallery = async () => {
213
+ await galleryPermissions(async (granted) => {
214
+ if (!granted)
215
+ return; // ❌ Permission denied, handled by your alert
216
+ if (mediaType === "photo") {
217
+ if (isMultiSelect) {
218
+ ImageCropPicker.openPicker({
219
+ mediaType: "photo",
220
+ multiple: true,
221
+ maxFiles: 5,
222
+ })
223
+ .then((images) => {
224
+ if (images.length > 5) {
225
+ Alert.alert("Limit Exceeded", "You can only select up to 5 images.");
226
+ }
227
+ else {
228
+ onComplete(images);
229
+ }
230
+ })
231
+ .catch(() => { });
232
+ }
233
+ else {
234
+ ImageCropPicker.openPicker({ mediaType: "photo" })
235
+ .then((response) => ImageCropPicker.openCropper({
236
+ path: response?.path,
237
+ width: response?.width,
238
+ height: response?.height,
239
+ mediaType: "photo",
240
+ freeStyleCropEnabled: true,
241
+ }).then(onComplete))
242
+ .catch(() => { });
243
+ }
244
+ }
245
+ else {
246
+ // 🎥 VIDEO FROM GALLERY
247
+ launchImageLibrary({ mediaType: "video" }, (result) => {
248
+ if (result?.assets?.length) {
249
+ onComplete({
250
+ path: result.assets[0]?.uri,
251
+ duration: result.assets[0]?.duration,
252
+ });
253
+ }
254
+ });
255
+ }
256
+ });
257
+ };
258
+ return (React.createElement(BottomSheet, { visible: visible, onClose: onClose, height: 230 },
259
+ React.createElement(View, { style: styles.container },
260
+ React.createElement(TouchableOpacity, { style: styles.row, onPress: handleCamera },
261
+ React.createElement(Image, { source: Images.video_icon, style: styles.icon }),
262
+ React.createElement(Text, { style: styles.text }, "Camera")),
263
+ React.createElement(Dividers, { small: true }),
264
+ React.createElement(TouchableOpacity, { style: styles.row, onPress: handleGallery },
265
+ React.createElement(Image, { source: Images.image_icon, style: styles.icon }),
266
+ React.createElement(Text, { style: styles.text }, "Gallery")),
267
+ React.createElement(Dividers, { small: true }),
268
+ React.createElement(TouchableOpacity, { style: styles.row, onPress: onClose },
269
+ React.createElement(Image, { source: Images.cancel, style: styles.icon }),
270
+ React.createElement(Text, { style: styles.text }, "Cancel")))));
271
+ };
272
+ export default ImagePicker;
273
+ const styles = StyleSheet.create({
274
+ container: { flex: 1, padding: 16 },
275
+ row: {
276
+ flexDirection: "row",
277
+ alignItems: "center",
278
+ },
279
+ text: { ...Typography.style.standardU(), color: Colors.white },
280
+ icon: {
281
+ width: Scale.moderateScale(20),
282
+ height: Scale.moderateScale(20),
283
+ marginRight: 10,
284
+ tintColor: Colors.white,
285
+ },
286
+ });
@@ -95,7 +95,7 @@ const Input = ({ intlType, textKey, placeholder, inputPlaceholderTextColor, left
95
95
  ? inputPlaceholderTextColor
96
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
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] },
98
+ React.createElement(Image, { source: secureText ? Images.Eyeoff : Images.Eyeon, style: [styles.icon, rightIconStyle], resizeMode: "contain" }))) : (rightIcon && (React.createElement(TouchableOpacity, { onPress: onRightIconPress, disabled: !onRightIconPress, style: [styles.iconWrapper, rightIconWrapperStyle] },
99
99
  React.createElement(Image, { source: rightIcon, style: [styles.icon, rightIconStyle], resizeMode: "contain" }))))),
100
100
  showError && (React.createElement(Text, { style: [styles.errorText, errorTextStyle] }, showError))));
101
101
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teamnhz/rn-ui-toolkit",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [