@momo-kits/foundation 0.168.1-beta.35 → 0.168.1-beta.37
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.hooks.ts +17 -37
- package/Application/BottomSheet.parts.tsx +81 -165
- package/Application/BottomSheet.styles.ts +7 -23
- package/Application/BottomSheet.tsx +61 -252
- package/Application/BottomTab/BottomTabBar.styles.ts +65 -0
- package/Application/BottomTab/BottomTabBar.tsx +4 -72
- package/Application/BottomTab/DuoRailTabBar.tsx +227 -0
- package/Application/BottomTab/DuoTabBar.styles.ts +81 -0
- package/Application/BottomTab/DuoTabBar.tsx +12 -305
- package/Application/BottomTab/TabScreen.tsx +164 -0
- package/Application/BottomTab/index.tsx +8 -165
- package/Application/ModalScreen.tsx +1 -1
- package/Application/index.ts +6 -2
- package/Application/modalLayout.ts +2 -5
- package/Application/types.tabs.ts +5 -0
- package/Application/types.ts +12 -247
- package/Application/utils.ts +0 -36
- package/Layout/Screen.tsx +63 -648
- package/Layout/index.ts +8 -3
- package/Layout/screenContent.tsx +90 -0
- package/Layout/screenFooter.tsx +53 -0
- package/Layout/screenHeader.tsx +315 -0
- package/Layout/screenQuickReturn.tsx +67 -0
- package/Layout/screenScroll.ts +110 -0
- package/Layout/screenTypes.ts +134 -0
- package/package.json +1 -1
- package/Application/device.ts +0 -21
|
@@ -1,65 +1,50 @@
|
|
|
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
|
-
BackHandler,
|
|
10
|
-
Dimensions,
|
|
11
|
-
Keyboard,
|
|
12
3
|
KeyboardAvoidingView,
|
|
13
|
-
KeyboardEvent,
|
|
14
|
-
LayoutAnimation,
|
|
15
4
|
Modal,
|
|
16
5
|
PanResponder,
|
|
17
6
|
Platform,
|
|
18
7
|
Pressable,
|
|
19
8
|
StyleSheet,
|
|
20
|
-
useWindowDimensions,
|
|
21
9
|
View,
|
|
22
10
|
} from 'react-native';
|
|
23
|
-
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
24
11
|
import { ApplicationContext, MiniAppContext } from '../Context';
|
|
25
12
|
import { BottomSheetParams } from './types';
|
|
26
|
-
import { Colors, Radius, Spacing, Styles } from '../Consts';
|
|
27
|
-
import { Text } from '../Text';
|
|
28
|
-
import { useHeaderHeight } from '@react-navigation/elements';
|
|
29
13
|
import Animated, {
|
|
30
14
|
Easing,
|
|
31
|
-
Extrapolation,
|
|
32
|
-
interpolate,
|
|
33
|
-
useAnimatedStyle,
|
|
34
15
|
useSharedValue,
|
|
35
16
|
withSpring,
|
|
36
17
|
withTiming,
|
|
37
18
|
} from 'react-native-reanimated';
|
|
38
19
|
import { scheduleOnRN } from 'react-native-worklets';
|
|
39
|
-
import
|
|
40
|
-
import {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
20
|
+
import { DUO_ORIENTATIONS, styles } from './BottomSheet.styles';
|
|
21
|
+
import {
|
|
22
|
+
useBottomSheetLayout,
|
|
23
|
+
useDuoKeyboardLift,
|
|
24
|
+
useSheetDismiss,
|
|
25
|
+
useSheetAnimatedStyles,
|
|
26
|
+
} from './BottomSheet.hooks';
|
|
27
|
+
import {
|
|
28
|
+
getSheetStyle,
|
|
29
|
+
renderSheetFooter,
|
|
30
|
+
renderSheetHeader,
|
|
31
|
+
} from './BottomSheet.parts';
|
|
47
32
|
|
|
48
33
|
const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
49
34
|
const { theme, navigator } = useContext(ApplicationContext);
|
|
50
35
|
const context = useContext<any>(MiniAppContext);
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
36
|
+
const {
|
|
37
|
+
windowSize,
|
|
38
|
+
isDuo,
|
|
39
|
+
isFoldable,
|
|
40
|
+
placement,
|
|
41
|
+
sheet,
|
|
42
|
+
scrimOpacity,
|
|
43
|
+
heightDevice,
|
|
44
|
+
bottomInset,
|
|
45
|
+
keyboardOffset,
|
|
46
|
+
} = useBottomSheetLayout();
|
|
57
47
|
const action = useRef<undefined | string>(undefined);
|
|
58
|
-
const insets = useSafeAreaInsets();
|
|
59
|
-
const heightHeader = useHeaderHeight();
|
|
60
|
-
const isIOS = Platform.OS === 'ios';
|
|
61
|
-
const bottomInset = isIOS ? Math.min(insets.bottom, 21) : insets.bottom;
|
|
62
|
-
const keyboardOffset = heightHeader - bottomInset;
|
|
63
48
|
|
|
64
49
|
const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;
|
|
65
50
|
|
|
@@ -81,43 +66,13 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
81
66
|
const translateY = useSharedValue(heightDevice);
|
|
82
67
|
const onDismissRef = useRef(props.route.params?.onDismiss);
|
|
83
68
|
onDismissRef.current = props.route.params?.onDismiss;
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
// KeyboardAvoidingView lifts the whole sheet past the top on iPhone Duo,
|
|
87
|
-
// so lift it here and shrink maxHeight by the same amount instead
|
|
88
|
-
useEffect(() => {
|
|
89
|
-
if (!isDuo || !useKeyboardAvoidingView) {
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
const onKeyboardChange = (e: KeyboardEvent) => {
|
|
93
|
-
const overlap = windowSize.height - e.endCoordinates.screenY;
|
|
94
|
-
const lift = Math.max(
|
|
95
|
-
overlap - bottomInset - (keyboardVerticalOffset ?? 0),
|
|
96
|
-
0,
|
|
97
|
-
);
|
|
98
|
-
if (e.duration) {
|
|
99
|
-
LayoutAnimation.configureNext({
|
|
100
|
-
duration: e.duration,
|
|
101
|
-
update: {
|
|
102
|
-
duration: e.duration,
|
|
103
|
-
type: LayoutAnimation.Types[e.easing] || 'keyboard',
|
|
104
|
-
},
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
setKeyboardLift(lift);
|
|
108
|
-
};
|
|
109
|
-
const subscriptions = [
|
|
110
|
-
Keyboard.addListener('keyboardWillChangeFrame', onKeyboardChange),
|
|
111
|
-
Keyboard.addListener('keyboardWillHide', onKeyboardChange),
|
|
112
|
-
];
|
|
113
|
-
return () => subscriptions.forEach(sub => sub.remove());
|
|
114
|
-
}, [
|
|
115
|
-
bottomInset,
|
|
69
|
+
const keyboardLift = useDuoKeyboardLift(
|
|
116
70
|
isDuo,
|
|
117
|
-
keyboardVerticalOffset,
|
|
118
71
|
useKeyboardAvoidingView,
|
|
119
72
|
windowSize.height,
|
|
120
|
-
|
|
73
|
+
bottomInset,
|
|
74
|
+
keyboardVerticalOffset,
|
|
75
|
+
);
|
|
121
76
|
|
|
122
77
|
const openAnimation = useCallback(() => {
|
|
123
78
|
translateY.value = withTiming(0, {
|
|
@@ -187,126 +142,35 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
187
142
|
};
|
|
188
143
|
}, [openAnimation]);
|
|
189
144
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
closeAnimation(() => {
|
|
199
|
-
navigator?.pop();
|
|
200
|
-
scheduleOnRN(() => {
|
|
201
|
-
callback?.();
|
|
202
|
-
});
|
|
203
|
-
});
|
|
204
|
-
},
|
|
205
|
-
[barrierDismissible, closeAnimation, navigator],
|
|
206
|
-
);
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* on request close
|
|
210
|
-
*/
|
|
211
|
-
const onRequestClose = useCallback(
|
|
212
|
-
(callback?: () => void) => {
|
|
213
|
-
onDismiss(true, callback);
|
|
214
|
-
},
|
|
215
|
-
[onDismiss],
|
|
216
|
-
);
|
|
217
|
-
|
|
218
|
-
useEffect(() => {
|
|
219
|
-
const backHandler = BackHandler.addEventListener(
|
|
220
|
-
'hardwareBackPress',
|
|
221
|
-
() => {
|
|
222
|
-
onDismiss();
|
|
223
|
-
return true;
|
|
224
|
-
},
|
|
225
|
-
);
|
|
226
|
-
return () => backHandler.remove();
|
|
227
|
-
}, [barrierDismissible, onDismiss]);
|
|
228
|
-
|
|
229
|
-
const onPressBack = useCallback(() => {
|
|
230
|
-
onDismiss(true, leftOptions?.onPressIconLeft);
|
|
231
|
-
}, [leftOptions, onDismiss]);
|
|
232
|
-
|
|
233
|
-
const onPressClose = useCallback(() => {
|
|
234
|
-
action.current = 'icon_close';
|
|
235
|
-
onDismiss(true);
|
|
236
|
-
}, [onDismiss]);
|
|
145
|
+
const { onDismiss, onRequestClose, onPressBack, onPressClose } =
|
|
146
|
+
useSheetDismiss({
|
|
147
|
+
barrierDismissible,
|
|
148
|
+
closeAnimation,
|
|
149
|
+
navigator,
|
|
150
|
+
leftOptions,
|
|
151
|
+
action,
|
|
152
|
+
});
|
|
237
153
|
|
|
238
154
|
const showBack = !!leftOptions?.onPressIconLeft;
|
|
239
155
|
const iconBack = leftOptions?.iconLeft ?? 'ic_back';
|
|
240
156
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
<View {...panResponder.panHandlers}>
|
|
247
|
-
<View style={{ height: INDICATOR_HEIGHT }}>
|
|
248
|
-
<View style={styles.indicator} />
|
|
249
|
-
</View>
|
|
250
|
-
<View
|
|
251
|
-
style={[
|
|
252
|
-
styles.header,
|
|
253
|
-
useDivider && {
|
|
254
|
-
borderBottomColor: theme.colors.border.default,
|
|
255
|
-
borderBottomWidth: 1,
|
|
256
|
-
},
|
|
257
|
-
]}
|
|
258
|
-
>
|
|
259
|
-
{showBack ? (
|
|
260
|
-
<ModalIconButton icon={iconBack} onPress={onPressBack} />
|
|
261
|
-
) : null}
|
|
262
|
-
|
|
263
|
-
{options.header ? (
|
|
264
|
-
<View style={Styles.flex}>{options.header}</View>
|
|
265
|
-
) : (
|
|
266
|
-
<>
|
|
267
|
-
{!leftOptions ? <View style={styles.iconButtonSpace} /> : null}
|
|
268
|
-
<Text
|
|
269
|
-
style={[Styles.flex, styles.title]}
|
|
270
|
-
numberOfLines={1}
|
|
271
|
-
typography="header_default_bold"
|
|
272
|
-
>
|
|
273
|
-
{options.title ?? ''}
|
|
274
|
-
</Text>
|
|
275
|
-
</>
|
|
276
|
-
)}
|
|
277
|
-
<ModalIconButton icon="navigation_close" onPress={onPressClose} />
|
|
278
|
-
</View>
|
|
279
|
-
</View>
|
|
280
|
-
);
|
|
281
|
-
}, [
|
|
282
|
-
iconBack,
|
|
283
|
-
leftOptions,
|
|
157
|
+
const headerParams = {
|
|
158
|
+
panHandlers: panResponder.panHandlers,
|
|
159
|
+
useDivider,
|
|
160
|
+
theme,
|
|
161
|
+
showBack,
|
|
284
162
|
onPressBack,
|
|
285
163
|
onPressClose,
|
|
286
|
-
|
|
287
|
-
options
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
theme.colors.border.default,
|
|
291
|
-
useDivider,
|
|
292
|
-
]);
|
|
293
|
-
|
|
294
|
-
const animatedStyle = useAnimatedStyle(() => {
|
|
295
|
-
return {
|
|
296
|
-
transform: [{ translateY: translateY.value }],
|
|
297
|
-
};
|
|
298
|
-
});
|
|
164
|
+
iconBack,
|
|
165
|
+
options,
|
|
166
|
+
leftOptions,
|
|
167
|
+
};
|
|
299
168
|
|
|
300
|
-
const animatedOverlayStyle =
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
[scrimOpacity, 0],
|
|
306
|
-
Extrapolation.CLAMP,
|
|
307
|
-
),
|
|
308
|
-
};
|
|
309
|
-
});
|
|
169
|
+
const { animatedStyle, animatedOverlayStyle } = useSheetAnimatedStyles(
|
|
170
|
+
translateY,
|
|
171
|
+
heightDevice,
|
|
172
|
+
scrimOpacity,
|
|
173
|
+
);
|
|
310
174
|
|
|
311
175
|
const screen = (
|
|
312
176
|
<Screen
|
|
@@ -350,51 +214,30 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
350
214
|
<Animated.View
|
|
351
215
|
style={[
|
|
352
216
|
animatedStyle,
|
|
353
|
-
{
|
|
217
|
+
getSheetStyle({
|
|
354
218
|
backgroundColor,
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
sheet.maxHeight !== undefined && {
|
|
363
|
-
// centered in the placement area, clear of the iPhone Duo
|
|
364
|
-
// control column and on the right half when half folded
|
|
365
|
-
width: sheet.width,
|
|
366
|
-
marginLeft: placement.x + (placement.width - sheet.width) / 2,
|
|
367
|
-
maxHeight: sheet.maxHeight - keyboardLift,
|
|
368
|
-
minHeight: sheet.minHeight,
|
|
369
|
-
},
|
|
370
|
-
showBaseLineDebug && styles.debugBaseLine,
|
|
219
|
+
isDuo,
|
|
220
|
+
isFoldable,
|
|
221
|
+
placement,
|
|
222
|
+
sheet,
|
|
223
|
+
keyboardLift,
|
|
224
|
+
showBaseLineDebug,
|
|
225
|
+
}),
|
|
371
226
|
]}
|
|
372
227
|
>
|
|
373
228
|
{isFoldable ? (
|
|
374
229
|
// content shrinks so a tall sheet keeps its header and footer
|
|
375
230
|
<View style={styles.shrink}>
|
|
376
|
-
{
|
|
231
|
+
{renderSheetHeader(headerParams)}
|
|
377
232
|
<View style={styles.shrink}>{screen}</View>
|
|
378
233
|
</View>
|
|
379
234
|
) : (
|
|
380
235
|
<>
|
|
381
|
-
{
|
|
236
|
+
{renderSheetHeader(headerParams)}
|
|
382
237
|
{screen}
|
|
383
238
|
</>
|
|
384
239
|
)}
|
|
385
|
-
{footerComponent
|
|
386
|
-
<View
|
|
387
|
-
style={[
|
|
388
|
-
layoutStyles.shadow,
|
|
389
|
-
{
|
|
390
|
-
paddingBottom: Spacing.S,
|
|
391
|
-
backgroundColor: theme.colors.background.surface,
|
|
392
|
-
},
|
|
393
|
-
]}
|
|
394
|
-
>
|
|
395
|
-
{footerComponent}
|
|
396
|
-
</View>
|
|
397
|
-
)}
|
|
240
|
+
{renderSheetFooter({ footerComponent, theme })}
|
|
398
241
|
{useBottomInset && (
|
|
399
242
|
<View
|
|
400
243
|
style={{
|
|
@@ -409,38 +252,4 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
409
252
|
);
|
|
410
253
|
};
|
|
411
254
|
|
|
412
|
-
const styles = StyleSheet.create({
|
|
413
|
-
container: {
|
|
414
|
-
flex: 1,
|
|
415
|
-
justifyContent: 'flex-end',
|
|
416
|
-
},
|
|
417
|
-
overlay: {
|
|
418
|
-
flex: 1,
|
|
419
|
-
backgroundColor: Colors.black_20,
|
|
420
|
-
},
|
|
421
|
-
indicator: {
|
|
422
|
-
width: 40,
|
|
423
|
-
height: 4,
|
|
424
|
-
borderRadius: Radius.S,
|
|
425
|
-
backgroundColor: Colors.black_06,
|
|
426
|
-
position: 'absolute',
|
|
427
|
-
alignSelf: 'center',
|
|
428
|
-
top: Spacing.S,
|
|
429
|
-
},
|
|
430
|
-
header: {
|
|
431
|
-
height: HEADER_HEIGHT,
|
|
432
|
-
flexDirection: 'row',
|
|
433
|
-
alignItems: 'center',
|
|
434
|
-
paddingHorizontal: Spacing.M,
|
|
435
|
-
gap: Spacing.S,
|
|
436
|
-
},
|
|
437
|
-
title: { textAlign: 'center' },
|
|
438
|
-
iconButtonSpace: {
|
|
439
|
-
width: MODAL_ICON_BUTTON_SIZE,
|
|
440
|
-
height: MODAL_ICON_BUTTON_SIZE,
|
|
441
|
-
},
|
|
442
|
-
shrink: { flexShrink: 1 },
|
|
443
|
-
debugBaseLine: { borderWidth: 1, borderColor: Colors.green_06 },
|
|
444
|
-
});
|
|
445
|
-
|
|
446
255
|
export default BottomSheet;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
import { Colors, Spacing } from '../../Consts';
|
|
3
|
+
import { CTA_SHADOW, TabBarMetrics } from './metrics';
|
|
4
|
+
|
|
5
|
+
export const styles = StyleSheet.create({
|
|
6
|
+
bar: {
|
|
7
|
+
position: 'absolute',
|
|
8
|
+
left: 0,
|
|
9
|
+
right: 0,
|
|
10
|
+
bottom: 0,
|
|
11
|
+
alignItems: 'center',
|
|
12
|
+
},
|
|
13
|
+
// transparent strip that keeps the rising center action touchable
|
|
14
|
+
barCtaRise: {
|
|
15
|
+
paddingTop: TabBarMetrics.ctaLift,
|
|
16
|
+
},
|
|
17
|
+
container: {
|
|
18
|
+
height: TabBarMetrics.height,
|
|
19
|
+
},
|
|
20
|
+
content: {
|
|
21
|
+
flex: 1,
|
|
22
|
+
flexDirection: 'row',
|
|
23
|
+
alignItems: 'center',
|
|
24
|
+
gap: TabBarMetrics.itemGap,
|
|
25
|
+
paddingVertical: TabBarMetrics.paddingVertical,
|
|
26
|
+
paddingHorizontal: TabBarMetrics.paddingHorizontal,
|
|
27
|
+
},
|
|
28
|
+
indicator: {
|
|
29
|
+
height: TabBarMetrics.indicatorHeight,
|
|
30
|
+
},
|
|
31
|
+
ctaSlot: {
|
|
32
|
+
width: TabBarMetrics.ctaSlotWidth,
|
|
33
|
+
alignSelf: 'stretch',
|
|
34
|
+
},
|
|
35
|
+
// the button rises ctaLift above the container top, the label ends on the item baseline
|
|
36
|
+
cta: {
|
|
37
|
+
position: 'absolute',
|
|
38
|
+
left: 0,
|
|
39
|
+
right: 0,
|
|
40
|
+
top: -TabBarMetrics.ctaLift - TabBarMetrics.paddingVertical,
|
|
41
|
+
alignItems: 'center',
|
|
42
|
+
gap: TabBarMetrics.ctaLabelGap,
|
|
43
|
+
},
|
|
44
|
+
ctaButton: {
|
|
45
|
+
boxShadow: CTA_SHADOW,
|
|
46
|
+
width: TabBarMetrics.ctaSize,
|
|
47
|
+
height: TabBarMetrics.ctaSize,
|
|
48
|
+
borderRadius: TabBarMetrics.ctaSize / 2,
|
|
49
|
+
alignItems: 'center',
|
|
50
|
+
justifyContent: 'center',
|
|
51
|
+
},
|
|
52
|
+
// custom label content over the label text, centered and unclipped
|
|
53
|
+
ctaLabelOverlay: {
|
|
54
|
+
...StyleSheet.absoluteFillObject,
|
|
55
|
+
alignItems: 'center',
|
|
56
|
+
justifyContent: 'center',
|
|
57
|
+
},
|
|
58
|
+
ctaLabel: {
|
|
59
|
+
maxWidth: TabBarMetrics.ctaSlotWidth,
|
|
60
|
+
minHeight: TabBarMetrics.ctaLabelHeight,
|
|
61
|
+
paddingHorizontal: Spacing.XXS,
|
|
62
|
+
justifyContent: 'center',
|
|
63
|
+
},
|
|
64
|
+
debugBaseLine: { borderWidth: 1, borderColor: Colors.green_06 },
|
|
65
|
+
});
|
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import { BottomTabBarProps } from '@react-navigation/bottom-tabs';
|
|
2
2
|
import React, { useContext, useState } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
Platform,
|
|
5
|
-
Pressable,
|
|
6
|
-
StyleSheet,
|
|
7
|
-
useWindowDimensions,
|
|
8
|
-
View,
|
|
9
|
-
} from 'react-native';
|
|
3
|
+
import { Platform, Pressable, useWindowDimensions, View } from 'react-native';
|
|
10
4
|
import Animated, {
|
|
11
5
|
useAnimatedStyle,
|
|
12
6
|
useSharedValue,
|
|
@@ -21,14 +15,10 @@ import CustomBottomTabItem from './CustomBottomTabItem';
|
|
|
21
15
|
import { ApplicationContext, MiniAppContext } from '../../Context';
|
|
22
16
|
import { CurvedContainer } from './CurvedContainer';
|
|
23
17
|
import { ActiveIndicator } from './ActiveIndicator';
|
|
24
|
-
import {
|
|
25
|
-
CTA_SHADOW,
|
|
26
|
-
getHorizontalBarWidth,
|
|
27
|
-
TabBarMetrics,
|
|
28
|
-
TabBarMotion,
|
|
29
|
-
} from './metrics';
|
|
18
|
+
import { getHorizontalBarWidth, TabBarMetrics, TabBarMotion } from './metrics';
|
|
30
19
|
import { getTabItems, TabItem } from './tabItems';
|
|
31
20
|
import { FixedScaleText } from './TabBarIcon';
|
|
21
|
+
import { styles } from './BottomTabBar.styles';
|
|
32
22
|
|
|
33
23
|
type Props = BottomTabBarProps & {
|
|
34
24
|
activeTintColor: string;
|
|
@@ -258,8 +248,8 @@ export default function BottomTabBar(props: Props) {
|
|
|
258
248
|
pointerEvents={'box-none'}
|
|
259
249
|
style={[
|
|
260
250
|
styles.bar,
|
|
251
|
+
withCta && styles.barCtaRise,
|
|
261
252
|
{
|
|
262
|
-
paddingTop: withCta ? TabBarMetrics.ctaLift : 0,
|
|
263
253
|
paddingBottom: getSystemIndicatorHeight(insets.bottom),
|
|
264
254
|
// centered between the side safe areas
|
|
265
255
|
paddingLeft: insets.left,
|
|
@@ -278,64 +268,6 @@ export default function BottomTabBar(props: Props) {
|
|
|
278
268
|
);
|
|
279
269
|
}
|
|
280
270
|
|
|
281
|
-
const styles = StyleSheet.create({
|
|
282
|
-
bar: {
|
|
283
|
-
position: 'absolute',
|
|
284
|
-
left: 0,
|
|
285
|
-
right: 0,
|
|
286
|
-
bottom: 0,
|
|
287
|
-
alignItems: 'center',
|
|
288
|
-
},
|
|
289
|
-
container: {
|
|
290
|
-
height: TabBarMetrics.height,
|
|
291
|
-
},
|
|
292
|
-
content: {
|
|
293
|
-
flex: 1,
|
|
294
|
-
flexDirection: 'row',
|
|
295
|
-
alignItems: 'center',
|
|
296
|
-
gap: TabBarMetrics.itemGap,
|
|
297
|
-
paddingVertical: TabBarMetrics.paddingVertical,
|
|
298
|
-
paddingHorizontal: TabBarMetrics.paddingHorizontal,
|
|
299
|
-
},
|
|
300
|
-
indicator: {
|
|
301
|
-
height: TabBarMetrics.indicatorHeight,
|
|
302
|
-
},
|
|
303
|
-
ctaSlot: {
|
|
304
|
-
width: TabBarMetrics.ctaSlotWidth,
|
|
305
|
-
alignSelf: 'stretch',
|
|
306
|
-
},
|
|
307
|
-
// the button rises ctaLift above the container top, the label ends on the item baseline
|
|
308
|
-
cta: {
|
|
309
|
-
position: 'absolute',
|
|
310
|
-
left: 0,
|
|
311
|
-
right: 0,
|
|
312
|
-
top: -TabBarMetrics.ctaLift - TabBarMetrics.paddingVertical,
|
|
313
|
-
alignItems: 'center',
|
|
314
|
-
gap: TabBarMetrics.ctaLabelGap,
|
|
315
|
-
},
|
|
316
|
-
ctaButton: {
|
|
317
|
-
boxShadow: CTA_SHADOW,
|
|
318
|
-
width: TabBarMetrics.ctaSize,
|
|
319
|
-
height: TabBarMetrics.ctaSize,
|
|
320
|
-
borderRadius: TabBarMetrics.ctaSize / 2,
|
|
321
|
-
alignItems: 'center',
|
|
322
|
-
justifyContent: 'center',
|
|
323
|
-
},
|
|
324
|
-
// custom label content over the label text, centered and unclipped
|
|
325
|
-
ctaLabelOverlay: {
|
|
326
|
-
...StyleSheet.absoluteFillObject,
|
|
327
|
-
alignItems: 'center',
|
|
328
|
-
justifyContent: 'center',
|
|
329
|
-
},
|
|
330
|
-
ctaLabel: {
|
|
331
|
-
maxWidth: TabBarMetrics.ctaSlotWidth,
|
|
332
|
-
minHeight: TabBarMetrics.ctaLabelHeight,
|
|
333
|
-
paddingHorizontal: Spacing.XXS,
|
|
334
|
-
justifyContent: 'center',
|
|
335
|
-
},
|
|
336
|
-
debugBaseLine: { borderWidth: 1, borderColor: Colors.green_06 },
|
|
337
|
-
});
|
|
338
|
-
|
|
339
271
|
export {
|
|
340
272
|
HorizontalTabBar,
|
|
341
273
|
getSystemIndicatorHeight,
|