react-native-tab-view 4.2.2 → 5.0.0-alpha.1

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 (70) hide show
  1. package/lib/module/Pager.android.js +1 -1
  2. package/lib/module/Pager.android.js.map +1 -1
  3. package/lib/module/Pager.ios.js +1 -1
  4. package/lib/module/Pager.ios.js.map +1 -1
  5. package/lib/module/PagerViewAdapter.js +3 -127
  6. package/lib/module/PagerViewAdapter.js.map +1 -1
  7. package/lib/module/PagerViewAdapter.native.js +130 -0
  8. package/lib/module/PagerViewAdapter.native.js.map +1 -0
  9. package/lib/module/PanResponderAdapter.js +43 -31
  10. package/lib/module/PanResponderAdapter.js.map +1 -1
  11. package/lib/module/PlatformPressable.js.map +1 -1
  12. package/lib/module/SceneView.js +22 -31
  13. package/lib/module/SceneView.js.map +1 -1
  14. package/lib/module/ScrollViewAdapter.js +210 -0
  15. package/lib/module/ScrollViewAdapter.js.map +1 -0
  16. package/lib/module/TabBar.js +98 -61
  17. package/lib/module/TabBar.js.map +1 -1
  18. package/lib/module/TabBarIndicator.js +6 -9
  19. package/lib/module/TabBarIndicator.js.map +1 -1
  20. package/lib/module/TabBarItem.js +4 -4
  21. package/lib/module/TabBarItem.js.map +1 -1
  22. package/lib/module/TabView.js +65 -84
  23. package/lib/module/TabView.js.map +1 -1
  24. package/lib/module/index.js +3 -0
  25. package/lib/module/index.js.map +1 -1
  26. package/lib/module/useMeasureLayout.js +36 -0
  27. package/lib/module/useMeasureLayout.js.map +1 -0
  28. package/lib/typescript/src/PagerViewAdapter.d.ts +3 -17
  29. package/lib/typescript/src/PagerViewAdapter.d.ts.map +1 -1
  30. package/lib/typescript/src/PagerViewAdapter.native.d.ts +6 -0
  31. package/lib/typescript/src/PagerViewAdapter.native.d.ts.map +1 -0
  32. package/lib/typescript/src/PanResponderAdapter.d.ts +3 -17
  33. package/lib/typescript/src/PanResponderAdapter.d.ts.map +1 -1
  34. package/lib/typescript/src/PlatformPressable.d.ts +2 -2
  35. package/lib/typescript/src/PlatformPressable.d.ts.map +1 -1
  36. package/lib/typescript/src/SceneView.d.ts +1 -1
  37. package/lib/typescript/src/SceneView.d.ts.map +1 -1
  38. package/lib/typescript/src/ScrollViewAdapter.d.ts +12 -0
  39. package/lib/typescript/src/ScrollViewAdapter.d.ts.map +1 -0
  40. package/lib/typescript/src/TabBar.d.ts +7 -7
  41. package/lib/typescript/src/TabBar.d.ts.map +1 -1
  42. package/lib/typescript/src/TabBarIndicator.d.ts +1 -1
  43. package/lib/typescript/src/TabBarIndicator.d.ts.map +1 -1
  44. package/lib/typescript/src/TabBarItem.d.ts +4 -4
  45. package/lib/typescript/src/TabBarItem.d.ts.map +1 -1
  46. package/lib/typescript/src/TabBarItemLabel.d.ts +2 -2
  47. package/lib/typescript/src/TabBarItemLabel.d.ts.map +1 -1
  48. package/lib/typescript/src/TabView.d.ts +99 -5
  49. package/lib/typescript/src/TabView.d.ts.map +1 -1
  50. package/lib/typescript/src/index.d.ts +4 -1
  51. package/lib/typescript/src/index.d.ts.map +1 -1
  52. package/lib/typescript/src/types.d.ts +64 -8
  53. package/lib/typescript/src/types.d.ts.map +1 -1
  54. package/lib/typescript/src/useMeasureLayout.d.ts +5 -0
  55. package/lib/typescript/src/useMeasureLayout.d.ts.map +1 -0
  56. package/package.json +8 -8
  57. package/src/PagerViewAdapter.native.tsx +174 -0
  58. package/src/PagerViewAdapter.tsx +8 -181
  59. package/src/PanResponderAdapter.tsx +64 -77
  60. package/src/PlatformPressable.tsx +2 -1
  61. package/src/SceneView.tsx +23 -45
  62. package/src/ScrollViewAdapter.tsx +268 -0
  63. package/src/TabBar.tsx +134 -133
  64. package/src/TabBarIndicator.tsx +7 -11
  65. package/src/TabBarItem.tsx +8 -6
  66. package/src/TabBarItemLabel.tsx +2 -2
  67. package/src/TabView.tsx +173 -100
  68. package/src/index.tsx +10 -0
  69. package/src/types.tsx +75 -17
  70. package/src/useMeasureLayout.tsx +34 -0
package/src/TabBar.tsx CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import {
3
3
  Animated,
4
+ type ColorValue,
4
5
  type DimensionValue,
5
6
  FlatList,
6
7
  I18nManager,
@@ -23,7 +24,7 @@ import {
23
24
  import { type Props as TabBarItemProps, TabBarItem } from './TabBarItem';
24
25
  import type {
25
26
  Event,
26
- Layout,
27
+ EventEmitterProps,
27
28
  LocaleDirection,
28
29
  NavigationState,
29
30
  Route,
@@ -32,31 +33,43 @@ import type {
32
33
  TabDescriptor,
33
34
  } from './types';
34
35
  import { useAnimatedValue } from './useAnimatedValue';
36
+ import { useMeasureLayout } from './useMeasureLayout';
37
+
38
+ export type Props<T extends Route> = SceneRendererProps &
39
+ EventEmitterProps & {
40
+ navigationState: NavigationState<T>;
41
+ scrollEnabled?: boolean;
42
+ bounces?: boolean;
43
+ activeColor?: ColorValue;
44
+ inactiveColor?: ColorValue;
45
+ pressColor?: ColorValue;
46
+ pressOpacity?: number;
47
+ options?: Record<string, TabDescriptor<T>>;
48
+ renderIndicator?: (props: IndicatorProps<T>) => React.ReactNode;
49
+ renderTabBarItem?: (
50
+ props: TabBarItemProps<T> & { key: string }
51
+ ) => React.ReactElement;
52
+ onTabPress?: (scene: Scene<T> & Event) => void;
53
+ onTabLongPress?: (scene: Scene<T>) => void;
54
+ tabStyle?: StyleProp<ViewStyle>;
55
+ indicatorStyle?: StyleProp<ViewStyle>;
56
+ indicatorContainerStyle?: StyleProp<ViewStyle>;
57
+ contentContainerStyle?: StyleProp<ViewStyle>;
58
+ style?: StyleProp<ViewStyle>;
59
+ direction?: LocaleDirection;
60
+ gap?: number;
61
+ testID?: string;
62
+ android_ripple?: PressableAndroidRippleConfig;
63
+ };
35
64
 
36
- export type Props<T extends Route> = SceneRendererProps & {
37
- navigationState: NavigationState<T>;
38
- scrollEnabled?: boolean;
39
- bounces?: boolean;
40
- activeColor?: string;
41
- inactiveColor?: string;
42
- pressColor?: string;
43
- pressOpacity?: number;
44
- options?: Record<string, TabDescriptor<T>>;
45
- renderIndicator?: (props: IndicatorProps<T>) => React.ReactNode;
46
- renderTabBarItem?: (
47
- props: TabBarItemProps<T> & { key: string }
48
- ) => React.ReactElement;
49
- onTabPress?: (scene: Scene<T> & Event) => void;
50
- onTabLongPress?: (scene: Scene<T>) => void;
51
- tabStyle?: StyleProp<ViewStyle>;
52
- indicatorStyle?: StyleProp<ViewStyle>;
53
- indicatorContainerStyle?: StyleProp<ViewStyle>;
54
- contentContainerStyle?: StyleProp<ViewStyle>;
55
- style?: StyleProp<ViewStyle>;
56
- direction?: LocaleDirection;
57
- gap?: number;
58
- testID?: string;
59
- android_ripple?: PressableAndroidRippleConfig;
65
+ type CalculationOptions = {
66
+ layoutWidth: number;
67
+ gap: number | undefined;
68
+ scrollEnabled: boolean | undefined;
69
+ tabWidths: Record<string, number>;
70
+ flattenedPaddingStart: DimensionValue | undefined;
71
+ flattenedPaddingEnd: DimensionValue | undefined;
72
+ flattenedTabWidth: DimensionValue | undefined;
60
73
  };
61
74
 
62
75
  const useNativeDriver = Platform.OS !== 'web';
@@ -95,7 +108,7 @@ const getFlattenedPaddingEnd = (style: StyleProp<ViewStyle>) => {
95
108
 
96
109
  const convertPaddingPercentToSize = (
97
110
  value: DimensionValue | undefined,
98
- layout: Layout
111
+ layoutWidth: number
99
112
  ): number => {
100
113
  switch (typeof value) {
101
114
  case 'number':
@@ -104,50 +117,53 @@ const convertPaddingPercentToSize = (
104
117
  if (value.endsWith('%')) {
105
118
  const width = parseFloat(value);
106
119
  if (Number.isFinite(width)) {
107
- return layout.width * (width / 100);
120
+ return layoutWidth * (width / 100);
108
121
  }
109
122
  }
110
123
  }
111
124
  return 0;
112
125
  };
113
126
 
114
- const getComputedTabWidth = (
115
- index: number,
116
- layout: Layout,
117
- routes: Route[],
118
- scrollEnabled: boolean | undefined,
119
- tabWidths: { [key: string]: number },
120
- flattenedWidth: DimensionValue | undefined,
121
- flattenedPaddingStart: DimensionValue | undefined,
122
- flattenedPaddingEnd: DimensionValue | undefined,
123
- gap?: number
124
- ) => {
125
- if (flattenedWidth === 'auto') {
127
+ const getComputedTabWidth = ({
128
+ index,
129
+ layoutWidth,
130
+ routes,
131
+ scrollEnabled,
132
+ tabWidths,
133
+ flattenedTabWidth,
134
+ flattenedPaddingStart,
135
+ flattenedPaddingEnd,
136
+ gap,
137
+ }: CalculationOptions & {
138
+ index: number;
139
+ routes: Route[];
140
+ }) => {
141
+ if (flattenedTabWidth === 'auto') {
126
142
  return tabWidths[routes[index].key] || 0;
127
143
  }
128
144
 
129
- switch (typeof flattenedWidth) {
145
+ switch (typeof flattenedTabWidth) {
130
146
  case 'number':
131
- return flattenedWidth;
147
+ return flattenedTabWidth;
132
148
  case 'string':
133
- if (flattenedWidth.endsWith('%')) {
134
- const width = parseFloat(flattenedWidth);
149
+ if (flattenedTabWidth.endsWith('%')) {
150
+ const width = parseFloat(flattenedTabWidth);
135
151
  if (Number.isFinite(width)) {
136
- return layout.width * (width / 100);
152
+ return layoutWidth * (width / 100);
137
153
  }
138
154
  }
139
155
  }
140
156
 
141
157
  if (scrollEnabled) {
142
- return (layout.width / 5) * 2;
158
+ return (layoutWidth / 5) * 2;
143
159
  }
144
160
 
145
161
  const gapTotalWidth = (gap ?? 0) * (routes.length - 1);
146
162
  const paddingTotalWidth =
147
- convertPaddingPercentToSize(flattenedPaddingStart, layout) +
148
- convertPaddingPercentToSize(flattenedPaddingEnd, layout);
163
+ convertPaddingPercentToSize(flattenedPaddingStart, layoutWidth) +
164
+ convertPaddingPercentToSize(flattenedPaddingEnd, layoutWidth);
149
165
 
150
- return (layout.width - gapTotalWidth - paddingTotalWidth) / routes.length;
166
+ return (layoutWidth - gapTotalWidth - paddingTotalWidth) / routes.length;
151
167
  };
152
168
 
153
169
  const getMaxScrollDistance = (tabBarWidth: number, layoutWidth: number) =>
@@ -166,50 +182,45 @@ const getTranslateX = (
166
182
  );
167
183
 
168
184
  const getTabBarWidth = <T extends Route>({
169
- navigationState,
170
- layout,
185
+ routes,
186
+ layoutWidth,
171
187
  gap,
172
188
  scrollEnabled,
173
189
  flattenedTabWidth,
174
190
  flattenedPaddingStart,
175
191
  flattenedPaddingEnd,
176
192
  tabWidths,
177
- }: Pick<Props<T>, 'navigationState' | 'gap' | 'layout' | 'scrollEnabled'> & {
178
- tabWidths: Record<string, number>;
179
- flattenedPaddingStart: DimensionValue | undefined;
180
- flattenedPaddingEnd: DimensionValue | undefined;
181
- flattenedTabWidth: DimensionValue | undefined;
193
+ }: CalculationOptions & {
194
+ routes: T[];
182
195
  }) => {
183
- const { routes } = navigationState;
184
-
185
196
  const paddingsWidth = Math.max(
186
197
  0,
187
- convertPaddingPercentToSize(flattenedPaddingStart, layout) +
188
- convertPaddingPercentToSize(flattenedPaddingEnd, layout)
198
+ convertPaddingPercentToSize(flattenedPaddingStart, layoutWidth) +
199
+ convertPaddingPercentToSize(flattenedPaddingEnd, layoutWidth)
189
200
  );
190
201
 
191
202
  return routes.reduce<number>(
192
203
  (acc, _, i) =>
193
204
  acc +
194
205
  (i > 0 ? (gap ?? 0) : 0) +
195
- getComputedTabWidth(
196
- i,
197
- layout,
206
+ getComputedTabWidth({
207
+ index: i,
208
+ layoutWidth,
198
209
  routes,
199
210
  scrollEnabled,
200
211
  tabWidths,
201
212
  flattenedTabWidth,
202
213
  flattenedPaddingStart,
203
214
  flattenedPaddingEnd,
204
- gap
205
- ),
215
+ gap,
216
+ }),
206
217
  paddingsWidth
207
218
  );
208
219
  };
209
220
 
210
221
  const normalizeScrollValue = <T extends Route>({
211
- layout,
212
- navigationState,
222
+ layoutWidth,
223
+ routes,
213
224
  gap,
214
225
  scrollEnabled,
215
226
  tabWidths,
@@ -218,17 +229,14 @@ const normalizeScrollValue = <T extends Route>({
218
229
  flattenedPaddingStart,
219
230
  flattenedPaddingEnd,
220
231
  direction,
221
- }: Pick<Props<T>, 'layout' | 'navigationState' | 'gap' | 'scrollEnabled'> & {
222
- tabWidths: Record<string, number>;
232
+ }: CalculationOptions & {
233
+ routes: T[];
223
234
  value: number;
224
- flattenedTabWidth: DimensionValue | undefined;
225
- flattenedPaddingStart: DimensionValue | undefined;
226
- flattenedPaddingEnd: DimensionValue | undefined;
227
235
  direction: LocaleDirection;
228
236
  }) => {
229
237
  const tabBarWidth = getTabBarWidth({
230
- layout,
231
- navigationState,
238
+ layoutWidth,
239
+ routes,
232
240
  tabWidths,
233
241
  gap,
234
242
  scrollEnabled,
@@ -236,7 +244,7 @@ const normalizeScrollValue = <T extends Route>({
236
244
  flattenedPaddingStart,
237
245
  flattenedPaddingEnd,
238
246
  });
239
- const maxDistance = getMaxScrollDistance(tabBarWidth, layout.width);
247
+ const maxDistance = getMaxScrollDistance(tabBarWidth, layoutWidth);
240
248
  const scrollValue = Math.max(Math.min(value, maxDistance), 0);
241
249
 
242
250
  if (Platform.OS === 'android' && direction === 'rtl') {
@@ -249,8 +257,9 @@ const normalizeScrollValue = <T extends Route>({
249
257
  };
250
258
 
251
259
  const getScrollAmount = <T extends Route>({
252
- layout,
253
- navigationState,
260
+ index,
261
+ routes,
262
+ layoutWidth,
254
263
  gap,
255
264
  scrollEnabled,
256
265
  flattenedTabWidth,
@@ -258,47 +267,43 @@ const getScrollAmount = <T extends Route>({
258
267
  flattenedPaddingStart,
259
268
  flattenedPaddingEnd,
260
269
  direction,
261
- }: Pick<Props<T>, 'layout' | 'navigationState' | 'scrollEnabled' | 'gap'> & {
262
- tabWidths: Record<string, number>;
263
- flattenedTabWidth: DimensionValue | undefined;
264
- flattenedPaddingStart: DimensionValue | undefined;
265
- flattenedPaddingEnd: DimensionValue | undefined;
270
+ }: CalculationOptions & {
271
+ index: number;
272
+ routes: T[];
266
273
  direction: LocaleDirection;
267
274
  }) => {
268
275
  const paddingInitial =
269
276
  direction === 'rtl'
270
- ? convertPaddingPercentToSize(flattenedPaddingEnd, layout)
271
- : convertPaddingPercentToSize(flattenedPaddingStart, layout);
277
+ ? convertPaddingPercentToSize(flattenedPaddingEnd, layoutWidth)
278
+ : convertPaddingPercentToSize(flattenedPaddingStart, layoutWidth);
272
279
 
273
280
  const centerDistance = Array.from({
274
- length: navigationState.index + 1,
281
+ length: index + 1,
275
282
  }).reduce<number>((total, _, i) => {
276
- const tabWidth = getComputedTabWidth(
277
- i,
278
- layout,
279
- navigationState.routes,
283
+ const tabWidth = getComputedTabWidth({
284
+ index: i,
285
+ layoutWidth,
286
+ routes,
280
287
  scrollEnabled,
281
288
  tabWidths,
282
289
  flattenedTabWidth,
283
290
  flattenedPaddingStart,
284
291
  flattenedPaddingEnd,
285
- gap
286
- );
292
+ gap,
293
+ });
287
294
 
288
295
  // To get the current index centered we adjust scroll amount by width of indexes
289
296
  // 0 through (i - 1) and add half the width of current index i
290
297
  return (
291
- total +
292
- (i > 0 ? (gap ?? 0) : 0) +
293
- (navigationState.index === i ? tabWidth / 2 : tabWidth)
298
+ total + (i > 0 ? (gap ?? 0) : 0) + (index === i ? tabWidth / 2 : tabWidth)
294
299
  );
295
300
  }, paddingInitial);
296
301
 
297
- const scrollAmount = centerDistance - layout.width / 2;
302
+ const scrollAmount = centerDistance - layoutWidth / 2;
298
303
 
299
304
  return normalizeScrollValue({
300
- layout,
301
- navigationState,
305
+ layoutWidth,
306
+ routes,
302
307
  tabWidths,
303
308
  value: scrollAmount,
304
309
  gap,
@@ -352,14 +357,13 @@ export function TabBar<T extends Route>({
352
357
  renderTabBarItem,
353
358
  style,
354
359
  tabStyle,
355
- layout: propLayout,
356
360
  testID,
357
361
  android_ripple,
358
362
  options,
359
363
  }: Props<T>) {
360
- const [layout, setLayout] = React.useState<Layout>(
361
- propLayout ?? { width: 0, height: 0 }
362
- );
364
+ const containerRef = React.useRef<View>(null);
365
+ const [layout, onLayout] = useMeasureLayout(containerRef);
366
+
363
367
  const [tabWidths, setTabWidths] = React.useState<Record<string, number>>({});
364
368
  const flatListRef = React.useRef<FlatList | null>(null);
365
369
  const isFirst = React.useRef(true);
@@ -370,9 +374,11 @@ export function TabBar<T extends Route>({
370
374
  const isWidthDynamic = flattenedTabWidth === 'auto';
371
375
  const flattenedPaddingEnd = getFlattenedPaddingEnd(contentContainerStyle);
372
376
  const flattenedPaddingStart = getFlattenedPaddingStart(contentContainerStyle);
377
+
373
378
  const scrollOffset = getScrollAmount({
374
- layout,
375
- navigationState,
379
+ layoutWidth: layout.width,
380
+ routes,
381
+ index: navigationState.index,
376
382
  tabWidths,
377
383
  gap,
378
384
  scrollEnabled,
@@ -383,7 +389,7 @@ export function TabBar<T extends Route>({
383
389
  });
384
390
 
385
391
  const hasMeasuredTabWidths =
386
- Boolean(layout.width) &&
392
+ Boolean(layout?.width) &&
387
393
  routes
388
394
  .slice(0, navigationState.index)
389
395
  .every((r) => typeof tabWidths[r.key] === 'number');
@@ -406,19 +412,9 @@ export function TabBar<T extends Route>({
406
412
  }
407
413
  }, [hasMeasuredTabWidths, isWidthDynamic, scrollEnabled, scrollOffset]);
408
414
 
409
- const handleLayout = (e: LayoutChangeEvent) => {
410
- const { height, width } = e.nativeEvent.layout;
411
-
412
- setLayout((layout) =>
413
- layout.width === width && layout.height === height
414
- ? layout
415
- : { width, height }
416
- );
417
- };
418
-
419
415
  const tabBarWidth = getTabBarWidth({
420
- layout,
421
- navigationState,
416
+ layoutWidth: layout.width,
417
+ routes,
422
418
  tabWidths,
423
419
  gap,
424
420
  scrollEnabled,
@@ -430,8 +426,8 @@ export function TabBar<T extends Route>({
430
426
  const separatorsWidth = Math.max(0, routes.length - 1) * gap;
431
427
  const paddingsWidth = Math.max(
432
428
  0,
433
- convertPaddingPercentToSize(flattenedPaddingStart, layout) +
434
- convertPaddingPercentToSize(flattenedPaddingEnd, layout)
429
+ convertPaddingPercentToSize(flattenedPaddingStart, layout.width) +
430
+ convertPaddingPercentToSize(flattenedPaddingEnd, layout.width)
435
431
  );
436
432
 
437
433
  const translateX = React.useMemo(
@@ -505,17 +501,19 @@ export function TabBar<T extends Route>({
505
501
 
506
502
  // Calculate the default width for tab for FlatList to work
507
503
  const defaultTabWidth = !isWidthDynamic
508
- ? getComputedTabWidth(
504
+ ? getComputedTabWidth({
509
505
  index,
510
- layout,
506
+ layoutWidth: layout.width,
511
507
  routes,
512
508
  scrollEnabled,
513
509
  tabWidths,
514
- getFlattenedTabWidth(tabStyle),
515
- getFlattenedPaddingEnd(contentContainerStyle),
516
- getFlattenedPaddingStart(contentContainerStyle),
517
- gap
518
- )
510
+ flattenedTabWidth: getFlattenedTabWidth(tabStyle),
511
+ flattenedPaddingStart: getFlattenedPaddingStart(
512
+ contentContainerStyle
513
+ ),
514
+ flattenedPaddingEnd: getFlattenedPaddingEnd(contentContainerStyle),
515
+ gap,
516
+ })
519
517
  : undefined;
520
518
 
521
519
  const props = {
@@ -620,9 +618,12 @@ export function TabBar<T extends Route>({
620
618
  );
621
619
 
622
620
  return (
623
- <Animated.View onLayout={handleLayout} style={[styles.tabBar, style]}>
621
+ <Animated.View
622
+ ref={containerRef}
623
+ onLayout={onLayout}
624
+ style={[styles.tabBar, style]}
625
+ >
624
626
  <Animated.View
625
- pointerEvents="none"
626
627
  style={[
627
628
  styles.indicatorContainer,
628
629
  scrollEnabled ? { transform: [{ translateX }] as any } : null,
@@ -632,7 +633,6 @@ export function TabBar<T extends Route>({
632
633
  >
633
634
  {renderIndicator({
634
635
  position,
635
- layout,
636
636
  navigationState,
637
637
  jumpTo,
638
638
  direction,
@@ -647,17 +647,17 @@ export function TabBar<T extends Route>({
647
647
  { start: flattenedPaddingStart, end: flattenedPaddingEnd },
648
648
  ],
649
649
  getTabWidth: (i: number) =>
650
- getComputedTabWidth(
651
- i,
652
- layout,
650
+ getComputedTabWidth({
651
+ index: i,
652
+ layoutWidth: layout.width,
653
653
  routes,
654
654
  scrollEnabled,
655
655
  tabWidths,
656
656
  flattenedTabWidth,
657
657
  flattenedPaddingEnd,
658
658
  flattenedPaddingStart,
659
- gap
660
- ),
659
+ gap,
660
+ }),
661
661
  gap,
662
662
  })}
663
663
  </Animated.View>
@@ -696,7 +696,7 @@ const styles = StyleSheet.create({
696
696
  },
697
697
  tabBar: {
698
698
  zIndex: 1,
699
- backgroundColor: '#2196f3',
699
+ backgroundColor: '#fff',
700
700
  elevation: 4,
701
701
  ...Platform.select({
702
702
  default: {
@@ -724,5 +724,6 @@ const styles = StyleSheet.create({
724
724
  start: 0,
725
725
  end: 0,
726
726
  bottom: 0,
727
+ pointerEvents: 'none',
727
728
  },
728
729
  });
@@ -71,7 +71,6 @@ const getTranslateX = (
71
71
 
72
72
  export function TabBarIndicator<T extends Route>({
73
73
  getTabWidth,
74
- layout,
75
74
  navigationState,
76
75
  position,
77
76
  width,
@@ -86,8 +85,7 @@ export function TabBarIndicator<T extends Route>({
86
85
  const opacity = useAnimatedValue(isWidthDynamic ? 0 : 1);
87
86
 
88
87
  const indicatorVisible = isWidthDynamic
89
- ? layout.width &&
90
- navigationState.routes
88
+ ? navigationState.routes
91
89
  .slice(0, navigationState.index)
92
90
  .every((_, r) => getTabWidth(r))
93
91
  : true;
@@ -120,14 +118,12 @@ export function TabBarIndicator<T extends Route>({
120
118
 
121
119
  const transform = [];
122
120
 
123
- if (layout.width) {
124
- const translateX =
125
- routes.length > 1
126
- ? getTranslateX(position, routes, getTabWidth, direction, gap, width)
127
- : 0;
121
+ const translateX =
122
+ routes.length > 1
123
+ ? getTranslateX(position, routes, getTabWidth, direction, gap, width)
124
+ : 0;
128
125
 
129
- transform.push({ translateX });
130
- }
126
+ transform.push({ translateX });
131
127
 
132
128
  if (width === 'auto') {
133
129
  const inputRange = routes.map((_, i) => i);
@@ -180,7 +176,7 @@ export function TabBarIndicator<T extends Route>({
180
176
 
181
177
  const styles = StyleSheet.create({
182
178
  indicator: {
183
- backgroundColor: '#ffeb3b',
179
+ backgroundColor: 'rgb(0, 122, 255)',
184
180
  position: 'absolute',
185
181
  start: 0,
186
182
  bottom: 0,
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import {
3
3
  Animated,
4
+ type ColorValue,
4
5
  type LayoutChangeEvent,
5
6
  Platform,
6
7
  type PressableAndroidRippleConfig,
@@ -19,9 +20,9 @@ export type Props<T extends Route> = TabDescriptor<T> & {
19
20
  position: Animated.AnimatedInterpolation<number>;
20
21
  route: T;
21
22
  navigationState: NavigationState<T>;
22
- activeColor?: string;
23
- inactiveColor?: string;
24
- pressColor?: string;
23
+ activeColor?: ColorValue;
24
+ inactiveColor?: ColorValue;
25
+ pressColor?: ColorValue;
25
26
  pressOpacity?: number;
26
27
  onLayout?: (event: LayoutChangeEvent) => void;
27
28
  onPress: () => void;
@@ -31,8 +32,8 @@ export type Props<T extends Route> = TabDescriptor<T> & {
31
32
  android_ripple?: PressableAndroidRippleConfig;
32
33
  };
33
34
 
34
- const DEFAULT_ACTIVE_COLOR = 'rgba(255, 255, 255, 1)';
35
- const DEFAULT_INACTIVE_COLOR = 'rgba(255, 255, 255, 0.7)';
35
+ const DEFAULT_ACTIVE_COLOR = 'rgba(0, 0, 0, 1)';
36
+ const DEFAULT_INACTIVE_COLOR = 'rgba(0, 0, 0, 0.5)';
36
37
  const ICON_SIZE = 24;
37
38
 
38
39
  const getActiveOpacity = (
@@ -228,7 +229,7 @@ const TabBarItemInternal = <T extends Route>({
228
229
  href={href}
229
230
  style={[styles.pressable, tabContainerStyle]}
230
231
  >
231
- <View pointerEvents="none" style={[styles.item, tabStyle]}>
232
+ <View style={[styles.item, tabStyle]}>
232
233
  {icon}
233
234
  <View>
234
235
  <Animated.View style={{ opacity: inactiveOpacity }}>
@@ -286,6 +287,7 @@ const styles = StyleSheet.create({
286
287
  justifyContent: 'center',
287
288
  padding: 10,
288
289
  minHeight: 48,
290
+ pointerEvents: 'none',
289
291
  },
290
292
  badge: {
291
293
  position: 'absolute',
@@ -1,9 +1,9 @@
1
1
  import React from 'react';
2
- import type { StyleProp, ViewStyle } from 'react-native';
2
+ import type { ColorValue, StyleProp, ViewStyle } from 'react-native';
3
3
  import { Animated, StyleSheet } from 'react-native';
4
4
 
5
5
  interface TabBarItemLabelProps {
6
- color: string;
6
+ color: ColorValue;
7
7
  label?: string;
8
8
  style: StyleProp<ViewStyle>;
9
9
  icon: React.ReactNode;