@momo-kits/tab-view 0.92.3-tracking.1 → 0.92.6-rc.3
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/index.tsx +23 -11
- package/package.json +1 -1
- package/styles.ts +16 -5
- package/tabBar/CardTabBar.tsx +36 -3
- package/tabBar/SrollableTabBar.tsx +5 -1
- package/tabBar/TabBar.tsx +15 -3
- package/tabItem/CardTabItem.tsx +36 -9
- package/tabItem/TabItem.tsx +109 -29
- package/types.ts +33 -6
package/index.tsx
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import React, {FC, useCallback, useRef, useState} from 'react';
|
|
2
|
-
import {LayoutChangeEvent, View} from 'react-native';
|
|
1
|
+
import React, {FC, useCallback, useContext, useRef, useState} from 'react';
|
|
2
|
+
import {Animated, LayoutChangeEvent, View} from 'react-native';
|
|
3
3
|
import {Tab, TabViewProps} from './types';
|
|
4
4
|
import TabBar from './tabBar/TabBar';
|
|
5
5
|
import styles from './styles';
|
|
6
6
|
import CardTabBar from './tabBar/CardTabBar';
|
|
7
7
|
import ScrollableTabBar from './tabBar/SrollableTabBar';
|
|
8
8
|
import PagerView from 'react-native-pager-view';
|
|
9
|
+
import {ApplicationContext} from '@momo-kits/foundation';
|
|
9
10
|
|
|
10
11
|
const TabView: FC<TabViewProps> = ({
|
|
11
12
|
scrollable = false,
|
|
@@ -14,6 +15,9 @@ const TabView: FC<TabViewProps> = ({
|
|
|
14
15
|
type = 'default',
|
|
15
16
|
initialPage = 0,
|
|
16
17
|
pagerProps,
|
|
18
|
+
direction,
|
|
19
|
+
selectedColor,
|
|
20
|
+
unselectedColor,
|
|
17
21
|
}) => {
|
|
18
22
|
const startPage =
|
|
19
23
|
initialPage > tabs.length - 1 ? tabs.length - 1 : initialPage;
|
|
@@ -21,7 +25,9 @@ const TabView: FC<TabViewProps> = ({
|
|
|
21
25
|
const [tabBarWidth, setTabBarWidth] = useState(0);
|
|
22
26
|
const isCardTab = type === 'card';
|
|
23
27
|
const pagerRef = useRef<PagerView>(null);
|
|
24
|
-
const
|
|
28
|
+
const scrollX = useRef(new Animated.Value(0));
|
|
29
|
+
const lazy = useRef([selectedIndex]).current;
|
|
30
|
+
const {theme} = useContext(ApplicationContext);
|
|
25
31
|
const _onPressTabItem = (index: number) => {
|
|
26
32
|
pagerRef.current?.setPage(index);
|
|
27
33
|
onPressTabItem?.(index);
|
|
@@ -32,10 +38,12 @@ const TabView: FC<TabViewProps> = ({
|
|
|
32
38
|
setTabBarWidth(e.nativeEvent.layout.width);
|
|
33
39
|
};
|
|
34
40
|
|
|
35
|
-
const onPageSelected = (e: {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
const onPageSelected = (e: {nativeEvent: {position: number}}) => {
|
|
42
|
+
const {position} = e.nativeEvent;
|
|
43
|
+
if (!lazy.includes(position)) {
|
|
44
|
+
lazy.push(position);
|
|
45
|
+
}
|
|
46
|
+
setSelectedIndex(position);
|
|
39
47
|
};
|
|
40
48
|
|
|
41
49
|
let TabBarComponent = scrollable ? ScrollableTabBar : TabBar;
|
|
@@ -46,11 +54,12 @@ const TabView: FC<TabViewProps> = ({
|
|
|
46
54
|
|
|
47
55
|
const onPageScroll = (e: {nativeEvent: {position: any; offset: any}}) => {
|
|
48
56
|
const {position, offset} = e.nativeEvent;
|
|
49
|
-
|
|
57
|
+
scrollX.current.setValue(position + offset);
|
|
50
58
|
};
|
|
51
59
|
|
|
52
60
|
const renderScreen = useCallback(
|
|
53
|
-
(tab: Tab) => {
|
|
61
|
+
(tab: Tab, index: number) => {
|
|
62
|
+
if (!lazy.includes(index)) return <View />;
|
|
54
63
|
return <View>{tab.component}</View>;
|
|
55
64
|
},
|
|
56
65
|
[tabs],
|
|
@@ -64,7 +73,10 @@ const TabView: FC<TabViewProps> = ({
|
|
|
64
73
|
selectedIndex={selectedIndex}
|
|
65
74
|
tabs={tabs}
|
|
66
75
|
containerWidth={tabBarWidth}
|
|
67
|
-
scrollX={scrollX}
|
|
76
|
+
scrollX={scrollX.current}
|
|
77
|
+
direction={direction}
|
|
78
|
+
selectedColor={selectedColor ?? theme.colors.primary}
|
|
79
|
+
unselectedColor={unselectedColor ?? theme.colors.text.default}
|
|
68
80
|
/>
|
|
69
81
|
</View>
|
|
70
82
|
|
|
@@ -75,7 +87,7 @@ const TabView: FC<TabViewProps> = ({
|
|
|
75
87
|
onPageSelected={onPageSelected}
|
|
76
88
|
style={styles.pagerView}
|
|
77
89
|
initialPage={startPage}>
|
|
78
|
-
{tabs.map(tab => renderScreen(tab))}
|
|
90
|
+
{tabs.map((tab, index) => renderScreen(tab, index))}
|
|
79
91
|
</PagerView>
|
|
80
92
|
</View>
|
|
81
93
|
);
|
package/package.json
CHANGED
package/styles.ts
CHANGED
|
@@ -14,7 +14,6 @@ export default StyleSheet.create({
|
|
|
14
14
|
borderBottomWidth: 1,
|
|
15
15
|
},
|
|
16
16
|
tabItem: {
|
|
17
|
-
padding: Spacing.M,
|
|
18
17
|
alignItems: 'center',
|
|
19
18
|
justifyContent: 'center',
|
|
20
19
|
},
|
|
@@ -26,9 +25,15 @@ export default StyleSheet.create({
|
|
|
26
25
|
bottom: 0,
|
|
27
26
|
},
|
|
28
27
|
icon: {
|
|
28
|
+
borderRadius: Radius.XS,
|
|
29
|
+
},
|
|
30
|
+
iconHolder: {
|
|
31
|
+
marginRight: Spacing.XS,
|
|
29
32
|
width: 24,
|
|
30
33
|
height: 24,
|
|
31
|
-
|
|
34
|
+
justifyContent: 'center',
|
|
35
|
+
alignItems: 'center',
|
|
36
|
+
overflow: 'hidden',
|
|
32
37
|
},
|
|
33
38
|
tabItemWrapper: {
|
|
34
39
|
paddingHorizontal: Spacing.XS,
|
|
@@ -65,14 +70,20 @@ export default StyleSheet.create({
|
|
|
65
70
|
},
|
|
66
71
|
dotSmall: {
|
|
67
72
|
position: 'absolute',
|
|
68
|
-
top: -Spacing.
|
|
69
|
-
right: -Spacing.
|
|
73
|
+
top: -Spacing.XS,
|
|
74
|
+
right: -Spacing.XS,
|
|
70
75
|
zIndex: 2,
|
|
71
76
|
},
|
|
72
77
|
dot: {
|
|
73
78
|
position: 'absolute',
|
|
74
79
|
top: -Spacing.S,
|
|
75
|
-
right: -Spacing.
|
|
80
|
+
right: -Spacing.S,
|
|
81
|
+
zIndex: 2,
|
|
82
|
+
},
|
|
83
|
+
badge: {
|
|
84
|
+
position: 'absolute',
|
|
85
|
+
top: -Spacing.S,
|
|
86
|
+
left: Spacing.S,
|
|
76
87
|
zIndex: 2,
|
|
77
88
|
},
|
|
78
89
|
});
|
package/tabBar/CardTabBar.tsx
CHANGED
|
@@ -4,6 +4,8 @@ import {TabBarProps} from '../types';
|
|
|
4
4
|
import styles from '../styles';
|
|
5
5
|
import {
|
|
6
6
|
ApplicationContext,
|
|
7
|
+
Badge,
|
|
8
|
+
BadgeDot,
|
|
7
9
|
Icon,
|
|
8
10
|
Radius,
|
|
9
11
|
Shadow,
|
|
@@ -18,6 +20,8 @@ const CardTabBar: FC<TabBarProps> = ({
|
|
|
18
20
|
onPressTabItem,
|
|
19
21
|
containerWidth,
|
|
20
22
|
selectedIndex,
|
|
23
|
+
selectedColor,
|
|
24
|
+
unselectedColor,
|
|
21
25
|
}) => {
|
|
22
26
|
const {theme} = useContext(ApplicationContext);
|
|
23
27
|
const itemWidth = containerWidth / tabs.length;
|
|
@@ -36,6 +40,8 @@ const CardTabBar: FC<TabBarProps> = ({
|
|
|
36
40
|
onPressTabItem?.(index);
|
|
37
41
|
}}
|
|
38
42
|
width={itemWidth}
|
|
43
|
+
selectedColor={selectedColor}
|
|
44
|
+
unselectedColor={unselectedColor}
|
|
39
45
|
/>
|
|
40
46
|
);
|
|
41
47
|
})}
|
|
@@ -61,19 +67,46 @@ const CardTabBar: FC<TabBarProps> = ({
|
|
|
61
67
|
borderTopLeftRadius: Radius.M,
|
|
62
68
|
},
|
|
63
69
|
]}>
|
|
64
|
-
{!!tabs[selectedIndex]?.
|
|
70
|
+
{!!tabs[selectedIndex]?.renderIcon &&
|
|
71
|
+
!['string', 'boolean', 'number'].includes(
|
|
72
|
+
typeof tabs[selectedIndex]?.renderIcon,
|
|
73
|
+
) && (
|
|
74
|
+
<View
|
|
75
|
+
style={[
|
|
76
|
+
styles.icon,
|
|
77
|
+
styles.iconHolder,
|
|
78
|
+
{marginRight: Spacing.XS},
|
|
79
|
+
]}>
|
|
80
|
+
{tabs[selectedIndex]?.renderIcon}
|
|
81
|
+
</View>
|
|
82
|
+
)}
|
|
83
|
+
{!tabs[selectedIndex]?.renderIcon && !!tabs[selectedIndex]?.icon && (
|
|
65
84
|
<Icon
|
|
66
|
-
|
|
85
|
+
color={selectedColor}
|
|
86
|
+
source={tabs[selectedIndex]?.icon as string}
|
|
67
87
|
style={[styles.icon, {marginRight: Spacing.XS}]}
|
|
68
88
|
/>
|
|
69
89
|
)}
|
|
70
90
|
<Text
|
|
71
|
-
color={
|
|
91
|
+
color={selectedColor}
|
|
72
92
|
numberOfLines={1}
|
|
73
93
|
style={styles.textCenter}
|
|
74
94
|
typography={'header_s_semibold'}>
|
|
75
95
|
{tabs[selectedIndex]?.title || ''}
|
|
76
96
|
</Text>
|
|
97
|
+
{tabs[selectedIndex]?.showDot && (
|
|
98
|
+
<BadgeDot
|
|
99
|
+
size={tabs[selectedIndex]?.dotSize ?? 'small'}
|
|
100
|
+
style={{
|
|
101
|
+
marginLeft: Spacing.XS,
|
|
102
|
+
}}
|
|
103
|
+
/>
|
|
104
|
+
)}
|
|
105
|
+
{!tabs[selectedIndex]?.showDot && tabs[selectedIndex]?.badgeValue && (
|
|
106
|
+
<View>
|
|
107
|
+
<Badge label={tabs[selectedIndex]?.badgeValue} />
|
|
108
|
+
</View>
|
|
109
|
+
)}
|
|
77
110
|
</View>
|
|
78
111
|
{!isLast && <PathSvg style={{right: 8}} />}
|
|
79
112
|
</View>
|
|
@@ -9,6 +9,8 @@ const ScrollableTabBar: FC<TabBarProps> = ({
|
|
|
9
9
|
tabs = [],
|
|
10
10
|
onPressTabItem,
|
|
11
11
|
selectedIndex,
|
|
12
|
+
selectedColor,
|
|
13
|
+
unselectedColor,
|
|
12
14
|
}) => {
|
|
13
15
|
const {theme} = useContext(ApplicationContext);
|
|
14
16
|
const [itemWidthMap, setItemWidthMap] = useState<
|
|
@@ -62,6 +64,8 @@ const ScrollableTabBar: FC<TabBarProps> = ({
|
|
|
62
64
|
}}
|
|
63
65
|
active={isActive}
|
|
64
66
|
tab={item}
|
|
67
|
+
selectedColor={selectedColor}
|
|
68
|
+
unselectedColor={unselectedColor}
|
|
65
69
|
/>
|
|
66
70
|
</View>
|
|
67
71
|
);
|
|
@@ -86,7 +90,7 @@ const ScrollableTabBar: FC<TabBarProps> = ({
|
|
|
86
90
|
{
|
|
87
91
|
left: itemWidthMap[selectedIndex]?.x || 0,
|
|
88
92
|
width: animatedWidth,
|
|
89
|
-
backgroundColor:
|
|
93
|
+
backgroundColor: selectedColor,
|
|
90
94
|
},
|
|
91
95
|
]}
|
|
92
96
|
/>
|
package/tabBar/TabBar.tsx
CHANGED
|
@@ -11,9 +11,11 @@ const TabBar: FC<TabBarProps> = ({
|
|
|
11
11
|
onPressTabItem,
|
|
12
12
|
containerWidth = 0,
|
|
13
13
|
scrollX,
|
|
14
|
+
direction,
|
|
15
|
+
selectedColor,
|
|
16
|
+
unselectedColor,
|
|
14
17
|
}) => {
|
|
15
18
|
const {theme} = useContext(ApplicationContext);
|
|
16
|
-
|
|
17
19
|
const itemWidth = containerWidth / tabs.length;
|
|
18
20
|
|
|
19
21
|
return (
|
|
@@ -35,6 +37,9 @@ const TabBar: FC<TabBarProps> = ({
|
|
|
35
37
|
}}
|
|
36
38
|
active={selectedIndex === index}
|
|
37
39
|
tab={tab}
|
|
40
|
+
direction={direction}
|
|
41
|
+
selectedColor={selectedColor}
|
|
42
|
+
unselectedColor={unselectedColor}
|
|
38
43
|
/>
|
|
39
44
|
);
|
|
40
45
|
})}
|
|
@@ -42,9 +47,16 @@ const TabBar: FC<TabBarProps> = ({
|
|
|
42
47
|
style={[
|
|
43
48
|
styles.indicator,
|
|
44
49
|
{
|
|
45
|
-
left: scrollX
|
|
50
|
+
left: scrollX.interpolate({
|
|
51
|
+
inputRange: [0, tabs.length - 1],
|
|
52
|
+
outputRange: [
|
|
53
|
+
Spacing.XS,
|
|
54
|
+
(tabs.length - 1) * itemWidth + Spacing.XS,
|
|
55
|
+
],
|
|
56
|
+
extrapolate: 'clamp',
|
|
57
|
+
}),
|
|
46
58
|
width: itemWidth - Spacing.XS * 2,
|
|
47
|
-
backgroundColor:
|
|
59
|
+
backgroundColor: selectedColor,
|
|
48
60
|
},
|
|
49
61
|
]}
|
|
50
62
|
/>
|
package/tabItem/CardTabItem.tsx
CHANGED
|
@@ -1,27 +1,41 @@
|
|
|
1
|
-
import React, {FC
|
|
2
|
-
import {TouchableOpacity} from 'react-native';
|
|
1
|
+
import React, {FC} from 'react';
|
|
2
|
+
import {TouchableOpacity, View} from 'react-native';
|
|
3
3
|
import {TabItemProps} from '../types';
|
|
4
4
|
import styles from '../styles';
|
|
5
|
-
import {
|
|
5
|
+
import {Badge, BadgeDot, Icon, Spacing, Text,} from '@momo-kits/foundation';
|
|
6
6
|
|
|
7
7
|
const CardTabItem: FC<TabItemProps> = ({
|
|
8
8
|
tab,
|
|
9
9
|
active,
|
|
10
10
|
onPressTabItem,
|
|
11
11
|
width,
|
|
12
|
+
selectedColor,
|
|
13
|
+
unselectedColor,
|
|
12
14
|
}) => {
|
|
13
|
-
const {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
const {
|
|
16
|
+
title,
|
|
17
|
+
icon,
|
|
18
|
+
renderIcon,
|
|
19
|
+
showDot = false,
|
|
20
|
+
dotSize = 'small',
|
|
21
|
+
badgeValue,
|
|
22
|
+
} = tab;
|
|
23
|
+
const color = active ? selectedColor : unselectedColor;
|
|
17
24
|
|
|
18
25
|
return (
|
|
19
26
|
<TouchableOpacity
|
|
20
27
|
onPress={onPressTabItem}
|
|
21
28
|
style={[styles.cardTabItem, {width}]}>
|
|
22
|
-
{
|
|
29
|
+
{renderIcon &&
|
|
30
|
+
!['string', 'boolean', 'number'].includes(typeof renderIcon) && (
|
|
31
|
+
<View
|
|
32
|
+
style={[styles.icon, styles.iconHolder, {marginRight: Spacing.XS}]}>
|
|
33
|
+
{renderIcon}
|
|
34
|
+
</View>
|
|
35
|
+
)}
|
|
36
|
+
{!renderIcon && !!icon && (
|
|
23
37
|
<Icon
|
|
24
|
-
color={
|
|
38
|
+
color={color}
|
|
25
39
|
style={[styles.icon, {marginRight: Spacing.XS}]}
|
|
26
40
|
source={icon}
|
|
27
41
|
/>
|
|
@@ -32,6 +46,19 @@ const CardTabItem: FC<TabItemProps> = ({
|
|
|
32
46
|
typography={'body_default_regular'}>
|
|
33
47
|
{title}
|
|
34
48
|
</Text>
|
|
49
|
+
{showDot && (
|
|
50
|
+
<BadgeDot
|
|
51
|
+
size={dotSize}
|
|
52
|
+
style={{
|
|
53
|
+
marginLeft: Spacing.XS,
|
|
54
|
+
}}
|
|
55
|
+
/>
|
|
56
|
+
)}
|
|
57
|
+
{!showDot && badgeValue && (
|
|
58
|
+
<View>
|
|
59
|
+
<Badge label={badgeValue} />
|
|
60
|
+
</View>
|
|
61
|
+
)}
|
|
35
62
|
</TouchableOpacity>
|
|
36
63
|
);
|
|
37
64
|
};
|
package/tabItem/TabItem.tsx
CHANGED
|
@@ -1,60 +1,140 @@
|
|
|
1
1
|
import React, {FC, useContext} from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import {TouchableOpacity, View, ViewStyle} from 'react-native';
|
|
2
|
+
import {TouchableOpacity, View} from 'react-native';
|
|
4
3
|
import {TabItemProps} from '../types';
|
|
5
4
|
import {
|
|
6
5
|
ApplicationContext,
|
|
6
|
+
Badge,
|
|
7
7
|
BadgeDot,
|
|
8
8
|
Icon,
|
|
9
|
+
scaleSize,
|
|
9
10
|
Spacing,
|
|
10
11
|
Text,
|
|
11
12
|
Typography,
|
|
12
13
|
} from '@momo-kits/foundation';
|
|
13
14
|
import styles from '../styles';
|
|
14
15
|
|
|
15
|
-
const TabItem: FC<TabItemProps> = ({
|
|
16
|
+
const TabItem: FC<TabItemProps> = ({
|
|
17
|
+
tab,
|
|
18
|
+
active,
|
|
19
|
+
onPressTabItem,
|
|
20
|
+
width,
|
|
21
|
+
direction,
|
|
22
|
+
selectedColor,
|
|
23
|
+
unselectedColor,
|
|
24
|
+
}) => {
|
|
16
25
|
const {theme} = useContext(ApplicationContext);
|
|
17
26
|
const {
|
|
18
27
|
title,
|
|
19
28
|
icon,
|
|
20
|
-
direction = 'row',
|
|
21
29
|
showDot = false,
|
|
22
30
|
dotSize = 'small',
|
|
31
|
+
badgeValue,
|
|
32
|
+
renderIcon,
|
|
23
33
|
} = tab;
|
|
24
34
|
const typography: Typography = active
|
|
25
35
|
? 'header_s_semibold'
|
|
26
36
|
: 'body_default_regular';
|
|
27
|
-
const color = active ?
|
|
28
|
-
const tintColor = icon?.includes('http') ? null : color;
|
|
37
|
+
const color = active ? selectedColor : unselectedColor;
|
|
29
38
|
const dotStyle = dotSize === 'large' ? styles.dot : styles.dotSmall;
|
|
30
|
-
const iconStyle: ViewStyle =
|
|
31
|
-
direction === 'row'
|
|
32
|
-
? {marginRight: Spacing.XS}
|
|
33
|
-
: {marginBottom: Spacing.XS};
|
|
34
39
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
const renderRowItem = () => {
|
|
41
|
+
return (
|
|
42
|
+
<TouchableOpacity
|
|
43
|
+
style={[
|
|
44
|
+
styles.tabItem,
|
|
45
|
+
{
|
|
46
|
+
width,
|
|
47
|
+
height: scaleSize(48),
|
|
48
|
+
flexDirection: 'row',
|
|
49
|
+
overflow: 'hidden',
|
|
50
|
+
},
|
|
51
|
+
]}
|
|
52
|
+
onPress={onPressTabItem}>
|
|
53
|
+
{renderIcon &&
|
|
54
|
+
!['string', 'boolean', 'number'].includes(typeof renderIcon) && (
|
|
55
|
+
<View
|
|
56
|
+
style={[
|
|
57
|
+
styles.icon,
|
|
58
|
+
styles.iconHolder,
|
|
59
|
+
{marginRight: Spacing.XS},
|
|
60
|
+
]}>
|
|
61
|
+
{renderIcon}
|
|
62
|
+
</View>
|
|
63
|
+
)}
|
|
64
|
+
{!renderIcon && !!icon && (
|
|
42
65
|
<Icon
|
|
43
|
-
|
|
44
|
-
style={[styles.icon, iconStyle as ImageStyle]}
|
|
66
|
+
style={[styles.icon, {marginRight: Spacing.XS}]}
|
|
45
67
|
source={icon}
|
|
68
|
+
color={color}
|
|
46
69
|
/>
|
|
70
|
+
)}
|
|
71
|
+
<Text numberOfLines={1} typography={typography} color={color}>
|
|
72
|
+
{title}
|
|
73
|
+
</Text>
|
|
74
|
+
{showDot && (
|
|
75
|
+
<BadgeDot size={dotSize} style={{marginLeft: Spacing.XS}} />
|
|
76
|
+
)}
|
|
77
|
+
{!showDot && badgeValue && (
|
|
78
|
+
<View>
|
|
79
|
+
<Badge label={badgeValue} />
|
|
80
|
+
</View>
|
|
81
|
+
)}
|
|
82
|
+
</TouchableOpacity>
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const renderColumnItem = () => {
|
|
87
|
+
return (
|
|
88
|
+
<TouchableOpacity
|
|
89
|
+
style={[
|
|
90
|
+
styles.tabItem,
|
|
91
|
+
{
|
|
92
|
+
width,
|
|
93
|
+
height: scaleSize(68),
|
|
94
|
+
flexDirection: 'column',
|
|
95
|
+
overflow: 'hidden',
|
|
96
|
+
},
|
|
97
|
+
]}
|
|
98
|
+
onPress={onPressTabItem}>
|
|
99
|
+
<View>
|
|
100
|
+
{renderIcon &&
|
|
101
|
+
!['string', 'boolean', 'number'].includes(typeof renderIcon) && (
|
|
102
|
+
<View
|
|
103
|
+
style={[
|
|
104
|
+
styles.icon,
|
|
105
|
+
styles.iconHolder,
|
|
106
|
+
{marginBottom: Spacing.XS},
|
|
107
|
+
]}>
|
|
108
|
+
{renderIcon}
|
|
109
|
+
</View>
|
|
110
|
+
)}
|
|
111
|
+
{!renderIcon && !!icon && (
|
|
112
|
+
<Icon
|
|
113
|
+
style={[
|
|
114
|
+
styles.icon,
|
|
115
|
+
{
|
|
116
|
+
marginBottom: Spacing.XS,
|
|
117
|
+
},
|
|
118
|
+
]}
|
|
119
|
+
source={icon}
|
|
120
|
+
color={color}
|
|
121
|
+
/>
|
|
122
|
+
)}
|
|
123
|
+
{(renderIcon || !!icon) && showDot && (
|
|
124
|
+
<BadgeDot style={dotStyle} size={dotSize} />
|
|
125
|
+
)}
|
|
126
|
+
{(renderIcon || !!icon) && !showDot && badgeValue && (
|
|
127
|
+
<Badge label={badgeValue} style={styles.badge} />
|
|
128
|
+
)}
|
|
47
129
|
</View>
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
</TouchableOpacity>
|
|
57
|
-
);
|
|
130
|
+
<Text numberOfLines={1} typography={typography} color={color}>
|
|
131
|
+
{title}
|
|
132
|
+
</Text>
|
|
133
|
+
</TouchableOpacity>
|
|
134
|
+
);
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
return direction === 'row' ? renderRowItem() : renderColumnItem();
|
|
58
138
|
};
|
|
59
139
|
|
|
60
140
|
export default TabItem;
|
package/types.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {ReactElement} from 'react';
|
|
1
|
+
import {ReactElement, ReactNode} from 'react';
|
|
2
2
|
import {PagerViewProps} from 'react-native-pager-view';
|
|
3
|
+
import {Animated} from 'react-native';
|
|
3
4
|
|
|
4
5
|
export type Tab = {
|
|
5
6
|
/**
|
|
@@ -12,10 +13,7 @@ export type Tab = {
|
|
|
12
13
|
*/
|
|
13
14
|
icon?: string;
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
* Optional. Specifies the layout direction for the tab's content, either in a row or column format.
|
|
17
|
-
*/
|
|
18
|
-
direction?: 'row' | 'column';
|
|
16
|
+
renderIcon?: ReactNode;
|
|
19
17
|
|
|
20
18
|
/**
|
|
21
19
|
* The main component or content to be displayed when this tab is active.
|
|
@@ -31,6 +29,8 @@ export type Tab = {
|
|
|
31
29
|
* Optional. Specifies the size of the dot indicator, either 'small' or 'large'.
|
|
32
30
|
*/
|
|
33
31
|
dotSize?: 'small' | 'large';
|
|
32
|
+
|
|
33
|
+
badgeValue?: string | number;
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
export type TabItemProps = {
|
|
@@ -53,6 +53,15 @@ export type TabItemProps = {
|
|
|
53
53
|
* Optional. Specifies the width of the tab item. Useful for customizing layout and appearance.
|
|
54
54
|
*/
|
|
55
55
|
width?: number;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Optional. Specifies the layout direction for the tab's content, either in a row or column format.
|
|
59
|
+
*/
|
|
60
|
+
direction?: 'row' | 'column';
|
|
61
|
+
|
|
62
|
+
selectedColor?: string;
|
|
63
|
+
|
|
64
|
+
unselectedColor?: string;
|
|
56
65
|
};
|
|
57
66
|
|
|
58
67
|
export type TabViewProps = {
|
|
@@ -85,6 +94,15 @@ export type TabViewProps = {
|
|
|
85
94
|
* Optional. Additional properties to pass to the underlying pager view component.
|
|
86
95
|
*/
|
|
87
96
|
pagerProps?: PagerViewProps;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Optional. Specifies the layout direction for the tab's content, either in a row or column format.
|
|
100
|
+
*/
|
|
101
|
+
direction?: 'row' | 'column';
|
|
102
|
+
|
|
103
|
+
selectedColor?: string;
|
|
104
|
+
|
|
105
|
+
unselectedColor?: string;
|
|
88
106
|
};
|
|
89
107
|
|
|
90
108
|
/**
|
|
@@ -114,5 +132,14 @@ export type TabBarProps = {
|
|
|
114
132
|
/**
|
|
115
133
|
* Represents the horizontal scroll position in a scrollable tab bar.
|
|
116
134
|
*/
|
|
117
|
-
scrollX:
|
|
135
|
+
scrollX: Animated.Value;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Optional. Specifies the layout direction for the tab's content, either in a row or column format.
|
|
139
|
+
*/
|
|
140
|
+
direction?: 'row' | 'column';
|
|
141
|
+
|
|
142
|
+
selectedColor?: string;
|
|
143
|
+
|
|
144
|
+
unselectedColor?: string;
|
|
118
145
|
};
|