1 | import { getHeaderTitle, HeaderBackContext, HeaderHeightContext, HeaderShownContext } from '@react-navigation/elements';
|
2 | import { useTheme } from '@react-navigation/native';
|
3 | import * as React from 'react';
|
4 | import { StyleSheet, View } from 'react-native';
|
5 | import ModalPresentationContext from '../../utils/ModalPresentationContext';
|
6 | import useKeyboardManager from '../../utils/useKeyboardManager';
|
7 | import Card from './Card';
|
8 | const EPSILON = 0.1;
|
9 |
|
10 | function CardContainer(_ref) {
|
11 | let {
|
12 | interpolationIndex,
|
13 | index,
|
14 | active,
|
15 | closing,
|
16 | gesture,
|
17 | focused,
|
18 | modal,
|
19 | getPreviousScene,
|
20 | getFocusedRoute,
|
21 | headerDarkContent,
|
22 | hasAbsoluteFloatHeader,
|
23 | headerHeight,
|
24 | onHeaderHeightChange,
|
25 | isParentHeaderShown,
|
26 | isNextScreenTransparent,
|
27 | detachCurrentScreen,
|
28 | layout,
|
29 | onCloseRoute,
|
30 | onOpenRoute,
|
31 | onGestureCancel,
|
32 | onGestureEnd,
|
33 | onGestureStart,
|
34 | onTransitionEnd,
|
35 | onTransitionStart,
|
36 | renderHeader,
|
37 | renderScene,
|
38 | safeAreaInsetBottom,
|
39 | safeAreaInsetLeft,
|
40 | safeAreaInsetRight,
|
41 | safeAreaInsetTop,
|
42 | scene
|
43 | } = _ref;
|
44 | const parentHeaderHeight = React.useContext(HeaderHeightContext);
|
45 | const {
|
46 | onPageChangeStart,
|
47 | onPageChangeCancel,
|
48 | onPageChangeConfirm
|
49 | } = useKeyboardManager(React.useCallback(() => {
|
50 | const {
|
51 | options,
|
52 | navigation
|
53 | } = scene.descriptor;
|
54 | return navigation.isFocused() && options.keyboardHandlingEnabled !== false;
|
55 | }, [scene.descriptor]));
|
56 |
|
57 | const handleOpen = () => {
|
58 | const {
|
59 | route
|
60 | } = scene.descriptor;
|
61 | onTransitionEnd({
|
62 | route
|
63 | }, false);
|
64 | onOpenRoute({
|
65 | route
|
66 | });
|
67 | };
|
68 |
|
69 | const handleClose = () => {
|
70 | const {
|
71 | route
|
72 | } = scene.descriptor;
|
73 | onTransitionEnd({
|
74 | route
|
75 | }, true);
|
76 | onCloseRoute({
|
77 | route
|
78 | });
|
79 | };
|
80 |
|
81 | const handleGestureBegin = () => {
|
82 | const {
|
83 | route
|
84 | } = scene.descriptor;
|
85 | onPageChangeStart();
|
86 | onGestureStart({
|
87 | route
|
88 | });
|
89 | };
|
90 |
|
91 | const handleGestureCanceled = () => {
|
92 | const {
|
93 | route
|
94 | } = scene.descriptor;
|
95 | onPageChangeCancel();
|
96 | onGestureCancel({
|
97 | route
|
98 | });
|
99 | };
|
100 |
|
101 | const handleGestureEnd = () => {
|
102 | const {
|
103 | route
|
104 | } = scene.descriptor;
|
105 | onGestureEnd({
|
106 | route
|
107 | });
|
108 | };
|
109 |
|
110 | const handleTransition = _ref2 => {
|
111 | let {
|
112 | closing,
|
113 | gesture
|
114 | } = _ref2;
|
115 | const {
|
116 | route
|
117 | } = scene.descriptor;
|
118 |
|
119 | if (!gesture) {
|
120 | onPageChangeConfirm === null || onPageChangeConfirm === void 0 ? void 0 : onPageChangeConfirm(true);
|
121 | } else if (active && closing) {
|
122 | onPageChangeConfirm === null || onPageChangeConfirm === void 0 ? void 0 : onPageChangeConfirm(false);
|
123 | } else {
|
124 | onPageChangeCancel === null || onPageChangeCancel === void 0 ? void 0 : onPageChangeCancel();
|
125 | }
|
126 |
|
127 | onTransitionStart === null || onTransitionStart === void 0 ? void 0 : onTransitionStart({
|
128 | route
|
129 | }, closing);
|
130 | };
|
131 |
|
132 | const insets = {
|
133 | top: safeAreaInsetTop,
|
134 | right: safeAreaInsetRight,
|
135 | bottom: safeAreaInsetBottom,
|
136 | left: safeAreaInsetLeft
|
137 | };
|
138 | const {
|
139 | colors
|
140 | } = useTheme();
|
141 | const [pointerEvents, setPointerEvents] = React.useState('box-none');
|
142 | React.useEffect(() => {
|
143 | var _scene$progress$next, _scene$progress$next$;
|
144 |
|
145 | const listener = (_scene$progress$next = scene.progress.next) === null || _scene$progress$next === void 0 ? void 0 : (_scene$progress$next$ = _scene$progress$next.addListener) === null || _scene$progress$next$ === void 0 ? void 0 : _scene$progress$next$.call(_scene$progress$next, _ref3 => {
|
146 | let {
|
147 | value
|
148 | } = _ref3;
|
149 | setPointerEvents(value <= EPSILON ? 'box-none' : 'none');
|
150 | });
|
151 | return () => {
|
152 | if (listener) {
|
153 | var _scene$progress$next2, _scene$progress$next3;
|
154 |
|
155 | (_scene$progress$next2 = scene.progress.next) === null || _scene$progress$next2 === void 0 ? void 0 : (_scene$progress$next3 = _scene$progress$next2.removeListener) === null || _scene$progress$next3 === void 0 ? void 0 : _scene$progress$next3.call(_scene$progress$next2, listener);
|
156 | }
|
157 | };
|
158 | }, [pointerEvents, scene.progress.next]);
|
159 | const {
|
160 | presentation,
|
161 | animationEnabled,
|
162 | cardOverlay,
|
163 | cardOverlayEnabled,
|
164 | cardShadowEnabled,
|
165 | cardStyle,
|
166 | cardStyleInterpolator,
|
167 | gestureDirection,
|
168 | gestureEnabled,
|
169 | gestureResponseDistance,
|
170 | gestureVelocityImpact,
|
171 | headerMode,
|
172 | headerShown,
|
173 | transitionSpec
|
174 | } = scene.descriptor.options;
|
175 | const previousScene = getPreviousScene({
|
176 | route: scene.descriptor.route
|
177 | });
|
178 | let backTitle;
|
179 |
|
180 | if (previousScene) {
|
181 | const {
|
182 | options,
|
183 | route
|
184 | } = previousScene.descriptor;
|
185 | backTitle = getHeaderTitle(options, route.name);
|
186 | }
|
187 |
|
188 | const headerBack = React.useMemo(() => backTitle !== undefined ? {
|
189 | title: backTitle
|
190 | } : undefined, [backTitle]);
|
191 | return React.createElement(Card, {
|
192 | interpolationIndex: interpolationIndex,
|
193 | gestureDirection: gestureDirection,
|
194 | layout: layout,
|
195 | insets: insets,
|
196 | gesture: gesture,
|
197 | current: scene.progress.current,
|
198 | next: scene.progress.next,
|
199 | closing: closing,
|
200 | onOpen: handleOpen,
|
201 | onClose: handleClose,
|
202 | overlay: cardOverlay,
|
203 | overlayEnabled: cardOverlayEnabled,
|
204 | shadowEnabled: cardShadowEnabled,
|
205 | onTransition: handleTransition,
|
206 | onGestureBegin: handleGestureBegin,
|
207 | onGestureCanceled: handleGestureCanceled,
|
208 | onGestureEnd: handleGestureEnd,
|
209 | gestureEnabled: index === 0 ? false : gestureEnabled,
|
210 | gestureResponseDistance: gestureResponseDistance,
|
211 | gestureVelocityImpact: gestureVelocityImpact,
|
212 | transitionSpec: transitionSpec,
|
213 | styleInterpolator: cardStyleInterpolator,
|
214 | accessibilityElementsHidden: !focused,
|
215 | importantForAccessibility: focused ? 'auto' : 'no-hide-descendants',
|
216 | pointerEvents: active ? 'box-none' : pointerEvents,
|
217 | pageOverflowEnabled: headerMode !== 'float' && presentation !== 'modal',
|
218 | headerDarkContent: headerDarkContent,
|
219 | containerStyle: hasAbsoluteFloatHeader && headerMode !== 'screen' ? {
|
220 | marginTop: headerHeight
|
221 | } : null,
|
222 | contentStyle: [{
|
223 | backgroundColor: presentation === 'transparentModal' ? 'transparent' : colors.background
|
224 | }, cardStyle],
|
225 | style: [{
|
226 |
|
227 |
|
228 | overflow: active ? undefined : 'hidden',
|
229 | display:
|
230 |
|
231 | animationEnabled === false && isNextScreenTransparent === false && detachCurrentScreen !== false && !focused ? 'none' : 'flex'
|
232 | }, StyleSheet.absoluteFill]
|
233 | }, React.createElement(View, {
|
234 | style: styles.container
|
235 | }, React.createElement(ModalPresentationContext.Provider, {
|
236 | value: modal
|
237 | }, React.createElement(View, {
|
238 | style: styles.scene
|
239 | }, React.createElement(HeaderBackContext.Provider, {
|
240 | value: headerBack
|
241 | }, React.createElement(HeaderShownContext.Provider, {
|
242 | value: isParentHeaderShown || headerShown !== false
|
243 | }, React.createElement(HeaderHeightContext.Provider, {
|
244 | value: headerShown ? headerHeight : parentHeaderHeight !== null && parentHeaderHeight !== void 0 ? parentHeaderHeight : 0
|
245 | }, renderScene({
|
246 | route: scene.descriptor.route
|
247 | }))))), headerMode !== 'float' ? renderHeader({
|
248 | mode: 'screen',
|
249 | layout,
|
250 | scenes: [previousScene, scene],
|
251 | getPreviousScene,
|
252 | getFocusedRoute,
|
253 | onContentHeightChange: onHeaderHeightChange
|
254 | }) : null)));
|
255 | }
|
256 |
|
257 | export default React.memo(CardContainer);
|
258 | const styles = StyleSheet.create({
|
259 | container: {
|
260 | flex: 1,
|
261 | flexDirection: 'column-reverse'
|
262 | },
|
263 | scene: {
|
264 | flex: 1
|
265 | }
|
266 | });
|
267 |
|
\ | No newline at end of file |