@momo-kits/foundation 0.163.1-beta.4 → 0.163.1-beta.6
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/Application/NavigationContainer.tsx +4 -1
- package/Application/utils.tsx +135 -3
- package/package.json +35 -34
|
@@ -16,7 +16,7 @@ import { DeviceEventEmitter } from 'react-native';
|
|
|
16
16
|
import StackScreen from './StackScreen';
|
|
17
17
|
import ModalScreen from './ModalScreen';
|
|
18
18
|
import Navigator from './Navigator';
|
|
19
|
-
import { getModalOptions, getStackOptions } from './utils';
|
|
19
|
+
import { getModalOptions, getStackOptions, useNativeCanGoBack } from './utils';
|
|
20
20
|
import { NavigationContainerProps } from './types';
|
|
21
21
|
import { ApplicationContext, MiniAppContext } from '../Context';
|
|
22
22
|
import Localize from './Localize';
|
|
@@ -93,6 +93,7 @@ const Navigation: React.FC<any> = ({
|
|
|
93
93
|
const navigator = useRef(new Navigator(navigationRef, isReady));
|
|
94
94
|
const [showGrid, setShowGrid] = useState(false);
|
|
95
95
|
const insets = useSafeAreaInsets();
|
|
96
|
+
const syncCanGoBack = useNativeCanGoBack();
|
|
96
97
|
|
|
97
98
|
let headerBackground = context?.designSystemConfig?.config?.headerBar;
|
|
98
99
|
let headerGradient = theme.colors?.gradient;
|
|
@@ -192,7 +193,9 @@ const Navigation: React.FC<any> = ({
|
|
|
192
193
|
ref={navigationRef}
|
|
193
194
|
onReady={() => {
|
|
194
195
|
isReady.current = true;
|
|
196
|
+
syncCanGoBack(navigationRef.current?.getRootState?.());
|
|
195
197
|
}}
|
|
198
|
+
onStateChange={syncCanGoBack}
|
|
196
199
|
>
|
|
197
200
|
<Stack.Navigator
|
|
198
201
|
initialRouteName="Stack"
|
package/Application/utils.tsx
CHANGED
|
@@ -1,11 +1,32 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
useCallback,
|
|
3
|
+
useContext,
|
|
4
|
+
useEffect,
|
|
5
|
+
useMemo,
|
|
6
|
+
useRef,
|
|
7
|
+
} from 'react';
|
|
2
8
|
import {
|
|
9
|
+
CardStyleInterpolators,
|
|
3
10
|
StackNavigationOptions,
|
|
4
11
|
TransitionPresets,
|
|
5
12
|
} from '@react-navigation/stack';
|
|
13
|
+
import type {
|
|
14
|
+
StackCardInterpolatedStyle,
|
|
15
|
+
StackCardInterpolationProps,
|
|
16
|
+
} from '@react-navigation/stack';
|
|
17
|
+
import type { NavigationState, PartialState } from '@react-navigation/native';
|
|
6
18
|
import type { HeaderTitleProps, NavigationOptions } from './types';
|
|
7
19
|
import { Colors, Spacing } from '../Consts';
|
|
8
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
Animated,
|
|
22
|
+
AppState,
|
|
23
|
+
NativeModules,
|
|
24
|
+
Platform,
|
|
25
|
+
StyleProp,
|
|
26
|
+
StyleSheet,
|
|
27
|
+
ViewStyle,
|
|
28
|
+
} from 'react-native';
|
|
29
|
+
import { BlurView } from '@sbaiahmed1/react-native-blur';
|
|
9
30
|
import type { SharedValue } from 'react-native-reanimated';
|
|
10
31
|
import { useSharedValue } from 'react-native-reanimated';
|
|
11
32
|
import {
|
|
@@ -18,6 +39,45 @@ import { HeaderBackground } from './Components/HeaderBackground';
|
|
|
18
39
|
import { HeaderLeft } from './Components/HeaderLeft';
|
|
19
40
|
import { HeaderRight } from './Components/HeaderRight';
|
|
20
41
|
|
|
42
|
+
const forStackTransitionWithOverlay = (
|
|
43
|
+
props: StackCardInterpolationProps,
|
|
44
|
+
): StackCardInterpolatedStyle => {
|
|
45
|
+
const { cardStyle, shadowStyle } =
|
|
46
|
+
CardStyleInterpolators.forHorizontalIOS(props);
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
cardStyle,
|
|
50
|
+
shadowStyle,
|
|
51
|
+
overlayStyle: {
|
|
52
|
+
opacity: props.current.progress.interpolate({
|
|
53
|
+
inputRange: [0, 1],
|
|
54
|
+
outputRange: [0, 1],
|
|
55
|
+
extrapolate: 'clamp',
|
|
56
|
+
}),
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* blur intensity stays fixed so only the wrapper's opacity animates per
|
|
63
|
+
* frame; animating blurAmount itself would re-render the native blur view
|
|
64
|
+
* on every frame of the transition
|
|
65
|
+
*/
|
|
66
|
+
const renderStackOverlay = ({
|
|
67
|
+
style,
|
|
68
|
+
}: {
|
|
69
|
+
style: Animated.WithAnimatedValue<StyleProp<ViewStyle>>;
|
|
70
|
+
}) => (
|
|
71
|
+
<Animated.View pointerEvents="none" style={[StyleSheet.absoluteFill, style]}>
|
|
72
|
+
<BlurView
|
|
73
|
+
style={StyleSheet.absoluteFill}
|
|
74
|
+
blurType="xlight"
|
|
75
|
+
blurAmount={2}
|
|
76
|
+
overlayColor="rgba(253, 234, 244, 0.3)"
|
|
77
|
+
/>
|
|
78
|
+
</Animated.View>
|
|
79
|
+
);
|
|
80
|
+
|
|
21
81
|
/**
|
|
22
82
|
* default options for stack screen
|
|
23
83
|
*/
|
|
@@ -38,8 +98,11 @@ const getStackOptions = (): StackNavigationOptions => {
|
|
|
38
98
|
headerLeft: (props: any) => <HeaderLeft {...props} />,
|
|
39
99
|
headerRight: (props: any) => <HeaderRight {...props} />,
|
|
40
100
|
headerTintColor: Colors.black_17,
|
|
41
|
-
gestureEnabled:
|
|
101
|
+
gestureEnabled: Platform.OS === 'ios',
|
|
42
102
|
...TransitionPresets.SlideFromRightIOS,
|
|
103
|
+
cardStyleInterpolator: forStackTransitionWithOverlay,
|
|
104
|
+
cardOverlayEnabled: true,
|
|
105
|
+
cardOverlay: renderStackOverlay,
|
|
43
106
|
};
|
|
44
107
|
};
|
|
45
108
|
|
|
@@ -54,9 +117,20 @@ const getModalOptions = (): StackNavigationOptions => {
|
|
|
54
117
|
cardOverlayEnabled: true,
|
|
55
118
|
animation: 'none',
|
|
56
119
|
presentation: 'transparentModal',
|
|
120
|
+
gestureEnabled: false,
|
|
57
121
|
};
|
|
58
122
|
};
|
|
59
123
|
|
|
124
|
+
/**
|
|
125
|
+
* screen owns its back flow (guard popup, custom handler or no back button),
|
|
126
|
+
* so swipe back must not bypass it
|
|
127
|
+
*/
|
|
128
|
+
const hasCustomBackHandling = (params: NavigationOptions) =>
|
|
129
|
+
params.preventBack !== undefined ||
|
|
130
|
+
params.hiddenBack === true ||
|
|
131
|
+
typeof params.onBackHandler === 'function' ||
|
|
132
|
+
typeof params.onPressLeftHeader === 'function';
|
|
133
|
+
|
|
60
134
|
/**
|
|
61
135
|
* build react-navigation options
|
|
62
136
|
*/
|
|
@@ -125,6 +199,13 @@ const getOptions = (
|
|
|
125
199
|
};
|
|
126
200
|
}
|
|
127
201
|
|
|
202
|
+
/**
|
|
203
|
+
* only ever turns swipe back off, screens opt in via gestureEnabled
|
|
204
|
+
*/
|
|
205
|
+
if (params.gestureEnabled === undefined && hasCustomBackHandling(params)) {
|
|
206
|
+
options.gestureEnabled = false;
|
|
207
|
+
}
|
|
208
|
+
|
|
128
209
|
return {
|
|
129
210
|
...params,
|
|
130
211
|
...options,
|
|
@@ -230,6 +311,55 @@ const useAppState = () => {
|
|
|
230
311
|
};
|
|
231
312
|
};
|
|
232
313
|
|
|
314
|
+
/**
|
|
315
|
+
* screens the focused navigation branch can still pop.
|
|
316
|
+
* only stack navigators count, switching bottom tab is not a back step
|
|
317
|
+
*/
|
|
318
|
+
const getStackDepth = (
|
|
319
|
+
state?: NavigationState | PartialState<NavigationState>,
|
|
320
|
+
): number => {
|
|
321
|
+
const routes = state?.routes;
|
|
322
|
+
if (!routes?.length) {
|
|
323
|
+
return 0;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const index = state?.index ?? routes.length - 1;
|
|
327
|
+
const depth = state?.type === 'stack' ? index : 0;
|
|
328
|
+
|
|
329
|
+
return depth + getStackDepth(routes[index]?.state);
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* report back ownership to the native container: `true` when the mini app sits
|
|
334
|
+
* on its root screen and native may dismiss the rootview, `false` while
|
|
335
|
+
* react-navigation still has screens (or a modal / bottom sheet) to pop.
|
|
336
|
+
*/
|
|
337
|
+
const useNativeCanGoBack = () => {
|
|
338
|
+
const lastValue = useRef<boolean | undefined>(undefined);
|
|
339
|
+
|
|
340
|
+
return useCallback(
|
|
341
|
+
(state?: NavigationState | PartialState<NavigationState>) => {
|
|
342
|
+
const canDismiss = getStackDepth(state) === 0;
|
|
343
|
+
if (lastValue.current === canDismiss) {
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const setCanGoBack = NativeModules?.MiniAppModule?.setCanGoBack;
|
|
348
|
+
if (typeof setCanGoBack !== 'function') {
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
lastValue.current = canDismiss;
|
|
353
|
+
try {
|
|
354
|
+
setCanGoBack(canDismiss);
|
|
355
|
+
} catch (error) {
|
|
356
|
+
console.warn('[NavigationContainer] setCanGoBack failed:', error);
|
|
357
|
+
}
|
|
358
|
+
},
|
|
359
|
+
[],
|
|
360
|
+
);
|
|
361
|
+
};
|
|
362
|
+
|
|
233
363
|
/**
|
|
234
364
|
* Union of the two animation runtimes an internal foundation component might
|
|
235
365
|
* receive. Public Screen props still accept React Native Animated.Value only;
|
|
@@ -271,9 +401,11 @@ export {
|
|
|
271
401
|
getStackOptions,
|
|
272
402
|
getModalOptions,
|
|
273
403
|
getOptions,
|
|
404
|
+
getStackDepth,
|
|
274
405
|
exportHeaderTitle,
|
|
275
406
|
setAutomationID,
|
|
276
407
|
useComponentId,
|
|
277
408
|
useAppState,
|
|
409
|
+
useNativeCanGoBack,
|
|
278
410
|
useNormalizedSharedValue,
|
|
279
411
|
};
|
package/package.json
CHANGED
|
@@ -1,35 +1,36 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
2
|
+
"name": "@momo-kits/foundation",
|
|
3
|
+
"version": "0.163.1-beta.6",
|
|
4
|
+
"description": "React Native Component Kits",
|
|
5
|
+
"main": "index.ts",
|
|
6
|
+
"scripts": {},
|
|
7
|
+
"keywords": [
|
|
8
|
+
"@momo-kits/foundation"
|
|
9
|
+
],
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"react-native-fast-image": "git+https://oauth2:TGi6oBj-LdzsKpLXQSoH@gitlab.mservice.com.vn/momo-platform/public/react-native-fast-image.git#v8.11.0",
|
|
12
|
+
"@sbaiahmed1/react-native-blur": "6.0.0",
|
|
13
|
+
"@react-navigation/bottom-tabs": "7.4.2",
|
|
14
|
+
"@react-navigation/core": "7.12.1",
|
|
15
|
+
"@react-navigation/elements": "2.5.2",
|
|
16
|
+
"@react-navigation/native": "7.1.14",
|
|
17
|
+
"@react-navigation/routers": "7.4.1",
|
|
18
|
+
"@react-navigation/stack": "7.4.2",
|
|
19
|
+
"react-native-gesture-handler": "2.27.1",
|
|
20
|
+
"react-native-linear-gradient": "git+https://oauth2:TGi6oBj-LdzsKpLXQSoH@gitlab.mservice.com.vn/momo-platform/public/react-native-linear-gradient#v3.0.0",
|
|
21
|
+
"react-native-reanimated": "4.2.2",
|
|
22
|
+
"react-native-safe-area-context": "5.5.2",
|
|
23
|
+
"@shopify/flash-list": "2.1.0",
|
|
24
|
+
"lottie-react-native": "7.2.4"
|
|
25
|
+
},
|
|
26
|
+
"peerDependencies": {
|
|
27
|
+
"react-native": "*"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/color": "3.0.6"
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"registry": "https://registry.npmjs.org/"
|
|
34
|
+
},
|
|
35
|
+
"license": "MoMo"
|
|
36
|
+
}
|