@momo-kits/tab-view 0.154.1-beta.11 → 0.154.1-beta.13
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 +44 -18
- package/package.json +15 -15
- package/tabItem/CardTabItem.tsx +23 -10
- package/tabItem/TabItem.tsx +20 -13
- package/types.ts +7 -0
package/index.tsx
CHANGED
|
@@ -3,6 +3,7 @@ import React, {
|
|
|
3
3
|
ForwardRefRenderFunction,
|
|
4
4
|
useCallback,
|
|
5
5
|
useContext,
|
|
6
|
+
useEffect,
|
|
6
7
|
useImperativeHandle,
|
|
7
8
|
useMemo,
|
|
8
9
|
useRef,
|
|
@@ -38,6 +39,7 @@ const TabComponent: ForwardRefRenderFunction<TabViewRef, TabViewProps> = (
|
|
|
38
39
|
style,
|
|
39
40
|
accessibilityLabel,
|
|
40
41
|
accessibilityLabelForSelectedCard,
|
|
42
|
+
fitContent = false,
|
|
41
43
|
},
|
|
42
44
|
ref,
|
|
43
45
|
) => {
|
|
@@ -66,7 +68,10 @@ const TabComponent: ForwardRefRenderFunction<TabViewRef, TabViewProps> = (
|
|
|
66
68
|
|
|
67
69
|
const _onPressTabItem = (index: number) => {
|
|
68
70
|
onPressTabItem?.(index);
|
|
69
|
-
|
|
71
|
+
|
|
72
|
+
if (!fitContent) {
|
|
73
|
+
pagerRef.current?.setPage(index);
|
|
74
|
+
}
|
|
70
75
|
|
|
71
76
|
if (!lazy.includes(index)) {
|
|
72
77
|
lazy.push(index);
|
|
@@ -99,6 +104,12 @@ const TabComponent: ForwardRefRenderFunction<TabViewRef, TabViewProps> = (
|
|
|
99
104
|
pagerProps?.onPageScroll?.(e);
|
|
100
105
|
};
|
|
101
106
|
|
|
107
|
+
useEffect(() => {
|
|
108
|
+
if (fitContent) {
|
|
109
|
+
scrollX.current.setValue(selectedIndex);
|
|
110
|
+
}
|
|
111
|
+
}, [selectedIndex, fitContent]);
|
|
112
|
+
|
|
102
113
|
const renderScreen = useCallback(
|
|
103
114
|
(tab: Tab, index: number) => {
|
|
104
115
|
if (!lazy.includes(index)) return <View key={`TabView-page-${index}`} />;
|
|
@@ -109,14 +120,23 @@ const TabComponent: ForwardRefRenderFunction<TabViewRef, TabViewProps> = (
|
|
|
109
120
|
|
|
110
121
|
useImperativeHandle(ref, () => ({
|
|
111
122
|
goToPage: (page: number) => {
|
|
112
|
-
if (page >= 0 && page <= tabs.length)
|
|
123
|
+
if (page >= 0 && page <= tabs.length) {
|
|
124
|
+
if (fitContent) {
|
|
125
|
+
setSelectedIndex(page);
|
|
126
|
+
if (!lazy.includes(page)) {
|
|
127
|
+
lazy.push(page);
|
|
128
|
+
}
|
|
129
|
+
} else {
|
|
130
|
+
pagerRef.current?.setPage(page);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
113
133
|
},
|
|
114
134
|
}));
|
|
115
135
|
|
|
116
136
|
return (
|
|
117
137
|
<View
|
|
118
138
|
onLayout={onLayout}
|
|
119
|
-
style={[styles.tabView, { flex: 1 }]}
|
|
139
|
+
style={[styles.tabView, fitContent ? {} : { flex: 1 }]}
|
|
120
140
|
accessibilityLabel={componentId}
|
|
121
141
|
>
|
|
122
142
|
<Animated.View style={style}>
|
|
@@ -133,21 +153,27 @@ const TabComponent: ForwardRefRenderFunction<TabViewRef, TabViewProps> = (
|
|
|
133
153
|
/>
|
|
134
154
|
</Animated.View>
|
|
135
155
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
pagerProps
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
156
|
+
{fitContent ? (
|
|
157
|
+
<View>
|
|
158
|
+
{tabs[selectedIndex]?.component}
|
|
159
|
+
</View>
|
|
160
|
+
) : (
|
|
161
|
+
<PagerView
|
|
162
|
+
{...pagerProps}
|
|
163
|
+
onPageScroll={onPageScroll}
|
|
164
|
+
ref={pagerRef}
|
|
165
|
+
scrollEnabled={scrollEnabled.current}
|
|
166
|
+
onLayout={e => {
|
|
167
|
+
pagerProps?.onLayout?.(e);
|
|
168
|
+
scrollEnabled.current = pagerProps?.scrollEnabled ?? false;
|
|
169
|
+
}}
|
|
170
|
+
onPageSelected={onPageSelected}
|
|
171
|
+
style={styles.pagerView}
|
|
172
|
+
initialPage={startPage}
|
|
173
|
+
>
|
|
174
|
+
{tabs.map((tab, index) => renderScreen(tab, index))}
|
|
175
|
+
</PagerView>
|
|
176
|
+
)}
|
|
151
177
|
</View>
|
|
152
178
|
);
|
|
153
179
|
};
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
2
|
+
"name": "@momo-kits/tab-view",
|
|
3
|
+
"version": "0.154.1-beta.13",
|
|
4
|
+
"private": false,
|
|
5
|
+
"main": "index.tsx",
|
|
6
|
+
"peerDependencies": {
|
|
7
|
+
"@momo-kits/foundation": "latest",
|
|
8
|
+
"react": "*",
|
|
9
|
+
"react-native": "*"
|
|
10
|
+
},
|
|
11
|
+
"license": "MoMo",
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"registry": "https://registry.npmjs.org/"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {}
|
|
16
|
+
}
|
package/tabItem/CardTabItem.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import React, {FC, useContext, useMemo} from 'react';
|
|
2
|
-
import {TouchableOpacity, View} from 'react-native';
|
|
3
|
-
import {TabItemProps} from '../types';
|
|
1
|
+
import React, { FC, useContext, useMemo } from 'react';
|
|
2
|
+
import { TouchableOpacity, View } from 'react-native';
|
|
3
|
+
import { TabItemProps } from '../types';
|
|
4
4
|
import styles from '../styles';
|
|
5
5
|
import {
|
|
6
6
|
Badge,
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
ScreenContext,
|
|
11
11
|
Spacing,
|
|
12
12
|
Text,
|
|
13
|
+
useScaleSize,
|
|
13
14
|
} from '@momo-kits/foundation';
|
|
14
15
|
|
|
15
16
|
const CardTabItem: FC<TabItemProps> = ({
|
|
@@ -49,14 +50,19 @@ const CardTabItem: FC<TabItemProps> = ({
|
|
|
49
50
|
<>
|
|
50
51
|
{typeof renderIcon === 'function' && (
|
|
51
52
|
<View
|
|
52
|
-
style={[
|
|
53
|
+
style={[
|
|
54
|
+
styles.icon,
|
|
55
|
+
styles.iconHolder,
|
|
56
|
+
{ marginRight: Spacing.XS },
|
|
57
|
+
]}
|
|
58
|
+
>
|
|
53
59
|
{renderIcon(active)}
|
|
54
60
|
</View>
|
|
55
61
|
)}
|
|
56
62
|
{!renderIcon && !!icon && (
|
|
57
63
|
<Icon
|
|
58
64
|
color={color}
|
|
59
|
-
style={[styles.icon, {marginRight: Spacing.XS}]}
|
|
65
|
+
style={[styles.icon, { marginRight: Spacing.XS }]}
|
|
60
66
|
source={icon}
|
|
61
67
|
/>
|
|
62
68
|
)}
|
|
@@ -67,15 +73,22 @@ const CardTabItem: FC<TabItemProps> = ({
|
|
|
67
73
|
return (
|
|
68
74
|
<TouchableOpacity
|
|
69
75
|
onPress={onPressTabItem}
|
|
70
|
-
style={[
|
|
76
|
+
style={[
|
|
77
|
+
styles.cardTabItem,
|
|
78
|
+
{
|
|
79
|
+
width,
|
|
80
|
+
},
|
|
81
|
+
]}
|
|
71
82
|
accessibilityLabel={componentId}
|
|
72
|
-
accessibilityState={{checked: active}}
|
|
83
|
+
accessibilityState={{ checked: active }}
|
|
84
|
+
>
|
|
73
85
|
{renderIconTabItem()}
|
|
74
86
|
<Text
|
|
75
87
|
numberOfLines={1}
|
|
76
|
-
style={[styles.textCenter, {flexShrink: 1}]}
|
|
88
|
+
style={[styles.textCenter, { flexShrink: 1 }]}
|
|
77
89
|
typography={'body_default_regular'}
|
|
78
|
-
accessibilityLabel={`${componentId}|text`}
|
|
90
|
+
accessibilityLabel={`${componentId}|text`}
|
|
91
|
+
>
|
|
79
92
|
{title}
|
|
80
93
|
</Text>
|
|
81
94
|
{showDot && (
|
|
@@ -90,7 +103,7 @@ const CardTabItem: FC<TabItemProps> = ({
|
|
|
90
103
|
<View>
|
|
91
104
|
<Badge
|
|
92
105
|
label={badgeValue}
|
|
93
|
-
style={{marginLeft: Spacing.XS}}
|
|
106
|
+
style={{ marginLeft: Spacing.XS }}
|
|
94
107
|
accessibilityLabel={`${componentId}|badge`}
|
|
95
108
|
/>
|
|
96
109
|
</View>
|
package/tabItem/TabItem.tsx
CHANGED
|
@@ -40,6 +40,7 @@ const TabItem: FC<TabItemProps> = ({
|
|
|
40
40
|
const dotStyle = dotSize === 'large' ? styles.dot : styles.dotSmall;
|
|
41
41
|
const app = useContext<any>(MiniAppContext);
|
|
42
42
|
const screen = useContext<any>(ScreenContext);
|
|
43
|
+
const size48 = useScaleSize(48);
|
|
43
44
|
|
|
44
45
|
const componentName = 'TabItem';
|
|
45
46
|
|
|
@@ -55,28 +56,30 @@ const TabItem: FC<TabItemProps> = ({
|
|
|
55
56
|
return (
|
|
56
57
|
<TouchableOpacity
|
|
57
58
|
accessibilityLabel={componentId}
|
|
58
|
-
accessibilityState={{checked: active}}
|
|
59
|
+
accessibilityState={{ checked: active }}
|
|
59
60
|
style={[
|
|
60
61
|
styles.tabItem,
|
|
61
62
|
{
|
|
62
63
|
width,
|
|
63
|
-
height:
|
|
64
|
+
height: size48,
|
|
64
65
|
flexDirection: 'row',
|
|
65
66
|
overflow: 'hidden',
|
|
66
67
|
paddingVertical: Spacing.M,
|
|
67
68
|
paddingHorizontal: Spacing.M,
|
|
68
69
|
},
|
|
69
70
|
]}
|
|
70
|
-
onPress={onPressTabItem}
|
|
71
|
+
onPress={onPressTabItem}
|
|
72
|
+
>
|
|
71
73
|
{renderIcon && typeof renderIcon === 'function' && (
|
|
72
74
|
<View
|
|
73
|
-
style={[styles.icon, styles.iconHolder, {marginRight: Spacing.S}]}
|
|
75
|
+
style={[styles.icon, styles.iconHolder, { marginRight: Spacing.S }]}
|
|
76
|
+
>
|
|
74
77
|
{renderIcon(active)}
|
|
75
78
|
</View>
|
|
76
79
|
)}
|
|
77
80
|
{!renderIcon && !!icon && (
|
|
78
81
|
<Icon
|
|
79
|
-
style={[styles.icon, {marginRight: Spacing.S}]}
|
|
82
|
+
style={[styles.icon, { marginRight: Spacing.S }]}
|
|
80
83
|
source={icon}
|
|
81
84
|
color={color}
|
|
82
85
|
/>
|
|
@@ -85,18 +88,19 @@ const TabItem: FC<TabItemProps> = ({
|
|
|
85
88
|
numberOfLines={1}
|
|
86
89
|
typography={typography}
|
|
87
90
|
color={color}
|
|
88
|
-
style={{flexShrink: 1}}
|
|
89
|
-
accessibilityLabel={`${componentId}|text`}
|
|
91
|
+
style={{ flexShrink: 1 }}
|
|
92
|
+
accessibilityLabel={`${componentId}|text`}
|
|
93
|
+
>
|
|
90
94
|
{title}
|
|
91
95
|
</Text>
|
|
92
96
|
{showDot && (
|
|
93
|
-
<BadgeDot size={dotSize} style={{marginLeft: Spacing.XS}} />
|
|
97
|
+
<BadgeDot size={dotSize} style={{ marginLeft: Spacing.XS }} />
|
|
94
98
|
)}
|
|
95
99
|
{!showDot && badgeValue && (
|
|
96
100
|
<View>
|
|
97
101
|
<Badge
|
|
98
102
|
label={badgeValue}
|
|
99
|
-
style={{marginLeft: Spacing.XS}}
|
|
103
|
+
style={{ marginLeft: Spacing.XS }}
|
|
100
104
|
accessibilityLabel={`${componentId}|badge`}
|
|
101
105
|
/>
|
|
102
106
|
</View>
|
|
@@ -121,15 +125,17 @@ const TabItem: FC<TabItemProps> = ({
|
|
|
121
125
|
]}
|
|
122
126
|
onPress={onPressTabItem}
|
|
123
127
|
accessibilityLabel={componentId}
|
|
124
|
-
accessibilityState={{checked: active}}
|
|
128
|
+
accessibilityState={{ checked: active }}
|
|
129
|
+
>
|
|
125
130
|
<View>
|
|
126
131
|
{renderIcon && typeof renderIcon === 'function' && (
|
|
127
132
|
<View
|
|
128
133
|
style={[
|
|
129
134
|
styles.icon,
|
|
130
135
|
styles.iconHolder,
|
|
131
|
-
{marginBottom: Spacing.XS},
|
|
132
|
-
]}
|
|
136
|
+
{ marginBottom: Spacing.XS },
|
|
137
|
+
]}
|
|
138
|
+
>
|
|
133
139
|
{renderIcon(active)}
|
|
134
140
|
</View>
|
|
135
141
|
)}
|
|
@@ -160,7 +166,8 @@ const TabItem: FC<TabItemProps> = ({
|
|
|
160
166
|
numberOfLines={1}
|
|
161
167
|
typography={typography}
|
|
162
168
|
color={color}
|
|
163
|
-
accessibilityLabel={`${componentId}|text`}
|
|
169
|
+
accessibilityLabel={`${componentId}|text`}
|
|
170
|
+
>
|
|
164
171
|
{title}
|
|
165
172
|
</Text>
|
|
166
173
|
</TouchableOpacity>
|
package/types.ts
CHANGED
|
@@ -111,6 +111,13 @@ export type TabViewProps = {
|
|
|
111
111
|
accessibilityLabel?: string;
|
|
112
112
|
|
|
113
113
|
accessibilityLabelForSelectedCard?: string;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Optional. If `true`, the TabView will wrap its content height instead of using flex layout.
|
|
117
|
+
* When enabled, swipe gestures are disabled and only the selected tab content is rendered.
|
|
118
|
+
* Default is `false` (uses PagerView with flex layout and swipe enabled).
|
|
119
|
+
*/
|
|
120
|
+
fitContent?: boolean;
|
|
114
121
|
};
|
|
115
122
|
|
|
116
123
|
/**
|