related-ui-components 4.0.9 → 4.1.1
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/lib/module/contexts/UniversalModalProvider.js +11 -23
- package/lib/module/contexts/UniversalModalProvider.js.map +1 -1
- package/lib/typescript/src/contexts/UniversalModalProvider.d.ts +2 -0
- package/lib/typescript/src/contexts/UniversalModalProvider.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/contexts/UniversalModalProvider.tsx +63 -53
|
@@ -32,6 +32,7 @@ const DefaultModalUI = ({
|
|
|
32
32
|
easing: Easing.bezier(0.25, 0.1, 0.25, 1)
|
|
33
33
|
},
|
|
34
34
|
position = "center",
|
|
35
|
+
animateFrom = "center",
|
|
35
36
|
avoidKeyboard = true,
|
|
36
37
|
backdropStyle,
|
|
37
38
|
containerStyle
|
|
@@ -43,7 +44,7 @@ const DefaultModalUI = ({
|
|
|
43
44
|
runOnJS(setIsRendered)(false);
|
|
44
45
|
}
|
|
45
46
|
});
|
|
46
|
-
}, [isVisible, animationConfig]);
|
|
47
|
+
}, [isVisible, animationConfig, opacity]);
|
|
47
48
|
useEffect(() => {
|
|
48
49
|
const backHandler = BackHandler.addEventListener("hardwareBackPress", () => {
|
|
49
50
|
if (isVisible && closeOnBackButton) {
|
|
@@ -58,13 +59,12 @@ const DefaultModalUI = ({
|
|
|
58
59
|
opacity: opacity.value
|
|
59
60
|
}));
|
|
60
61
|
const contentAnimatedStyle = useAnimatedStyle(() => {
|
|
61
|
-
// Simple slide/fade effect based on position
|
|
62
62
|
let transform = [];
|
|
63
|
-
if (
|
|
63
|
+
if (animateFrom === "bottom") {
|
|
64
64
|
transform.push({
|
|
65
65
|
translateY: (1 - opacity.value) * 100
|
|
66
66
|
});
|
|
67
|
-
} else if (
|
|
67
|
+
} else if (animateFrom === "top") {
|
|
68
68
|
transform.push({
|
|
69
69
|
translateY: (1 - opacity.value) * -100
|
|
70
70
|
});
|
|
@@ -96,9 +96,11 @@ const DefaultModalUI = ({
|
|
|
96
96
|
})
|
|
97
97
|
}), /*#__PURE__*/_jsx(ContentWrapper, {
|
|
98
98
|
behavior: "padding",
|
|
99
|
+
keyboardVerticalOffset: 16,
|
|
99
100
|
style: [styles.keyboardView, {
|
|
100
101
|
paddingBottom,
|
|
101
|
-
paddingTop
|
|
102
|
+
paddingTop,
|
|
103
|
+
justifyContent
|
|
102
104
|
}],
|
|
103
105
|
pointerEvents: "box-none",
|
|
104
106
|
children: /*#__PURE__*/_jsx(Animated.View, {
|
|
@@ -110,7 +112,6 @@ const DefaultModalUI = ({
|
|
|
110
112
|
};
|
|
111
113
|
|
|
112
114
|
// --- Provider ---
|
|
113
|
-
|
|
114
115
|
export const UniversalModalProvider = ({
|
|
115
116
|
children,
|
|
116
117
|
defaultOptions = {},
|
|
@@ -133,6 +134,7 @@ export const UniversalModalProvider = ({
|
|
|
133
134
|
});
|
|
134
135
|
}, [defaultOptions]);
|
|
135
136
|
const hideModal = useCallback(() => {
|
|
137
|
+
const currentOnDismiss = state.options.onDismiss;
|
|
136
138
|
setState(prev => ({
|
|
137
139
|
...prev,
|
|
138
140
|
isVisible: false
|
|
@@ -146,6 +148,9 @@ export const UniversalModalProvider = ({
|
|
|
146
148
|
content: null
|
|
147
149
|
} : prev;
|
|
148
150
|
});
|
|
151
|
+
if (currentOnDismiss) {
|
|
152
|
+
currentOnDismiss();
|
|
153
|
+
}
|
|
149
154
|
}, 350);
|
|
150
155
|
}, []);
|
|
151
156
|
const ModalUI = CustomModalComponent || DefaultModalUI;
|
|
@@ -171,9 +176,6 @@ export const UniversalModalProvider = ({
|
|
|
171
176
|
})
|
|
172
177
|
});
|
|
173
178
|
};
|
|
174
|
-
|
|
175
|
-
// --- Hook ---
|
|
176
|
-
|
|
177
179
|
export const useModal = () => {
|
|
178
180
|
const context = useContext(ModalContext);
|
|
179
181
|
if (!context) {
|
|
@@ -181,9 +183,6 @@ export const useModal = () => {
|
|
|
181
183
|
}
|
|
182
184
|
return context;
|
|
183
185
|
};
|
|
184
|
-
|
|
185
|
-
// --- Default Styles ---
|
|
186
|
-
|
|
187
186
|
const styles = StyleSheet.create({
|
|
188
187
|
overlayWrapper: {
|
|
189
188
|
zIndex: 1000,
|
|
@@ -193,22 +192,11 @@ const styles = StyleSheet.create({
|
|
|
193
192
|
backgroundColor: "rgba(0, 0, 0, 0.6)"
|
|
194
193
|
},
|
|
195
194
|
keyboardView: {
|
|
196
|
-
flexGrow: 1,
|
|
197
195
|
justifyContent: "center",
|
|
198
196
|
alignItems: "center"
|
|
199
197
|
},
|
|
200
198
|
baseContainer: {
|
|
201
|
-
// backgroundColor: "white", // Default, allows override
|
|
202
|
-
// borderRadius: 16,
|
|
203
|
-
// padding: 20,
|
|
204
199
|
width: "90%"
|
|
205
|
-
// maxWidth: 500,
|
|
206
|
-
// alignItems: "center",
|
|
207
|
-
// shadowColor: "#000",
|
|
208
|
-
// shadowOffset: { width: 0, height: 2 },
|
|
209
|
-
// shadowOpacity: 0.25,
|
|
210
|
-
// shadowRadius: 3.84,
|
|
211
|
-
// elevation: 5,
|
|
212
200
|
}
|
|
213
201
|
});
|
|
214
202
|
//# sourceMappingURL=UniversalModalProvider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Portal","PortalHost","PortalProvider","React","createContext","useCallback","useContext","useEffect","useMemo","useState","BackHandler","StyleSheet","TouchableOpacity","View","KeyboardAvoidingView","Animated","Easing","runOnJS","useAnimatedStyle","useSharedValue","withTiming","useSafeAreaInsets","jsx","_jsx","jsxs","_jsxs","ModalContext","undefined","DEFAULT_MODAL_HOST","DefaultModalUI","isVisible","children","options","onClose","insets","isRendered","setIsRendered","opacity","closeOnBackdropPress","closeOnBackButton","animationConfig","duration","easing","bezier","position","avoidKeyboard","backdropStyle","containerStyle","value","finished","backHandler","addEventListener","remove","backdropAnimatedStyle","contentAnimatedStyle","transform","push","translateY","scale","justifyContent","paddingBottom","bottom","paddingTop","top","ContentWrapper","style","absoluteFill","styles","overlayWrapper","backdrop","activeOpacity","onPress","behavior","keyboardView","pointerEvents","baseContainer","UniversalModalProvider","defaultOptions","portalHostName","CustomModalComponent","state","setState","content","showModal","hideModal","prev","setTimeout","ModalUI","Provider","name","hostName","useModal","context","Error","create","zIndex","elevation","backgroundColor","
|
|
1
|
+
{"version":3,"names":["Portal","PortalHost","PortalProvider","React","createContext","useCallback","useContext","useEffect","useMemo","useState","BackHandler","StyleSheet","TouchableOpacity","View","KeyboardAvoidingView","Animated","Easing","runOnJS","useAnimatedStyle","useSharedValue","withTiming","useSafeAreaInsets","jsx","_jsx","jsxs","_jsxs","ModalContext","undefined","DEFAULT_MODAL_HOST","DefaultModalUI","isVisible","children","options","onClose","insets","isRendered","setIsRendered","opacity","closeOnBackdropPress","closeOnBackButton","animationConfig","duration","easing","bezier","position","animateFrom","avoidKeyboard","backdropStyle","containerStyle","value","finished","backHandler","addEventListener","remove","backdropAnimatedStyle","contentAnimatedStyle","transform","push","translateY","scale","justifyContent","paddingBottom","bottom","paddingTop","top","ContentWrapper","style","absoluteFill","styles","overlayWrapper","backdrop","activeOpacity","onPress","behavior","keyboardVerticalOffset","keyboardView","pointerEvents","baseContainer","UniversalModalProvider","defaultOptions","portalHostName","CustomModalComponent","state","setState","content","showModal","hideModal","currentOnDismiss","onDismiss","prev","setTimeout","ModalUI","Provider","name","hostName","useModal","context","Error","create","zIndex","elevation","backgroundColor","alignItems","width"],"sourceRoot":"..\\..\\..\\src","sources":["contexts/UniversalModalProvider.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -14,8 +14,10 @@ export interface ModalOptions {
|
|
|
14
14
|
containerStyle?: StyleProp<ViewStyle>;
|
|
15
15
|
/** Position of the modal. Default: 'center' */
|
|
16
16
|
position?: "center" | "bottom" | "top";
|
|
17
|
+
animateFrom?: "center" | "bottom" | "top";
|
|
17
18
|
/** If true, avoids keyboard view. Default: true */
|
|
18
19
|
avoidKeyboard?: boolean;
|
|
20
|
+
onDismiss?: () => void;
|
|
19
21
|
}
|
|
20
22
|
interface ModalContextType {
|
|
21
23
|
showModal: (content: ReactNode, options?: ModalOptions) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UniversalModalProvider.d.ts","sourceRoot":"","sources":["../../../../src/contexts/UniversalModalProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAEZ,SAAS,EAMV,MAAM,OAAO,CAAC;AACf,OAAO,
|
|
1
|
+
{"version":3,"file":"UniversalModalProvider.d.ts","sourceRoot":"","sources":["../../../../src/contexts/UniversalModalProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAEZ,SAAS,EAMV,MAAM,OAAO,CAAC;AACf,OAAO,EAEL,SAAS,EAIT,SAAS,EACV,MAAM,cAAc,CAAC;AAEtB,OAAiB,EAMf,gBAAgB,EACjB,MAAM,yBAAyB,CAAC;AAIjC,MAAM,WAAW,YAAY;IAC3B,sEAAsE;IACtE,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qEAAqE;IACrE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,6CAA6C;IAC7C,eAAe,CAAC,EAAE,gBAAgB,CAAC;IACnC,qCAAqC;IACrC,aAAa,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACrC,4DAA4D;IAC5D,cAAc,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACtC,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,KAAK,CAAC;IACvC,WAAW,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,KAAK,CAAC;IAC1C,mDAAmD;IACnD,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,UAAU,gBAAgB;IACxB,SAAS,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,YAAY,KAAK,IAAI,CAAC;IAChE,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,SAAS,CAAC;IACpB,4CAA4C;IAC5C,cAAc,CAAC,EAAE,YAAY,CAAC;IAC9B,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oEAAoE;IACpE,oBAAoB,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;QAC9B,SAAS,EAAE,OAAO,CAAC;QACnB,QAAQ,EAAE,SAAS,CAAC;QACpB,OAAO,EAAE,YAAY,CAAC;QACtB,OAAO,EAAE,MAAM,IAAI,CAAC;KACrB,CAAC,CAAC;CACJ;AAMD,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AAsIvD,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAoE/D,CAAC;AAEF,eAAO,MAAM,QAAQ,wBAMpB,CAAC"}
|
package/package.json
CHANGED
|
@@ -10,18 +10,15 @@ import React, {
|
|
|
10
10
|
} from "react";
|
|
11
11
|
import {
|
|
12
12
|
BackHandler,
|
|
13
|
-
Platform,
|
|
14
13
|
StyleProp,
|
|
15
14
|
StyleSheet,
|
|
16
15
|
TouchableOpacity,
|
|
17
16
|
View,
|
|
18
17
|
ViewStyle,
|
|
19
18
|
} from "react-native";
|
|
20
|
-
import {
|
|
19
|
+
import { KeyboardAvoidingView } from "react-native-keyboard-controller";
|
|
21
20
|
import Animated, {
|
|
22
21
|
Easing,
|
|
23
|
-
FadeIn,
|
|
24
|
-
FadeOut,
|
|
25
22
|
runOnJS,
|
|
26
23
|
useAnimatedStyle,
|
|
27
24
|
useSharedValue,
|
|
@@ -44,8 +41,11 @@ export interface ModalOptions {
|
|
|
44
41
|
containerStyle?: StyleProp<ViewStyle>;
|
|
45
42
|
/** Position of the modal. Default: 'center' */
|
|
46
43
|
position?: "center" | "bottom" | "top";
|
|
44
|
+
animateFrom?: "center" | "bottom" | "top";
|
|
47
45
|
/** If true, avoids keyboard view. Default: true */
|
|
48
46
|
avoidKeyboard?: boolean;
|
|
47
|
+
|
|
48
|
+
onDismiss?: () => void;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
interface ModalContextType {
|
|
@@ -89,8 +89,12 @@ const DefaultModalUI: React.FC<{
|
|
|
89
89
|
const {
|
|
90
90
|
closeOnBackdropPress = true,
|
|
91
91
|
closeOnBackButton = true,
|
|
92
|
-
animationConfig = {
|
|
92
|
+
animationConfig = {
|
|
93
|
+
duration: 300,
|
|
94
|
+
easing: Easing.bezier(0.25, 0.1, 0.25, 1),
|
|
95
|
+
},
|
|
93
96
|
position = "center",
|
|
97
|
+
animateFrom = "center",
|
|
94
98
|
avoidKeyboard = true,
|
|
95
99
|
backdropStyle,
|
|
96
100
|
containerStyle,
|
|
@@ -106,18 +110,21 @@ const DefaultModalUI: React.FC<{
|
|
|
106
110
|
if (finished && !isVisible) {
|
|
107
111
|
runOnJS(setIsRendered)(false);
|
|
108
112
|
}
|
|
109
|
-
}
|
|
113
|
+
},
|
|
110
114
|
);
|
|
111
|
-
}, [isVisible, animationConfig]);
|
|
115
|
+
}, [isVisible, animationConfig, opacity]);
|
|
112
116
|
|
|
113
117
|
useEffect(() => {
|
|
114
|
-
const backHandler = BackHandler.addEventListener(
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
118
|
+
const backHandler = BackHandler.addEventListener(
|
|
119
|
+
"hardwareBackPress",
|
|
120
|
+
() => {
|
|
121
|
+
if (isVisible && closeOnBackButton) {
|
|
122
|
+
onClose();
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
return false;
|
|
126
|
+
},
|
|
127
|
+
);
|
|
121
128
|
return () => backHandler.remove();
|
|
122
129
|
}, [isVisible, closeOnBackButton, onClose]);
|
|
123
130
|
|
|
@@ -126,16 +133,15 @@ const DefaultModalUI: React.FC<{
|
|
|
126
133
|
}));
|
|
127
134
|
|
|
128
135
|
const contentAnimatedStyle = useAnimatedStyle(() => {
|
|
129
|
-
// Simple slide/fade effect based on position
|
|
130
136
|
let transform = [];
|
|
131
|
-
if (
|
|
137
|
+
if (animateFrom === "bottom") {
|
|
132
138
|
transform.push({ translateY: (1 - opacity.value) * 100 });
|
|
133
|
-
} else if (
|
|
139
|
+
} else if (animateFrom === "top") {
|
|
134
140
|
transform.push({ translateY: (1 - opacity.value) * -100 });
|
|
135
141
|
} else {
|
|
136
142
|
transform.push({ scale: 0.9 + opacity.value * 0.1 });
|
|
137
143
|
}
|
|
138
|
-
|
|
144
|
+
|
|
139
145
|
return {
|
|
140
146
|
opacity: opacity.value,
|
|
141
147
|
transform,
|
|
@@ -145,7 +151,11 @@ const DefaultModalUI: React.FC<{
|
|
|
145
151
|
if (!isRendered) return null;
|
|
146
152
|
|
|
147
153
|
const justifyContent =
|
|
148
|
-
position === "bottom"
|
|
154
|
+
position === "bottom"
|
|
155
|
+
? "flex-end"
|
|
156
|
+
: position === "top"
|
|
157
|
+
? "flex-start"
|
|
158
|
+
: "center";
|
|
149
159
|
|
|
150
160
|
const paddingBottom = position === "bottom" ? insets.bottom : 0;
|
|
151
161
|
const paddingTop = position === "top" ? insets.top : 0;
|
|
@@ -153,9 +163,22 @@ const DefaultModalUI: React.FC<{
|
|
|
153
163
|
const ContentWrapper = avoidKeyboard ? KeyboardAvoidingView : View;
|
|
154
164
|
|
|
155
165
|
return (
|
|
156
|
-
<View
|
|
166
|
+
<View
|
|
167
|
+
style={[
|
|
168
|
+
StyleSheet.absoluteFill,
|
|
169
|
+
styles.overlayWrapper,
|
|
170
|
+
{ justifyContent },
|
|
171
|
+
]}
|
|
172
|
+
>
|
|
157
173
|
{/* Backdrop */}
|
|
158
|
-
<Animated.View
|
|
174
|
+
<Animated.View
|
|
175
|
+
style={[
|
|
176
|
+
StyleSheet.absoluteFill,
|
|
177
|
+
styles.backdrop,
|
|
178
|
+
backdropStyle,
|
|
179
|
+
backdropAnimatedStyle,
|
|
180
|
+
]}
|
|
181
|
+
>
|
|
159
182
|
<TouchableOpacity
|
|
160
183
|
style={StyleSheet.absoluteFill}
|
|
161
184
|
activeOpacity={1}
|
|
@@ -166,15 +189,15 @@ const DefaultModalUI: React.FC<{
|
|
|
166
189
|
{/* Content */}
|
|
167
190
|
<ContentWrapper
|
|
168
191
|
behavior={"padding"}
|
|
169
|
-
|
|
192
|
+
keyboardVerticalOffset={16}
|
|
193
|
+
style={[
|
|
194
|
+
styles.keyboardView,
|
|
195
|
+
{ paddingBottom, paddingTop, justifyContent },
|
|
196
|
+
]}
|
|
170
197
|
pointerEvents="box-none"
|
|
171
198
|
>
|
|
172
199
|
<Animated.View
|
|
173
|
-
style={[
|
|
174
|
-
styles.baseContainer,
|
|
175
|
-
containerStyle,
|
|
176
|
-
contentAnimatedStyle,
|
|
177
|
-
]}
|
|
200
|
+
style={[styles.baseContainer, containerStyle, contentAnimatedStyle]}
|
|
178
201
|
>
|
|
179
202
|
{children}
|
|
180
203
|
</Animated.View>
|
|
@@ -184,7 +207,6 @@ const DefaultModalUI: React.FC<{
|
|
|
184
207
|
};
|
|
185
208
|
|
|
186
209
|
// --- Provider ---
|
|
187
|
-
|
|
188
210
|
export const UniversalModalProvider: React.FC<ModalProviderProps> = ({
|
|
189
211
|
children,
|
|
190
212
|
defaultOptions = {},
|
|
@@ -209,32 +231,35 @@ export const UniversalModalProvider: React.FC<ModalProviderProps> = ({
|
|
|
209
231
|
options: { ...defaultOptions, ...options },
|
|
210
232
|
});
|
|
211
233
|
},
|
|
212
|
-
[defaultOptions]
|
|
234
|
+
[defaultOptions],
|
|
213
235
|
);
|
|
214
236
|
|
|
215
237
|
const hideModal = useCallback(() => {
|
|
238
|
+
const currentOnDismiss = state.options.onDismiss;
|
|
239
|
+
|
|
216
240
|
setState((prev) => ({ ...prev, isVisible: false }));
|
|
217
241
|
// Clear content after animation normally finishes to avoid flicker
|
|
218
242
|
setTimeout(() => {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
243
|
+
setState((prev) => {
|
|
244
|
+
// Only clear if still hidden (prevent race condition if immediately reshown)
|
|
245
|
+
return !prev.isVisible ? { ...prev, content: null } : prev;
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
if (currentOnDismiss) {
|
|
249
|
+
currentOnDismiss();
|
|
250
|
+
}
|
|
251
|
+
}, 350);
|
|
224
252
|
}, []);
|
|
225
253
|
|
|
226
254
|
const ModalUI = CustomModalComponent || DefaultModalUI;
|
|
227
255
|
|
|
228
256
|
const value = useMemo(
|
|
229
257
|
() => ({ showModal, hideModal, isVisible: state.isVisible }),
|
|
230
|
-
[showModal, hideModal, state.isVisible]
|
|
258
|
+
[showModal, hideModal, state.isVisible],
|
|
231
259
|
);
|
|
232
260
|
|
|
233
261
|
return (
|
|
234
262
|
<ModalContext.Provider value={value}>
|
|
235
|
-
{/* Ensure PortalProvider exists if not wrapped at root */}
|
|
236
|
-
{/* Note: If you already have PortalProvider at root, this nested one might not be strictly necessary depending on usage,
|
|
237
|
-
but wrapping the host ensures the modal renders here. */}
|
|
238
263
|
<PortalProvider>
|
|
239
264
|
{children}
|
|
240
265
|
<PortalHost name={portalHostName} />
|
|
@@ -252,8 +277,6 @@ export const UniversalModalProvider: React.FC<ModalProviderProps> = ({
|
|
|
252
277
|
);
|
|
253
278
|
};
|
|
254
279
|
|
|
255
|
-
// --- Hook ---
|
|
256
|
-
|
|
257
280
|
export const useModal = () => {
|
|
258
281
|
const context = useContext(ModalContext);
|
|
259
282
|
if (!context) {
|
|
@@ -262,8 +285,6 @@ export const useModal = () => {
|
|
|
262
285
|
return context;
|
|
263
286
|
};
|
|
264
287
|
|
|
265
|
-
// --- Default Styles ---
|
|
266
|
-
|
|
267
288
|
const styles = StyleSheet.create({
|
|
268
289
|
overlayWrapper: {
|
|
269
290
|
zIndex: 1000,
|
|
@@ -273,21 +294,10 @@ const styles = StyleSheet.create({
|
|
|
273
294
|
backgroundColor: "rgba(0, 0, 0, 0.6)",
|
|
274
295
|
},
|
|
275
296
|
keyboardView: {
|
|
276
|
-
flexGrow: 1,
|
|
277
297
|
justifyContent: "center",
|
|
278
298
|
alignItems: "center",
|
|
279
299
|
},
|
|
280
300
|
baseContainer: {
|
|
281
|
-
// backgroundColor: "white", // Default, allows override
|
|
282
|
-
// borderRadius: 16,
|
|
283
|
-
// padding: 20,
|
|
284
301
|
width: "90%",
|
|
285
|
-
// maxWidth: 500,
|
|
286
|
-
// alignItems: "center",
|
|
287
|
-
// shadowColor: "#000",
|
|
288
|
-
// shadowOffset: { width: 0, height: 2 },
|
|
289
|
-
// shadowOpacity: 0.25,
|
|
290
|
-
// shadowRadius: 3.84,
|
|
291
|
-
// elevation: 5,
|
|
292
302
|
},
|
|
293
303
|
});
|