@haroldtran/react-native-modals 0.0.6 → 0.0.10
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/package.json +41 -65
- package/src/BottomModal.tsx +1 -3
- package/src/Modal.tsx +4 -6
- package/src/ModalPortal.tsx +108 -75
- package/src/animations/Animation.tsx +10 -12
- package/src/animations/FadeAnimation.tsx +8 -18
- package/src/animations/ScaleAnimation.tsx +14 -7
- package/src/animations/SlideAnimation.tsx +35 -13
- package/src/components/Backdrop.tsx +40 -51
- package/src/components/BaseModal.tsx +265 -228
- package/src/components/BottomModal.tsx +23 -19
- package/src/components/DraggableView.tsx +192 -227
- package/src/components/ModalButton.tsx +15 -24
- package/src/components/ModalContent.tsx +4 -13
- package/src/components/ModalFooter.tsx +13 -24
- package/src/components/ModalTitle.tsx +11 -19
- package/src/index.tsx +14 -14
- package/src/type.ts +16 -16
- package/src/components/SlideAnimation.tsx +0 -91
|
@@ -1,59 +1,48 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const { visible, useNativeDriver = true, opacity: toOpacity = 0.5, animationDuration: duration = 200 } = this.props;
|
|
28
|
-
if (prevProps.visible !== visible) {
|
|
1
|
+
import React, { forwardRef, memo, useEffect, useImperativeHandle, useRef } from 'react';
|
|
2
|
+
import { Animated, StyleSheet, TouchableOpacity } from 'react-native';
|
|
3
|
+
import { BackdropProps } from '../type';
|
|
4
|
+
|
|
5
|
+
const Backdrop = memo(
|
|
6
|
+
forwardRef((props: BackdropProps, ref) => {
|
|
7
|
+
const {
|
|
8
|
+
backgroundColor = '#000',
|
|
9
|
+
opacity: toOpacity = 0.5,
|
|
10
|
+
animationDuration: duration = 200,
|
|
11
|
+
animationDelay: delay = 0,
|
|
12
|
+
visible = false,
|
|
13
|
+
useNativeDriver = true,
|
|
14
|
+
onPress = () => {},
|
|
15
|
+
pointerEvents,
|
|
16
|
+
} = props;
|
|
17
|
+
|
|
18
|
+
const opacity = useRef(new Animated.Value(0)).current;
|
|
19
|
+
|
|
20
|
+
useImperativeHandle(ref, () => ({
|
|
21
|
+
setOpacity: (value: number) => {
|
|
22
|
+
opacity.setValue(value);
|
|
23
|
+
},
|
|
24
|
+
}));
|
|
25
|
+
|
|
26
|
+
useEffect(() => {
|
|
29
27
|
const toValue = visible ? toOpacity : 0;
|
|
30
|
-
Animated.timing(
|
|
28
|
+
Animated.timing(opacity, {
|
|
31
29
|
toValue,
|
|
32
30
|
duration,
|
|
33
31
|
useNativeDriver,
|
|
32
|
+
delay: visible ? 0 : delay,
|
|
34
33
|
}).start();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
render() {
|
|
43
|
-
const { onPress, pointerEvents, backgroundColor, useBlurView, blurProps } = this.props;
|
|
44
|
-
const { opacity } = this;
|
|
45
|
-
const overlayStyle: any = [StyleSheet.absoluteFill, { backgroundColor, opacity }];
|
|
46
|
-
const _children = (
|
|
34
|
+
}, [visible, toOpacity, duration, delay, useNativeDriver]);
|
|
35
|
+
|
|
36
|
+
const overlayStyle = [StyleSheet.absoluteFill, { backgroundColor, opacity }];
|
|
37
|
+
|
|
38
|
+
return (
|
|
47
39
|
<Animated.View pointerEvents={pointerEvents as any} style={overlayStyle}>
|
|
48
|
-
<TouchableOpacity onPress={onPress} style={StyleSheet.absoluteFill} />
|
|
40
|
+
<TouchableOpacity activeOpacity={1} onPress={onPress} style={StyleSheet.absoluteFill} />
|
|
49
41
|
</Animated.View>
|
|
50
42
|
);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
43
|
+
}),
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
Backdrop.displayName = 'Backdrop';
|
|
47
|
+
|
|
48
|
+
export default Backdrop;
|
|
@@ -1,275 +1,312 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
|
|
1
|
+
import React, {
|
|
2
|
+
forwardRef,
|
|
3
|
+
Fragment,
|
|
4
|
+
memo,
|
|
5
|
+
useCallback,
|
|
6
|
+
useEffect,
|
|
7
|
+
useImperativeHandle,
|
|
8
|
+
useMemo,
|
|
9
|
+
useRef,
|
|
10
|
+
useState,
|
|
11
|
+
} from 'react';
|
|
12
|
+
import { Animated, BackHandler, StyleSheet, useWindowDimensions, View } from 'react-native';
|
|
3
13
|
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import ModalContext from "./ModalContext";
|
|
14
|
+
import FadeAnimation from '../animations/FadeAnimation';
|
|
15
|
+
import type { ModalProps } from '../type';
|
|
16
|
+
import Backdrop from './Backdrop';
|
|
17
|
+
import DraggableView from './DraggableView';
|
|
18
|
+
import ModalContext from './ModalContext';
|
|
10
19
|
|
|
11
|
-
const HARDWARE_BACK_PRESS_EVENT =
|
|
20
|
+
const HARDWARE_BACK_PRESS_EVENT = 'hardwareBackPress' as const;
|
|
12
21
|
|
|
13
22
|
// dialog states
|
|
14
|
-
const MODAL_OPENING
|
|
15
|
-
const MODAL_OPENED
|
|
16
|
-
const MODAL_CLOSING
|
|
17
|
-
const MODAL_CLOSED
|
|
23
|
+
const MODAL_OPENING = 'opening' as const;
|
|
24
|
+
const MODAL_OPENED = 'opened' as const;
|
|
25
|
+
const MODAL_CLOSING = 'closing' as const;
|
|
26
|
+
const MODAL_CLOSED = 'closed' as const;
|
|
18
27
|
|
|
19
|
-
|
|
20
|
-
const DEFAULT_ANIMATION_DURATION: number = 150;
|
|
28
|
+
const DEFAULT_ANIMATION_DURATION = 150;
|
|
21
29
|
|
|
22
30
|
const styles = StyleSheet.create({
|
|
23
31
|
container: {
|
|
24
32
|
...StyleSheet.absoluteFillObject,
|
|
25
33
|
},
|
|
26
34
|
modal: {
|
|
27
|
-
overflow:
|
|
28
|
-
backgroundColor:
|
|
35
|
+
overflow: 'hidden',
|
|
36
|
+
backgroundColor: '#ffffff',
|
|
29
37
|
},
|
|
30
38
|
hidden: {
|
|
31
|
-
|
|
32
|
-
left: 0,
|
|
33
|
-
height: 0,
|
|
34
|
-
width: 0,
|
|
39
|
+
display: 'none',
|
|
35
40
|
},
|
|
36
41
|
round: {
|
|
37
42
|
borderRadius: 8,
|
|
38
43
|
},
|
|
39
44
|
draggableView: {
|
|
40
45
|
flex: 1,
|
|
41
|
-
justifyContent:
|
|
42
|
-
alignItems:
|
|
46
|
+
justifyContent: 'center',
|
|
47
|
+
alignItems: 'center',
|
|
43
48
|
},
|
|
44
49
|
});
|
|
45
50
|
|
|
46
51
|
type ModalState = typeof MODAL_OPENING | typeof MODAL_OPENED | typeof MODAL_CLOSING | typeof MODAL_CLOSED;
|
|
47
52
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
constructor(props: ModalProps) {
|
|
93
|
-
super(props);
|
|
94
|
-
|
|
95
|
-
this.state = {
|
|
96
|
-
modalAnimation:
|
|
97
|
-
props.modalAnimation ||
|
|
53
|
+
const BaseModal = memo(
|
|
54
|
+
forwardRef((props: ModalProps, ref) => {
|
|
55
|
+
const {
|
|
56
|
+
rounded = true,
|
|
57
|
+
modalTitle = null,
|
|
58
|
+
visible = false,
|
|
59
|
+
style = null,
|
|
60
|
+
animationDuration = DEFAULT_ANIMATION_DURATION,
|
|
61
|
+
animationDurationIn,
|
|
62
|
+
animationDurationOut,
|
|
63
|
+
modalStyle = null,
|
|
64
|
+
width: propWidth = null,
|
|
65
|
+
height: propHeight = null,
|
|
66
|
+
onTouchOutside = () => {},
|
|
67
|
+
onHardwareBackPress: propOnHardwareBackPress = () => false,
|
|
68
|
+
hasOverlay = true,
|
|
69
|
+
overlayOpacity = 0.5,
|
|
70
|
+
overlayPointerEvents = null,
|
|
71
|
+
overlayBackgroundColor = '#000',
|
|
72
|
+
overlayAnimationDelay = 250,
|
|
73
|
+
onShow = () => {},
|
|
74
|
+
onDismiss = () => {},
|
|
75
|
+
footer = null,
|
|
76
|
+
onMove = () => {},
|
|
77
|
+
onSwiping = () => {},
|
|
78
|
+
onSwipeRelease = () => {},
|
|
79
|
+
onSwipingOut: propOnSwipingOut = () => {},
|
|
80
|
+
onSwipeOut,
|
|
81
|
+
swipeDirection,
|
|
82
|
+
swipeThreshold,
|
|
83
|
+
useNativeDriver = true,
|
|
84
|
+
isDelay = false,
|
|
85
|
+
children,
|
|
86
|
+
modalAnimation: propModalAnimation,
|
|
87
|
+
} = props;
|
|
88
|
+
|
|
89
|
+
const { width: screenWidth, height: screenHeight } = useWindowDimensions();
|
|
90
|
+
|
|
91
|
+
const [modalState, setModalState] = useState<ModalState>(MODAL_CLOSED);
|
|
92
|
+
|
|
93
|
+
// Instances that don't need re-renders but need to persist
|
|
94
|
+
const modalAnimation = useRef(
|
|
95
|
+
propModalAnimation ||
|
|
98
96
|
new FadeAnimation({
|
|
99
|
-
animationDuration:
|
|
97
|
+
animationDuration: animationDuration || DEFAULT_ANIMATION_DURATION,
|
|
100
98
|
}),
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
99
|
+
).current;
|
|
100
|
+
|
|
101
|
+
const backdropRef = useRef<any>(null);
|
|
102
|
+
const closeTimerRef = useRef<any>(null);
|
|
103
|
+
const lastSwipeEventRef = useRef<any | null>(null);
|
|
104
|
+
const isSwipingOutRef = useRef<boolean>(false);
|
|
105
|
+
|
|
106
|
+
const onHardwareBackPress = useCallback((): boolean => {
|
|
107
|
+
return propOnHardwareBackPress ? propOnHardwareBackPress() : false;
|
|
108
|
+
}, [propOnHardwareBackPress]);
|
|
109
|
+
|
|
110
|
+
const show = useCallback((): void => {
|
|
111
|
+
isSwipingOutRef.current = false;
|
|
112
|
+
clearTimeout(closeTimerRef.current);
|
|
113
|
+
setModalState(MODAL_OPENING);
|
|
114
|
+
modalAnimation.in(() => {
|
|
115
|
+
setModalState(MODAL_OPENED);
|
|
116
|
+
onShow?.();
|
|
117
|
+
}, animationDurationIn || animationDuration);
|
|
118
|
+
}, [modalAnimation, onShow, animationDurationIn, animationDuration]);
|
|
119
|
+
|
|
120
|
+
const dismiss = useCallback((): void => {
|
|
121
|
+
const duration = animationDurationOut || animationDuration;
|
|
122
|
+
clearTimeout(closeTimerRef.current);
|
|
123
|
+
setModalState(MODAL_CLOSING);
|
|
124
|
+
|
|
125
|
+
const delay = hasOverlay ? overlayAnimationDelay || 0 : 0;
|
|
126
|
+
|
|
127
|
+
const finishDismiss = () => {
|
|
128
|
+
if (delay > 0) {
|
|
129
|
+
closeTimerRef.current = setTimeout(() => {
|
|
130
|
+
setModalState(MODAL_CLOSED);
|
|
131
|
+
onDismiss?.();
|
|
132
|
+
}, delay);
|
|
133
|
+
} else {
|
|
134
|
+
setModalState(MODAL_CLOSED);
|
|
135
|
+
onDismiss?.();
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
if (isSwipingOutRef.current) {
|
|
140
|
+
finishDismiss();
|
|
116
141
|
return;
|
|
117
142
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
return { width, height };
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
show(): void {
|
|
150
|
-
this.setState({ modalState: MODAL_OPENING }, () => {
|
|
151
|
-
this.state.modalAnimation.in(() => {
|
|
152
|
-
this.setState({ modalState: MODAL_OPENED }, this.props.onShow);
|
|
153
|
-
});
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
dismiss(): void {
|
|
158
|
-
this.setState({ modalState: MODAL_CLOSING }, () => {
|
|
159
|
-
if (this.isSwipingOut) {
|
|
160
|
-
this.setState({ modalState: MODAL_CLOSED }, this.props.onDismiss);
|
|
161
|
-
return;
|
|
143
|
+
|
|
144
|
+
modalAnimation.out(finishDismiss, duration);
|
|
145
|
+
}, [modalAnimation, onDismiss, animationDurationOut, animationDuration, hasOverlay, overlayAnimationDelay]);
|
|
146
|
+
|
|
147
|
+
useImperativeHandle(ref, () => ({
|
|
148
|
+
show,
|
|
149
|
+
dismiss,
|
|
150
|
+
}));
|
|
151
|
+
|
|
152
|
+
useEffect(() => {
|
|
153
|
+
const backHandler = BackHandler.addEventListener(HARDWARE_BACK_PRESS_EVENT, onHardwareBackPress);
|
|
154
|
+
return () => {
|
|
155
|
+
backHandler.remove();
|
|
156
|
+
clearTimeout(closeTimerRef.current);
|
|
157
|
+
};
|
|
158
|
+
}, [onHardwareBackPress]);
|
|
159
|
+
|
|
160
|
+
useEffect(() => {
|
|
161
|
+
if (visible) {
|
|
162
|
+
if (modalState === MODAL_CLOSED || modalState === MODAL_CLOSING) {
|
|
163
|
+
show();
|
|
164
|
+
}
|
|
165
|
+
} else {
|
|
166
|
+
if (modalState === MODAL_OPENED || modalState === MODAL_OPENING) {
|
|
167
|
+
dismiss();
|
|
168
|
+
} else if (modalState === MODAL_CLOSED) {
|
|
169
|
+
onDismiss?.();
|
|
170
|
+
}
|
|
162
171
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
} else {
|
|
184
|
-
const lastAxis = Math.abs(this.lastSwipeEvent.layout.x);
|
|
185
|
-
const currAxis = Math.abs(event.axis.x);
|
|
186
|
-
newOpacity = opacity - (opacity * currAxis) / (Dimensions.get("window").width - lastAxis);
|
|
187
|
-
}
|
|
188
|
-
this.backdrop?.setOpacity(newOpacity);
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
handleSwipingOut = (event: any) => {
|
|
192
|
-
this.isSwipingOut = true;
|
|
193
|
-
this.props.onSwipingOut?.(event);
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
render() {
|
|
197
|
-
const { modalState, modalAnimation } = this.state;
|
|
198
|
-
const {
|
|
199
|
-
rounded,
|
|
200
|
-
modalTitle,
|
|
201
|
-
children,
|
|
202
|
-
onTouchOutside,
|
|
203
|
-
hasOverlay,
|
|
204
|
-
modalStyle,
|
|
205
|
-
animationDuration,
|
|
206
|
-
overlayOpacity,
|
|
207
|
-
useNativeDriver,
|
|
208
|
-
overlayBackgroundColor,
|
|
209
|
-
style,
|
|
210
|
-
footer,
|
|
211
|
-
onSwiping,
|
|
212
|
-
onSwipeRelease,
|
|
213
|
-
onSwipeOut,
|
|
214
|
-
swipeDirection,
|
|
215
|
-
swipeThreshold,
|
|
216
|
-
useBlurView,
|
|
217
|
-
blurProps,
|
|
218
|
-
isDelay,
|
|
219
|
-
} = this.props;
|
|
172
|
+
}, [visible, modalState, show, dismiss, onDismiss]);
|
|
173
|
+
|
|
174
|
+
const pointerEvents = useMemo(() => {
|
|
175
|
+
if (overlayPointerEvents) {
|
|
176
|
+
return overlayPointerEvents;
|
|
177
|
+
}
|
|
178
|
+
return modalState === MODAL_OPENED || modalState === MODAL_OPENING ? 'auto' : 'none';
|
|
179
|
+
}, [overlayPointerEvents, modalState]);
|
|
180
|
+
|
|
181
|
+
const modalSizeStyle = useMemo(() => {
|
|
182
|
+
let w = propWidth;
|
|
183
|
+
let h = propHeight;
|
|
184
|
+
if (w && w > 0.0 && w <= 1.0) {
|
|
185
|
+
w *= screenWidth;
|
|
186
|
+
}
|
|
187
|
+
if (h && h > 0.0 && h <= 1.0) {
|
|
188
|
+
h *= screenHeight;
|
|
189
|
+
}
|
|
190
|
+
return { width: w ?? undefined, height: h ?? undefined };
|
|
191
|
+
}, [propWidth, propHeight, screenWidth, screenHeight]);
|
|
220
192
|
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
|
|
193
|
+
const handleMove = useCallback(
|
|
194
|
+
(event: any): void => {
|
|
195
|
+
if (modalState === MODAL_CLOSING) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (!lastSwipeEventRef.current) {
|
|
199
|
+
lastSwipeEventRef.current = event;
|
|
200
|
+
}
|
|
201
|
+
let newOpacity;
|
|
202
|
+
const opacity = overlayOpacity ?? 0;
|
|
203
|
+
if (Math.abs(event.axis.y)) {
|
|
204
|
+
const lastAxis = Math.abs(lastSwipeEventRef.current.layout.y);
|
|
205
|
+
const currAxis = Math.abs(event.axis.y);
|
|
206
|
+
newOpacity = opacity - (opacity * currAxis) / (screenHeight - lastAxis);
|
|
207
|
+
} else {
|
|
208
|
+
const lastAxis = Math.abs(lastSwipeEventRef.current.layout.x);
|
|
209
|
+
const currAxis = Math.abs(event.axis.x);
|
|
210
|
+
newOpacity = opacity - (opacity * currAxis) / (screenWidth - lastAxis);
|
|
211
|
+
}
|
|
212
|
+
backdropRef.current?.setOpacity(newOpacity);
|
|
213
|
+
onMove?.(event);
|
|
214
|
+
},
|
|
215
|
+
[modalState, overlayOpacity, screenWidth, screenHeight, onMove],
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
const handleSwipingOut = useCallback(
|
|
219
|
+
(event: any) => {
|
|
220
|
+
isSwipingOutRef.current = true;
|
|
221
|
+
propOnSwipingOut?.(event);
|
|
222
|
+
},
|
|
223
|
+
[propOnSwipingOut],
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
const overlayVisible = hasOverlay && (modalState === MODAL_OPENING || modalState === MODAL_OPENED);
|
|
227
|
+
const currentOverlayDuration =
|
|
228
|
+
modalState === MODAL_CLOSING
|
|
229
|
+
? animationDurationOut || animationDuration
|
|
230
|
+
: animationDurationIn || animationDuration;
|
|
231
|
+
|
|
232
|
+
const roundStyle = rounded ? styles.round : null;
|
|
233
|
+
const hiddenStyle = modalState === MODAL_CLOSED ? styles.hidden : null;
|
|
234
|
+
|
|
235
|
+
const draggableViewStyle = useMemo(() => StyleSheet.flatten([styles.draggableView, style]), [style]);
|
|
236
|
+
const modalViewStyle = useMemo(
|
|
237
|
+
() => [styles.modal, roundStyle, modalSizeStyle, modalStyle, modalAnimation.getAnimations()],
|
|
238
|
+
[roundStyle, modalSizeStyle, modalStyle, modalAnimation],
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
const renderDraggableContent = useCallback(
|
|
242
|
+
({ pan, onLayout }: any) => (
|
|
243
|
+
<Fragment>
|
|
244
|
+
<Backdrop
|
|
245
|
+
ref={backdropRef}
|
|
246
|
+
pointerEvents={pointerEvents}
|
|
247
|
+
visible={overlayVisible}
|
|
248
|
+
onPress={onTouchOutside}
|
|
249
|
+
backgroundColor={overlayBackgroundColor}
|
|
250
|
+
opacity={overlayOpacity}
|
|
251
|
+
animationDuration={currentOverlayDuration}
|
|
252
|
+
animationDelay={overlayAnimationDelay}
|
|
253
|
+
useNativeDriver={useNativeDriver}
|
|
254
|
+
/>
|
|
255
|
+
<Animated.View style={pan.getLayout()} onLayout={onLayout}>
|
|
256
|
+
<Animated.View style={modalViewStyle}>
|
|
257
|
+
{modalTitle}
|
|
258
|
+
{isDelay ? (modalState === MODAL_OPENED ? children : null) : children}
|
|
259
|
+
{footer}
|
|
260
|
+
</Animated.View>
|
|
261
|
+
</Animated.View>
|
|
262
|
+
</Fragment>
|
|
263
|
+
),
|
|
264
|
+
[
|
|
265
|
+
pointerEvents,
|
|
266
|
+
overlayVisible,
|
|
267
|
+
onTouchOutside,
|
|
268
|
+
overlayBackgroundColor,
|
|
269
|
+
overlayOpacity,
|
|
270
|
+
currentOverlayDuration,
|
|
271
|
+
overlayAnimationDelay,
|
|
272
|
+
useNativeDriver,
|
|
273
|
+
modalViewStyle,
|
|
274
|
+
modalTitle,
|
|
275
|
+
isDelay,
|
|
276
|
+
modalState,
|
|
277
|
+
children,
|
|
278
|
+
footer,
|
|
279
|
+
],
|
|
280
|
+
);
|
|
224
281
|
|
|
225
282
|
return (
|
|
226
283
|
<ModalContext.Provider
|
|
227
284
|
value={{
|
|
228
285
|
hasTitle: Boolean(modalTitle),
|
|
229
286
|
hasFooter: Boolean(footer),
|
|
230
|
-
}}
|
|
231
|
-
|
|
232
|
-
|
|
287
|
+
}}>
|
|
288
|
+
<View
|
|
289
|
+
pointerEvents={modalState === MODAL_CLOSED || isSwipingOutRef.current ? 'none' : 'box-none'}
|
|
290
|
+
style={[styles.container, hiddenStyle]}
|
|
291
|
+
>
|
|
233
292
|
<DraggableView
|
|
234
|
-
style={
|
|
235
|
-
|
|
293
|
+
style={draggableViewStyle}
|
|
294
|
+
pointerEvents={pointerEvents}
|
|
295
|
+
onMove={handleMove}
|
|
236
296
|
onSwiping={onSwiping}
|
|
237
297
|
onRelease={onSwipeRelease}
|
|
238
|
-
onSwipingOut={
|
|
298
|
+
onSwipingOut={handleSwipingOut}
|
|
239
299
|
onSwipeOut={onSwipeOut}
|
|
240
300
|
swipeDirection={swipeDirection}
|
|
241
|
-
swipeThreshold={swipeThreshold}
|
|
242
|
-
|
|
243
|
-
{({ pan, onLayout }) => (
|
|
244
|
-
<Fragment>
|
|
245
|
-
<Backdrop
|
|
246
|
-
ref={(ref) => {
|
|
247
|
-
this.backdrop = ref;
|
|
248
|
-
}}
|
|
249
|
-
pointerEvents={this.pointerEvents}
|
|
250
|
-
visible={overlayVisible}
|
|
251
|
-
onPress={onTouchOutside}
|
|
252
|
-
backgroundColor={overlayBackgroundColor}
|
|
253
|
-
opacity={overlayOpacity}
|
|
254
|
-
animationDuration={animationDuration}
|
|
255
|
-
useNativeDriver={useNativeDriver}
|
|
256
|
-
useBlurView={useBlurView}
|
|
257
|
-
blurProps={blurProps}
|
|
258
|
-
/>
|
|
259
|
-
<Animated.View style={pan.getLayout()} onLayout={onLayout}>
|
|
260
|
-
<Animated.View style={[styles.modal, round, this.modalSize, modalStyle, modalAnimation.getAnimations()]}>
|
|
261
|
-
{modalTitle}
|
|
262
|
-
{isDelay ? (modalState === MODAL_OPENED ? children : null) : children}
|
|
263
|
-
{footer}
|
|
264
|
-
</Animated.View>
|
|
265
|
-
</Animated.View>
|
|
266
|
-
</Fragment>
|
|
267
|
-
)}
|
|
301
|
+
swipeThreshold={swipeThreshold}>
|
|
302
|
+
{renderDraggableContent}
|
|
268
303
|
</DraggableView>
|
|
269
304
|
</View>
|
|
270
305
|
</ModalContext.Provider>
|
|
271
306
|
);
|
|
272
|
-
}
|
|
273
|
-
|
|
307
|
+
}),
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
BaseModal.displayName = 'BaseModal';
|
|
274
311
|
|
|
275
312
|
export default BaseModal;
|