@momo-kits/foundation 0.92.7-rc.21 → 0.92.7-rc.23

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.
Files changed (59) hide show
  1. package/Application/BottomSheet.tsx +216 -0
  2. package/Application/BottomTab/BottomTabBar.tsx +62 -223
  3. package/Application/BottomTab/index.tsx +15 -11
  4. package/Application/Components.tsx +291 -45
  5. package/Application/Localize.ts +44 -0
  6. package/Application/ModalScreen.tsx +11 -181
  7. package/Application/Navigation.ts +4 -18
  8. package/Application/NavigationContainer.tsx +10 -28
  9. package/Application/Navigator.ts +14 -16
  10. package/Application/StackScreen.tsx +222 -42
  11. package/Application/index.ts +5 -3
  12. package/Application/types.ts +47 -29
  13. package/Application/utils.tsx +61 -19
  14. package/Assets/icon_bank.json +1 -1
  15. package/Badge/BadgeDotAnimation.tsx +95 -0
  16. package/Badge/index.tsx +2 -1
  17. package/Badge/styles.ts +50 -6
  18. package/Button/index.tsx +7 -8
  19. package/Icon/index.tsx +1 -1
  20. package/Icon/types.ts +1 -2
  21. package/Image/index.tsx +0 -1
  22. package/Input/Input.tsx +51 -17
  23. package/Input/InputDropDown.tsx +42 -45
  24. package/Input/InputMoney.tsx +65 -6
  25. package/Input/InputOTP.tsx +14 -13
  26. package/Input/InputSearch.tsx +259 -146
  27. package/Input/InputTextArea.tsx +0 -1
  28. package/Input/TextTyping.tsx +113 -0
  29. package/Input/common.tsx +29 -10
  30. package/Input/index.tsx +84 -89
  31. package/Input/styles.ts +44 -7
  32. package/Input/utils.ts +1 -1
  33. package/Layout/Card.tsx +4 -3
  34. package/Layout/FloatingButton.tsx +3 -3
  35. package/Layout/GridSystem.tsx +1 -1
  36. package/Layout/ItemList.tsx +3 -2
  37. package/Layout/Screen.tsx +188 -102
  38. package/Layout/Section.tsx +4 -3
  39. package/Layout/styles.ts +0 -6
  40. package/Layout/types.ts +1 -1
  41. package/Layout/utils.ts +2 -2
  42. package/Loader/index.tsx +2 -0
  43. package/Pagination/PaginationScroll.tsx +2 -2
  44. package/Pagination/styles.ts +1 -1
  45. package/Popup/PopupNotify.tsx +7 -7
  46. package/Popup/PopupPromotion.tsx +1 -1
  47. package/Popup/types.ts +1 -1
  48. package/Tag/index.tsx +9 -2
  49. package/Tag/styles.ts +3 -2
  50. package/Tag/types.ts +12 -0
  51. package/Text/index.tsx +3 -1
  52. package/Text/utils.ts +14 -2
  53. package/Title/index.tsx +20 -7
  54. package/Title/styles.ts +4 -4
  55. package/code-scanner.js +141 -124
  56. package/index.ts +7 -0
  57. package/package.json +5 -4
  58. package/publish.sh +16 -21
  59. package/tsconfig.json +1 -1
@@ -0,0 +1,216 @@
1
+ import React, {useRef, useEffect, useCallback, useContext} from 'react';
2
+ import {
3
+ Animated,
4
+ Dimensions,
5
+ KeyboardAvoidingView,
6
+ PanResponder,
7
+ Platform,
8
+ StyleSheet,
9
+ TouchableOpacity,
10
+ View,
11
+ Modal,
12
+ } from 'react-native';
13
+ import {useSafeAreaInsets} from 'react-native-safe-area-context';
14
+ import {ApplicationContext} from './index';
15
+ import {BottomSheetParams} from './types';
16
+ import {Colors, Radius, Spacing, Styles} from '../Consts';
17
+ import {Text} from '../Text';
18
+ import {Icon} from '../Icon';
19
+
20
+ const BottomSheet: React.FC<BottomSheetParams> = props => {
21
+ const {theme, navigator} = useContext(ApplicationContext);
22
+ const heightDevice = Dimensions.get('screen').height;
23
+ const insets = useSafeAreaInsets();
24
+ const {
25
+ screen: Screen,
26
+ options,
27
+ useNativeModal = false,
28
+ surface,
29
+ barrierDismissible = false,
30
+ draggable = true,
31
+ useBottomInset = true,
32
+ keyboardVerticalOffset,
33
+ }: BottomSheetParams = props.route.params;
34
+ const pan = useRef(
35
+ new Animated.ValueXY({
36
+ y: heightDevice,
37
+ x: 0,
38
+ })
39
+ ).current;
40
+
41
+ const panResponder = useRef(
42
+ PanResponder.create({
43
+ onStartShouldSetPanResponder: () => draggable,
44
+ onMoveShouldSetPanResponder: (_, gestureState) => {
45
+ return draggable && gestureState.dy > 0;
46
+ },
47
+ onPanResponderMove: (e, gestureState) => {
48
+ gestureState.dy > 0 &&
49
+ Animated.event([null, {dy: pan.y}], {useNativeDriver: false})(
50
+ e,
51
+ gestureState
52
+ );
53
+ },
54
+ onPanResponderRelease: (_, gestureState) => {
55
+ if (gestureState.dy > 100) {
56
+ onDismiss();
57
+ } else {
58
+ Animated.spring(pan, {
59
+ toValue: {x: 0, y: 0},
60
+ useNativeDriver: false,
61
+ }).start();
62
+ }
63
+ },
64
+ })
65
+ ).current;
66
+ let Container: any = View;
67
+ if (useNativeModal) {
68
+ Container = Modal;
69
+ }
70
+ let backgroundColor = theme.colors.background.default;
71
+ if (surface) {
72
+ backgroundColor = theme.colors.background.surface;
73
+ }
74
+
75
+ /**
76
+ * emit dismiss event
77
+ */
78
+ useEffect(() => {
79
+ Animated.timing(pan, {
80
+ toValue: {x: 0, y: 0},
81
+ useNativeDriver: false,
82
+ duration: 150,
83
+ }).start();
84
+ return () => {
85
+ props.route.params?.onDismiss?.();
86
+ };
87
+ }, []);
88
+
89
+ /**
90
+ * handler dismiss
91
+ */
92
+ const onDismiss = (force = false, callback?: () => void) => {
93
+ if (barrierDismissible && !force) {
94
+ return;
95
+ }
96
+ setTimeout(() => {
97
+ callback?.();
98
+ }, 300);
99
+ Animated.timing(pan, {
100
+ toValue: {x: 0, y: heightDevice},
101
+ useNativeDriver: false,
102
+ duration: 200,
103
+ }).start(() => {
104
+ navigator?.pop();
105
+ });
106
+ };
107
+
108
+ /**
109
+ * on request close
110
+ */
111
+ const onRequestClose = useCallback((callback?: () => void) => {
112
+ onDismiss(true, callback);
113
+ }, []);
114
+
115
+ /**
116
+ * render header
117
+ */
118
+ const renderHeader = useCallback(() => {
119
+ return (
120
+ <View
121
+ style={{
122
+ backgroundColor,
123
+ borderTopLeftRadius: Radius.M,
124
+ borderTopRightRadius: Radius.M,
125
+ }}
126
+ {...panResponder.panHandlers}>
127
+ <View style={{height: 16}}>
128
+ <View style={styles.indicator} />
129
+ </View>
130
+ <View
131
+ style={[
132
+ styles.header,
133
+ surface && {
134
+ borderBottomColor: theme.colors.border.default,
135
+ borderBottomWidth: 1,
136
+ },
137
+ ]}>
138
+ <View style={styles.iconButton} />
139
+ <Text
140
+ style={[Styles.flex, {textAlign: 'center'}]}
141
+ numberOfLines={1}
142
+ typography="header_default_bold">
143
+ {options.title ?? ''}
144
+ </Text>
145
+ <TouchableOpacity
146
+ style={styles.iconButton}
147
+ onPress={() => onDismiss(true)}>
148
+ <Icon source="navigation_close" />
149
+ </TouchableOpacity>
150
+ </View>
151
+ </View>
152
+ );
153
+ }, []);
154
+
155
+ return (
156
+ <Container
157
+ transparent
158
+ visible={true}
159
+ onRequestClose={() => onDismiss()}
160
+ style={styles.overlay}>
161
+ <KeyboardAvoidingView
162
+ behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
163
+ keyboardVerticalOffset={keyboardVerticalOffset ?? -20}
164
+ style={[Styles.flex, {justifyContent: 'flex-end'}]}>
165
+ <TouchableOpacity
166
+ style={Styles.flex}
167
+ activeOpacity={1}
168
+ onPress={() => onDismiss()}
169
+ />
170
+ <Animated.View style={{transform: pan.getTranslateTransform()}}>
171
+ {renderHeader()}
172
+ <View style={{backgroundColor: backgroundColor}}>
173
+ <Screen
174
+ {...props}
175
+ {...props.route.params}
176
+ onRequestClose={onRequestClose}
177
+ />
178
+ {useBottomInset && (
179
+ <View style={{height: Math.min(insets.bottom, 21)}} />
180
+ )}
181
+ </View>
182
+ </Animated.View>
183
+ </KeyboardAvoidingView>
184
+ </Container>
185
+ );
186
+ };
187
+
188
+ const styles = StyleSheet.create({
189
+ overlay: {
190
+ ...StyleSheet.absoluteFillObject,
191
+ justifyContent: 'flex-end',
192
+ },
193
+ indicator: {
194
+ width: 40,
195
+ height: 4,
196
+ borderRadius: Radius.S,
197
+ backgroundColor: Colors.black_06,
198
+ position: 'absolute',
199
+ alignSelf: 'center',
200
+ top: Spacing.S,
201
+ },
202
+ header: {
203
+ height: 56,
204
+ flexDirection: 'row',
205
+ alignItems: 'center',
206
+ },
207
+ iconButton: {
208
+ width: 24,
209
+ height: 24,
210
+ alignItems: 'center',
211
+ justifyContent: 'center',
212
+ marginHorizontal: Spacing.M,
213
+ },
214
+ });
215
+
216
+ export default BottomSheet;
@@ -1,222 +1,70 @@
1
1
  import {BottomTabBarProps} from '@react-navigation/bottom-tabs';
2
- import {LabelPosition} from '@react-navigation/bottom-tabs/src/types';
3
- import BottomTabBarHeightCallbackContext from '@react-navigation/bottom-tabs/src/utils/BottomTabBarHeightCallbackContext';
4
2
  import BottomTabBarItem from '@react-navigation/bottom-tabs/src/views/BottomTabItem';
5
3
  import {
6
4
  CommonActions,
7
5
  NavigationContext,
8
6
  NavigationRouteContext,
9
- ParamListBase,
10
- TabNavigationState,
11
7
  useLinkBuilder,
12
- useTheme,
13
8
  } from '@react-navigation/native';
14
- import React, {useCallback} from 'react';
9
+ import React, {useCallback, useContext} from 'react';
15
10
  import {
16
11
  Animated,
17
- LayoutChangeEvent,
18
12
  Platform,
19
- StyleProp,
20
13
  StyleSheet,
21
14
  TouchableOpacity,
22
15
  useWindowDimensions,
23
16
  View,
24
- ViewStyle,
25
17
  } from 'react-native';
26
18
  import {EdgeInsets, useSafeAreaInsets} from 'react-native-safe-area-context';
27
19
  import {Radius} from '../../Consts';
28
20
  import {Icon} from '../../Icon';
29
21
  import {Text} from '../../Text';
30
22
  import {FloatingButtonProps} from '../types';
23
+ import {ApplicationContext} from '../index';
31
24
 
32
25
  type Props = BottomTabBarProps & {
33
26
  activeTintColor?: string;
34
27
  inactiveTintColor?: string;
35
28
  floatingButton?: FloatingButtonProps;
36
- accessibilityLabel?: string;
37
29
  };
38
30
 
39
- type Options = {
40
- state: TabNavigationState<ParamListBase>;
41
- layout: {height: number; width: number};
42
- dimensions: {height: number; width: number};
43
- tabStyle: StyleProp<ViewStyle>;
44
- labelPosition: LabelPosition | undefined;
45
- adaptive: boolean | undefined;
31
+ const getPaddingBottom = (insets: EdgeInsets) => {
32
+ return Math.max(insets.bottom - Platform.select({ios: 4, default: 0}), 0);
46
33
  };
47
34
 
48
- const DEFAULT_MAX_TAB_ITEM_WIDTH = 125;
49
-
50
- const shouldUseHorizontalLabels = ({
51
- state,
52
- layout,
53
- dimensions,
54
- adaptive = true,
55
- labelPosition,
56
- tabStyle,
57
- }: Options) => {
58
- if (labelPosition) {
59
- return labelPosition === 'beside-icon';
60
- }
61
-
62
- if (!adaptive) {
63
- return false;
64
- }
65
-
66
- if (layout.width >= 768) {
67
- // Screen size matches a tablet
68
- let maxTabItemWidth = DEFAULT_MAX_TAB_ITEM_WIDTH;
69
-
70
- const flattenedStyle = StyleSheet.flatten(tabStyle);
71
-
72
- if (flattenedStyle) {
73
- if (typeof flattenedStyle.width === 'number') {
74
- maxTabItemWidth = flattenedStyle.width;
75
- } else if (typeof flattenedStyle.maxWidth === 'number') {
76
- maxTabItemWidth = flattenedStyle.maxWidth;
77
- }
78
- }
79
-
80
- return state.routes.length * maxTabItemWidth <= layout.width;
81
- } else {
82
- return dimensions.width > dimensions.height;
83
- }
84
- };
85
- const getPaddingBottom = (insets: EdgeInsets) =>
86
- Math.max(insets.bottom - Platform.select({ios: 4, default: 0}), 0);
87
-
88
35
  export default function BottomTabBar({
89
36
  state,
90
37
  navigation,
91
38
  descriptors,
92
39
  activeBackgroundColor,
93
40
  activeTintColor,
94
- adaptive,
95
41
  allowFontScaling,
96
42
  inactiveBackgroundColor,
97
43
  inactiveTintColor,
98
- keyboardHidesTabBar = false,
99
- labelPosition,
100
44
  labelStyle,
101
45
  iconStyle,
102
- safeAreaInsets,
103
46
  showLabel,
104
47
  style,
105
48
  tabStyle,
106
49
  floatingButton,
107
50
  }: Props) {
51
+ const {theme} = useContext(ApplicationContext);
108
52
  const {routes} = state;
109
- const dimensions = useWindowDimensions();
110
- const isFloating = floatingButton?.icon && state.routes.length == 4;
111
- const itemWidth = isFloating
112
- ? dimensions.width / 5
113
- : dimensions.width / state.routes.length;
114
-
115
- const [layout, setLayout] = React.useState({
116
- height: 0,
117
- width: dimensions.width,
118
- });
53
+ const widthDevice = useWindowDimensions()?.width;
54
+ const useFloating = floatingButton && state.routes.length % 2 === 0;
55
+ const itemWidth = widthDevice / (state.routes.length + (useFloating ? 1 : 0));
119
56
  const buildLink = useLinkBuilder();
120
- const {colors} = useTheme();
121
-
122
- const hasHorizontalLabels = shouldUseHorizontalLabels({
123
- state,
124
- dimensions,
125
- layout,
126
- adaptive,
127
- labelPosition,
128
- tabStyle,
129
- });
130
- const focusedRoute = state.routes[state.index] as any;
131
- const focusedDescriptor = descriptors[focusedRoute?.key] as any;
132
- const focusedOptions = focusedDescriptor?.options;
133
- const shouldShowTabBar =
134
- focusedOptions?.tabBarVisible !== false && !keyboardHidesTabBar;
135
- const [visible] = React.useState(
136
- () => new Animated.Value(shouldShowTabBar ? 1 : 0),
137
- );
138
-
139
57
  const indicatorAnimated = React.useRef(new Animated.Value(0)).current;
140
-
141
- const visibilityAnimationConfigRef = React.useRef(
142
- focusedOptions?.tabBarVisibilityAnimationConfig,
143
- );
144
- const onHeightChange = React.useContext(BottomTabBarHeightCallbackContext);
145
- const [isTabBarHidden, setIsTabBarHidden] = React.useState(!shouldShowTabBar);
146
- React.useEffect(() => {
147
- visibilityAnimationConfigRef.current =
148
- focusedOptions?.tabBarVisibilityAnimationConfig;
149
- });
150
-
151
- const handleLayout = (e: LayoutChangeEvent) => {
152
- const {height, width} = e.nativeEvent.layout;
153
-
154
- onHeightChange?.(height);
155
-
156
- setLayout(layout => {
157
- if (height === layout.height && width === layout.width) {
158
- return layout;
159
- } else {
160
- return {
161
- height,
162
- width,
163
- };
164
- }
165
- });
166
- };
167
-
168
- React.useEffect(() => {
169
- const visibilityAnimationConfig = visibilityAnimationConfigRef.current;
170
-
171
- if (shouldShowTabBar) {
172
- const animation =
173
- visibilityAnimationConfig?.show?.animation === 'spring'
174
- ? Animated.spring
175
- : Animated.timing;
176
-
177
- animation(visible, {
178
- toValue: 1,
179
- useNativeDriver: true,
180
- duration: 250,
181
- ...visibilityAnimationConfig?.show?.config,
182
- }).start(({finished}) => {
183
- if (finished) {
184
- setIsTabBarHidden(false);
185
- }
186
- });
187
- } else {
188
- setIsTabBarHidden(true);
189
-
190
- const animation =
191
- visibilityAnimationConfig?.hide?.animation === 'spring'
192
- ? Animated.spring
193
- : Animated.timing;
194
-
195
- animation(visible, {
196
- toValue: 0,
197
- useNativeDriver: true,
198
- duration: 200,
199
- ...visibilityAnimationConfig?.hide?.config,
200
- }).start();
201
- }
202
- }, [visible, shouldShowTabBar]);
203
- const defaultInsets = useSafeAreaInsets();
204
-
205
- const insets = {
206
- top: safeAreaInsets?.top ?? defaultInsets.top,
207
- right: safeAreaInsets?.right ?? defaultInsets.right,
208
- bottom: safeAreaInsets?.bottom ?? defaultInsets.bottom,
209
- left: safeAreaInsets?.left ?? defaultInsets.left,
210
- };
58
+ const insets = useSafeAreaInsets();
211
59
  const paddingBottom = getPaddingBottom(insets);
212
-
213
- const leftArr = routes.slice(0, 2);
214
- const rightArr = routes.slice(2, routes.length);
215
60
  const focusedTab = state?.routes[state.index]?.name || routes[0]?.params;
216
61
 
62
+ /**
63
+ * render tab item
64
+ */
217
65
  const renderTabItem = useCallback(
218
66
  (data: any[]) => {
219
- return data?.map((route, index) => {
67
+ return data?.map((route, _) => {
220
68
  const focused = route.params.name === focusedTab;
221
69
  const {options} = descriptors[route?.key] as any;
222
70
  const onPress = () => {
@@ -241,19 +89,7 @@ export default function BottomTabBar({
241
89
  });
242
90
  };
243
91
 
244
- const label =
245
- options.tabBarLabel !== undefined
246
- ? options.tabBarLabel
247
- : options.title !== undefined
248
- ? options.title
249
- : route.name;
250
-
251
- const accessibilityLabel =
252
- options.tabBarAccessibilityLabel !== undefined
253
- ? options.tabBarAccessibilityLabel
254
- : typeof label === 'string'
255
- ? `${label}, tab, ${index + 1} of ${routes.length}`
256
- : undefined;
92
+ const label = options.tabBarLabel || options.title || route.name;
257
93
 
258
94
  return (
259
95
  <NavigationContext.Provider
@@ -263,10 +99,10 @@ export default function BottomTabBar({
263
99
  <BottomTabBarItem
264
100
  route={route}
265
101
  focused={focused}
266
- horizontal={hasHorizontalLabels}
102
+ horizontal={false}
267
103
  onPress={onPress}
268
104
  onLongPress={onLongPress}
269
- accessibilityLabel={accessibilityLabel}
105
+ accessibilityLabel={`tab_item_${route.name}`}
270
106
  to={buildLink(route.name, route.params)}
271
107
  testID={options.tabBarTestID}
272
108
  allowFontScaling={allowFontScaling}
@@ -289,18 +125,15 @@ export default function BottomTabBar({
289
125
  );
290
126
  });
291
127
  },
292
- [JSON.stringify(routes), state, descriptors, focusedTab],
128
+ [JSON.stringify(routes), state, descriptors, focusedTab]
293
129
  );
294
130
 
295
- const renderCenterComponent = useCallback(() => {
296
- if (floatingButton?.icon && state.routes.length !== 4) {
297
- console.warn(
298
- "Can't render floating button with icon when routes length is not 4",
299
- );
300
- return null;
301
- }
131
+ /**
132
+ * render floating button
133
+ */
134
+ const renderFloatingButton = useCallback(() => {
302
135
  const renderFloatingButton = () => {
303
- if (typeof floatingButton?.icon == 'string') {
136
+ if (typeof floatingButton?.icon === 'string') {
304
137
  return <Icon source={floatingButton?.icon} size={32} color={'white'} />;
305
138
  }
306
139
  return floatingButton?.icon;
@@ -314,14 +147,14 @@ export default function BottomTabBar({
314
147
  <View
315
148
  style={{
316
149
  ...styles.floatingContent,
317
- backgroundColor: activeTintColor ?? colors.primary,
150
+ backgroundColor: activeTintColor ?? theme.colors.primary,
318
151
  }}>
319
152
  {renderFloatingButton()}
320
153
  </View>
321
154
  <View
322
155
  style={{
323
- top: -6,
324
- backgroundColor: activeTintColor ?? colors.primary,
156
+ top: -4,
157
+ backgroundColor: activeTintColor ?? theme.colors.primary,
325
158
  borderRadius: Radius.XL,
326
159
  paddingHorizontal: 6,
327
160
  }}>
@@ -335,40 +168,49 @@ export default function BottomTabBar({
335
168
  </TouchableOpacity>
336
169
  </View>
337
170
  );
338
- }, [floatingButton]);
171
+ }, [useFloating]);
339
172
 
173
+ /**
174
+ * animated indicator
175
+ */
340
176
  React.useEffect(() => {
177
+ let index = state.index;
178
+ if (useFloating && index > (state.routes.length - 1) / 2) {
179
+ index += 1;
180
+ }
341
181
  Animated.timing(indicatorAnimated, {
342
- toValue:
343
- isFloating && state.index > 1
344
- ? itemWidth * (state.index + 1)
345
- : itemWidth * state.index,
346
- useNativeDriver: false,
182
+ toValue: itemWidth * index,
183
+ useNativeDriver: true,
347
184
  duration: 200,
348
185
  }).start();
349
- }, [state.index, itemWidth, indicatorAnimated, isFloating]);
186
+ }, [state.index, itemWidth, indicatorAnimated, useFloating]);
187
+
188
+ /**
189
+ * render tab bar
190
+ */
191
+ const renderTabBar = () => {
192
+ if (useFloating) {
193
+ const middleIndex = routes.length / 2;
194
+ const leftArr = routes.slice(0, middleIndex);
195
+ const rightArr = routes.slice(middleIndex);
196
+ return (
197
+ <>
198
+ {renderTabItem(leftArr)}
199
+ {renderFloatingButton()}
200
+ {renderTabItem(rightArr)}
201
+ </>
202
+ );
203
+ }
204
+ return renderTabItem(routes);
205
+ };
350
206
 
351
207
  return (
352
208
  <Animated.View
353
209
  style={[
354
210
  styles.tabBar,
355
211
  {
356
- backgroundColor: colors.card,
357
- borderTopColor: colors.border,
358
- },
359
- {
360
- transform: [
361
- {
362
- translateY: visible.interpolate({
363
- inputRange: [0, 1],
364
- outputRange: [
365
- layout.height + paddingBottom + StyleSheet.hairlineWidth,
366
- 0,
367
- ],
368
- }),
369
- },
370
- ],
371
- position: isTabBarHidden ? 'absolute' : (null as any),
212
+ backgroundColor: theme.colors.background.surface,
213
+ borderTopColor: theme.colors.border.default,
372
214
  },
373
215
  {
374
216
  paddingBottom: paddingBottom,
@@ -376,10 +218,9 @@ export default function BottomTabBar({
376
218
  },
377
219
  style,
378
220
  ]}
379
- pointerEvents={isTabBarHidden ? 'none' : 'auto'}
380
- onLayout={handleLayout}>
381
- <View style={styles.content}>
382
- {isFloating && floatingButton?.container}
221
+ pointerEvents={'auto'}>
222
+ <View style={styles.content} accessibilityLabel={'bottom_tab_bar'}>
223
+ {useFloating && floatingButton?.container}
383
224
  <Animated.View
384
225
  style={{
385
226
  width: itemWidth,
@@ -390,13 +231,11 @@ export default function BottomTabBar({
390
231
  <View
391
232
  style={[
392
233
  styles.indicator,
393
- {backgroundColor: activeTintColor ?? colors.primary},
234
+ {backgroundColor: activeTintColor ?? theme.colors.primary},
394
235
  ]}
395
236
  />
396
237
  </Animated.View>
397
- {isFloating ? renderTabItem(leftArr) : renderTabItem(routes)}
398
- {isFloating && renderCenterComponent()}
399
- {isFloating && renderTabItem(rightArr)}
238
+ {renderTabBar()}
400
239
  </View>
401
240
  </Animated.View>
402
241
  );
@@ -17,18 +17,22 @@ const Tab = createBottomTabNavigator();
17
17
  const Stack = createStackNavigator();
18
18
 
19
19
  const TabScreen: React.FC<NavigationScreenProps> = ({route}) => {
20
- const {theme} = useContext(ApplicationContext);
21
20
  let options = {};
22
21
  if (route.params?.options) {
23
- options = getOptions(route.params?.options, theme);
22
+ options = getOptions(route.params?.options);
24
23
  }
24
+
25
25
  if (route.params?.nested) {
26
26
  return (
27
27
  <Stack.Navigator>
28
28
  <Stack.Screen
29
29
  name="Stack"
30
30
  component={StackScreen}
31
- initialParams={{screen: route.params?.screen, options}}
31
+ initialParams={{
32
+ screen: route.params?.screen,
33
+ options,
34
+ initialParams: route.params?.initialParams,
35
+ }}
32
36
  options={{...getStackOptions()}}
33
37
  />
34
38
  </Stack.Navigator>
@@ -40,7 +44,11 @@ const TabScreen: React.FC<NavigationScreenProps> = ({route}) => {
40
44
  <Stack.Screen
41
45
  name="Stack"
42
46
  component={StackScreen}
43
- initialParams={{screen: route.params?.screen, options}}
47
+ initialParams={{
48
+ screen: route.params?.screen,
49
+ options,
50
+ initialParams: route.params?.initialParams,
51
+ }}
44
52
  options={{...getStackOptions(), ...route.params?.options}}
45
53
  />
46
54
  </Stack.Navigator>
@@ -72,11 +80,7 @@ const BottomTab: React.FC<BottomTabProps> = ({
72
80
  initialRouteName={initialRouteName}
73
81
  backBehavior={'firstRoute'}
74
82
  tabBar={props => (
75
- <BottomTabBar
76
- {...props}
77
- accessibilityLabel={'BottomTabBar'}
78
- floatingButton={floatingButton}
79
- />
83
+ <BottomTabBar {...props} floatingButton={floatingButton} />
80
84
  )}
81
85
  tabBarOptions={{
82
86
  style: {
@@ -89,14 +93,14 @@ const BottomTab: React.FC<BottomTabProps> = ({
89
93
  }}>
90
94
  {tabs.map(item => {
91
95
  const isNum = !isNaN(parseInt(`${item?.badgeLabel}`));
92
- const isDot = typeof item?.badgeLabel == 'string' && !item?.badgeLabel;
96
+ const isDot = typeof item?.badgeLabel === 'string' && !item?.badgeLabel;
93
97
  return (
94
98
  <Tab.Screen
95
99
  key={item.name}
96
100
  name={item.name}
97
101
  component={TabScreen}
98
102
  initialParams={{...item, nested}}
99
- listeners={listeners}
103
+ listeners={item.listeners ?? listeners}
100
104
  options={{
101
105
  tabBarLabel: ({color, focused}) => {
102
106
  return (