@momo-kits/tab-view 0.0.55-alpha.31 → 0.77.8-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/assets/Path.tsx +22 -0
- package/index.tsx +76 -10
- package/package.json +4 -8
- package/publish.sh +2 -2
- package/styles.ts +80 -0
- package/tabBar/CardTabBar.tsx +73 -0
- package/tabBar/SrollableTabBar.tsx +97 -0
- package/tabBar/TabBar.tsx +55 -0
- package/tabItem/CardTabItem.tsx +30 -0
- package/tabItem/TabItem.tsx +52 -0
- package/types.ts +35 -0
- package/Pager.android.tsx +0 -1
- package/Pager.ios.tsx +0 -1
- package/Pager.tsx +0 -1
- package/PagerViewAdapter.tsx +0 -160
- package/PanResponderAdapter.tsx +0 -331
- package/PlatformPressable.tsx +0 -45
- package/SceneMap.tsx +0 -25
- package/SceneView.tsx +0 -142
- package/TabBar.tsx +0 -559
- package/TabBarIndicator.tsx +0 -160
- package/TabBarItem.tsx +0 -296
- package/TabView.tsx +0 -156
- package/types.tsx +0 -58
- package/useAnimatedValue.tsx +0 -12
package/assets/Path.tsx
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React, {FC} from 'react';
|
|
2
|
+
import {ViewProps} from 'react-native';
|
|
3
|
+
import Svg, {Path} from 'react-native-svg';
|
|
4
|
+
|
|
5
|
+
const PathSvg: FC<ViewProps> = ({style}) => {
|
|
6
|
+
return (
|
|
7
|
+
<Svg
|
|
8
|
+
width="28"
|
|
9
|
+
height="44"
|
|
10
|
+
viewBox="0 0 28 44"
|
|
11
|
+
fill="none"
|
|
12
|
+
style={style}
|
|
13
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
14
|
+
<Path
|
|
15
|
+
d="M0 0H0.60765C6.47582 0 11.4819 4.23831 12.4602 10.0244C13.9248 18.6872 15.9294 30.37 16.6925 34C17.9536 40 22.259 44 27.9996 44H0V0Z"
|
|
16
|
+
fill="white"
|
|
17
|
+
/>
|
|
18
|
+
</Svg>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default PathSvg;
|
package/index.tsx
CHANGED
|
@@ -1,15 +1,81 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import React, {FC, useRef, useState} from 'react';
|
|
2
|
+
import {LayoutChangeEvent, View} from 'react-native';
|
|
3
|
+
import {Tab, TabViewProps} from './types';
|
|
4
|
+
import TabBar from './tabBar/TabBar';
|
|
5
|
+
import styles from './styles';
|
|
6
|
+
import CardTabBar from './tabBar/CardTabBar';
|
|
7
|
+
import ScrollableTabBar from './tabBar/SrollableTabBar';
|
|
8
|
+
import PagerView from 'react-native-pager-view';
|
|
3
9
|
|
|
4
|
-
|
|
5
|
-
|
|
10
|
+
const TabView: FC<TabViewProps> = ({
|
|
11
|
+
scrollable = false,
|
|
12
|
+
tabs = [],
|
|
13
|
+
onPressTabItem,
|
|
14
|
+
type = 'default',
|
|
15
|
+
initialPage = 0,
|
|
16
|
+
pagerProps,
|
|
17
|
+
}) => {
|
|
18
|
+
const startPage =
|
|
19
|
+
initialPage > tabs.length - 1 ? tabs.length - 1 : initialPage;
|
|
20
|
+
const [selectedIndex, setSelectedIndex] = useState(startPage);
|
|
21
|
+
const [tabBarWidth, setTabBarWidth] = useState(0);
|
|
22
|
+
const isCardTab = type === 'card';
|
|
23
|
+
const pagerRef = useRef<PagerView>(null);
|
|
24
|
+
const [scrollX, setScrollX] = useState(0);
|
|
6
25
|
|
|
7
|
-
|
|
8
|
-
|
|
26
|
+
const _onPressTabItem = (index: number) => {
|
|
27
|
+
pagerRef.current?.setPage(index);
|
|
28
|
+
onPressTabItem?.(index);
|
|
29
|
+
setSelectedIndex(index);
|
|
30
|
+
};
|
|
9
31
|
|
|
10
|
-
|
|
11
|
-
|
|
32
|
+
const onLayout = (e: LayoutChangeEvent) => {
|
|
33
|
+
setTabBarWidth(e.nativeEvent.layout.width);
|
|
34
|
+
};
|
|
12
35
|
|
|
13
|
-
|
|
36
|
+
const onPageSelected = (e: {
|
|
37
|
+
nativeEvent: {position: React.SetStateAction<number>};
|
|
38
|
+
}) => {
|
|
39
|
+
setSelectedIndex(e.nativeEvent.position);
|
|
40
|
+
};
|
|
14
41
|
|
|
15
|
-
|
|
42
|
+
let TabBarComponent = scrollable ? ScrollableTabBar : TabBar;
|
|
43
|
+
|
|
44
|
+
if (isCardTab) {
|
|
45
|
+
TabBarComponent = CardTabBar;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const onPageScroll = (e: {nativeEvent: {position: any; offset: any}}) => {
|
|
49
|
+
const {position, offset} = e.nativeEvent;
|
|
50
|
+
setScrollX(position + offset);
|
|
51
|
+
};
|
|
52
|
+
return (
|
|
53
|
+
<View onLayout={onLayout} style={[styles.tabView, {flex: 1}]}>
|
|
54
|
+
<View>
|
|
55
|
+
<TabBarComponent
|
|
56
|
+
onPressTabItem={_onPressTabItem}
|
|
57
|
+
selectedIndex={selectedIndex}
|
|
58
|
+
tabs={tabs}
|
|
59
|
+
containerWidth={tabBarWidth}
|
|
60
|
+
scrollX={scrollX}
|
|
61
|
+
/>
|
|
62
|
+
</View>
|
|
63
|
+
|
|
64
|
+
<PagerView
|
|
65
|
+
{...pagerProps}
|
|
66
|
+
onPageScroll={onPageScroll}
|
|
67
|
+
ref={pagerRef}
|
|
68
|
+
onPageSelected={onPageSelected}
|
|
69
|
+
style={styles.pagerView}
|
|
70
|
+
initialPage={startPage}>
|
|
71
|
+
{tabs.map((i, index) => {
|
|
72
|
+
i.component.key = `Tab View Screen ${i.title}-${index}`;
|
|
73
|
+
return i.component;
|
|
74
|
+
})}
|
|
75
|
+
</PagerView>
|
|
76
|
+
</View>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export default TabView;
|
|
81
|
+
export type {TabViewProps, Tab};
|
package/package.json
CHANGED
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@momo-kits/tab-view",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.77.8-beta.06",
|
|
4
4
|
"private": false,
|
|
5
5
|
"main": "index.tsx",
|
|
6
|
-
"dependencies": {
|
|
7
|
-
"@momo-platform/versions": "4.0.2"
|
|
8
|
-
},
|
|
6
|
+
"dependencies": {},
|
|
9
7
|
"peerDependencies": {
|
|
10
|
-
"@momo-kits/
|
|
11
|
-
"@momo-kits/core-v2": ">=0.0.5-beta",
|
|
12
|
-
"lodash": "^4.17.15",
|
|
8
|
+
"@momo-kits/foundation": "latest",
|
|
13
9
|
"prop-types": "^15.7.2",
|
|
14
10
|
"react": "16.9.0",
|
|
15
11
|
"react-native": ">=0.55"
|
|
16
12
|
},
|
|
17
13
|
"devDependencies": {},
|
|
18
14
|
"license": "MoMo"
|
|
19
|
-
}
|
|
15
|
+
}
|
package/publish.sh
CHANGED
|
@@ -9,7 +9,7 @@ VERSIONSTRING=( v$(jq .version package.json) )
|
|
|
9
9
|
VERSION=(${VERSIONSTRING//[\"]/})
|
|
10
10
|
echo VERSION: $VERSION
|
|
11
11
|
|
|
12
|
-
rsync -r --verbose --exclude '*.mdx' --exclude '*Demo.js' --exclude 'props-type.js' --exclude 'prop-types.js'
|
|
12
|
+
rsync -r --verbose --exclude '*.mdx' --exclude '*Demo.js' --exclude 'props-type.js' --exclude 'prop-types.js' ./* dist
|
|
13
13
|
|
|
14
14
|
# #babel component to dist
|
|
15
15
|
#babel ./dist -d dist --copy-files
|
|
@@ -26,4 +26,4 @@ cd ..
|
|
|
26
26
|
rm -rf dist
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
##curl -X POST -H 'Content-Type: application/json' 'https://chat.googleapis.com/v1/spaces/AAAAbP8987c/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=UGSFRvk_oYb9uGsAgs31bVvMm6jDkmD8zihGm3eyaQA%3D&threadKey=JoaXTEYaNNkl' -d '{"text": "@momo-kits/tab-view new version release: '*"$VERSION"*' https://www.npmjs.com/package/@momo-kits/tab-view"}'
|
package/styles.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import {StyleSheet} from 'react-native';
|
|
2
|
+
import {Colors, Radius, Spacing} from '@momo-kits/foundation';
|
|
3
|
+
|
|
4
|
+
export default StyleSheet.create({
|
|
5
|
+
pagerView: {flex: 1},
|
|
6
|
+
textCenter: {
|
|
7
|
+
textAlign: 'center',
|
|
8
|
+
},
|
|
9
|
+
tabView: {
|
|
10
|
+
width: '100%',
|
|
11
|
+
},
|
|
12
|
+
tabBar: {
|
|
13
|
+
flexDirection: 'row',
|
|
14
|
+
borderBottomWidth: 1,
|
|
15
|
+
},
|
|
16
|
+
tabItem: {
|
|
17
|
+
padding: Spacing.M,
|
|
18
|
+
alignItems: 'center',
|
|
19
|
+
justifyContent: 'center',
|
|
20
|
+
},
|
|
21
|
+
indicator: {
|
|
22
|
+
height: 2,
|
|
23
|
+
borderTopLeftRadius: Radius.XXS,
|
|
24
|
+
borderTopRightRadius: Radius.XXS,
|
|
25
|
+
position: 'absolute',
|
|
26
|
+
bottom: 0,
|
|
27
|
+
},
|
|
28
|
+
icon: {
|
|
29
|
+
width: 24,
|
|
30
|
+
height: 24,
|
|
31
|
+
borderRadius: Radius.XS,
|
|
32
|
+
},
|
|
33
|
+
tabItemWrapper: {
|
|
34
|
+
paddingHorizontal: Spacing.XS,
|
|
35
|
+
alignItems: 'center',
|
|
36
|
+
},
|
|
37
|
+
cardTabBar: {
|
|
38
|
+
flexDirection: 'row',
|
|
39
|
+
marginTop: Spacing.XS,
|
|
40
|
+
alignItems: 'flex-end',
|
|
41
|
+
},
|
|
42
|
+
cardTabItem: {
|
|
43
|
+
paddingVertical: Spacing.M,
|
|
44
|
+
paddingHorizontal: Spacing.S,
|
|
45
|
+
borderTopLeftRadius: Spacing.M,
|
|
46
|
+
borderTopRightRadius: Spacing.M,
|
|
47
|
+
height: 40,
|
|
48
|
+
backgroundColor: Colors.black_02,
|
|
49
|
+
flexDirection: 'row',
|
|
50
|
+
justifyContent: 'center',
|
|
51
|
+
alignItems: 'center',
|
|
52
|
+
},
|
|
53
|
+
cardTabOverlay: {
|
|
54
|
+
flexDirection: 'row',
|
|
55
|
+
height: 44,
|
|
56
|
+
position: 'absolute',
|
|
57
|
+
top: -Spacing.XS,
|
|
58
|
+
borderTopLeftRadius: Spacing.M,
|
|
59
|
+
borderTopRightRadius: Spacing.M,
|
|
60
|
+
},
|
|
61
|
+
overlayTextWrapper: {
|
|
62
|
+
height: '100%',
|
|
63
|
+
alignItems: 'center',
|
|
64
|
+
justifyContent: 'center',
|
|
65
|
+
paddingTop: Spacing.XS,
|
|
66
|
+
flexDirection: 'row',
|
|
67
|
+
},
|
|
68
|
+
dotSmall: {
|
|
69
|
+
position: 'absolute',
|
|
70
|
+
top: -Spacing.XXS,
|
|
71
|
+
right: -Spacing.XXS,
|
|
72
|
+
zIndex: 2,
|
|
73
|
+
},
|
|
74
|
+
dot: {
|
|
75
|
+
position: 'absolute',
|
|
76
|
+
top: -Spacing.S,
|
|
77
|
+
right: -Spacing.XS,
|
|
78
|
+
zIndex: 2,
|
|
79
|
+
},
|
|
80
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import React, {FC, useContext, useEffect, useRef} from 'react';
|
|
2
|
+
import {Animated, View} from 'react-native';
|
|
3
|
+
import {TabBarProps} from '../types';
|
|
4
|
+
import styles from '../styles';
|
|
5
|
+
import {ApplicationContext, Image, Spacing, Text} from '@momo-kits/foundation';
|
|
6
|
+
import CardTabItem from '../tabItem/CardTabItem';
|
|
7
|
+
import PathSvg from '../assets/Path';
|
|
8
|
+
|
|
9
|
+
const CardTabBar: FC<TabBarProps> = ({
|
|
10
|
+
tabs,
|
|
11
|
+
onPressTabItem,
|
|
12
|
+
containerWidth,
|
|
13
|
+
selectedIndex,
|
|
14
|
+
}) => {
|
|
15
|
+
const {theme} = useContext(ApplicationContext);
|
|
16
|
+
const itemWidth = containerWidth / tabs.length;
|
|
17
|
+
const isFirst = selectedIndex === 0;
|
|
18
|
+
const isLast = selectedIndex === tabs.length - 1;
|
|
19
|
+
const backSpace = isFirst ? 0 : 28;
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<View style={styles.cardTabBar}>
|
|
23
|
+
{tabs.map((tab, index) => {
|
|
24
|
+
return (
|
|
25
|
+
<CardTabItem
|
|
26
|
+
tab={tab}
|
|
27
|
+
active={selectedIndex === index}
|
|
28
|
+
onPressTabItem={() => {
|
|
29
|
+
onPressTabItem?.(index);
|
|
30
|
+
}}
|
|
31
|
+
width={itemWidth}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
})}
|
|
35
|
+
<View
|
|
36
|
+
style={[
|
|
37
|
+
styles.cardTabOverlay,
|
|
38
|
+
{
|
|
39
|
+
width: containerWidth / tabs.length,
|
|
40
|
+
left: itemWidth * selectedIndex - backSpace,
|
|
41
|
+
},
|
|
42
|
+
]}>
|
|
43
|
+
{!isFirst && <PathSvg style={{transform: [{rotateY: '180deg'}]}} />}
|
|
44
|
+
<View
|
|
45
|
+
style={[
|
|
46
|
+
styles.overlayTextWrapper,
|
|
47
|
+
{
|
|
48
|
+
backgroundColor: theme.colors.background.surface,
|
|
49
|
+
width: containerWidth / tabs.length,
|
|
50
|
+
borderTopRightRadius: isLast ? Spacing.M : 0,
|
|
51
|
+
borderTopLeftRadius: isFirst ? Spacing.M : 0,
|
|
52
|
+
},
|
|
53
|
+
]}>
|
|
54
|
+
{!!tabs[selectedIndex]?.icon && (
|
|
55
|
+
<Image
|
|
56
|
+
source={{uri: tabs[selectedIndex]?.icon}}
|
|
57
|
+
style={[styles.icon, {marginRight: Spacing.XS}]}
|
|
58
|
+
/>
|
|
59
|
+
)}
|
|
60
|
+
<Text
|
|
61
|
+
numberOfLines={1}
|
|
62
|
+
style={styles.textCenter}
|
|
63
|
+
typography={'header_s'}>
|
|
64
|
+
{tabs[selectedIndex]?.title || ''}
|
|
65
|
+
</Text>
|
|
66
|
+
</View>
|
|
67
|
+
{!isLast && <PathSvg />}
|
|
68
|
+
</View>
|
|
69
|
+
</View>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default CardTabBar;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import React, {FC, useContext, useEffect, useRef, useState} from 'react';
|
|
2
|
+
import {Animated, LayoutChangeEvent, ScrollView, View} from 'react-native';
|
|
3
|
+
import {Tab, TabBarProps} from '../types';
|
|
4
|
+
import styles from '../styles';
|
|
5
|
+
import {ApplicationContext} from '@momo-kits/foundation';
|
|
6
|
+
import TabItem from '../tabItem/TabItem';
|
|
7
|
+
|
|
8
|
+
const ScrollableTabBar: FC<TabBarProps> = ({
|
|
9
|
+
tabs = [],
|
|
10
|
+
onPressTabItem,
|
|
11
|
+
selectedIndex,
|
|
12
|
+
}) => {
|
|
13
|
+
const {theme} = useContext(ApplicationContext);
|
|
14
|
+
const [itemWidthMap, setItemWidthMap] = useState<
|
|
15
|
+
{width: number; x: number}[]
|
|
16
|
+
>([]);
|
|
17
|
+
const animatedWidth = useRef(new Animated.Value(0)).current;
|
|
18
|
+
const scrollViewRef = useRef<ScrollView>(null);
|
|
19
|
+
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
moveIndicator();
|
|
22
|
+
scrollToIndex(selectedIndex);
|
|
23
|
+
}, [selectedIndex, itemWidthMap]);
|
|
24
|
+
const moveIndicator = () => {
|
|
25
|
+
Animated.timing(animatedWidth, {
|
|
26
|
+
toValue: itemWidthMap[selectedIndex]?.width || 0,
|
|
27
|
+
duration: 250,
|
|
28
|
+
useNativeDriver: false,
|
|
29
|
+
}).start();
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const onLayout = (e: LayoutChangeEvent, index: number) => {
|
|
33
|
+
const {width, x} = e.nativeEvent.layout;
|
|
34
|
+
|
|
35
|
+
const newMap: Array<any> = [...itemWidthMap];
|
|
36
|
+
newMap[index] = {width, x};
|
|
37
|
+
setItemWidthMap(newMap);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const scrollToIndex = (index: number) => {
|
|
41
|
+
scrollViewRef.current?.scrollTo({
|
|
42
|
+
x: itemWidthMap[index]?.x || 0,
|
|
43
|
+
animated: true,
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const _onPressTabItem = (index: number) => {
|
|
48
|
+
scrollToIndex(index);
|
|
49
|
+
onPressTabItem?.(index);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const renderItem = (params: {item: Tab; index: number}) => {
|
|
53
|
+
const {item, index} = params;
|
|
54
|
+
const isActive = selectedIndex === index;
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<View onLayout={e => onLayout(e, index)} style={styles.tabItemWrapper}>
|
|
58
|
+
<TabItem
|
|
59
|
+
key={`Tab View Item ${item.title}-${index}`}
|
|
60
|
+
onPressTabItem={() => {
|
|
61
|
+
_onPressTabItem(index);
|
|
62
|
+
}}
|
|
63
|
+
active={isActive}
|
|
64
|
+
tab={item}
|
|
65
|
+
/>
|
|
66
|
+
</View>
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<ScrollView
|
|
72
|
+
ref={scrollViewRef}
|
|
73
|
+
showsHorizontalScrollIndicator={false}
|
|
74
|
+
style={[
|
|
75
|
+
styles.tabBar,
|
|
76
|
+
{
|
|
77
|
+
borderColor: theme.colors.border.default,
|
|
78
|
+
backgroundColor: theme.colors.background.surface,
|
|
79
|
+
},
|
|
80
|
+
]}
|
|
81
|
+
horizontal>
|
|
82
|
+
{tabs.map((item, index) => renderItem({item, index}))}
|
|
83
|
+
<Animated.View
|
|
84
|
+
style={[
|
|
85
|
+
styles.indicator,
|
|
86
|
+
{
|
|
87
|
+
left: itemWidthMap[selectedIndex]?.x || 0,
|
|
88
|
+
width: animatedWidth,
|
|
89
|
+
backgroundColor: theme.colors.primary,
|
|
90
|
+
},
|
|
91
|
+
]}
|
|
92
|
+
/>
|
|
93
|
+
</ScrollView>
|
|
94
|
+
);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export default ScrollableTabBar;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React, {FC, useContext} from 'react';
|
|
2
|
+
import {Animated, View} from 'react-native';
|
|
3
|
+
import {TabBarProps} from '../types';
|
|
4
|
+
import TabItem from '../tabItem/TabItem';
|
|
5
|
+
import styles from '../styles';
|
|
6
|
+
import {ApplicationContext, Spacing} from '@momo-kits/foundation';
|
|
7
|
+
|
|
8
|
+
const TabBar: FC<TabBarProps> = ({
|
|
9
|
+
tabs = [],
|
|
10
|
+
selectedIndex,
|
|
11
|
+
onPressTabItem,
|
|
12
|
+
containerWidth = 0,
|
|
13
|
+
scrollX,
|
|
14
|
+
}) => {
|
|
15
|
+
const {theme} = useContext(ApplicationContext);
|
|
16
|
+
|
|
17
|
+
const itemWidth = containerWidth / tabs.length;
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<View
|
|
21
|
+
style={[
|
|
22
|
+
styles.tabBar,
|
|
23
|
+
{
|
|
24
|
+
borderColor: theme.colors.border.default,
|
|
25
|
+
backgroundColor: theme.colors.background.surface,
|
|
26
|
+
},
|
|
27
|
+
]}>
|
|
28
|
+
{tabs.map((tab, index) => {
|
|
29
|
+
return (
|
|
30
|
+
<TabItem
|
|
31
|
+
key={`Tab View Item ${tab.title}-${index}`}
|
|
32
|
+
width={itemWidth}
|
|
33
|
+
onPressTabItem={() => {
|
|
34
|
+
onPressTabItem?.(index);
|
|
35
|
+
}}
|
|
36
|
+
active={selectedIndex === index}
|
|
37
|
+
tab={tab}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
})}
|
|
41
|
+
<Animated.View
|
|
42
|
+
style={[
|
|
43
|
+
styles.indicator,
|
|
44
|
+
{
|
|
45
|
+
left: scrollX * itemWidth + Spacing.XS,
|
|
46
|
+
width: itemWidth - Spacing.XS * 2,
|
|
47
|
+
backgroundColor: theme.colors.primary,
|
|
48
|
+
},
|
|
49
|
+
]}
|
|
50
|
+
/>
|
|
51
|
+
</View>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default TabBar;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React, {FC} from 'react';
|
|
2
|
+
import {TouchableOpacity, View} from 'react-native';
|
|
3
|
+
import {TabItemProps} from '../types';
|
|
4
|
+
import styles from '../styles';
|
|
5
|
+
import {Image, Spacing, Text} from '@momo-kits/foundation';
|
|
6
|
+
|
|
7
|
+
const CardTabItem: FC<TabItemProps> = ({tab, onPressTabItem, width}) => {
|
|
8
|
+
const {title, icon} = tab;
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<TouchableOpacity
|
|
12
|
+
onPress={onPressTabItem}
|
|
13
|
+
style={[styles.cardTabItem, {width}]}>
|
|
14
|
+
{!!icon && (
|
|
15
|
+
<Image
|
|
16
|
+
source={{uri: icon}}
|
|
17
|
+
style={[styles.icon, {marginRight: Spacing.XS}]}
|
|
18
|
+
/>
|
|
19
|
+
)}
|
|
20
|
+
<Text
|
|
21
|
+
numberOfLines={1}
|
|
22
|
+
style={styles.textCenter}
|
|
23
|
+
typography={'description_default'}>
|
|
24
|
+
{title}
|
|
25
|
+
</Text>
|
|
26
|
+
</TouchableOpacity>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default CardTabItem;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React, {FC, useContext} from 'react';
|
|
2
|
+
import {TouchableOpacity, View, ViewStyle} from 'react-native';
|
|
3
|
+
import {TabItemProps} from '../types';
|
|
4
|
+
import {
|
|
5
|
+
ApplicationContext,
|
|
6
|
+
Image,
|
|
7
|
+
Spacing,
|
|
8
|
+
Text,
|
|
9
|
+
Typography,
|
|
10
|
+
} from '@momo-kits/foundation';
|
|
11
|
+
import styles from '../styles';
|
|
12
|
+
import {BadgeDot} from '@momo-kits/badge';
|
|
13
|
+
|
|
14
|
+
const TabItem: FC<TabItemProps> = ({tab, active, onPressTabItem, width}) => {
|
|
15
|
+
const {theme} = useContext(ApplicationContext);
|
|
16
|
+
const {
|
|
17
|
+
title,
|
|
18
|
+
icon,
|
|
19
|
+
direction = 'row',
|
|
20
|
+
showDot = false,
|
|
21
|
+
dotSize = 'small',
|
|
22
|
+
} = tab;
|
|
23
|
+
const typography: Typography = active ? 'header_s' : 'description_default';
|
|
24
|
+
const color = active ? theme.colors.primary : theme.colors.text.default;
|
|
25
|
+
const dotStyle = dotSize === 'large' ? styles.dot : styles.dotSmall;
|
|
26
|
+
const iconStyle: ViewStyle =
|
|
27
|
+
direction === 'row'
|
|
28
|
+
? {marginRight: Spacing.XS}
|
|
29
|
+
: {marginBottom: Spacing.XS};
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<TouchableOpacity
|
|
33
|
+
onPress={onPressTabItem}
|
|
34
|
+
style={[styles.tabItem, {width, flexDirection: direction}]}>
|
|
35
|
+
{!!icon && (
|
|
36
|
+
<View>
|
|
37
|
+
{showDot && <BadgeDot style={dotStyle} size={dotSize} />}
|
|
38
|
+
<Image style={[styles.icon, iconStyle]} source={{uri: icon}} />
|
|
39
|
+
</View>
|
|
40
|
+
)}
|
|
41
|
+
<Text
|
|
42
|
+
style={styles.textCenter}
|
|
43
|
+
numberOfLines={1}
|
|
44
|
+
color={color}
|
|
45
|
+
typography={typography}>
|
|
46
|
+
{title}
|
|
47
|
+
</Text>
|
|
48
|
+
</TouchableOpacity>
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export default TabItem;
|
package/types.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {ReactElement} from 'react';
|
|
2
|
+
import {PagerViewProps} from 'react-native-pager-view';
|
|
3
|
+
|
|
4
|
+
export type Tab = {
|
|
5
|
+
title: string;
|
|
6
|
+
icon?: string;
|
|
7
|
+
direction?: 'row' | 'column';
|
|
8
|
+
component: ReactElement;
|
|
9
|
+
showDot?: boolean;
|
|
10
|
+
dotSize?: 'small' | 'large';
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type TabItemProps = {
|
|
14
|
+
tab: Tab;
|
|
15
|
+
active: boolean;
|
|
16
|
+
onPressTabItem?: () => void;
|
|
17
|
+
width?: number;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type TabViewProps = {
|
|
21
|
+
scrollable?: boolean;
|
|
22
|
+
tabs: Tab[];
|
|
23
|
+
onPressTabItem?: (index: number) => void;
|
|
24
|
+
type?: 'default' | 'card';
|
|
25
|
+
initialPage?: number;
|
|
26
|
+
pagerProps?: PagerViewProps;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type TabBarProps = {
|
|
30
|
+
tabs: Tab[];
|
|
31
|
+
selectedIndex: number;
|
|
32
|
+
onPressTabItem?: (index: number) => void;
|
|
33
|
+
containerWidth: number;
|
|
34
|
+
scrollX: number;
|
|
35
|
+
};
|
package/Pager.android.tsx
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from './PagerViewAdapter';
|
package/Pager.ios.tsx
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from './PagerViewAdapter';
|
package/Pager.tsx
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from './PanResponderAdapter';
|