@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.
@@ -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
- export { default as TabBar } from './TabBar';
2
- export type { Props as TabBarProps } from './TabBar';
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
- export { default as TabView } from './TabView';
5
- export type { Props as TabViewProps } from './TabView';
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
- export { default as TabBarIndicator } from './TabBarIndicator';
8
- export type { Props as TabBarIndicatorProps } from './TabBarIndicator';
26
+ const _onPressTabItem = (index: number) => {
27
+ pagerRef.current?.setPage(index);
28
+ onPressTabItem?.(index);
29
+ setSelectedIndex(index);
30
+ };
9
31
 
10
- export { default as TabBarItem } from './TabBarItem';
11
- export type { Props as TabBarItemProps } from './TabBarItem';
32
+ const onLayout = (e: LayoutChangeEvent) => {
33
+ setTabBarWidth(e.nativeEvent.layout.width);
34
+ };
12
35
 
13
- export { default as SceneMap } from './SceneMap';
36
+ const onPageSelected = (e: {
37
+ nativeEvent: {position: React.SetStateAction<number>};
38
+ }) => {
39
+ setSelectedIndex(e.nativeEvent.position);
40
+ };
14
41
 
15
- export type { Route, NavigationState, SceneRendererProps } from './types';
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.0.55-alpha.31",
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/core": ">=0.0.5-beta",
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' --exclude 'web.js' ./* dist
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
- #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"}'
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';