react-native-tab-view 4.0.0-alpha.0 → 4.0.0-alpha.10

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 (85) hide show
  1. package/lib/commonjs/Pager.android.js.map +1 -1
  2. package/lib/commonjs/Pager.ios.js.map +1 -1
  3. package/lib/commonjs/Pager.js.map +1 -1
  4. package/lib/commonjs/PagerViewAdapter.js +9 -13
  5. package/lib/commonjs/PagerViewAdapter.js.map +1 -1
  6. package/lib/commonjs/PanResponderAdapter.js +4 -4
  7. package/lib/commonjs/PanResponderAdapter.js.map +1 -1
  8. package/lib/commonjs/PlatformPressable.js +24 -3
  9. package/lib/commonjs/PlatformPressable.js.map +1 -1
  10. package/lib/commonjs/SceneMap.js +2 -2
  11. package/lib/commonjs/SceneMap.js.map +1 -1
  12. package/lib/commonjs/SceneView.js +3 -4
  13. package/lib/commonjs/SceneView.js.map +1 -1
  14. package/lib/commonjs/TabBar.js +112 -97
  15. package/lib/commonjs/TabBar.js.map +1 -1
  16. package/lib/commonjs/TabBarIndicator.js +21 -16
  17. package/lib/commonjs/TabBarIndicator.js.map +1 -1
  18. package/lib/commonjs/TabBarItem.js +58 -80
  19. package/lib/commonjs/TabBarItem.js.map +1 -1
  20. package/lib/commonjs/TabBarItemLabel.js +4 -4
  21. package/lib/commonjs/TabBarItemLabel.js.map +1 -1
  22. package/lib/commonjs/TabView.js +3 -3
  23. package/lib/commonjs/TabView.js.map +1 -1
  24. package/lib/commonjs/index.js.map +1 -1
  25. package/lib/commonjs/types.js.map +1 -1
  26. package/lib/commonjs/useAnimatedValue.js +2 -2
  27. package/lib/commonjs/useAnimatedValue.js.map +1 -1
  28. package/lib/module/Pager.android.js.map +1 -1
  29. package/lib/module/Pager.ios.js.map +1 -1
  30. package/lib/module/Pager.js.map +1 -1
  31. package/lib/module/PagerViewAdapter.js +7 -11
  32. package/lib/module/PagerViewAdapter.js.map +1 -1
  33. package/lib/module/PanResponderAdapter.js +2 -2
  34. package/lib/module/PanResponderAdapter.js.map +1 -1
  35. package/lib/module/PlatformPressable.js +22 -1
  36. package/lib/module/PlatformPressable.js.map +1 -1
  37. package/lib/module/SceneMap.js.map +1 -1
  38. package/lib/module/SceneView.js +1 -2
  39. package/lib/module/SceneView.js.map +1 -1
  40. package/lib/module/TabBar.js +110 -95
  41. package/lib/module/TabBar.js.map +1 -1
  42. package/lib/module/TabBarIndicator.js +19 -14
  43. package/lib/module/TabBarIndicator.js.map +1 -1
  44. package/lib/module/TabBarItem.js +56 -78
  45. package/lib/module/TabBarItem.js.map +1 -1
  46. package/lib/module/TabBarItemLabel.js +3 -2
  47. package/lib/module/TabBarItemLabel.js.map +1 -1
  48. package/lib/module/TabView.js +1 -1
  49. package/lib/module/TabView.js.map +1 -1
  50. package/lib/module/index.js.map +1 -1
  51. package/lib/module/types.js.map +1 -1
  52. package/lib/module/useAnimatedValue.js.map +1 -1
  53. package/lib/typescript/src/PlatformPressable.d.ts +4 -3
  54. package/lib/typescript/src/PlatformPressable.d.ts.map +1 -1
  55. package/lib/typescript/src/SceneMap.d.ts +2 -2
  56. package/lib/typescript/src/SceneMap.d.ts.map +1 -1
  57. package/lib/typescript/src/SceneView.d.ts +2 -2
  58. package/lib/typescript/src/SceneView.d.ts.map +1 -1
  59. package/lib/typescript/src/TabBar.d.ts +7 -18
  60. package/lib/typescript/src/TabBar.d.ts.map +1 -1
  61. package/lib/typescript/src/TabBarIndicator.d.ts +3 -3
  62. package/lib/typescript/src/TabBarIndicator.d.ts.map +1 -1
  63. package/lib/typescript/src/TabBarItem.d.ts +4 -19
  64. package/lib/typescript/src/TabBarItem.d.ts.map +1 -1
  65. package/lib/typescript/src/TabBarItemLabel.d.ts +1 -1
  66. package/lib/typescript/src/TabBarItemLabel.d.ts.map +1 -1
  67. package/lib/typescript/src/TabView.d.ts +5 -5
  68. package/lib/typescript/src/TabView.d.ts.map +1 -1
  69. package/lib/typescript/src/index.d.ts +1 -1
  70. package/lib/typescript/src/index.d.ts.map +1 -1
  71. package/lib/typescript/src/types.d.ts +25 -1
  72. package/lib/typescript/src/types.d.ts.map +1 -1
  73. package/package.json +11 -11
  74. package/src/PagerViewAdapter.tsx +2 -2
  75. package/src/PanResponderAdapter.tsx +4 -4
  76. package/src/PlatformPressable.tsx +31 -2
  77. package/src/SceneMap.tsx +1 -3
  78. package/src/SceneView.tsx +4 -4
  79. package/src/TabBar.tsx +178 -179
  80. package/src/TabBarIndicator.tsx +22 -14
  81. package/src/TabBarItem.tsx +92 -118
  82. package/src/TabBarItemLabel.tsx +2 -1
  83. package/src/TabView.tsx +5 -5
  84. package/src/index.tsx +6 -1
  85. package/src/types.tsx +25 -1
@@ -1,21 +1,21 @@
1
1
  import * as React from 'react';
2
2
  import {
3
3
  Animated,
4
- LayoutChangeEvent,
5
- PressableAndroidRippleConfig,
6
- StyleProp,
4
+ type LayoutChangeEvent,
5
+ type PressableAndroidRippleConfig,
6
+ type StyleProp,
7
7
  StyleSheet,
8
- TextStyle,
8
+ type TextStyle,
9
9
  View,
10
- ViewStyle,
10
+ type ViewStyle,
11
11
  } from 'react-native';
12
12
  import useLatestCallback from 'use-latest-callback';
13
13
 
14
14
  import { PlatformPressable } from './PlatformPressable';
15
15
  import { TabBarItemLabel } from './TabBarItemLabel';
16
- import type { NavigationState, Route, Scene } from './types';
16
+ import type { NavigationState, Route, TabDescriptor } from './types';
17
17
 
18
- export type Props<T extends Route> = {
18
+ export type Props<T extends Route> = TabDescriptor<T> & {
19
19
  position: Animated.AnimatedInterpolation<number>;
20
20
  route: T;
21
21
  navigationState: NavigationState<T>;
@@ -23,21 +23,6 @@ export type Props<T extends Route> = {
23
23
  inactiveColor?: string;
24
24
  pressColor?: string;
25
25
  pressOpacity?: number;
26
- getLabelText: (scene: Scene<T>) => string | undefined;
27
- getAccessible: (scene: Scene<T>) => boolean | undefined;
28
- getAccessibilityLabel: (scene: Scene<T>) => string | undefined;
29
- getTestID: (scene: Scene<T>) => string | undefined;
30
- renderLabel?: (scene: {
31
- route: T;
32
- focused: boolean;
33
- color: string;
34
- }) => React.ReactNode;
35
- renderIcon?: (scene: {
36
- route: T;
37
- focused: boolean;
38
- color: string;
39
- }) => React.ReactNode;
40
- renderBadge?: (scene: Scene<T>) => React.ReactNode;
41
26
  onLayout?: (event: LayoutChangeEvent) => void;
42
27
  onPress: () => void;
43
28
  onLongPress: () => void;
@@ -49,6 +34,7 @@ export type Props<T extends Route> = {
49
34
 
50
35
  const DEFAULT_ACTIVE_COLOR = 'rgba(255, 255, 255, 1)';
51
36
  const DEFAULT_INACTIVE_COLOR = 'rgba(255, 255, 255, 0.7)';
37
+ const ICON_SIZE = 24;
52
38
 
53
39
  const getActiveOpacity = (
54
40
  position: Animated.AnimatedInterpolation<number>,
@@ -91,26 +77,22 @@ type TabBarItemInternalProps<T extends Route> = Omit<
91
77
  | 'getLabelText'
92
78
  | 'getTestID'
93
79
  | 'getAccessible'
80
+ | 'options'
94
81
  > & {
95
82
  isFocused: boolean;
96
83
  index: number;
97
84
  routesLength: number;
98
- accessibilityLabel?: string;
99
- label?: string;
100
- testID?: string;
101
- accessible?: boolean;
102
- };
85
+ } & TabDescriptor<T>;
103
86
 
104
87
  const TabBarItemInternal = <T extends Route>({
105
88
  accessibilityLabel,
106
89
  accessible,
107
- label: labelText,
90
+ label: customlabel,
108
91
  testID,
109
92
  onLongPress,
110
93
  onPress,
111
94
  isFocused,
112
95
  position,
113
- route,
114
96
  style,
115
97
  inactiveColor: inactiveColorCustom,
116
98
  activeColor: activeColorCustom,
@@ -119,12 +101,15 @@ const TabBarItemInternal = <T extends Route>({
119
101
  index: tabIndex,
120
102
  pressColor,
121
103
  pressOpacity,
122
- renderBadge,
123
- renderIcon,
124
104
  defaultTabWidth,
105
+ icon: customIcon,
106
+ badge: customBadge,
107
+ href,
108
+ labelText,
125
109
  routesLength,
126
- renderLabel: renderLabelCustom,
127
110
  android_ripple = { borderless: true },
111
+ labelAllowFontScaling,
112
+ route,
128
113
  }: TabBarItemInternalProps<T>) => {
129
114
  const labelColorFromStyle = StyleSheet.flatten(labelStyle || {}).color;
130
115
 
@@ -132,85 +117,88 @@ const TabBarItemInternal = <T extends Route>({
132
117
  activeColorCustom !== undefined
133
118
  ? activeColorCustom
134
119
  : typeof labelColorFromStyle === 'string'
135
- ? labelColorFromStyle
136
- : DEFAULT_ACTIVE_COLOR;
120
+ ? labelColorFromStyle
121
+ : DEFAULT_ACTIVE_COLOR;
137
122
  const inactiveColor =
138
123
  inactiveColorCustom !== undefined
139
124
  ? inactiveColorCustom
140
125
  : typeof labelColorFromStyle === 'string'
141
- ? labelColorFromStyle
142
- : DEFAULT_INACTIVE_COLOR;
126
+ ? labelColorFromStyle
127
+ : DEFAULT_INACTIVE_COLOR;
143
128
 
144
129
  const activeOpacity = getActiveOpacity(position, routesLength, tabIndex);
145
130
  const inactiveOpacity = getInactiveOpacity(position, routesLength, tabIndex);
146
131
 
147
- let icon: React.ReactNode | null = null;
148
- let label: React.ReactNode | null = null;
132
+ const icon = React.useMemo(() => {
133
+ if (!customIcon) {
134
+ return null;
135
+ }
149
136
 
150
- if (renderIcon) {
151
- const activeIcon = renderIcon({
152
- route,
153
- focused: true,
154
- color: activeColor,
155
- });
156
- const inactiveIcon = renderIcon({
157
- route,
137
+ const inactiveIcon = customIcon({
158
138
  focused: false,
159
139
  color: inactiveColor,
140
+ size: ICON_SIZE,
141
+ route,
160
142
  });
161
143
 
162
- if (inactiveIcon != null && activeIcon != null) {
163
- icon = (
164
- <View style={styles.icon}>
165
- <Animated.View style={{ opacity: inactiveOpacity }}>
166
- {inactiveIcon}
167
- </Animated.View>
168
- <Animated.View
169
- style={[StyleSheet.absoluteFill, { opacity: activeOpacity }]}
170
- >
171
- {activeIcon}
172
- </Animated.View>
173
- </View>
174
- );
175
- }
176
- }
177
-
178
- const renderLabel = renderLabelCustom
179
- ? renderLabelCustom
180
- : (labelProps: { color: string }) => (
181
- <TabBarItemLabel
182
- {...labelProps}
183
- icon={icon}
184
- label={labelText}
185
- labelStyle={labelStyle}
186
- />
187
- );
188
-
189
- if (renderLabel) {
190
- const activeLabel = renderLabel({
191
- route,
144
+ const activeIcon = customIcon({
192
145
  focused: true,
193
146
  color: activeColor,
194
- });
195
- const inactiveLabel = renderLabel({
147
+ size: ICON_SIZE,
196
148
  route,
197
- focused: false,
198
- color: inactiveColor,
199
149
  });
200
150
 
201
- label = (
202
- <View>
151
+ return (
152
+ <View style={styles.icon}>
203
153
  <Animated.View style={{ opacity: inactiveOpacity }}>
204
- {inactiveLabel}
154
+ {inactiveIcon}
205
155
  </Animated.View>
206
156
  <Animated.View
207
157
  style={[StyleSheet.absoluteFill, { opacity: activeOpacity }]}
208
158
  >
209
- {activeLabel}
159
+ {activeIcon}
210
160
  </Animated.View>
211
161
  </View>
212
162
  );
213
- }
163
+ }, [
164
+ activeColor,
165
+ activeOpacity,
166
+ customIcon,
167
+ inactiveColor,
168
+ inactiveOpacity,
169
+ route,
170
+ ]);
171
+
172
+ const renderLabel = React.useCallback(
173
+ (focused: boolean) =>
174
+ customlabel ? (
175
+ customlabel({
176
+ focused,
177
+ color: focused ? activeColor : inactiveColor,
178
+ style: labelStyle,
179
+ label: labelText,
180
+ allowFontScaling: labelAllowFontScaling,
181
+ route,
182
+ })
183
+ ) : (
184
+ <TabBarItemLabel
185
+ color={focused ? activeColor : inactiveColor}
186
+ icon={icon}
187
+ label={labelText}
188
+ labelStyle={labelStyle}
189
+ />
190
+ ),
191
+ [
192
+ customlabel,
193
+ activeColor,
194
+ labelStyle,
195
+ labelText,
196
+ labelAllowFontScaling,
197
+ route,
198
+ inactiveColor,
199
+ icon,
200
+ ]
201
+ );
214
202
 
215
203
  const tabStyle = StyleSheet.flatten(style);
216
204
  const isWidthSet = tabStyle?.width !== undefined;
@@ -219,13 +207,9 @@ const TabBarItemInternal = <T extends Route>({
219
207
  ? null
220
208
  : { width: defaultTabWidth };
221
209
 
222
- const scene = { route };
223
-
224
210
  accessibilityLabel =
225
211
  typeof accessibilityLabel !== 'undefined' ? accessibilityLabel : labelText;
226
212
 
227
- const badge = renderBadge ? renderBadge(scene) : null;
228
-
229
213
  return (
230
214
  <PlatformPressable
231
215
  android_ripple={android_ripple}
@@ -234,20 +218,30 @@ const TabBarItemInternal = <T extends Route>({
234
218
  accessibilityLabel={accessibilityLabel}
235
219
  accessibilityRole="tab"
236
220
  accessibilityState={{ selected: isFocused }}
237
- // @ts-ignore: this is to support older React Native versions
238
- accessibilityStates={isFocused ? ['selected'] : []}
239
221
  pressColor={pressColor}
240
222
  pressOpacity={pressOpacity}
241
- delayPressIn={0}
223
+ unstable_pressDelay={0}
242
224
  onLayout={onLayout}
243
225
  onPress={onPress}
244
226
  onLongPress={onLongPress}
227
+ href={href}
245
228
  style={[styles.pressable, tabContainerStyle]}
246
229
  >
247
230
  <View pointerEvents="none" style={[styles.item, tabStyle]}>
248
231
  {icon}
249
- {label}
250
- {badge != null ? <View style={styles.badge}>{badge}</View> : null}
232
+ <View>
233
+ <Animated.View style={{ opacity: inactiveOpacity }}>
234
+ {renderLabel(false)}
235
+ </Animated.View>
236
+ <Animated.View
237
+ style={[StyleSheet.absoluteFill, { opacity: activeOpacity }]}
238
+ >
239
+ {renderLabel(true)}
240
+ </Animated.View>
241
+ </View>
242
+ {customBadge != null ? (
243
+ <View style={styles.badge}>{customBadge()}</View>
244
+ ) : null}
251
245
  </View>
252
246
  </PlatformPressable>
253
247
  );
@@ -258,31 +252,15 @@ const MemoizedTabBarItemInternal = React.memo(
258
252
  ) as typeof TabBarItemInternal;
259
253
 
260
254
  export function TabBarItem<T extends Route>(props: Props<T>) {
261
- const {
262
- onPress,
263
- onLongPress,
264
- onLayout,
265
- navigationState,
266
- route,
267
- getAccessibilityLabel,
268
- getLabelText,
269
- getTestID,
270
- getAccessible,
271
- ...rest
272
- } = props;
255
+ const { onPress, onLongPress, onLayout, navigationState, route, ...rest } =
256
+ props;
257
+
273
258
  const onPressLatest = useLatestCallback(onPress);
274
259
  const onLongPressLatest = useLatestCallback(onLongPress);
275
260
  const onLayoutLatest = useLatestCallback(onLayout ? onLayout : () => {});
276
261
 
277
262
  const tabIndex = navigationState.routes.indexOf(route);
278
263
 
279
- const scene = { route };
280
-
281
- const accessibilityLabel = getAccessibilityLabel(scene);
282
- const label = getLabelText(scene);
283
- const testID = getTestID(scene);
284
- const accessible = getAccessible(scene);
285
-
286
264
  return (
287
265
  <MemoizedTabBarItemInternal
288
266
  {...rest}
@@ -293,10 +271,6 @@ export function TabBarItem<T extends Route>(props: Props<T>) {
293
271
  route={route}
294
272
  index={tabIndex}
295
273
  routesLength={navigationState.routes.length}
296
- accessibilityLabel={accessibilityLabel}
297
- label={label}
298
- testID={testID}
299
- accessible={accessible}
300
274
  />
301
275
  );
302
276
  }
@@ -315,7 +289,7 @@ const styles = StyleSheet.create({
315
289
  badge: {
316
290
  position: 'absolute',
317
291
  top: 0,
318
- right: 0,
292
+ end: 0,
319
293
  },
320
294
  pressable: {
321
295
  // The label is not pressable on Windows
@@ -33,7 +33,8 @@ export const TabBarItemLabel = React.memo(
33
33
  const styles = StyleSheet.create({
34
34
  label: {
35
35
  margin: 4,
36
+ fontSize: 14,
37
+ fontWeight: '500',
36
38
  backgroundColor: 'transparent',
37
- textTransform: 'uppercase',
38
39
  },
39
40
  });
package/src/TabView.tsx CHANGED
@@ -1,12 +1,12 @@
1
1
  import * as React from 'react';
2
2
  import {
3
3
  I18nManager,
4
- LayoutChangeEvent,
4
+ type LayoutChangeEvent,
5
5
  Platform,
6
- StyleProp,
6
+ type StyleProp,
7
7
  StyleSheet,
8
8
  View,
9
- ViewStyle,
9
+ type ViewStyle,
10
10
  } from 'react-native';
11
11
 
12
12
  import { Pager } from './Pager';
@@ -24,7 +24,6 @@ import type {
24
24
  export type Props<T extends Route> = Omit<PagerProps, 'layoutDirection'> & {
25
25
  onIndexChange: (index: number) => void;
26
26
  navigationState: NavigationState<T>;
27
- renderScene: (props: SceneRendererProps & { route: T }) => React.ReactNode;
28
27
  renderLazyPlaceholder?: (props: { route: T }) => React.ReactNode;
29
28
  renderTabBar?: (
30
29
  props: SceneRendererProps & { navigationState: NavigationState<T> }
@@ -37,6 +36,7 @@ export type Props<T extends Route> = Omit<PagerProps, 'layoutDirection'> & {
37
36
  direction?: LocaleDirection;
38
37
  pagerStyle?: StyleProp<ViewStyle>;
39
38
  style?: StyleProp<ViewStyle>;
39
+ renderScene: (props: SceneRendererProps & { route: T }) => React.ReactNode;
40
40
  };
41
41
 
42
42
  export function TabView<T extends Route>({
@@ -111,7 +111,7 @@ export function TabView<T extends Route>({
111
111
  layoutDirection={direction}
112
112
  >
113
113
  {({ position, render, addEnterListener, jumpTo }) => {
114
- // All of the props here must not change between re-renders
114
+ // All the props here must not change between re-renders
115
115
  // This is crucial to optimizing the routes with PureComponent
116
116
  const sceneRendererProps = {
117
117
  position,
package/src/index.tsx CHANGED
@@ -7,4 +7,9 @@ export type { Props as TabBarItemProps } from './TabBarItem';
7
7
  export { TabBarItem } from './TabBarItem';
8
8
  export type { Props as TabViewProps } from './TabView';
9
9
  export { TabView } from './TabView';
10
- export type { NavigationState, Route, SceneRendererProps } from './types';
10
+ export type {
11
+ NavigationState,
12
+ Route,
13
+ SceneRendererProps,
14
+ TabDescriptor,
15
+ } from './types';
package/src/types.tsx CHANGED
@@ -1,6 +1,30 @@
1
- import type { Animated } from 'react-native';
1
+ import type { Animated, StyleProp, TextStyle } from 'react-native';
2
2
  import type { PagerViewProps } from 'react-native-pager-view';
3
3
 
4
+ export type TabDescriptor<T extends Route> = {
5
+ accessibilityLabel?: string;
6
+ accessible?: boolean;
7
+ testID?: string;
8
+ labelText?: string;
9
+ labelAllowFontScaling?: boolean;
10
+ href?: string;
11
+ label?: (props: {
12
+ focused: boolean;
13
+ color: string;
14
+ style?: StyleProp<TextStyle>;
15
+ allowFontScaling?: boolean;
16
+ label?: string;
17
+ route: T;
18
+ }) => React.ReactElement;
19
+ icon?: (props: {
20
+ focused: boolean;
21
+ color: string;
22
+ size: number;
23
+ route: T;
24
+ }) => React.ReactElement;
25
+ badge?: () => React.ReactElement;
26
+ };
27
+
4
28
  export type LocaleDirection = 'ltr' | 'rtl';
5
29
 
6
30
  export type Route = {