app-expo-cli 1.1.1 → 1.1.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.
- package/.github/workflows/npm-publish.yml +31 -0
- package/README.md +11 -1
- package/package.json +1 -1
- package/template/src/lib/DateTimePicker/DateTimePicker.tsx +0 -63
- package/template/src/lib/Empty/EmptyCard.tsx +0 -67
- package/template/src/lib/Error/GlobalErrorBoundary.tsx +0 -111
- package/template/src/lib/animate/AniImage.tsx +0 -32
- package/template/src/lib/backHeader/BackButton.tsx +0 -62
- package/template/src/lib/backHeader/BackWithCoponent.tsx +0 -112
- package/template/src/lib/backHeader/BackWithHeader.tsx +0 -46
- package/template/src/lib/backHeader/BackWithTitle.tsx +0 -53
- package/template/src/lib/buttons/IButton.tsx +0 -69
- package/template/src/lib/buttons/IwtButton.tsx +0 -199
- package/template/src/lib/buttons/Or.tsx +0 -27
- package/template/src/lib/buttons/SimpleButton.tsx +0 -45
- package/template/src/lib/buttons/TButton.tsx +0 -70
- package/template/src/lib/cards/Card.tsx +0 -175
- package/template/src/lib/cards/OptionSelect.tsx +0 -44
- package/template/src/lib/cards/SearchCard.tsx +0 -35
- package/template/src/lib/editor/TextEditor.tsx +0 -81
- package/template/src/lib/expend/ExpendComponent.tsx +0 -36
- package/template/src/lib/imageViewer/ImageViwer.tsx +0 -332
- package/template/src/lib/imageZoomer/ImageZoomer.tsx +0 -104
- package/template/src/lib/inputs/CheckBox.tsx +0 -86
- package/template/src/lib/inputs/InputText.tsx +0 -232
- package/template/src/lib/loader/GLoading.tsx +0 -26
- package/template/src/lib/loading/MLoading.tsx +0 -14
- package/template/src/lib/loading/SLoading.tsx +0 -14
- package/template/src/lib/modals/ActionModal.tsx +0 -97
- package/template/src/lib/modals/BottomModal.tsx +0 -224
- package/template/src/lib/modals/ConfrimationModal.tsx +0 -116
- package/template/src/lib/modals/DateModal.tsx +0 -152
- package/template/src/lib/modals/NormalModal.tsx +0 -73
- package/template/src/lib/modals/SideModal.tsx +0 -57
- package/template/src/lib/modals/Toaster.tsx +0 -256
- package/template/src/lib/payment/PaymentCardForD.tsx +0 -47
- package/template/src/lib/progressBar/ProgressBar.tsx +0 -64
- package/template/src/lib/tailwind.js +0 -9
- package/template/src/lib/ui/Avatar.tsx +0 -55
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
import React, { useCallback } from "react";
|
|
2
|
-
import {
|
|
3
|
-
Animated,
|
|
4
|
-
Easing,
|
|
5
|
-
NativeSyntheticEvent,
|
|
6
|
-
Text,
|
|
7
|
-
TextInput,
|
|
8
|
-
TextInputFocusEventData,
|
|
9
|
-
TextInputProps,
|
|
10
|
-
TouchableOpacity,
|
|
11
|
-
View,
|
|
12
|
-
} from "react-native";
|
|
13
|
-
|
|
14
|
-
import { SvgXml } from "react-native-svg";
|
|
15
|
-
import tw from "../tailwind";
|
|
16
|
-
|
|
17
|
-
const eye = `<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" x="0" y="0" viewBox="0 0 511.999 511.999" style="enable-background:new 0 0 512 512" xml:space="preserve" class=""><g><path d="M508.745 246.041c-4.574-6.257-113.557-153.206-252.748-153.206S7.818 239.784 3.249 246.035a16.896 16.896 0 0 0 0 19.923c4.569 6.257 113.557 153.206 252.748 153.206s248.174-146.95 252.748-153.201a16.875 16.875 0 0 0 0-19.922zM255.997 385.406c-102.529 0-191.33-97.533-217.617-129.418 26.253-31.913 114.868-129.395 217.617-129.395 102.524 0 191.319 97.516 217.617 129.418-26.253 31.912-114.868 129.395-217.617 129.395z" fill="#fff" opacity="1" data-original="#fff" class=""></path><path d="M255.997 154.725c-55.842 0-101.275 45.433-101.275 101.275s45.433 101.275 101.275 101.275S357.272 311.842 357.272 256s-45.433-101.275-101.275-101.275zm0 168.791c-37.23 0-67.516-30.287-67.516-67.516s30.287-67.516 67.516-67.516 67.516 30.287 67.516 67.516-30.286 67.516-67.516 67.516z" fill="#fff" opacity="1" data-original="#fff" class=""></path></g></svg>`;
|
|
18
|
-
|
|
19
|
-
const eyeOff = `<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" x="0" y="0" viewBox="0 0 128 128" style="enable-background:new 0 0 512 512" xml:space="preserve" class=""><g><path d="m79.891 65.078 7.27-7.27C87.69 59.787 88 61.856 88 64c0 13.234-10.766 24-24 24-2.144 0-4.213-.31-6.192-.839l7.27-7.27a15.929 15.929 0 0 0 14.813-14.813zm47.605-3.021c-.492-.885-7.47-13.112-21.11-23.474l-5.821 5.821c9.946 7.313 16.248 15.842 18.729 19.602C114.553 71.225 95.955 96 64 96c-4.792 0-9.248-.613-13.441-1.591l-6.573 6.573C50.029 102.835 56.671 104 64 104c41.873 0 62.633-36.504 63.496-38.057a3.997 3.997 0 0 0 0-3.886zm-16.668-39.229-88 88C22.047 111.609 21.023 112 20 112s-2.047-.391-2.828-1.172a3.997 3.997 0 0 1 0-5.656l11.196-11.196C10.268 83.049 1.071 66.964.504 65.943a4 4 0 0 1 0-3.887C1.367 60.504 22.127 24 64 24c10.827 0 20.205 2.47 28.222 6.122l12.95-12.95c1.563-1.563 4.094-1.563 5.656 0s1.563 4.094 0 5.656zM34.333 88.011 44.46 77.884C41.663 73.96 40 69.175 40 64c0-13.234 10.766-24 24-24 5.175 0 9.96 1.663 13.884 4.459l8.189-8.189C79.603 33.679 72.251 32 64 32 32.045 32 13.447 56.775 8.707 63.994c3.01 4.562 11.662 16.11 25.626 24.017zm15.934-15.935 21.809-21.809C69.697 48.862 66.958 48 64 48c-8.822 0-16 7.178-16 16 0 2.958.862 5.697 2.267 8.076z" fill="#fff" opacity="1" data-original="#fff" class=""></path></g></svg>`;
|
|
20
|
-
|
|
21
|
-
interface InputTextProps {
|
|
22
|
-
onPress?: () => void;
|
|
23
|
-
svgFirstIcon?: string;
|
|
24
|
-
fieldStyle?: any;
|
|
25
|
-
focusSTyle?: any;
|
|
26
|
-
label?: string;
|
|
27
|
-
required?: boolean;
|
|
28
|
-
labelStyle?: any;
|
|
29
|
-
svgSecondIcon?: string;
|
|
30
|
-
placeholder?: string;
|
|
31
|
-
placeholderStyle?: any;
|
|
32
|
-
textInputProps?: TextInputProps;
|
|
33
|
-
svgSecondOnPress?: () => void;
|
|
34
|
-
textXValue?: number;
|
|
35
|
-
textXOutRangeFirst?: number;
|
|
36
|
-
textXOutRangeSecond?: number;
|
|
37
|
-
svgSecondStyle?: any;
|
|
38
|
-
errorText?: string;
|
|
39
|
-
errorSvgIcon?: any;
|
|
40
|
-
onFocus?: () => void;
|
|
41
|
-
onBlur?: (e: NativeSyntheticEvent<TextInputFocusEventData>) => void;
|
|
42
|
-
onChangeText?: (text: string) => void;
|
|
43
|
-
value?: string;
|
|
44
|
-
touched?: boolean;
|
|
45
|
-
containerLayoutStyle?: any;
|
|
46
|
-
containerStyle?: any;
|
|
47
|
-
editable?: boolean;
|
|
48
|
-
errorTextTop?: boolean;
|
|
49
|
-
variant?: "default" | "password";
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const InputText = ({
|
|
53
|
-
onPress,
|
|
54
|
-
svgFirstIcon,
|
|
55
|
-
fieldStyle,
|
|
56
|
-
focusSTyle,
|
|
57
|
-
label,
|
|
58
|
-
required,
|
|
59
|
-
labelStyle,
|
|
60
|
-
svgSecondIcon,
|
|
61
|
-
placeholder,
|
|
62
|
-
textXValue = -28,
|
|
63
|
-
textXOutRangeFirst = 25,
|
|
64
|
-
textXOutRangeSecond = 45,
|
|
65
|
-
errorSvgIcon,
|
|
66
|
-
textInputProps,
|
|
67
|
-
errorText,
|
|
68
|
-
onBlur,
|
|
69
|
-
onChangeText,
|
|
70
|
-
onFocus,
|
|
71
|
-
svgSecondStyle,
|
|
72
|
-
svgSecondOnPress,
|
|
73
|
-
variant,
|
|
74
|
-
value,
|
|
75
|
-
touched,
|
|
76
|
-
containerLayoutStyle,
|
|
77
|
-
containerStyle,
|
|
78
|
-
editable = true,
|
|
79
|
-
placeholderStyle,
|
|
80
|
-
errorTextTop = false,
|
|
81
|
-
}: InputTextProps) => {
|
|
82
|
-
const [focus, setFocus] = React.useState(false);
|
|
83
|
-
const [isPasswordVisible, setIsPasswordVisible] = React.useState(false);
|
|
84
|
-
// const [text, setText] = React.useState("");
|
|
85
|
-
const textInputRef = React.useRef<TextInput>(null); // Ref to focus the TextInput
|
|
86
|
-
|
|
87
|
-
const textY = React.useRef(new Animated.Value(0));
|
|
88
|
-
|
|
89
|
-
const handleFocus = useCallback(() => {
|
|
90
|
-
setFocus(true);
|
|
91
|
-
Animated.timing(textY.current, {
|
|
92
|
-
toValue: -28,
|
|
93
|
-
duration: 200,
|
|
94
|
-
useNativeDriver: true,
|
|
95
|
-
easing: Easing.ease,
|
|
96
|
-
}).start();
|
|
97
|
-
textInputRef.current?.focus(); // Focus the TextInput
|
|
98
|
-
}, []);
|
|
99
|
-
|
|
100
|
-
const handleBlur = useCallback(() => {
|
|
101
|
-
setFocus(false);
|
|
102
|
-
Animated.timing(textY.current, {
|
|
103
|
-
toValue: 0,
|
|
104
|
-
duration: 200,
|
|
105
|
-
useNativeDriver: true,
|
|
106
|
-
easing: Easing.linear,
|
|
107
|
-
}).start();
|
|
108
|
-
}, []);
|
|
109
|
-
|
|
110
|
-
// React.useEffect(() => {
|
|
111
|
-
// if (value?.trim().length) {
|
|
112
|
-
// if (!textInputRef.current?.focus()) {
|
|
113
|
-
// handleFocus();
|
|
114
|
-
// }
|
|
115
|
-
// } else {
|
|
116
|
-
// handleBlur();
|
|
117
|
-
// }
|
|
118
|
-
// }, [value]);
|
|
119
|
-
|
|
120
|
-
const textX = textY.current.interpolate({
|
|
121
|
-
inputRange: [textXValue, 0],
|
|
122
|
-
outputRange: [textXOutRangeFirst, textXOutRangeSecond],
|
|
123
|
-
extrapolate: "clamp",
|
|
124
|
-
});
|
|
125
|
-
const textScale = textY.current.interpolate({
|
|
126
|
-
inputRange: [-28, 0],
|
|
127
|
-
outputRange: [0.8, 1],
|
|
128
|
-
extrapolate: "clamp",
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
return (
|
|
132
|
-
<TouchableOpacity
|
|
133
|
-
disabled={!editable}
|
|
134
|
-
activeOpacity={1} // Ensure the opacity doesn't change on press
|
|
135
|
-
onPress={editable ? onPress : handleFocus} // Focus the input when the container is pressed
|
|
136
|
-
style={[tw``, containerLayoutStyle]}
|
|
137
|
-
>
|
|
138
|
-
{label && (
|
|
139
|
-
<Text
|
|
140
|
-
style={[tw`text-base font-InterRegular py-2 text-white`, labelStyle]}
|
|
141
|
-
>
|
|
142
|
-
{label}
|
|
143
|
-
{required && (
|
|
144
|
-
<Text style={tw`text-red-500 font-InterRegular`}> *</Text>
|
|
145
|
-
)}
|
|
146
|
-
</Text>
|
|
147
|
-
)}
|
|
148
|
-
{errorText && touched && errorTextTop && (
|
|
149
|
-
<View style={tw`px-2 py-1 flex-row gap-1 items-center`}>
|
|
150
|
-
{errorSvgIcon && <SvgXml xml={errorSvgIcon} />}
|
|
151
|
-
|
|
152
|
-
<Text style={tw`text-red-500 text-xs`}>{errorText}</Text>
|
|
153
|
-
</View>
|
|
154
|
-
)}
|
|
155
|
-
<View
|
|
156
|
-
style={[
|
|
157
|
-
tw`flex-row w-full border items-center px-6 gap-2 ${
|
|
158
|
-
errorText && touched ? "border-red-500" : "border border-white/20"
|
|
159
|
-
} rounded-full h-14 `,
|
|
160
|
-
// tw`${focus ? "border-blue-500" : "bg-white/10"}`,
|
|
161
|
-
containerStyle,
|
|
162
|
-
]}
|
|
163
|
-
>
|
|
164
|
-
{svgFirstIcon && <SvgXml xml={svgFirstIcon} />}
|
|
165
|
-
{placeholder?.trim() && (
|
|
166
|
-
<Animated.Text
|
|
167
|
-
numberOfLines={1}
|
|
168
|
-
style={[
|
|
169
|
-
tw`absolute bg-base rounded-full text-base font-InterRegular py-2 px-2 ${
|
|
170
|
-
errorText && touched ? "text-red-500" : "text-gray-400"
|
|
171
|
-
}`,
|
|
172
|
-
placeholderStyle,
|
|
173
|
-
{
|
|
174
|
-
transform: [
|
|
175
|
-
{ translateY: textY.current },
|
|
176
|
-
{ translateX: textX },
|
|
177
|
-
{ scale: textScale },
|
|
178
|
-
],
|
|
179
|
-
},
|
|
180
|
-
]}
|
|
181
|
-
>
|
|
182
|
-
{placeholder}
|
|
183
|
-
</Animated.Text>
|
|
184
|
-
)}
|
|
185
|
-
|
|
186
|
-
<TextInput
|
|
187
|
-
editable={editable}
|
|
188
|
-
ref={textInputRef} // Assign the ref to the TextInput
|
|
189
|
-
onFocus={() => {
|
|
190
|
-
onFocus && onFocus();
|
|
191
|
-
}}
|
|
192
|
-
onBlur={(e) => {
|
|
193
|
-
onBlur && onBlur(e);
|
|
194
|
-
}}
|
|
195
|
-
style={tw`flex-1 px-2 h-12 text-sm font-InterRegular text-white `}
|
|
196
|
-
secureTextEntry={variant === "password" && !isPasswordVisible}
|
|
197
|
-
{...textInputProps}
|
|
198
|
-
value={value}
|
|
199
|
-
onChangeText={(text) => {
|
|
200
|
-
// setText(text);
|
|
201
|
-
onChangeText && onChangeText(text);
|
|
202
|
-
}}
|
|
203
|
-
/>
|
|
204
|
-
{svgSecondIcon && (
|
|
205
|
-
<TouchableOpacity
|
|
206
|
-
onPress={svgSecondOnPress}
|
|
207
|
-
disabled={!svgSecondOnPress}
|
|
208
|
-
>
|
|
209
|
-
<SvgXml xml={svgSecondIcon} />
|
|
210
|
-
</TouchableOpacity>
|
|
211
|
-
)}
|
|
212
|
-
|
|
213
|
-
{variant === "password" && (
|
|
214
|
-
<TouchableOpacity
|
|
215
|
-
onPress={() => setIsPasswordVisible(!isPasswordVisible)}
|
|
216
|
-
>
|
|
217
|
-
{isPasswordVisible ? <SvgXml xml={eyeOff} /> : <SvgXml xml={eye} />}
|
|
218
|
-
</TouchableOpacity>
|
|
219
|
-
)}
|
|
220
|
-
</View>
|
|
221
|
-
{errorText && touched && !errorTextTop && (
|
|
222
|
-
<View style={tw`px-2 py-1 flex-row gap-1 items-center`}>
|
|
223
|
-
{errorSvgIcon && <SvgXml xml={errorSvgIcon} />}
|
|
224
|
-
|
|
225
|
-
<Text style={tw`text-red-500 text-xs`}>{errorText}</Text>
|
|
226
|
-
</View>
|
|
227
|
-
)}
|
|
228
|
-
</TouchableOpacity>
|
|
229
|
-
);
|
|
230
|
-
};
|
|
231
|
-
|
|
232
|
-
export default InputText;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { ActivityIndicator, View } from "react-native";
|
|
2
|
-
|
|
3
|
-
import { PrimaryColor } from "../../utils/utils";
|
|
4
|
-
import React from "react";
|
|
5
|
-
import tw from "../tailwind";
|
|
6
|
-
|
|
7
|
-
interface IGLoadingProps {
|
|
8
|
-
loading: boolean;
|
|
9
|
-
setLoading: React.Dispatch<React.SetStateAction<boolean>>;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const GLoading = ({ loading, setLoading }: IGLoadingProps) => {
|
|
13
|
-
return (
|
|
14
|
-
<>
|
|
15
|
-
{loading && (
|
|
16
|
-
<View
|
|
17
|
-
style={tw` bg-base z-50 w-full bg-opacity-40 h-full absolute justify-center items-center`}
|
|
18
|
-
>
|
|
19
|
-
<ActivityIndicator size={"large"} color={PrimaryColor} />
|
|
20
|
-
</View>
|
|
21
|
-
)}
|
|
22
|
-
</>
|
|
23
|
-
);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export default GLoading;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { ActivityIndicator, View } from "react-native";
|
|
2
|
-
|
|
3
|
-
import React from "react";
|
|
4
|
-
import tw from "../tailwind";
|
|
5
|
-
|
|
6
|
-
const MLoading = () => {
|
|
7
|
-
return (
|
|
8
|
-
<View style={tw`flex-1 justify-center items-center bg-base `}>
|
|
9
|
-
<ActivityIndicator size={"large"} color={"#fff"} />
|
|
10
|
-
</View>
|
|
11
|
-
);
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export default MLoading;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { ActivityIndicator, View } from "react-native";
|
|
2
|
-
|
|
3
|
-
import React from "react";
|
|
4
|
-
import tw from "../tailwind";
|
|
5
|
-
|
|
6
|
-
const SLoading = () => {
|
|
7
|
-
return (
|
|
8
|
-
<View style={tw`flex-1 bg-[#121212] justify-center items-center`}>
|
|
9
|
-
<ActivityIndicator size={"large"} color={"#fff"} />
|
|
10
|
-
</View>
|
|
11
|
-
);
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export default SLoading;
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { Pressable, Text, TouchableOpacity, View } from "react-native";
|
|
2
|
-
import React, { SetStateAction } from "react";
|
|
3
|
-
|
|
4
|
-
import tw from "../tailwind";
|
|
5
|
-
|
|
6
|
-
export interface IActionModalDataProp {
|
|
7
|
-
title?: string;
|
|
8
|
-
icon?: React.ReactNode;
|
|
9
|
-
titleStyle?: any;
|
|
10
|
-
enableBoth?: boolean;
|
|
11
|
-
customComponent?: React.ReactNode;
|
|
12
|
-
onPress?: () => void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface IActionModalProps {
|
|
16
|
-
visible: boolean;
|
|
17
|
-
setVisible: React.Dispatch<SetStateAction<boolean>>;
|
|
18
|
-
actionData?: Array<IActionModalDataProp>;
|
|
19
|
-
containerStyle?: any;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const ActionModal = ({
|
|
23
|
-
setVisible,
|
|
24
|
-
visible,
|
|
25
|
-
actionData,
|
|
26
|
-
containerStyle,
|
|
27
|
-
}: IActionModalProps) => {
|
|
28
|
-
return (
|
|
29
|
-
<>
|
|
30
|
-
{visible && (
|
|
31
|
-
<Pressable
|
|
32
|
-
onPress={() => setVisible(!visible)}
|
|
33
|
-
style={[
|
|
34
|
-
tw`absolute w-full h-full z-10`,
|
|
35
|
-
{
|
|
36
|
-
backgroundColor: "rgba(0,0,0,0.2)",
|
|
37
|
-
},
|
|
38
|
-
]}
|
|
39
|
-
>
|
|
40
|
-
<Pressable
|
|
41
|
-
onPress={(e) => e.stopPropagation()} // Prevent closing modal when clicking inside
|
|
42
|
-
style={[
|
|
43
|
-
tw`absolute bg-white w-[60%] md:w-[55%] tablet:w-[20%] top-[8%] right-[4%] rounded-3xl px-5 py-4 pt-7 z-20 gap-3`,
|
|
44
|
-
containerStyle,
|
|
45
|
-
]}
|
|
46
|
-
>
|
|
47
|
-
{actionData?.map((item, index) => {
|
|
48
|
-
return (
|
|
49
|
-
<React.Fragment key={index}>
|
|
50
|
-
<>
|
|
51
|
-
{item.enableBoth ? (
|
|
52
|
-
<>
|
|
53
|
-
<View style={tw`pb-4 flex-row justify-between`}>
|
|
54
|
-
<Text
|
|
55
|
-
style={[
|
|
56
|
-
tw`text-black900 font-RobotoBold text-sm`,
|
|
57
|
-
item.titleStyle,
|
|
58
|
-
]}
|
|
59
|
-
>
|
|
60
|
-
{item.title}
|
|
61
|
-
</Text>
|
|
62
|
-
<View>{item.customComponent}</View>
|
|
63
|
-
</View>
|
|
64
|
-
</>
|
|
65
|
-
) : (
|
|
66
|
-
<>
|
|
67
|
-
{item.customComponent ? (
|
|
68
|
-
<View style={tw`pb-4`}>{item.customComponent}</View>
|
|
69
|
-
) : (
|
|
70
|
-
<TouchableOpacity
|
|
71
|
-
style={tw`pb-4`}
|
|
72
|
-
onPress={item.onPress}
|
|
73
|
-
>
|
|
74
|
-
<Text
|
|
75
|
-
style={[
|
|
76
|
-
tw`text-black900 font-RobotoBold text-sm`,
|
|
77
|
-
item.titleStyle,
|
|
78
|
-
]}
|
|
79
|
-
>
|
|
80
|
-
{item.title}
|
|
81
|
-
</Text>
|
|
82
|
-
</TouchableOpacity>
|
|
83
|
-
)}
|
|
84
|
-
</>
|
|
85
|
-
)}
|
|
86
|
-
</>
|
|
87
|
-
</React.Fragment>
|
|
88
|
-
);
|
|
89
|
-
})}
|
|
90
|
-
</Pressable>
|
|
91
|
-
</Pressable>
|
|
92
|
-
)}
|
|
93
|
-
</>
|
|
94
|
-
);
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
export default React.memo(ActionModal);
|
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Animated,
|
|
3
|
-
KeyboardAvoidingView,
|
|
4
|
-
Modal,
|
|
5
|
-
PanResponder,
|
|
6
|
-
Platform,
|
|
7
|
-
SafeAreaView,
|
|
8
|
-
StyleSheet,
|
|
9
|
-
TouchableOpacity,
|
|
10
|
-
View,
|
|
11
|
-
} from "react-native";
|
|
12
|
-
// Importing necessary packages and components
|
|
13
|
-
import React, { useRef } from "react";
|
|
14
|
-
|
|
15
|
-
// Defining the props for RBSheet
|
|
16
|
-
interface RBSheetProps {
|
|
17
|
-
height?: number;
|
|
18
|
-
openDuration?: number;
|
|
19
|
-
closeDuration?: number;
|
|
20
|
-
closeOnPressMask?: boolean;
|
|
21
|
-
closeOnPressBack?: boolean;
|
|
22
|
-
draggable?: boolean;
|
|
23
|
-
dragOnContent?: boolean;
|
|
24
|
-
useNativeDriver?: boolean;
|
|
25
|
-
customStyles?: any;
|
|
26
|
-
customModalProps?: any;
|
|
27
|
-
customAvoidingViewProps?: any;
|
|
28
|
-
visible?: boolean;
|
|
29
|
-
setVisible?: React.Dispatch<React.SetStateAction<boolean>>;
|
|
30
|
-
title?: string;
|
|
31
|
-
headerComponent?: React.ReactNode;
|
|
32
|
-
children?: React.ReactNode;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const BottomModal = React.forwardRef(
|
|
36
|
-
(
|
|
37
|
-
{
|
|
38
|
-
height = 100,
|
|
39
|
-
openDuration = 300,
|
|
40
|
-
closeDuration = 200,
|
|
41
|
-
closeOnPressMask = true,
|
|
42
|
-
closeOnPressBack = false,
|
|
43
|
-
draggable = false,
|
|
44
|
-
dragOnContent = false,
|
|
45
|
-
useNativeDriver = false,
|
|
46
|
-
customStyles = {},
|
|
47
|
-
customModalProps = {},
|
|
48
|
-
customAvoidingViewProps = {},
|
|
49
|
-
setVisible,
|
|
50
|
-
visible,
|
|
51
|
-
title = "Modal Title",
|
|
52
|
-
children = <View />,
|
|
53
|
-
headerComponent,
|
|
54
|
-
}: RBSheetProps,
|
|
55
|
-
ref
|
|
56
|
-
) => {
|
|
57
|
-
// Animated height and pan values
|
|
58
|
-
const animatedHeight = useRef(new Animated.Value(0)).current;
|
|
59
|
-
const pan = useRef(new Animated.ValueXY()).current;
|
|
60
|
-
|
|
61
|
-
// Function to handle modal visibility
|
|
62
|
-
const handleSetVisible = (isVisible: boolean) => {
|
|
63
|
-
if (isVisible) {
|
|
64
|
-
// Open animation
|
|
65
|
-
Animated.timing(animatedHeight, {
|
|
66
|
-
useNativeDriver,
|
|
67
|
-
toValue: height,
|
|
68
|
-
duration: openDuration,
|
|
69
|
-
}).start();
|
|
70
|
-
} else {
|
|
71
|
-
// Close animation
|
|
72
|
-
Animated.timing(animatedHeight, {
|
|
73
|
-
useNativeDriver,
|
|
74
|
-
toValue: 0,
|
|
75
|
-
duration: closeDuration,
|
|
76
|
-
}).start(() => {
|
|
77
|
-
setVisible && setVisible(false);
|
|
78
|
-
pan.setValue({ x: 0, y: 0 }); // Reset pan values
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
// Creating PanResponder for drag functionality
|
|
84
|
-
const panResponder = useRef(
|
|
85
|
-
PanResponder.create({
|
|
86
|
-
onStartShouldSetPanResponder: () => draggable,
|
|
87
|
-
onMoveShouldSetPanResponder: (e, gestureState) =>
|
|
88
|
-
draggable && dragOnContent && gestureState.dy > 0,
|
|
89
|
-
onPanResponderMove: (e, gestureState) => {
|
|
90
|
-
if (gestureState.dy > 0) {
|
|
91
|
-
Animated.event([null, { dy: pan.y }], { useNativeDriver })(
|
|
92
|
-
e,
|
|
93
|
-
gestureState
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
},
|
|
97
|
-
onPanResponderRelease: (e, gestureState) => {
|
|
98
|
-
if (gestureState.dy > 100) {
|
|
99
|
-
handleSetVisible(false);
|
|
100
|
-
} else {
|
|
101
|
-
Animated.spring(pan, {
|
|
102
|
-
toValue: { x: 0, y: 0 },
|
|
103
|
-
useNativeDriver,
|
|
104
|
-
}).start();
|
|
105
|
-
}
|
|
106
|
-
},
|
|
107
|
-
})
|
|
108
|
-
).current;
|
|
109
|
-
|
|
110
|
-
React.useEffect(() => {
|
|
111
|
-
if (visible) {
|
|
112
|
-
handleSetVisible(visible);
|
|
113
|
-
} else {
|
|
114
|
-
handleSetVisible(false);
|
|
115
|
-
}
|
|
116
|
-
}, [visible]);
|
|
117
|
-
|
|
118
|
-
// React Native modal render
|
|
119
|
-
|
|
120
|
-
return (
|
|
121
|
-
<Modal
|
|
122
|
-
transparent
|
|
123
|
-
visible={visible}
|
|
124
|
-
onRequestClose={closeOnPressBack ? () => handleSetVisible(false) : null}
|
|
125
|
-
{...customModalProps}
|
|
126
|
-
>
|
|
127
|
-
<KeyboardAvoidingView
|
|
128
|
-
behavior={Platform.OS === "ios" ? "padding" : "height"}
|
|
129
|
-
style={[styles.wrapper, customStyles]}
|
|
130
|
-
{...customAvoidingViewProps}
|
|
131
|
-
>
|
|
132
|
-
<TouchableOpacity
|
|
133
|
-
style={styles.mask}
|
|
134
|
-
activeOpacity={1}
|
|
135
|
-
onPress={
|
|
136
|
-
closeOnPressMask ? () => handleSetVisible(false) : () => {}
|
|
137
|
-
}
|
|
138
|
-
/>
|
|
139
|
-
<ModalContent>
|
|
140
|
-
<Animated.View
|
|
141
|
-
style={[
|
|
142
|
-
styles.container,
|
|
143
|
-
{ transform: pan.getTranslateTransform() },
|
|
144
|
-
{ height: animatedHeight },
|
|
145
|
-
customStyles,
|
|
146
|
-
]}
|
|
147
|
-
{...(dragOnContent && panResponder.panHandlers)}
|
|
148
|
-
>
|
|
149
|
-
{draggable && (
|
|
150
|
-
<View
|
|
151
|
-
style={styles.draggableContainer}
|
|
152
|
-
{...(!dragOnContent && panResponder.panHandlers)}
|
|
153
|
-
>
|
|
154
|
-
{headerComponent ? (
|
|
155
|
-
headerComponent
|
|
156
|
-
) : (
|
|
157
|
-
<View
|
|
158
|
-
style={[styles.draggableIcon, customStyles.draggableIcon]}
|
|
159
|
-
/>
|
|
160
|
-
)}
|
|
161
|
-
</View>
|
|
162
|
-
)}
|
|
163
|
-
{children}
|
|
164
|
-
</Animated.View>
|
|
165
|
-
</ModalContent>
|
|
166
|
-
</KeyboardAvoidingView>
|
|
167
|
-
</Modal>
|
|
168
|
-
);
|
|
169
|
-
}
|
|
170
|
-
);
|
|
171
|
-
|
|
172
|
-
export default BottomModal;
|
|
173
|
-
|
|
174
|
-
export const ModalContent = ({ children }: any): React.ReactElement => {
|
|
175
|
-
if (Platform.OS === "ios") {
|
|
176
|
-
return children;
|
|
177
|
-
} else {
|
|
178
|
-
return <SafeAreaView style={styles.safeArea}>{children}</SafeAreaView>;
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
const styles = StyleSheet.create({
|
|
183
|
-
safeArea: {
|
|
184
|
-
flex: 1,
|
|
185
|
-
justifyContent: "flex-end", // Ensures the modal content starts at the bottom
|
|
186
|
-
},
|
|
187
|
-
wrapper: {
|
|
188
|
-
flex: 1,
|
|
189
|
-
backgroundColor: "#00000077",
|
|
190
|
-
},
|
|
191
|
-
mask: {
|
|
192
|
-
flex: 1,
|
|
193
|
-
backgroundColor: "transparent",
|
|
194
|
-
},
|
|
195
|
-
container: {
|
|
196
|
-
backgroundColor: "transparent",
|
|
197
|
-
width: "100%",
|
|
198
|
-
height: 0,
|
|
199
|
-
overflow: "hidden",
|
|
200
|
-
},
|
|
201
|
-
header: {
|
|
202
|
-
padding: 15,
|
|
203
|
-
borderBottomWidth: 1,
|
|
204
|
-
borderBottomColor: "#ccc",
|
|
205
|
-
backgroundColor: "#f8f8f8",
|
|
206
|
-
},
|
|
207
|
-
title: {
|
|
208
|
-
fontSize: 16,
|
|
209
|
-
fontWeight: "bold",
|
|
210
|
-
textAlign: "center",
|
|
211
|
-
},
|
|
212
|
-
draggableContainer: {
|
|
213
|
-
width: "100%",
|
|
214
|
-
alignItems: "center",
|
|
215
|
-
backgroundColor: "transparent",
|
|
216
|
-
},
|
|
217
|
-
draggableIcon: {
|
|
218
|
-
width: 35,
|
|
219
|
-
height: 5,
|
|
220
|
-
borderRadius: 5,
|
|
221
|
-
margin: 10,
|
|
222
|
-
backgroundColor: "#ccc",
|
|
223
|
-
},
|
|
224
|
-
});
|