@jescon-technologies/react-native-ui-kit 0.0.15 → 0.0.17

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,10 +1,228 @@
1
- import { View, Text } from 'react-native'
2
- import React from 'react'
1
+ import React, { memo, useState } from 'react';
2
+ import {
3
+ Text,
4
+ View,
5
+ Image,
6
+ TouchableOpacity,
7
+ StyleSheet,
8
+ Dimensions,
9
+ Platform,
10
+ } from 'react-native';
11
+ import styles from '../CommonStyle/optionListStyles';
12
+ import { normalize } from '../CommonStyle/componentStyle';
13
+ import RNExitApp from 'react-native-exit-app';
14
+ import { Global, GlobalUserData } from '../../../../../src/Common/Global';
15
+ import { imageURL } from '../../../../../src/Common/apiConstants';
16
+ import { useNavigation } from '../Navigation/useNavigation';
17
+ import CModalOverlay from '../CustomComponents/CModalOverlay';
18
+ import HIcons from '../Hoc/HIcons';
19
+
20
+ // ---------------------------------------------------------------------------
21
+ // Types
22
+ // ---------------------------------------------------------------------------
23
+
24
+ interface MenuOption {
25
+ optionname: string;
26
+ key: number;
27
+ iconname: string;
28
+ }
29
+
30
+ interface SliderUserData extends GlobalUserData {
31
+ photo?: string;
32
+ designation?: string;
33
+ qualification?: string;
34
+ wardname?: string;
35
+ wardcode?: string | number;
36
+ }
37
+
38
+ export interface CSliderMenuProps {
39
+ isShow: boolean;
40
+ /** Called to dismiss the drawer. */
41
+ visibility: (val: boolean) => void;
42
+ [key: string]: unknown;
43
+ }
44
+
45
+ // ---------------------------------------------------------------------------
46
+ // Component
47
+ // ---------------------------------------------------------------------------
48
+
49
+ function CSliderMenu(props: CSliderMenuProps): React.ReactElement {
50
+ const isAndroid = Platform.OS === 'android';
51
+ const navigation = useNavigation();
52
+ const [refresh, setRefresh] = useState<number>(0);
53
+ const { width, height } = Dimensions.get('window');
54
+
55
+ const optionData: MenuOption[] = [
56
+ { optionname: 'Home', key: 1, iconname: 'home' },
57
+ { optionname: 'Change Password', key: 2, iconname: 'key' },
58
+ { optionname: 'Exit', key: 11, iconname: 'power-off' },
59
+ ];
60
+
61
+ const userData = Global.userData as SliderUserData | null | undefined;
62
+
63
+ const OptionSelectNav = (data: MenuOption): void => {
64
+ switch (data.key) {
65
+ case 1:
66
+ navigation.navigate('MoreOptionsScreen');
67
+ break;
68
+ case 2:
69
+ navigation.navigate('ForgotPassword');
70
+ break;
71
+ case 11:
72
+ RNExitApp.exitApp();
73
+ break;
74
+ }
75
+ props.visibility(false);
76
+ };
3
77
 
4
- export default function CSliderMenu() {
5
78
  return (
6
- <View>
7
- <Text>CSliderMenu</Text>
8
- </View>
9
- )
10
- }
79
+ <CModalOverlay
80
+ visible={props.isShow}
81
+ onClose={() => props.visibility(false)}
82
+ closeOnTouchOutside
83
+ animationType="fadeInRight"
84
+ containerStyle={{
85
+ position: 'absolute',
86
+ left: 0,
87
+ right: 0,
88
+ elevation: 999,
89
+ margin: 0,
90
+ zIndex: 10000,
91
+ height,
92
+ flexDirection: 'column',
93
+ justifyContent: 'flex-end',
94
+ alignItems: 'flex-end',
95
+ }}
96
+ animationDuration={900}
97
+ childrenWrapperStyle={{
98
+ backgroundColor: Global.AppTheme.primary_color,
99
+ width: width * 0.75,
100
+ height,
101
+ marginVertical: -50,
102
+ }}
103
+ >
104
+ <View style={{ backgroundColor: '#fff', width: width * 0.75, flex: 1, borderWidth: 0 }}>
105
+ <View style={{ backgroundColor: Global.AppTheme.primary_color }}>
106
+ {/* Header */}
107
+ <View style={{ flexDirection: 'row', alignItems: 'flex-start', borderWidth: 0 }}>
108
+ <View style={{ justifyContent: 'center', borderWidth: 0 }}>
109
+ <Image
110
+ style={{
111
+ borderWidth: 0.5,
112
+ margin: normalize(4),
113
+ borderColor: 'white',
114
+ width: normalize(50),
115
+ height: normalize(50),
116
+ borderRadius: 1000,
117
+ resizeMode: 'contain',
118
+ }}
119
+ source={{
120
+ uri:
121
+ userData?.photo &&
122
+ userData.photo !== 'hisfiles/user/profileimage/user-blue.png'
123
+ ? imageURL + userData.photo
124
+ : 'https://i.ibb.co/NW42Gjj/user.png',
125
+ }}
126
+ />
127
+ </View>
128
+ <View style={{ flex: 1, justifyContent: 'center', borderWidth: 0 }}>
129
+ <Text style={styles.usernameStyle}>{userData?.username}</Text>
130
+ <Text style={styles.departmeNameStyle}>
131
+ {userData?.designation} - {userData?.department}
132
+ </Text>
133
+ <Text style={styles.departmeNameStyle}>{userData?.qualification}</Text>
134
+ </View>
135
+ <TouchableOpacity
136
+ style={{
137
+ borderWidth: 0,
138
+ marginRight: isAndroid ? normalize(15) : normalize(25),
139
+ }}
140
+ onPress={() => {
141
+ props.visibility(false);
142
+ if (Platform.OS === 'web' && typeof window !== 'undefined') {
143
+ window.close();
144
+ }
145
+ }}
146
+ >
147
+ <HIcons.FontAwesome
148
+ name={'power-off'}
149
+ color={'red'}
150
+ size={normalize(17)}
151
+ style={{
152
+ backgroundColor: '#fff',
153
+ padding: normalize(7),
154
+ margin: normalize(4),
155
+ borderRadius: 60,
156
+ }}
157
+ />
158
+ </TouchableOpacity>
159
+ </View>
160
+ </View>
161
+
162
+ {/* Menu items */}
163
+ <View style={{ borderWidth: 0, flex: 1 }}>
164
+ {optionData.map((block, i) => (
165
+ <View key={i} style={{ borderWidth: 0 }}>
166
+ <TouchableOpacity
167
+ onPress={() => OptionSelectNav(block)}
168
+ style={{ flexDirection: 'row', margin: normalize(5) }}
169
+ >
170
+ <View style={layoutstyles.option_icon_container}>
171
+ <HIcons.FontAwesome5
172
+ name={block.iconname}
173
+ color={Global.AppTheme.primary_color}
174
+ size={25}
175
+ />
176
+ </View>
177
+ <View style={layoutstyles.option_text_container}>
178
+ <Text
179
+ numberOfLines={2}
180
+ style={{ color: Global.AppTheme.primary_color, fontWeight: 'bold' }}
181
+ >
182
+ {block.optionname}
183
+ </Text>
184
+ </View>
185
+ </TouchableOpacity>
186
+ </View>
187
+ ))}
188
+ </View>
189
+
190
+ {/* Footer illustration */}
191
+ <View
192
+ style={{
193
+ borderWidth: 0,
194
+ flex: 1,
195
+ backgroundColor: '#fff',
196
+ bottom: normalize(-15),
197
+ }}
198
+ >
199
+ <Image
200
+ style={{ flex: 1, marginTop: normalize(0), resizeMode: 'contain' }}
201
+ source={{
202
+ uri: 'https://us.123rf.com/450wm/elnurss/elnurss1809/elnurss180902306/108495744-medical-care-vector-icon.jpg?ver=6',
203
+ }}
204
+ />
205
+ </View>
206
+ </View>
207
+ </CModalOverlay>
208
+ );
209
+ }
210
+
211
+ // ---------------------------------------------------------------------------
212
+ // Styles
213
+ // ---------------------------------------------------------------------------
214
+
215
+ const layoutstyles = StyleSheet.create({
216
+ option_text_container: {
217
+ justifyContent: 'center',
218
+ flex: 6,
219
+ },
220
+ option_icon_container: {
221
+ width: 50,
222
+ paddingLeft: 5,
223
+ alignItems: 'baseline',
224
+ justifyContent: 'center',
225
+ },
226
+ });
227
+
228
+ export default memo(CSliderMenu);
@@ -0,0 +1,216 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import {
3
+ StyleSheet,
4
+ View,
5
+ Modal,
6
+ Animated,
7
+ Easing,
8
+ Text,
9
+ Image,
10
+ ImageSourcePropType,
11
+ Platform,
12
+ StyleProp,
13
+ TextStyle,
14
+ } from 'react-native';
15
+ import { normalize } from '../CommonStyle/componentStyle';
16
+ import { APIURL } from '../../../../../src/Common/apiConstants';
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // Types
20
+ // ---------------------------------------------------------------------------
21
+
22
+ type ModalAnimationType = 'none' | 'slide' | 'fade';
23
+
24
+ export interface LoaderProps {
25
+ visible?: boolean;
26
+ overlayColor?: string;
27
+ loaderColor?: string;
28
+ size?: number;
29
+ /** Pass `null`/`undefined` to use the built-in spinning ring instead of a GIF. */
30
+ gifSource?: ImageSourcePropType | null;
31
+ message?: string;
32
+ messageStyle?: StyleProp<TextStyle>;
33
+ animationType?: ModalAnimationType;
34
+ hasBackground?: boolean;
35
+ borderRadius?: number;
36
+ shadow?: boolean;
37
+ }
38
+
39
+ // ---------------------------------------------------------------------------
40
+ // Component
41
+ // ---------------------------------------------------------------------------
42
+
43
+ export default function Loader({
44
+ visible = true,
45
+ overlayColor = 'rgba(0,0,0,0.4)',
46
+ loaderColor = 'lightblue',
47
+ size = Platform.OS !== 'web' ? 30 : 50,
48
+ gifSource = { uri: `${APIURL}file/getCommonFile/image/heartpulse.gif` },
49
+ message = '',
50
+ messageStyle = {},
51
+ animationType = 'fade',
52
+ hasBackground = true,
53
+ borderRadius = 20,
54
+ shadow = true,
55
+ }: LoaderProps): React.ReactElement {
56
+ const [rotation] = useState(new Animated.Value(0));
57
+ const [pulse] = useState(new Animated.Value(1));
58
+ const [fade] = useState(new Animated.Value(0));
59
+
60
+ // Rotation animation
61
+ useEffect(() => {
62
+ // Only animate if not using a GIF
63
+ if (!gifSource) {
64
+ Animated.loop(
65
+ Animated.timing(rotation, {
66
+ toValue: 1,
67
+ duration: 1500,
68
+ easing: Easing.linear,
69
+ useNativeDriver: true,
70
+ })
71
+ ).start();
72
+ }
73
+
74
+ // Pulse animation
75
+ Animated.loop(
76
+ Animated.sequence([
77
+ Animated.timing(pulse, {
78
+ toValue: 1.1,
79
+ duration: 800,
80
+ useNativeDriver: true,
81
+ }),
82
+ Animated.timing(pulse, {
83
+ toValue: 1,
84
+ duration: 800,
85
+ useNativeDriver: true,
86
+ }),
87
+ ])
88
+ ).start();
89
+
90
+ // Fade in animation
91
+ Animated.timing(fade, {
92
+ toValue: 1,
93
+ duration: 300,
94
+ useNativeDriver: true,
95
+ }).start();
96
+ // eslint-disable-next-line react-hooks/exhaustive-deps
97
+ }, []);
98
+
99
+ const spin = rotation.interpolate({
100
+ inputRange: [0, 1],
101
+ outputRange: ['0deg', '360deg'],
102
+ });
103
+
104
+ const loaderContent = gifSource ? (
105
+ <Image
106
+ style={[styles.icon_style, { width: normalize(size), height: normalize(size) }]}
107
+ source={gifSource}
108
+ resizeMode="contain"
109
+ />
110
+ ) : (
111
+ <Animated.View
112
+ style={[
113
+ styles.defaultLoader,
114
+ {
115
+ borderColor: loaderColor,
116
+ transform: [{ rotate: spin }, { scale: pulse }],
117
+ width: normalize(size),
118
+ height: normalize(size),
119
+ borderWidth: normalize(size / 10),
120
+ },
121
+ ]}
122
+ >
123
+ <View
124
+ style={[
125
+ styles.innerCircle,
126
+ {
127
+ backgroundColor: loaderColor,
128
+ width: normalize(size / 2),
129
+ height: normalize(size / 2),
130
+ },
131
+ ]}
132
+ />
133
+ </Animated.View>
134
+ );
135
+
136
+ return (
137
+ <Modal
138
+ animationType={animationType}
139
+ transparent={true}
140
+ visible={visible}
141
+ onRequestClose={() => {}}
142
+ >
143
+ <Animated.View
144
+ style={[
145
+ styles.modalContainer,
146
+ {
147
+ backgroundColor: overlayColor,
148
+ opacity: fade,
149
+ },
150
+ ]}
151
+ >
152
+ <Animated.View
153
+ style={[
154
+ styles.loaderContainer,
155
+ {
156
+ backgroundColor: hasBackground ? 'white' : 'transparent',
157
+ borderRadius: normalize(borderRadius),
158
+ transform: [{ scale: pulse }],
159
+ ...(shadow ? styles.shadowStyle : {}),
160
+ },
161
+ ]}
162
+ >
163
+ {loaderContent}
164
+ {message ? (
165
+ <Text style={[styles.messageText, messageStyle]}>{message}</Text>
166
+ ) : null}
167
+ </Animated.View>
168
+ </Animated.View>
169
+ </Modal>
170
+ );
171
+ }
172
+
173
+ // ---------------------------------------------------------------------------
174
+ // Styles
175
+ // ---------------------------------------------------------------------------
176
+
177
+ const styles = StyleSheet.create({
178
+ modalContainer: {
179
+ flex: 1,
180
+ justifyContent: 'center',
181
+ alignItems: 'center',
182
+ },
183
+ loaderContainer: {
184
+ padding: normalize(20),
185
+ justifyContent: 'center',
186
+ alignItems: 'center',
187
+ },
188
+ icon_style: {
189
+ justifyContent: 'center',
190
+ alignItems: 'center',
191
+ },
192
+ defaultLoader: {
193
+ borderRadius: normalize(100),
194
+ justifyContent: 'center',
195
+ alignItems: 'center',
196
+ },
197
+ innerCircle: {
198
+ borderRadius: normalize(100),
199
+ },
200
+ messageText: {
201
+ marginTop: normalize(15),
202
+ fontSize: normalize(14),
203
+ color: '#555',
204
+ textAlign: 'center',
205
+ },
206
+ shadowStyle: {
207
+ shadowColor: '#000',
208
+ shadowOffset: {
209
+ width: 0,
210
+ height: 2,
211
+ },
212
+ shadowOpacity: 0.25,
213
+ shadowRadius: 3.84,
214
+ elevation: 5,
215
+ },
216
+ });