@momo-kits/foundation 0.167.1-duotest.2 → 0.167.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/Application/BottomSheet.tsx +14 -115
- package/Application/BottomTab/BottomTabBar.tsx +3 -6
- package/Application/BottomTab/index.tsx +135 -162
- package/Application/Components/HeaderExtendHeader.tsx +28 -75
- package/Application/Components/HeaderLeft.tsx +0 -38
- package/Application/Components/HeaderRight.tsx +9 -142
- package/Application/Components/HeaderTitle.tsx +7 -43
- package/Application/Components/SearchHeader.tsx +15 -22
- package/Application/ModalScreen.tsx +2 -16
- package/Application/NavigationContainer.tsx +38 -22
- package/Application/Navigator.ts +3 -1
- package/Application/StackScreen.tsx +9 -63
- package/Application/types.ts +1 -27
- package/Application/utils.tsx +6 -242
- package/Consts/theme.ts +4 -3
- package/Input/Input.tsx +4 -3
- package/Input/InputMoney.tsx +8 -5
- package/Input/InputPhoneNumber.tsx +4 -3
- package/Input/InputSearch.tsx +4 -3
- package/Input/InputTextArea.tsx +4 -3
- package/Layout/Card.tsx +26 -8
- package/Layout/FloatingButton.tsx +3 -3
- package/Layout/GridSystem.tsx +137 -0
- package/Layout/Item.tsx +10 -1
- package/Layout/Screen.tsx +52 -199
- package/Layout/Section.tsx +18 -5
- package/Layout/index.ts +4 -4
- package/Layout/styles.ts +0 -5
- package/Layout/utils.ts +5 -465
- package/Popup/PopupNotify.tsx +22 -33
- package/Popup/PopupPromotion.tsx +8 -20
- package/Text/utils.ts +2 -1
- package/package.json +2 -3
- package/Application/BottomTab/DuoBarCompression.tsx +0 -135
- package/Application/BottomTab/DuoTabBar.tsx +0 -462
- package/Application/Components/DuoGlassBackground.tsx +0 -179
- package/Application/Components/DuoQuickReturnHeader.tsx +0 -42
- package/Application/Components/OptionalGlassView.ts +0 -11
- package/Application/Components/OptionalScrollObserver.ts +0 -12
- package/Application/Components/SideBarButton.tsx +0 -139
- package/Application/device.ts +0 -29
- package/Layout/ReservedRegions.tsx +0 -47
- package/Popup/utils.ts +0 -32
|
@@ -1,24 +1,14 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
useCallback,
|
|
3
|
-
useContext,
|
|
4
|
-
useEffect,
|
|
5
|
-
useRef,
|
|
6
|
-
useState,
|
|
7
|
-
} from 'react';
|
|
1
|
+
import React, { useCallback, useContext, useEffect, useRef } from 'react';
|
|
8
2
|
import {
|
|
9
3
|
BackHandler,
|
|
10
4
|
Dimensions,
|
|
11
|
-
Keyboard,
|
|
12
5
|
KeyboardAvoidingView,
|
|
13
|
-
KeyboardEvent,
|
|
14
|
-
LayoutAnimation,
|
|
15
6
|
Modal,
|
|
16
7
|
PanResponder,
|
|
17
8
|
Platform,
|
|
18
9
|
Pressable,
|
|
19
10
|
StyleSheet,
|
|
20
11
|
TouchableOpacity,
|
|
21
|
-
useWindowDimensions,
|
|
22
12
|
View,
|
|
23
13
|
} from 'react-native';
|
|
24
14
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
@@ -32,38 +22,22 @@ import Animated, {
|
|
|
32
22
|
Easing,
|
|
33
23
|
Extrapolation,
|
|
34
24
|
interpolate,
|
|
25
|
+
runOnJS,
|
|
35
26
|
useAnimatedStyle,
|
|
36
27
|
useSharedValue,
|
|
37
28
|
withSpring,
|
|
38
29
|
withTiming,
|
|
39
30
|
} from 'react-native-reanimated';
|
|
40
|
-
import { scheduleOnRN } from 'react-native-worklets';
|
|
41
31
|
import layoutStyles from '../Layout/styles';
|
|
42
|
-
import { getDuoTopInset, isIPhoneDuo } from './device';
|
|
43
|
-
|
|
44
|
-
// iPhone Duo inner display: center the sheet instead of spanning the width
|
|
45
|
-
const DUO_REGULAR_MIN_WIDTH = 600;
|
|
46
32
|
|
|
47
33
|
const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
48
34
|
const { theme, navigator } = useContext(ApplicationContext);
|
|
49
35
|
const context = useContext<any>(MiniAppContext);
|
|
50
|
-
const
|
|
51
|
-
const isDuo = isIPhoneDuo();
|
|
52
|
-
const isDuoCentered = isDuo && windowSize.width >= DUO_REGULAR_MIN_WIDTH;
|
|
53
|
-
const isPortrait = windowSize.height > windowSize.width;
|
|
54
|
-
// 'screen' is the outer display on iPhone Duo, even when unfolded
|
|
55
|
-
const heightDevice = isDuo
|
|
56
|
-
? windowSize.height
|
|
57
|
-
: Dimensions.get('screen').height;
|
|
36
|
+
const heightDevice = Dimensions.get('screen').height;
|
|
58
37
|
const action = useRef<undefined | string>(undefined);
|
|
59
38
|
const insets = useSafeAreaInsets();
|
|
60
39
|
const heightHeader = useHeaderHeight();
|
|
61
|
-
const
|
|
62
|
-
getDuoTopInset(insets, windowSize.width, windowSize.height),
|
|
63
|
-
Spacing.XL,
|
|
64
|
-
);
|
|
65
|
-
const bottomInset =
|
|
66
|
-
Platform.OS === 'ios' ? Math.min(insets.bottom, 21) : insets.bottom;
|
|
40
|
+
const bottomInset = Platform.OS === 'ios' ? Math.min(insets.bottom, 21) : insets.bottom;
|
|
67
41
|
const keyboardOffset = heightHeader - bottomInset;
|
|
68
42
|
|
|
69
43
|
const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;
|
|
@@ -84,43 +58,6 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
84
58
|
}: BottomSheetParams = props.route.params;
|
|
85
59
|
|
|
86
60
|
const translateY = useSharedValue(heightDevice);
|
|
87
|
-
const [keyboardLift, setKeyboardLift] = useState(0);
|
|
88
|
-
|
|
89
|
-
// KeyboardAvoidingView lifts the whole sheet past the top on iPhone Duo,
|
|
90
|
-
// so lift it here and shrink maxHeight by the same amount instead
|
|
91
|
-
useEffect(() => {
|
|
92
|
-
if (!isDuo || !useKeyboardAvoidingView) {
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
const onKeyboardChange = (e: KeyboardEvent) => {
|
|
96
|
-
const overlap = windowSize.height - e.endCoordinates.screenY;
|
|
97
|
-
const lift = Math.max(
|
|
98
|
-
overlap - bottomInset - (keyboardVerticalOffset ?? 0),
|
|
99
|
-
0,
|
|
100
|
-
);
|
|
101
|
-
if (e.duration) {
|
|
102
|
-
LayoutAnimation.configureNext({
|
|
103
|
-
duration: e.duration,
|
|
104
|
-
update: {
|
|
105
|
-
duration: e.duration,
|
|
106
|
-
type: LayoutAnimation.Types[e.easing] || 'keyboard',
|
|
107
|
-
},
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
setKeyboardLift(lift);
|
|
111
|
-
};
|
|
112
|
-
const subscriptions = [
|
|
113
|
-
Keyboard.addListener('keyboardWillChangeFrame', onKeyboardChange),
|
|
114
|
-
Keyboard.addListener('keyboardWillHide', onKeyboardChange),
|
|
115
|
-
];
|
|
116
|
-
return () => subscriptions.forEach(sub => sub.remove());
|
|
117
|
-
}, [
|
|
118
|
-
bottomInset,
|
|
119
|
-
isDuo,
|
|
120
|
-
keyboardVerticalOffset,
|
|
121
|
-
useKeyboardAvoidingView,
|
|
122
|
-
windowSize.height,
|
|
123
|
-
]);
|
|
124
61
|
|
|
125
62
|
const openAnimation = useCallback(() => {
|
|
126
63
|
translateY.value = withTiming(0, {
|
|
@@ -137,7 +74,7 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
137
74
|
duration: 200,
|
|
138
75
|
easing: Easing.bezier(0.3, 0.0, 0.8, 0.15),
|
|
139
76
|
},
|
|
140
|
-
() =>
|
|
77
|
+
() => runOnJS(callback)(),
|
|
141
78
|
);
|
|
142
79
|
},
|
|
143
80
|
[heightDevice, translateY],
|
|
@@ -200,9 +137,9 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
200
137
|
}
|
|
201
138
|
closeAnimation(() => {
|
|
202
139
|
navigator?.pop();
|
|
203
|
-
|
|
140
|
+
runOnJS(() => {
|
|
204
141
|
callback?.();
|
|
205
|
-
});
|
|
142
|
+
})();
|
|
206
143
|
});
|
|
207
144
|
},
|
|
208
145
|
[barrierDismissible, closeAnimation, navigator],
|
|
@@ -311,23 +248,6 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
311
248
|
};
|
|
312
249
|
});
|
|
313
250
|
|
|
314
|
-
// landscape side buttons span the full height, so inset the content; in
|
|
315
|
-
// portrait the side status bar only covers the top corner
|
|
316
|
-
const sideInsetStyle = isDuo &&
|
|
317
|
-
!isDuoCentered &&
|
|
318
|
-
!isPortrait && {
|
|
319
|
-
paddingLeft: insets.left,
|
|
320
|
-
paddingRight: insets.right,
|
|
321
|
-
};
|
|
322
|
-
|
|
323
|
-
const screen = (
|
|
324
|
-
<Screen
|
|
325
|
-
{...props}
|
|
326
|
-
{...props.route.params}
|
|
327
|
-
onRequestClose={onRequestClose}
|
|
328
|
-
/>
|
|
329
|
-
);
|
|
330
|
-
|
|
331
251
|
return (
|
|
332
252
|
<Container
|
|
333
253
|
transparent
|
|
@@ -344,7 +264,7 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
344
264
|
android: undefined,
|
|
345
265
|
})}
|
|
346
266
|
keyboardVerticalOffset={keyboardVerticalOffset ?? keyboardOffset}
|
|
347
|
-
enabled={useKeyboardAvoidingView
|
|
267
|
+
enabled={useKeyboardAvoidingView}
|
|
348
268
|
contentContainerStyle={styles.container}
|
|
349
269
|
style={styles.container}
|
|
350
270
|
>
|
|
@@ -367,34 +287,15 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
367
287
|
borderTopRightRadius: Radius.M,
|
|
368
288
|
overflow: 'hidden',
|
|
369
289
|
},
|
|
370
|
-
isDuo && {
|
|
371
|
-
maxHeight: windowSize.height - topGap - keyboardLift,
|
|
372
|
-
marginBottom: keyboardLift,
|
|
373
|
-
},
|
|
374
|
-
isDuoCentered && {
|
|
375
|
-
// keeps the portrait width in landscape, like system sheets
|
|
376
|
-
width: Math.min(
|
|
377
|
-
Math.min(windowSize.width, windowSize.height) - Spacing.L * 2,
|
|
378
|
-
windowSize.width -
|
|
379
|
-
Math.max(insets.left, insets.right, Spacing.L) * 2,
|
|
380
|
-
),
|
|
381
|
-
alignSelf: 'center',
|
|
382
|
-
},
|
|
383
290
|
showBaseLineDebug && styles.debugBaseLine,
|
|
384
291
|
]}
|
|
385
292
|
>
|
|
386
|
-
{
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
) : (
|
|
393
|
-
<>
|
|
394
|
-
{renderHeader()}
|
|
395
|
-
{screen}
|
|
396
|
-
</>
|
|
397
|
-
)}
|
|
293
|
+
{renderHeader()}
|
|
294
|
+
<Screen
|
|
295
|
+
{...props}
|
|
296
|
+
{...props.route.params}
|
|
297
|
+
onRequestClose={onRequestClose}
|
|
298
|
+
/>
|
|
398
299
|
{footerComponent && (
|
|
399
300
|
<View
|
|
400
301
|
style={[
|
|
@@ -403,7 +304,6 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
403
304
|
paddingBottom: Spacing.S,
|
|
404
305
|
backgroundColor: theme.colors.background.surface,
|
|
405
306
|
},
|
|
406
|
-
sideInsetStyle,
|
|
407
307
|
]}
|
|
408
308
|
>
|
|
409
309
|
{footerComponent}
|
|
@@ -453,7 +353,6 @@ const styles = StyleSheet.create({
|
|
|
453
353
|
justifyContent: 'center',
|
|
454
354
|
marginHorizontal: Spacing.M,
|
|
455
355
|
},
|
|
456
|
-
shrink: { flexShrink: 1 },
|
|
457
356
|
debugBaseLine: { borderWidth: 1, borderColor: Colors.green_06 },
|
|
458
357
|
});
|
|
459
358
|
|
|
@@ -58,13 +58,11 @@ export default function BottomTabBar({
|
|
|
58
58
|
const { theme } = useContext(ApplicationContext);
|
|
59
59
|
const { routes } = state;
|
|
60
60
|
const widthDevice = useWindowDimensions()?.width;
|
|
61
|
-
const insets = useSafeAreaInsets();
|
|
62
61
|
const useFloating = floatingButton && state.routes.length % 2 === 0;
|
|
63
|
-
const itemWidth =
|
|
64
|
-
(widthDevice - insets.left - insets.right) /
|
|
65
|
-
(state.routes.length + (useFloating ? 1 : 0));
|
|
62
|
+
const itemWidth = widthDevice / (state.routes.length + (useFloating ? 1 : 0));
|
|
66
63
|
// const buildLink = useLinkBuilder();
|
|
67
64
|
const indicatorAnimated = useSharedValue(0);
|
|
65
|
+
const insets = useSafeAreaInsets();
|
|
68
66
|
|
|
69
67
|
const indicatorStyle = useAnimatedStyle(() => ({
|
|
70
68
|
width: itemWidth,
|
|
@@ -248,8 +246,7 @@ export default function BottomTabBar({
|
|
|
248
246
|
},
|
|
249
247
|
{
|
|
250
248
|
paddingBottom: paddingBottom,
|
|
251
|
-
|
|
252
|
-
paddingRight: insets.right,
|
|
249
|
+
paddingHorizontal: Math.max(insets.left, insets.right),
|
|
253
250
|
},
|
|
254
251
|
style,
|
|
255
252
|
]}
|
|
@@ -27,15 +27,7 @@ import StackScreen from '../StackScreen';
|
|
|
27
27
|
import { BottomTabProps } from '../types';
|
|
28
28
|
import { getOptions, getStackOptions, useAppState } from '../utils';
|
|
29
29
|
import BottomTabBar from './BottomTabBar';
|
|
30
|
-
import {
|
|
31
|
-
import { DuoBarCompressionProvider } from './DuoBarCompression';
|
|
32
|
-
import {
|
|
33
|
-
ApplicationContext,
|
|
34
|
-
MiniAppContext,
|
|
35
|
-
ScreenContext,
|
|
36
|
-
} from '../../Context';
|
|
37
|
-
import { useScreenLayout } from '../../Layout';
|
|
38
|
-
import { getHeaderRowOptions } from '../../Layout/utils';
|
|
30
|
+
import { ApplicationContext, MiniAppContext } from '../../Context';
|
|
39
31
|
|
|
40
32
|
const Tab = createBottomTabNavigator();
|
|
41
33
|
const Stack = createStackNavigator();
|
|
@@ -44,7 +36,7 @@ const TabScreen: React.FC<any> = ({ route, navigation }) => {
|
|
|
44
36
|
const { navigator } = useContext(ApplicationContext);
|
|
45
37
|
const context = useContext<any>(MiniAppContext);
|
|
46
38
|
const { nested, options, screen, initialParams } = route?.params;
|
|
47
|
-
const
|
|
39
|
+
const insets = useSafeAreaInsets();
|
|
48
40
|
|
|
49
41
|
const opacityValue = 0.3;
|
|
50
42
|
const scaleValue = 0.97;
|
|
@@ -147,7 +139,11 @@ const TabScreen: React.FC<any> = ({ route, navigation }) => {
|
|
|
147
139
|
return (
|
|
148
140
|
<Animated.View style={[styles.container, tabAnimatedStyle]}>
|
|
149
141
|
<Stack.Navigator
|
|
150
|
-
screenOptions={
|
|
142
|
+
screenOptions={{
|
|
143
|
+
headerStyle: {
|
|
144
|
+
height: 52 + insets.top,
|
|
145
|
+
},
|
|
146
|
+
}}
|
|
151
147
|
>
|
|
152
148
|
<Stack.Screen
|
|
153
149
|
name="Stack"
|
|
@@ -178,7 +174,11 @@ const TabScreen: React.FC<any> = ({ route, navigation }) => {
|
|
|
178
174
|
<NavigationIndependentTree>
|
|
179
175
|
<NavigationContainer>
|
|
180
176
|
<Stack.Navigator
|
|
181
|
-
screenOptions={
|
|
177
|
+
screenOptions={{
|
|
178
|
+
headerStyle: {
|
|
179
|
+
height: 52 + insets.top,
|
|
180
|
+
},
|
|
181
|
+
}}
|
|
182
182
|
>
|
|
183
183
|
<Stack.Screen
|
|
184
184
|
name="Stack"
|
|
@@ -205,17 +205,8 @@ const BottomTab: React.FC<BottomTabProps> = ({
|
|
|
205
205
|
navigation,
|
|
206
206
|
initialRouteName,
|
|
207
207
|
floatingButton,
|
|
208
|
-
compressionBehavior,
|
|
209
208
|
}) => {
|
|
210
209
|
const { theme, navigator } = useContext(ApplicationContext);
|
|
211
|
-
const screen: any = useContext(ScreenContext);
|
|
212
|
-
const { isIPhoneDuo } = useScreenLayout();
|
|
213
|
-
// each tab lays itself out, the hosting stack screen must not add a header or insets
|
|
214
|
-
screen?.claimHeader?.();
|
|
215
|
-
useEffect(() => {
|
|
216
|
-
screen?.syncHeader?.();
|
|
217
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
218
|
-
}, []);
|
|
219
210
|
const dimensions = useWindowDimensions();
|
|
220
211
|
const insets = useSafeAreaInsets();
|
|
221
212
|
const initialIndex = tabs.findIndex(i => i.name === initialRouteName);
|
|
@@ -289,156 +280,138 @@ const BottomTab: React.FC<BottomTabProps> = ({
|
|
|
289
280
|
};
|
|
290
281
|
|
|
291
282
|
return (
|
|
292
|
-
<
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
283
|
+
<Tab.Navigator
|
|
284
|
+
screenOptions={{
|
|
285
|
+
headerShown: false,
|
|
286
|
+
headerTransparent: true,
|
|
287
|
+
headerBackground: undefined,
|
|
288
|
+
tabBarLabelPosition: 'below-icon',
|
|
289
|
+
tabBarBackground: () => (
|
|
290
|
+
<View
|
|
291
|
+
style={[
|
|
292
|
+
styles.container,
|
|
293
|
+
{
|
|
294
|
+
backgroundColor: theme.colors.background.surface,
|
|
295
|
+
},
|
|
296
|
+
]}
|
|
297
|
+
>
|
|
298
|
+
<Animated.View style={[styles.indicatorContainer, indicatorStyle]}>
|
|
299
|
+
<View
|
|
300
|
+
style={[
|
|
301
|
+
styles.indicator,
|
|
302
|
+
{ backgroundColor: theme.colors.primary },
|
|
303
|
+
]}
|
|
304
|
+
/>
|
|
305
|
+
</Animated.View>
|
|
306
|
+
</View>
|
|
307
|
+
),
|
|
308
|
+
}}
|
|
309
|
+
tabBar={props => (
|
|
310
|
+
<BottomTabBar
|
|
311
|
+
{...props}
|
|
312
|
+
floatingButton={floatingButton}
|
|
313
|
+
inactiveTintColor={theme.colors.text.hint}
|
|
314
|
+
activeTintColor={theme.colors.primary}
|
|
315
|
+
style={[
|
|
316
|
+
{
|
|
317
|
+
height:
|
|
318
|
+
64 +
|
|
319
|
+
(Platform.OS === 'ios'
|
|
320
|
+
? Math.min(insets.bottom, 21)
|
|
321
|
+
: insets.bottom),
|
|
322
|
+
},
|
|
323
|
+
]}
|
|
324
|
+
/>
|
|
325
|
+
)}
|
|
326
|
+
initialRouteName={initialRouteName}
|
|
296
327
|
>
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
style={[
|
|
306
|
-
styles.container,
|
|
307
|
-
{
|
|
308
|
-
backgroundColor: theme.colors.background.surface,
|
|
309
|
-
},
|
|
310
|
-
]}
|
|
311
|
-
>
|
|
312
|
-
<Animated.View
|
|
313
|
-
style={[styles.indicatorContainer, indicatorStyle]}
|
|
314
|
-
>
|
|
315
|
-
<View
|
|
316
|
-
style={[
|
|
317
|
-
styles.indicator,
|
|
318
|
-
{ backgroundColor: theme.colors.primary },
|
|
319
|
-
]}
|
|
320
|
-
/>
|
|
321
|
-
</Animated.View>
|
|
322
|
-
</View>
|
|
323
|
-
),
|
|
324
|
-
}}
|
|
325
|
-
tabBar={props =>
|
|
326
|
-
isIPhoneDuo ? (
|
|
327
|
-
<DuoTabBar
|
|
328
|
-
{...props}
|
|
329
|
-
floatingButton={floatingButton}
|
|
330
|
-
inactiveTintColor={theme.colors.text.default}
|
|
331
|
-
activeTintColor={theme.colors.primary}
|
|
332
|
-
/>
|
|
333
|
-
) : (
|
|
334
|
-
<BottomTabBar
|
|
335
|
-
{...props}
|
|
336
|
-
floatingButton={floatingButton}
|
|
337
|
-
inactiveTintColor={theme.colors.text.hint}
|
|
338
|
-
activeTintColor={theme.colors.primary}
|
|
339
|
-
style={[
|
|
340
|
-
{
|
|
341
|
-
height:
|
|
342
|
-
64 +
|
|
343
|
-
(Platform.OS === 'ios'
|
|
344
|
-
? Math.min(insets.bottom, 21)
|
|
345
|
-
: insets.bottom),
|
|
346
|
-
},
|
|
347
|
-
]}
|
|
348
|
-
/>
|
|
349
|
-
)
|
|
328
|
+
{tabs.map((item, index) => {
|
|
329
|
+
const isNum = !isNaN(parseInt(`${item?.badgeLabel}`, 10));
|
|
330
|
+
const isDot = typeof item?.badgeLabel === 'string' && !item?.badgeLabel;
|
|
331
|
+
const isNumZero = isNum && Number(item.badgeLabel) === 0;
|
|
332
|
+
|
|
333
|
+
let badgeLabel = item?.badgeLabel;
|
|
334
|
+
if (isNumZero) {
|
|
335
|
+
badgeLabel = undefined;
|
|
350
336
|
}
|
|
351
|
-
initialRouteName={initialRouteName}
|
|
352
|
-
>
|
|
353
|
-
{tabs.map((item, index) => {
|
|
354
|
-
const isNum = !isNaN(parseInt(`${item?.badgeLabel}`, 10));
|
|
355
|
-
const isDot =
|
|
356
|
-
typeof item?.badgeLabel === 'string' && !item?.badgeLabel;
|
|
357
|
-
const isNumZero = isNum && Number(item.badgeLabel) === 0;
|
|
358
337
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
338
|
+
let badgeStyle: {
|
|
339
|
+
marginRight: number;
|
|
340
|
+
top: number;
|
|
341
|
+
backgroundColor: string;
|
|
342
|
+
width?: number;
|
|
343
|
+
} = {
|
|
344
|
+
marginRight: -8,
|
|
345
|
+
top: -4,
|
|
346
|
+
backgroundColor: Colors.orange_03,
|
|
347
|
+
};
|
|
363
348
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
backgroundColor: string;
|
|
368
|
-
width?: number;
|
|
369
|
-
} = {
|
|
370
|
-
marginRight: -8,
|
|
349
|
+
if (isNum) {
|
|
350
|
+
badgeStyle = {
|
|
351
|
+
marginRight: -4,
|
|
371
352
|
top: -4,
|
|
353
|
+
backgroundColor: Colors.red_03,
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
if (isDot) {
|
|
357
|
+
badgeStyle = {
|
|
358
|
+
marginRight: -2,
|
|
359
|
+
top: -2,
|
|
372
360
|
backgroundColor: Colors.orange_03,
|
|
361
|
+
width: 12,
|
|
373
362
|
};
|
|
363
|
+
}
|
|
374
364
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
return (
|
|
401
|
-
<Text
|
|
402
|
-
numberOfLines={1}
|
|
403
|
-
typography={
|
|
404
|
-
focused ? 'label_xs_medium' : 'description_xs_regular'
|
|
405
|
-
}
|
|
406
|
-
color={color}
|
|
407
|
-
>
|
|
408
|
-
{item.label}
|
|
409
|
-
</Text>
|
|
410
|
-
);
|
|
365
|
+
return (
|
|
366
|
+
<Tab.Screen
|
|
367
|
+
key={`BottomTab-${item.name}`}
|
|
368
|
+
name={item.name}
|
|
369
|
+
component={TabScreen}
|
|
370
|
+
initialParams={{ ...item, nested, index }}
|
|
371
|
+
listeners={handler}
|
|
372
|
+
options={{
|
|
373
|
+
tabBarLabel: ({ focused, color }) => {
|
|
374
|
+
return (
|
|
375
|
+
<Text
|
|
376
|
+
numberOfLines={1}
|
|
377
|
+
typography={
|
|
378
|
+
focused ? 'label_xs_medium' : 'description_xs_regular'
|
|
379
|
+
}
|
|
380
|
+
color={color}
|
|
381
|
+
>
|
|
382
|
+
{item.label}
|
|
383
|
+
</Text>
|
|
384
|
+
);
|
|
385
|
+
},
|
|
386
|
+
title: item.label,
|
|
387
|
+
tabBarStyle: [
|
|
388
|
+
{
|
|
389
|
+
height: 64,
|
|
411
390
|
},
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
}}
|
|
437
|
-
/>
|
|
438
|
-
);
|
|
439
|
-
})}
|
|
440
|
-
</Tab.Navigator>
|
|
441
|
-
</DuoBarCompressionProvider>
|
|
391
|
+
styles.tabStyle,
|
|
392
|
+
],
|
|
393
|
+
tabBarBadge: badgeLabel,
|
|
394
|
+
tabBarBadgeStyle: [
|
|
395
|
+
{
|
|
396
|
+
borderColor: 'white',
|
|
397
|
+
borderWidth: 2,
|
|
398
|
+
fontSize: 10,
|
|
399
|
+
lineHeight: 14,
|
|
400
|
+
fontWeight: 'bold',
|
|
401
|
+
alignSelf: 'center',
|
|
402
|
+
fontFamily: exportFontFamily('bold'),
|
|
403
|
+
},
|
|
404
|
+
badgeStyle,
|
|
405
|
+
],
|
|
406
|
+
tabBarIcon: ({ color }) => (
|
|
407
|
+
<Icon source={item.icon} color={color} size={28} />
|
|
408
|
+
),
|
|
409
|
+
...item,
|
|
410
|
+
}}
|
|
411
|
+
/>
|
|
412
|
+
);
|
|
413
|
+
})}
|
|
414
|
+
</Tab.Navigator>
|
|
442
415
|
);
|
|
443
416
|
};
|
|
444
417
|
|