@react-navigation/material-top-tabs 8.0.0-alpha.51 → 8.0.0-alpha.52

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.
@@ -6,6 +6,7 @@ import { useLinkBuilder, useLocale, useTheme } from '@react-navigation/native';
6
6
  import * as React from 'react';
7
7
  import { StyleSheet } from 'react-native';
8
8
  import { TabBar } from 'react-native-tab-view';
9
+ import useLatestCallback from 'use-latest-callback';
9
10
  import { jsx as _jsx } from "react/jsx-runtime";
10
11
  const MaterialLabel = ({
11
12
  color,
@@ -52,8 +53,8 @@ export function MaterialTopTabBar({
52
53
  const activeColor = focusedOptions.tabBarActiveTintColor ?? (tabBarVariant === 'primary' ? colors.primary : colors.text);
53
54
  const inactiveColor = focusedOptions.tabBarInactiveTintColor ?? Color(colors.text)?.alpha(0.68).string() ?? (dark ? 'rgba(255, 255, 255, 0.68)' : 'rgba(0, 0, 0, 0.68)');
54
55
  const pressColor = focusedOptions.tabBarPressColor ?? Color(tabBarVariant === 'primary' ? colors.primary : colors.text)?.alpha(0.12).string() ?? (dark ? 'rgba(255, 255, 255, 0.12)' : 'rgba(0, 0, 0, 0.12)');
55
- const tabBarOptions = Object.fromEntries(state.routes.map(route => {
56
- const options = descriptors[route.key]?.options ?? {};
56
+ const optionsCache = React.useRef({});
57
+ const nextOptions = Object.fromEntries(state.routes.map(route => {
57
58
  const {
58
59
  title,
59
60
  tabBarLabel,
@@ -65,11 +66,16 @@ export function MaterialTopTabBar({
65
66
  tabBarIcon,
66
67
  tabBarAllowFontScaling,
67
68
  tabBarLabelStyle
68
- } = options;
69
+ } = descriptors[route.key]?.options ?? {};
70
+ const focused = focusedRoute.key === route.key;
71
+ const href = buildHref(route.name, route.params);
72
+ const previous = optionsCache.current[route.key];
73
+ const deps = [href, route.name, title, tabBarLabel, tabBarButtonTestID, tabBarAccessibilityLabel, tabBarBadge, tabBarShowIcon, tabBarShowLabel, tabBarIcon, tabBarAllowFontScaling, tabBarLabelStyle, typeof tabBarLabel === 'function' && focused];
74
+ if (previous && Object.hasOwn(optionsCache.current, route.key) && previous.deps.length === deps.length && deps.every((dep, index) => Object.is(dep, previous.deps[index]))) {
75
+ return [route.key, previous];
76
+ }
69
77
  let icon;
70
- if (tabBarShowIcon === false) {
71
- icon = undefined;
72
- } else if (tabBarIcon) {
78
+ if (tabBarShowIcon !== false && tabBarIcon) {
73
79
  icon = ({
74
80
  focused,
75
81
  color,
@@ -93,8 +99,8 @@ export function MaterialTopTabBar({
93
99
  return null;
94
100
  };
95
101
  }
96
- return [route.key, {
97
- href: buildHref(route.name, route.params),
102
+ const tabOptions = {
103
+ href,
98
104
  testID: tabBarButtonTestID,
99
105
  accessibilityLabel: tabBarAccessibilityLabel,
100
106
  badge: tabBarBadge,
@@ -103,20 +109,48 @@ export function MaterialTopTabBar({
103
109
  labelText,
104
110
  color
105
111
  }) => tabBarLabel({
106
- focused: focusedRoute.key === route.key,
112
+ focused,
107
113
  color,
108
114
  children: labelText ?? route.name
109
115
  }) : renderLabelDefault,
110
116
  labelAllowFontScaling: tabBarAllowFontScaling,
111
117
  labelStyle: tabBarLabelStyle,
112
- labelText: options.tabBarShowLabel === false ? undefined : typeof tabBarLabel === 'string' ? tabBarLabel : title !== undefined ? title : route.name
118
+ labelText: tabBarShowLabel === false ? undefined : typeof tabBarLabel === 'string' ? tabBarLabel : title !== undefined ? title : route.name
119
+ };
120
+ return [route.key, {
121
+ deps,
122
+ options: tabOptions
113
123
  }];
114
124
  }));
125
+ React.useInsertionEffect(() => {
126
+ optionsCache.current = nextOptions;
127
+ });
128
+ const onTabPress = useLatestCallback(({
129
+ route,
130
+ preventDefault
131
+ }) => {
132
+ const event = navigation.emit({
133
+ type: 'tabPress',
134
+ target: route.key,
135
+ canPreventDefault: true
136
+ });
137
+ if (event.defaultPrevented) {
138
+ preventDefault();
139
+ }
140
+ });
141
+ const onTabLongPress = useLatestCallback(({
142
+ route
143
+ }) => navigation.emit({
144
+ type: 'tabLongPress',
145
+ target: route.key
146
+ }));
115
147
  const tabBarIndicator = focusedOptions.tabBarIndicator;
116
148
  return /*#__PURE__*/_jsx(TabBar, {
117
149
  ...rest,
118
150
  navigationState: state,
119
- options: tabBarOptions,
151
+ options: Object.fromEntries(Object.entries(nextOptions).map(([key, {
152
+ options
153
+ }]) => [key, options])),
120
154
  direction: direction,
121
155
  scrollEnabled: focusedOptions.tabBarScrollEnabled,
122
156
  bounces: focusedOptions.tabBarBounces,
@@ -137,25 +171,8 @@ export function MaterialTopTabBar({
137
171
  backgroundColor: colors.card,
138
172
  borderBottomColor: colors.border
139
173
  }, focusedOptions.tabBarStyle],
140
- onTabPress: ({
141
- route,
142
- preventDefault
143
- }) => {
144
- const event = navigation.emit({
145
- type: 'tabPress',
146
- target: route.key,
147
- canPreventDefault: true
148
- });
149
- if (event.defaultPrevented) {
150
- preventDefault();
151
- }
152
- },
153
- onTabLongPress: ({
154
- route
155
- }) => navigation.emit({
156
- type: 'tabLongPress',
157
- target: route.key
158
- }),
174
+ onTabPress: onTabPress,
175
+ onTabLongPress: onTabLongPress,
159
176
  renderIndicator: tabBarIndicator ? ({
160
177
  navigationState: _,
161
178
  ...rest
@@ -1 +1 @@
1
- {"version":3,"names":["PlatformIcon","Text","Color","useLinkBuilder","useLocale","useTheme","React","StyleSheet","TabBar","jsx","_jsx","MaterialLabel","color","labelText","style","allowFontScaling","fonts","medium","styles","label","children","renderLabelDefault","props","MaterialTopTabBar","state","navigation","descriptors","rest","colors","dark","direction","buildHref","focusedRoute","routes","index","Error","focusedOptions","key","options","tabBarVariant","activeColor","tabBarActiveTintColor","primary","text","inactiveColor","tabBarInactiveTintColor","alpha","string","pressColor","tabBarPressColor","tabBarOptions","Object","fromEntries","map","route","title","tabBarLabel","tabBarButtonTestID","tabBarAccessibilityLabel","tabBarBadge","tabBarShowIcon","tabBarShowLabel","tabBarIcon","tabBarAllowFontScaling","tabBarLabelStyle","icon","undefined","focused","size","iconValue","isValidElement","href","name","params","testID","accessibilityLabel","badge","labelAllowFontScaling","labelStyle","tabBarIndicator","navigationState","scrollEnabled","tabBarScrollEnabled","bounces","tabBarBounces","pressOpacity","tabBarPressOpacity","tabStyle","tabBarItemStyle","indicatorStyle","backgroundColor","tabBarIndicatorStyle","gap","tabBarGap","variant","android_ripple","tabBarAndroidRipple","indicatorContainerStyle","tabBarIndicatorContainerStyle","contentContainerStyle","tabBarContentContainerStyle","card","borderBottomColor","border","tabBarStyle","onTabPress","preventDefault","event","emit","type","target","canPreventDefault","defaultPrevented","onTabLongPress","renderIndicator","_","create","textAlign","fontSize"],"sourceRoot":"../../../src","sources":["views/MaterialTopTabBar.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["PlatformIcon","Text","Color","useLinkBuilder","useLocale","useTheme","React","StyleSheet","TabBar","useLatestCallback","jsx","_jsx","MaterialLabel","color","labelText","style","allowFontScaling","fonts","medium","styles","label","children","renderLabelDefault","props","MaterialTopTabBar","state","navigation","descriptors","rest","colors","dark","direction","buildHref","focusedRoute","routes","index","Error","focusedOptions","key","options","tabBarVariant","activeColor","tabBarActiveTintColor","primary","text","inactiveColor","tabBarInactiveTintColor","alpha","string","pressColor","tabBarPressColor","optionsCache","useRef","nextOptions","Object","fromEntries","map","route","title","tabBarLabel","tabBarButtonTestID","tabBarAccessibilityLabel","tabBarBadge","tabBarShowIcon","tabBarShowLabel","tabBarIcon","tabBarAllowFontScaling","tabBarLabelStyle","focused","href","name","params","previous","current","deps","hasOwn","length","every","dep","is","icon","size","iconValue","isValidElement","tabOptions","testID","accessibilityLabel","badge","undefined","labelAllowFontScaling","labelStyle","useInsertionEffect","onTabPress","preventDefault","event","emit","type","target","canPreventDefault","defaultPrevented","onTabLongPress","tabBarIndicator","navigationState","entries","scrollEnabled","tabBarScrollEnabled","bounces","tabBarBounces","pressOpacity","tabBarPressOpacity","tabStyle","tabBarItemStyle","indicatorStyle","backgroundColor","tabBarIndicatorStyle","gap","tabBarGap","variant","android_ripple","tabBarAndroidRipple","indicatorContainerStyle","tabBarIndicatorContainerStyle","contentContainerStyle","tabBarContentContainerStyle","card","borderBottomColor","border","tabBarStyle","renderIndicator","_","create","textAlign","fontSize"],"sourceRoot":"../../../src","sources":["views/MaterialTopTabBar.tsx"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"MaterialTopTabBar.d.ts","sourceRoot":"","sources":["../../../../src/views/MaterialTopTabBar.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAU,CAAC;AA4BvD,wBAAgB,iBAAiB,CAAC,EAChC,KAAK,EACL,UAAU,EACV,WAAW,EACX,GAAG,IAAI,EACR,EAAE,sBAAsB,qBAyKxB"}
1
+ {"version":3,"file":"MaterialTopTabBar.d.ts","sourceRoot":"","sources":["../../../../src/views/MaterialTopTabBar.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAU/B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAU,CAAC;AAiCvD,wBAAgB,iBAAiB,CAAC,EAChC,KAAK,EACL,UAAU,EACV,WAAW,EACX,GAAG,IAAI,EACR,EAAE,sBAAsB,qBAkNxB"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@react-navigation/material-top-tabs",
3
3
  "description": "Integration for the animated tab view component from react-native-tab-view",
4
- "version": "8.0.0-alpha.51",
4
+ "version": "8.0.0-alpha.52",
5
5
  "keywords": [
6
6
  "react-native-component",
7
7
  "react-component",
@@ -46,12 +46,13 @@
46
46
  "clean": "del lib"
47
47
  },
48
48
  "dependencies": {
49
- "@react-navigation/elements": "^3.0.0-alpha.50",
50
- "react-native-tab-view": "^5.0.0-alpha.15"
49
+ "@react-navigation/elements": "^3.0.0-alpha.51",
50
+ "react-native-tab-view": "^5.0.0-alpha.16",
51
+ "use-latest-callback": "^0.3.5"
51
52
  },
52
53
  "devDependencies": {
53
54
  "@jest/globals": "^30.4.1",
54
- "@react-navigation/native": "^8.0.0-alpha.46",
55
+ "@react-navigation/native": "^8.0.0-alpha.47",
55
56
  "@testing-library/react-native": "^14.0.0",
56
57
  "@types/react": "~19.2.17",
57
58
  "del-cli": "^7.0.0",
@@ -59,12 +60,12 @@
59
60
  "react-native": "0.85.3",
60
61
  "react-native-builder-bob": "^0.43.0",
61
62
  "react-native-pager-view": "^8.0.1",
62
- "react-native-safe-area-context": "~5.7.0",
63
+ "react-native-safe-area-context": "~5.10.0",
63
64
  "test-renderer": "1.2.0",
64
65
  "typescript": "^6.0.3"
65
66
  },
66
67
  "peerDependencies": {
67
- "@react-navigation/native": "^8.0.0-alpha.46",
68
+ "@react-navigation/native": "^8.0.0-alpha.47",
68
69
  "react": ">= 19.2.0",
69
70
  "react-native": "*",
70
71
  "react-native-pager-view": ">= 7.0.0",
@@ -88,5 +89,5 @@
88
89
  ]
89
90
  ]
90
91
  },
91
- "gitHead": "ac6baf188f7a456429a87b644053e765233f0151"
92
+ "gitHead": "e83cb9a88ab92d24caad272442c338de046cfac2"
92
93
  }
@@ -3,7 +3,13 @@ import { Color } from '@react-navigation/elements/internal';
3
3
  import { useLinkBuilder, useLocale, useTheme } from '@react-navigation/native';
4
4
  import * as React from 'react';
5
5
  import { type ColorValue, StyleSheet } from 'react-native';
6
- import { type Route, TabBar, type TabDescriptor } from 'react-native-tab-view';
6
+ import {
7
+ type Route,
8
+ TabBar,
9
+ type TabBarProps,
10
+ type TabDescriptor,
11
+ } from 'react-native-tab-view';
12
+ import useLatestCallback from 'use-latest-callback';
7
13
 
8
14
  import type { MaterialTopTabBarProps } from '../types';
9
15
 
@@ -11,6 +17,11 @@ type MaterialLabelProps = Parameters<
11
17
  NonNullable<TabDescriptor<Route>['label']>
12
18
  >[0];
13
19
 
20
+ type CachedOptions = {
21
+ deps: readonly unknown[];
22
+ options: TabDescriptor<Route>;
23
+ };
24
+
14
25
  const MaterialLabel = ({
15
26
  color,
16
27
  labelText,
@@ -68,10 +79,10 @@ export function MaterialTopTabBar({
68
79
  .string() ??
69
80
  (dark ? 'rgba(255, 255, 255, 0.12)' : 'rgba(0, 0, 0, 0.12)');
70
81
 
71
- const tabBarOptions = Object.fromEntries(
72
- state.routes.map((route) => {
73
- const options = descriptors[route.key]?.options ?? {};
82
+ const optionsCache = React.useRef<Record<string, CachedOptions>>({});
74
83
 
84
+ const nextOptions = Object.fromEntries<CachedOptions>(
85
+ state.routes.map((route) => {
75
86
  const {
76
87
  title,
77
88
  tabBarLabel,
@@ -83,13 +94,41 @@ export function MaterialTopTabBar({
83
94
  tabBarIcon,
84
95
  tabBarAllowFontScaling,
85
96
  tabBarLabelStyle,
86
- } = options;
97
+ } = descriptors[route.key]?.options ?? {};
98
+
99
+ const focused = focusedRoute.key === route.key;
100
+ const href = buildHref(route.name, route.params);
101
+
102
+ const previous = optionsCache.current[route.key];
103
+
104
+ const deps = [
105
+ href,
106
+ route.name,
107
+ title,
108
+ tabBarLabel,
109
+ tabBarButtonTestID,
110
+ tabBarAccessibilityLabel,
111
+ tabBarBadge,
112
+ tabBarShowIcon,
113
+ tabBarShowLabel,
114
+ tabBarIcon,
115
+ tabBarAllowFontScaling,
116
+ tabBarLabelStyle,
117
+ typeof tabBarLabel === 'function' && focused,
118
+ ];
119
+
120
+ if (
121
+ previous &&
122
+ Object.hasOwn(optionsCache.current, route.key) &&
123
+ previous.deps.length === deps.length &&
124
+ deps.every((dep, index) => Object.is(dep, previous.deps[index]))
125
+ ) {
126
+ return [route.key, previous];
127
+ }
87
128
 
88
129
  let icon;
89
130
 
90
- if (tabBarShowIcon === false) {
91
- icon = undefined;
92
- } else if (tabBarIcon) {
131
+ if (tabBarShowIcon !== false && tabBarIcon) {
93
132
  icon = ({
94
133
  focused,
95
134
  color,
@@ -120,37 +159,63 @@ export function MaterialTopTabBar({
120
159
  };
121
160
  }
122
161
 
123
- return [
124
- route.key,
125
- {
126
- href: buildHref(route.name, route.params),
127
- testID: tabBarButtonTestID,
128
- accessibilityLabel: tabBarAccessibilityLabel,
129
- badge: tabBarBadge,
130
- icon,
131
- label:
132
- tabBarShowLabel === false
133
- ? undefined
134
- : typeof tabBarLabel === 'function'
135
- ? ({ labelText, color }: MaterialLabelProps) =>
136
- tabBarLabel({
137
- focused: focusedRoute.key === route.key,
138
- color,
139
- children: labelText ?? route.name,
140
- })
141
- : renderLabelDefault,
142
- labelAllowFontScaling: tabBarAllowFontScaling,
143
- labelStyle: tabBarLabelStyle,
144
- labelText:
145
- options.tabBarShowLabel === false
146
- ? undefined
147
- : typeof tabBarLabel === 'string'
148
- ? tabBarLabel
149
- : title !== undefined
150
- ? title
151
- : route.name,
152
- },
153
- ];
162
+ const tabOptions: TabDescriptor<Route> = {
163
+ href,
164
+ testID: tabBarButtonTestID,
165
+ accessibilityLabel: tabBarAccessibilityLabel,
166
+ badge: tabBarBadge,
167
+ icon,
168
+ label:
169
+ tabBarShowLabel === false
170
+ ? undefined
171
+ : typeof tabBarLabel === 'function'
172
+ ? ({ labelText, color }: MaterialLabelProps) =>
173
+ tabBarLabel({
174
+ focused,
175
+ color,
176
+ children: labelText ?? route.name,
177
+ })
178
+ : renderLabelDefault,
179
+ labelAllowFontScaling: tabBarAllowFontScaling,
180
+ labelStyle: tabBarLabelStyle,
181
+ labelText:
182
+ tabBarShowLabel === false
183
+ ? undefined
184
+ : typeof tabBarLabel === 'string'
185
+ ? tabBarLabel
186
+ : title !== undefined
187
+ ? title
188
+ : route.name,
189
+ };
190
+
191
+ return [route.key, { deps, options: tabOptions }];
192
+ })
193
+ );
194
+
195
+ React.useInsertionEffect(() => {
196
+ optionsCache.current = nextOptions;
197
+ });
198
+
199
+ const onTabPress = useLatestCallback<
200
+ NonNullable<TabBarProps<Route>['onTabPress']>
201
+ >(({ route, preventDefault }) => {
202
+ const event = navigation.emit({
203
+ type: 'tabPress',
204
+ target: route.key,
205
+ canPreventDefault: true,
206
+ });
207
+
208
+ if (event.defaultPrevented) {
209
+ preventDefault();
210
+ }
211
+ });
212
+
213
+ const onTabLongPress = useLatestCallback<
214
+ NonNullable<TabBarProps<Route>['onTabLongPress']>
215
+ >(({ route }) =>
216
+ navigation.emit({
217
+ type: 'tabLongPress',
218
+ target: route.key,
154
219
  })
155
220
  );
156
221
 
@@ -160,7 +225,9 @@ export function MaterialTopTabBar({
160
225
  <TabBar
161
226
  {...rest}
162
227
  navigationState={state}
163
- options={tabBarOptions}
228
+ options={Object.fromEntries(
229
+ Object.entries(nextOptions).map(([key, { options }]) => [key, options])
230
+ )}
164
231
  direction={direction}
165
232
  scrollEnabled={focusedOptions.tabBarScrollEnabled}
166
233
  bounces={focusedOptions.tabBarBounces}
@@ -182,23 +249,8 @@ export function MaterialTopTabBar({
182
249
  { backgroundColor: colors.card, borderBottomColor: colors.border },
183
250
  focusedOptions.tabBarStyle,
184
251
  ]}
185
- onTabPress={({ route, preventDefault }) => {
186
- const event = navigation.emit({
187
- type: 'tabPress',
188
- target: route.key,
189
- canPreventDefault: true,
190
- });
191
-
192
- if (event.defaultPrevented) {
193
- preventDefault();
194
- }
195
- }}
196
- onTabLongPress={({ route }) =>
197
- navigation.emit({
198
- type: 'tabLongPress',
199
- target: route.key,
200
- })
201
- }
252
+ onTabPress={onTabPress}
253
+ onTabLongPress={onTabLongPress}
202
254
  renderIndicator={
203
255
  tabBarIndicator
204
256
  ? ({ navigationState: _, ...rest }) =>