@react-navigation/elements 3.0.0-alpha.1 → 3.0.0-alpha.11

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 (118) hide show
  1. package/lib/module/Badge.js +1 -1
  2. package/lib/module/Badge.js.map +1 -1
  3. package/lib/module/Button.js +1 -1
  4. package/lib/module/Button.js.map +1 -1
  5. package/lib/module/Color.js +95 -0
  6. package/lib/module/Color.js.map +1 -1
  7. package/lib/module/Container.js +8 -1
  8. package/lib/module/Container.js.map +1 -1
  9. package/lib/module/Header/Header.js +15 -2
  10. package/lib/module/Header/Header.js.map +1 -1
  11. package/lib/module/Header/HeaderBackButton.js +27 -13
  12. package/lib/module/Header/HeaderBackButton.js.map +1 -1
  13. package/lib/module/Header/HeaderIcon.js +29 -10
  14. package/lib/module/Header/HeaderIcon.js.map +1 -1
  15. package/lib/module/Header/HeaderSearchBar.js +28 -21
  16. package/lib/module/Header/HeaderSearchBar.js.map +1 -1
  17. package/lib/module/PlatformColor.js +1 -0
  18. package/lib/module/PlatformColor.js.map +1 -1
  19. package/lib/module/PlatformColor.native.js +1 -1
  20. package/lib/module/PlatformColor.native.js.map +1 -1
  21. package/lib/module/Screen.js +11 -7
  22. package/lib/module/Screen.js.map +1 -1
  23. package/lib/module/index.js +1 -7
  24. package/lib/module/index.js.map +1 -1
  25. package/lib/typescript/src/Color.d.ts +4 -3
  26. package/lib/typescript/src/Color.d.ts.map +1 -1
  27. package/lib/typescript/src/Container.d.ts +3 -1
  28. package/lib/typescript/src/Container.d.ts.map +1 -1
  29. package/lib/typescript/src/Header/Header.d.ts.map +1 -1
  30. package/lib/typescript/src/Header/HeaderBackButton.d.ts +1 -1
  31. package/lib/typescript/src/Header/HeaderBackButton.d.ts.map +1 -1
  32. package/lib/typescript/src/Header/HeaderIcon.d.ts +8 -4
  33. package/lib/typescript/src/Header/HeaderIcon.d.ts.map +1 -1
  34. package/lib/typescript/src/Header/HeaderSearchBar.d.ts.map +1 -1
  35. package/lib/typescript/src/PlatformColor.d.ts +1 -0
  36. package/lib/typescript/src/PlatformColor.d.ts.map +1 -1
  37. package/lib/typescript/src/PlatformColor.native.d.ts +1 -1
  38. package/lib/typescript/src/PlatformColor.native.d.ts.map +1 -1
  39. package/lib/typescript/src/Screen.d.ts +2 -2
  40. package/lib/typescript/src/Screen.d.ts.map +1 -1
  41. package/lib/typescript/src/index.d.ts +1 -2
  42. package/lib/typescript/src/index.d.ts.map +1 -1
  43. package/lib/typescript/src/types.d.ts +26 -5
  44. package/lib/typescript/src/types.d.ts.map +1 -1
  45. package/package.json +5 -5
  46. package/src/Badge.tsx +1 -1
  47. package/src/Button.tsx +1 -3
  48. package/src/Color.tsx +133 -3
  49. package/src/Container.tsx +13 -2
  50. package/src/Header/Header.tsx +17 -1
  51. package/src/Header/HeaderBackButton.tsx +28 -14
  52. package/src/Header/HeaderIcon.tsx +49 -9
  53. package/src/Header/HeaderSearchBar.tsx +27 -18
  54. package/src/PlatformColor.native.tsx +1 -1
  55. package/src/PlatformColor.tsx +4 -0
  56. package/src/Screen.tsx +13 -13
  57. package/src/index.tsx +1 -16
  58. package/src/types.tsx +33 -2
  59. package/lib/module/assets/back-icon.ios.svg +0 -4
  60. package/lib/module/assets/back-icon@1x.android.png +0 -0
  61. package/lib/module/assets/back-icon@1x.ios.png +0 -0
  62. package/lib/module/assets/back-icon@2x.android.png +0 -0
  63. package/lib/module/assets/back-icon@2x.ios.png +0 -0
  64. package/lib/module/assets/back-icon@3x.android.png +0 -0
  65. package/lib/module/assets/back-icon@3x.ios.png +0 -0
  66. package/lib/module/assets/back-icon@4x.android.png +0 -0
  67. package/lib/module/assets/back-icon@4x.ios.png +0 -0
  68. package/lib/module/assets/clear-icon@1x.png +0 -0
  69. package/lib/module/assets/clear-icon@2x.png +0 -0
  70. package/lib/module/assets/clear-icon@3x.png +0 -0
  71. package/lib/module/assets/clear-icon@4x.png +0 -0
  72. package/lib/module/assets/close-icon@1x.png +0 -0
  73. package/lib/module/assets/close-icon@2x.png +0 -0
  74. package/lib/module/assets/close-icon@3x.png +0 -0
  75. package/lib/module/assets/close-icon@4x.png +0 -0
  76. package/lib/module/assets/search-icon-legacy@1x.ios.png +0 -0
  77. package/lib/module/assets/search-icon-legacy@2x.ios.png +0 -0
  78. package/lib/module/assets/search-icon-legacy@3x.ios.png +0 -0
  79. package/lib/module/assets/search-icon-legacy@4x.ios.png +0 -0
  80. package/lib/module/assets/search-icon.ios.svg +0 -4
  81. package/lib/module/assets/search-icon@1x.android.png +0 -0
  82. package/lib/module/assets/search-icon@1x.ios.png +0 -0
  83. package/lib/module/assets/search-icon@2x.android.png +0 -0
  84. package/lib/module/assets/search-icon@2x.ios.png +0 -0
  85. package/lib/module/assets/search-icon@3x.android.png +0 -0
  86. package/lib/module/assets/search-icon@3x.ios.png +0 -0
  87. package/lib/module/assets/search-icon@4x.android.png +0 -0
  88. package/lib/module/assets/search-icon@4x.ios.png +0 -0
  89. package/src/assets/back-icon.ios.svg +0 -4
  90. package/src/assets/back-icon@1x.android.png +0 -0
  91. package/src/assets/back-icon@1x.ios.png +0 -0
  92. package/src/assets/back-icon@2x.android.png +0 -0
  93. package/src/assets/back-icon@2x.ios.png +0 -0
  94. package/src/assets/back-icon@3x.android.png +0 -0
  95. package/src/assets/back-icon@3x.ios.png +0 -0
  96. package/src/assets/back-icon@4x.android.png +0 -0
  97. package/src/assets/back-icon@4x.ios.png +0 -0
  98. package/src/assets/clear-icon@1x.png +0 -0
  99. package/src/assets/clear-icon@2x.png +0 -0
  100. package/src/assets/clear-icon@3x.png +0 -0
  101. package/src/assets/clear-icon@4x.png +0 -0
  102. package/src/assets/close-icon@1x.png +0 -0
  103. package/src/assets/close-icon@2x.png +0 -0
  104. package/src/assets/close-icon@3x.png +0 -0
  105. package/src/assets/close-icon@4x.png +0 -0
  106. package/src/assets/search-icon-legacy@1x.ios.png +0 -0
  107. package/src/assets/search-icon-legacy@2x.ios.png +0 -0
  108. package/src/assets/search-icon-legacy@3x.ios.png +0 -0
  109. package/src/assets/search-icon-legacy@4x.ios.png +0 -0
  110. package/src/assets/search-icon.ios.svg +0 -4
  111. package/src/assets/search-icon@1x.android.png +0 -0
  112. package/src/assets/search-icon@1x.ios.png +0 -0
  113. package/src/assets/search-icon@2x.android.png +0 -0
  114. package/src/assets/search-icon@2x.ios.png +0 -0
  115. package/src/assets/search-icon@3x.android.png +0 -0
  116. package/src/assets/search-icon@3x.ios.png +0 -0
  117. package/src/assets/search-icon@4x.android.png +0 -0
  118. package/src/assets/search-icon@4x.ios.png +0 -0
package/src/Color.tsx CHANGED
@@ -1,10 +1,10 @@
1
1
  // eslint-disable-next-line no-restricted-imports
2
2
  import OriginalColor from 'color';
3
- import type { ColorValue } from 'react-native';
3
+ import { type ColorValue, Platform } from 'react-native';
4
+
5
+ import { DynamicColorIOS, PlatformColor } from './PlatformColor';
4
6
 
5
7
  type ColorType = {
6
- isLight(): boolean;
7
- isDark(): boolean;
8
8
  alpha(amount: number): ColorType;
9
9
  alpha(): number;
10
10
  fade(amount: number): ColorType;
@@ -19,3 +19,133 @@ export function Color(value: ColorValue): ColorType | undefined {
19
19
 
20
20
  return undefined;
21
21
  }
22
+
23
+ Color.foreground = (color: ColorValue): ColorValue => {
24
+ const value = color as unknown;
25
+
26
+ if (typeof value === 'object' && value != null) {
27
+ // Special case for Android platform colors
28
+ // Available colors: https://developer.android.com/reference/android/R.color
29
+ if (
30
+ Platform.OS === 'android' &&
31
+ PlatformColor &&
32
+ 'resource_paths' in value &&
33
+ Array.isArray(value.resource_paths) &&
34
+ typeof value.resource_paths[0] === 'string'
35
+ ) {
36
+ const name = value.resource_paths[0].replace('@android:color/', '');
37
+
38
+ if (name in ANDROID_COLOR_MAP) {
39
+ return PlatformColor(`@android:color/${ANDROID_COLOR_MAP[name]}`);
40
+ }
41
+ }
42
+
43
+ // Special case for iOS platform colors
44
+ if (
45
+ Platform.OS === 'ios' &&
46
+ PlatformColor &&
47
+ 'semantic' in value &&
48
+ Array.isArray(value.semantic) &&
49
+ typeof value.semantic[0] === 'string'
50
+ ) {
51
+ const name = value.semantic[0];
52
+
53
+ if (name in IOS_COLOR_MAP) {
54
+ const foreground = IOS_COLOR_MAP[name];
55
+ return foreground === 'white' || foreground === 'black'
56
+ ? foreground
57
+ : PlatformColor(foreground);
58
+ }
59
+ }
60
+
61
+ // Special case for iOS dynamic colors
62
+ if (
63
+ Platform.OS === 'ios' &&
64
+ DynamicColorIOS &&
65
+ 'dynamic' in value &&
66
+ typeof value.dynamic === 'object' &&
67
+ value.dynamic != null &&
68
+ 'light' in value.dynamic &&
69
+ typeof value.dynamic.light === 'string' &&
70
+ 'dark' in value.dynamic &&
71
+ typeof value.dynamic.dark === 'string'
72
+ ) {
73
+ const lightForeground = Color.foreground(value.dynamic.light);
74
+ const darkForeground = Color.foreground(value.dynamic.dark);
75
+
76
+ if (lightForeground && darkForeground) {
77
+ return DynamicColorIOS({
78
+ light: lightForeground,
79
+ dark: darkForeground,
80
+ });
81
+ }
82
+ }
83
+ } else if (typeof color === 'string' && !color.startsWith('var(')) {
84
+ const processed = OriginalColor(color);
85
+
86
+ if (processed.isLight()) {
87
+ return processed.darken(0.71).string();
88
+ }
89
+ }
90
+
91
+ return '#fff';
92
+ };
93
+
94
+ const ANDROID_COLOR_MAP: Record<string, string> = {
95
+ system_background_dark: 'system_on_background_dark',
96
+ system_background_light: 'system_on_background_light',
97
+ system_error_container_dark: 'system_on_error_container_dark',
98
+ system_error_container_light: 'system_on_error_container_light',
99
+ system_error_dark: 'system_on_error_dark',
100
+ system_error_light: 'system_on_error_light',
101
+ system_primary_container_dark: 'system_on_primary_container_dark',
102
+ system_primary_container_light: 'system_on_primary_container_light',
103
+ system_primary_dark: 'system_on_primary_dark',
104
+ system_primary_fixed: 'system_on_primary_fixed',
105
+ system_primary_light: 'system_on_primary_light',
106
+ system_secondary_container_dark: 'system_on_secondary_container_dark',
107
+ system_secondary_container_light: 'system_on_secondary_container_light',
108
+ system_secondary_dark: 'system_on_secondary_dark',
109
+ system_secondary_fixed: 'system_on_secondary_fixed',
110
+ system_secondary_light: 'system_on_secondary_light',
111
+ system_surface_dark: 'system_on_surface_dark',
112
+ system_surface_disabled: 'system_on_surface_disabled',
113
+ system_surface_light: 'system_on_surface_light',
114
+ system_surface_variant_dark: 'system_on_surface_variant_dark',
115
+ system_surface_variant_light: 'system_on_surface_variant_light',
116
+ };
117
+
118
+ const IOS_COLOR_MAP: Record<string, string> = {
119
+ systemBackground: 'label',
120
+ secondarySystemBackground: 'label',
121
+ tertiarySystemBackground: 'label',
122
+ systemGroupedBackground: 'label',
123
+ secondarySystemGroupedBackground: 'label',
124
+ tertiarySystemGroupedBackground: 'label',
125
+
126
+ systemFill: 'label',
127
+ secondarySystemFill: 'label',
128
+ tertiarySystemFill: 'label',
129
+ quaternarySystemFill: 'label',
130
+
131
+ systemRed: 'white',
132
+ systemGreen: 'white',
133
+ systemBlue: 'white',
134
+ systemIndigo: 'white',
135
+ systemPurple: 'white',
136
+ systemBrown: 'white',
137
+
138
+ systemOrange: 'black',
139
+ systemYellow: 'black',
140
+ systemMint: 'black',
141
+ systemTeal: 'black',
142
+ systemCyan: 'black',
143
+ systemPink: 'black',
144
+
145
+ systemGray: 'label',
146
+ systemGray2: 'label',
147
+ systemGray3: 'label',
148
+ systemGray4: 'label',
149
+ systemGray5: 'label',
150
+ systemGray6: 'label',
151
+ };
package/src/Container.tsx CHANGED
@@ -2,17 +2,28 @@ import { Platform, View, type ViewStyle } from 'react-native';
2
2
 
3
3
  export type Props = {
4
4
  inert?: boolean;
5
- style?: React.CSSProperties & ViewStyle;
5
+ style?: ViewStyle &
6
+ Omit<React.CSSProperties, 'backgroundColor'> & {
7
+ backgroundColor?: ViewStyle['backgroundColor'];
8
+ };
6
9
  children: React.ReactNode;
7
10
  };
8
11
 
9
12
  export function Container({ inert, children, style }: Props) {
10
13
  if (Platform.OS === 'web') {
14
+ const { backgroundColor, ...rest } = style ?? {};
15
+
11
16
  return (
12
17
  <div
13
18
  inert={inert}
14
19
  aria-hidden={inert}
15
- style={{ ...DEFAULT_STYLE, ...style }}
20
+ style={{
21
+ ...DEFAULT_STYLE,
22
+ ...rest,
23
+ backgroundColor:
24
+ // In practice we only get string on web instead of OpaqueValue
25
+ typeof backgroundColor === 'string' ? backgroundColor : undefined,
26
+ }}
16
27
  >
17
28
  {children}
18
29
  </div>
@@ -458,7 +458,23 @@ export function Header(props: Props) {
458
458
  headerSearchBarOptions?.onOpen?.();
459
459
  }}
460
460
  >
461
- <HeaderIcon source={searchIcon} tintColor={iconTintColor} />
461
+ <HeaderIcon
462
+ icon={Platform.select({
463
+ android: {
464
+ type: 'materialSymbol',
465
+ name: 'search',
466
+ },
467
+ ios: {
468
+ type: 'sfSymbol',
469
+ name: 'magnifyingglass',
470
+ },
471
+ default: {
472
+ type: 'image',
473
+ source: searchIcon,
474
+ },
475
+ })}
476
+ color={iconTintColor}
477
+ />
462
478
  </HeaderButton>
463
479
  ) : null}
464
480
  </HeaderButtonBackground>
@@ -12,11 +12,12 @@ import {
12
12
  View,
13
13
  } from 'react-native';
14
14
 
15
- import backIcon from '../assets/back-icon.png';
15
+ import backIconImage from '../assets/back-icon.png';
16
16
  import { isLiquidGlassSupported } from '../LiquidGlassView';
17
17
  import type {
18
18
  HeaderBackButtonDisplayMode,
19
19
  HeaderBackButtonProps,
20
+ HeaderIcon as HeaderIconType,
20
21
  } from '../types';
21
22
  import { BUTTON_SIZE, HeaderButton } from './HeaderButton';
22
23
  import { HeaderIcon } from './HeaderIcon';
@@ -24,7 +25,7 @@ import { HeaderIcon } from './HeaderIcon';
24
25
  export function HeaderBackButton({
25
26
  disabled,
26
27
  allowFontScaling,
27
- backImage,
28
+ icon,
28
29
  label,
29
30
  labelStyle,
30
31
  displayMode = 'minimal',
@@ -48,17 +49,30 @@ export function HeaderBackButton({
48
49
  const isMinimal = displayMode === 'minimal' || measuredMinimal;
49
50
 
50
51
  const renderBackImage = () => {
51
- if (backImage) {
52
- return backImage({ tintColor: tintColor ?? colors.text });
53
- } else {
54
- return (
55
- <HeaderIcon
56
- source={backIcon}
57
- tintColor={tintColor ?? colors.text}
58
- style={styles.icon}
59
- />
60
- );
52
+ const color = tintColor ?? colors.text;
53
+
54
+ if (typeof icon === 'function') {
55
+ return icon({ tintColor: color });
61
56
  }
57
+
58
+ const backIcon =
59
+ icon ??
60
+ Platform.select<HeaderIconType>({
61
+ ios: {
62
+ type: 'sfSymbol',
63
+ name: 'chevron.left',
64
+ },
65
+ android: {
66
+ type: 'materialSymbol',
67
+ name: 'arrow_back',
68
+ },
69
+ default: {
70
+ type: 'image',
71
+ source: backIconImage,
72
+ },
73
+ });
74
+
75
+ return <HeaderIcon icon={backIcon} color={color} style={styles.icon} />;
62
76
  };
63
77
 
64
78
  const handlePress = () => {
@@ -231,8 +245,8 @@ function HeaderBackLabel({
231
245
  // iOS uses a smaller chevron, Android uses a larger arrow
232
246
  const ICON_WIDTH = Platform.OS === 'ios' ? 13 : 24;
233
247
  const ICON_SPACING_START = isLiquidGlassSupported
234
- ? 13 // Standard distance of chevron from left edge in liquid glass
235
- : 0; // Otherwise icon is aligned to the start of the button
248
+ ? 15 // Standard distance of chevron from left edge in liquid glass
249
+ : 2; // Otherwise icon is aligned to the start of the button
236
250
 
237
251
  // Standard distance between chevron and label
238
252
  const ICON_LABEL_SPACING = 9;
@@ -1,24 +1,64 @@
1
- import { useLocale, useTheme } from '@react-navigation/native';
2
- import { Image, type ImageProps, Platform, StyleSheet } from 'react-native';
1
+ import { MaterialSymbol, SFSymbol, useLocale } from '@react-navigation/native';
2
+ import {
3
+ type ColorValue,
4
+ Image,
5
+ type ImageProps,
6
+ Platform,
7
+ StyleSheet,
8
+ } from 'react-native';
3
9
 
4
- export function HeaderIcon({ source, style, ...rest }: ImageProps) {
5
- const { colors } = useTheme();
10
+ import type { HeaderIcon as HeaderIconType } from '../types';
11
+
12
+ type Props = Omit<ImageProps, 'source'> & {
13
+ icon: HeaderIconType;
14
+ color: ColorValue;
15
+ };
16
+
17
+ export function HeaderIcon({ icon, color, style, ...rest }: Props) {
6
18
  const { direction } = useLocale();
7
19
 
20
+ const iconStyle = [styles.icon, direction === 'rtl' && styles.flip, style];
21
+
22
+ if (icon.type === 'sfSymbol') {
23
+ return (
24
+ <SFSymbol
25
+ name={icon.name}
26
+ color={color}
27
+ size={ICON_SIZE}
28
+ style={iconStyle}
29
+ {...rest}
30
+ />
31
+ );
32
+ }
33
+
34
+ if (icon.type === 'materialSymbol') {
35
+ return (
36
+ <MaterialSymbol
37
+ name={icon.name}
38
+ variant={icon.variant}
39
+ weight={icon.weight}
40
+ color={color}
41
+ size={ICON_SIZE}
42
+ style={iconStyle}
43
+ {...rest}
44
+ />
45
+ );
46
+ }
47
+
8
48
  return (
9
49
  <Image
10
- source={source}
50
+ source={icon.source}
11
51
  resizeMode="contain"
12
52
  fadeDuration={0}
13
- tintColor={colors.text}
14
- style={[styles.icon, direction === 'rtl' && styles.flip, style]}
53
+ tintColor={color}
54
+ style={iconStyle}
15
55
  {...rest}
16
56
  />
17
57
  );
18
58
  }
19
59
 
20
- export const ICON_SIZE = Platform.OS === 'ios' ? 21 : 24;
21
- export const ICON_MARGIN = Platform.OS === 'ios' ? 8 : 3;
60
+ const ICON_SIZE = Platform.OS === 'ios' ? 21 : 24;
61
+ const ICON_MARGIN = Platform.OS === 'ios' ? 8 : 3;
22
62
 
23
63
  const styles = StyleSheet.create({
24
64
  icon: {
@@ -1,10 +1,9 @@
1
- import { useNavigation, useTheme } from '@react-navigation/native';
1
+ import { SFSymbol, useNavigation, useTheme } from '@react-navigation/native';
2
2
  import * as React from 'react';
3
3
  import {
4
4
  Animated,
5
5
  BackHandler,
6
6
  type ColorValue,
7
- Image,
8
7
  type NativeEventSubscription,
9
8
  Platform,
10
9
  type StyleProp,
@@ -14,10 +13,7 @@ import {
14
13
  type ViewStyle,
15
14
  } from 'react-native';
16
15
 
17
- import clearIcon from '../assets/clear-icon.png';
18
16
  import closeIcon from '../assets/close-icon.png';
19
- import searchIcon from '../assets/search-icon.png';
20
- import searchIconLegacy from '../assets/search-icon-legacy.png';
21
17
  import { Color } from '../Color';
22
18
  import {
23
19
  AnimatedLiquidGlassContainerView,
@@ -210,9 +206,10 @@ function HeaderSearchBarInternal(
210
206
  ) : null}
211
207
  <HeaderButtonBackground style={styles.searchbarContainer}>
212
208
  {Platform.OS === 'ios' ? (
213
- <HeaderIcon
214
- source={isLiquidGlassSupported ? searchIcon : searchIconLegacy}
215
- tintColor={textColor}
209
+ <SFSymbol
210
+ name="magnifyingglass"
211
+ size={SEARCH_ICON_SIZE}
212
+ color={textColor}
216
213
  style={[
217
214
  styles.inputSearchIconIos,
218
215
  !isLiquidGlassSupported && styles.inputSearchIconIosLegacy,
@@ -263,10 +260,10 @@ function HeaderSearchBarInternal(
263
260
  !isLiquidGlassSupported && styles.clearButtonIosLegacy,
264
261
  ]}
265
262
  >
266
- <Image
267
- source={clearIcon}
268
- resizeMode="contain"
269
- tintColor={textColor}
263
+ <SFSymbol
264
+ name="xmark.circle.fill"
265
+ size={CLEAR_ICON_SIZE}
266
+ color={textColor}
270
267
  style={styles.clearIconIos}
271
268
  />
272
269
  </PlatformPressable>
@@ -278,7 +275,19 @@ function HeaderSearchBarInternal(
278
275
  onPress={onClear}
279
276
  style={[styles.closeButton, { opacity: clearVisibleAnim }]}
280
277
  >
281
- <HeaderIcon source={closeIcon} tintColor={textColor} />
278
+ <HeaderIcon
279
+ icon={Platform.select({
280
+ android: {
281
+ type: 'materialSymbol',
282
+ name: 'close',
283
+ },
284
+ default: {
285
+ type: 'image',
286
+ source: closeIcon,
287
+ },
288
+ })}
289
+ color={textColor}
290
+ />
282
291
  </HeaderButton>
283
292
  ) : null}
284
293
  {Platform.OS === 'ios' ? (
@@ -288,7 +297,7 @@ function HeaderSearchBarInternal(
288
297
  accessibilityLabel={cancelButtonText}
289
298
  onPress={cancelSearch}
290
299
  >
291
- <HeaderIcon source={closeIcon} tintColor={textColor} />
300
+ <SFSymbol name="xmark" color={textColor} />
292
301
  </HeaderButton>
293
302
  </HeaderButtonBackground>
294
303
  ) : (
@@ -332,14 +341,14 @@ const styles = StyleSheet.create({
332
341
  },
333
342
  inputSearchIconIos: {
334
343
  position: 'absolute',
335
- opacity: 0.5,
336
- top: SEARCHBAR_ICON_SPACING,
337
- left: SEARCHBAR_ICON_SPACING,
344
+ top: '50%',
345
+ left: BUTTON_SPACING + SEARCHBAR_ICON_SPACING / 2,
346
+ marginTop: -SEARCH_ICON_SIZE / 2,
338
347
  height: SEARCH_ICON_SIZE,
339
348
  width: SEARCH_ICON_SIZE,
340
349
  },
341
350
  inputSearchIconIosLegacy: {
342
- top: SEARCHBAR_LEGACY_VERTICAL_OFFSET_IOS,
351
+ top: SEARCHBAR_ICON_SPACING,
343
352
  },
344
353
  backButton: {
345
354
  alignSelf: 'center',
@@ -1 +1 @@
1
- export { PlatformColor } from 'react-native';
1
+ export { DynamicColorIOS, PlatformColor } from 'react-native';
@@ -6,3 +6,7 @@
6
6
  export const PlatformColor:
7
7
  | typeof import('react-native').PlatformColor
8
8
  | undefined = undefined;
9
+
10
+ export const DynamicColorIOS:
11
+ | typeof import('react-native').DynamicColorIOS
12
+ | undefined = undefined;
package/src/Screen.tsx CHANGED
@@ -6,18 +6,13 @@ import {
6
6
  useTheme,
7
7
  } from '@react-navigation/native';
8
8
  import * as React from 'react';
9
- import {
10
- Animated,
11
- type StyleProp,
12
- StyleSheet,
13
- View,
14
- type ViewStyle,
15
- } from 'react-native';
9
+ import { StyleSheet, View } from 'react-native';
16
10
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
17
11
 
18
12
  import { getDefaultHeaderHeight } from './Header/getDefaultHeaderHeight';
19
13
  import { HeaderHeightContext } from './Header/HeaderHeightContext';
20
14
  import { HeaderShownContext } from './Header/HeaderShownContext';
15
+ import { Container } from './internal';
21
16
  import { useFrameSize } from './useFrameSize';
22
17
 
23
18
  type Props = {
@@ -29,7 +24,7 @@ type Props = {
29
24
  headerShown?: boolean;
30
25
  headerStatusBarHeight?: number;
31
26
  headerTransparent?: boolean;
32
- style?: Animated.WithAnimatedValue<StyleProp<ViewStyle>>;
27
+ style?: React.ComponentProps<typeof Container>['style'];
33
28
  children: React.ReactNode;
34
29
  };
35
30
 
@@ -72,12 +67,17 @@ export function Screen(props: Props) {
72
67
  }, [route.name]);
73
68
 
74
69
  return (
75
- <Animated.View
76
- aria-hidden={!focused}
77
- style={[styles.container, { backgroundColor: colors.background }, style]}
70
+ <Container
71
+ inert={!focused}
72
+ style={{
73
+ ...styles.container,
74
+ backgroundColor: colors.background,
75
+ ...style,
76
+ }}
78
77
  // On Fabric we need to disable collapsing for the background to ensure
79
78
  // that we won't render unnecessary views due to the view flattening.
80
- collapsable={false}
79
+ // Container sets `collapsable` to `false` internally
80
+ // This comment is left to make sure refactors don't remove it by mistake
81
81
  >
82
82
  {headerShown ? (
83
83
  <NavigationProvider navigation={navigation} route={route}>
@@ -105,7 +105,7 @@ export function Screen(props: Props) {
105
105
  </HeaderHeightContext.Provider>
106
106
  </HeaderShownContext.Provider>
107
107
  </View>
108
- </Animated.View>
108
+ </Container>
109
109
  );
110
110
  }
111
111
 
package/src/index.tsx CHANGED
@@ -1,9 +1,3 @@
1
- import backIcon from './assets/back-icon.png';
2
- import clearIcon from './assets/clear-icon.png';
3
- import closeIcon from './assets/close-icon.png';
4
- import searchIcon from './assets/search-icon.png';
5
- import searchIconLegacy from './assets/search-icon-legacy.png';
6
-
7
1
  export { Badge } from './Badge';
8
2
  export { Button } from './Button';
9
3
  export { getDefaultSidebarWidth } from './getDefaultSidebarWidth';
@@ -22,14 +16,5 @@ export { getLabel } from './Label/getLabel';
22
16
  export { Label } from './Label/Label';
23
17
  export { PlatformPressable } from './PlatformPressable';
24
18
  export { Text } from './Text';
25
- export { useFrameSize } from './useFrameSize';
26
-
27
- export const Assets = [
28
- backIcon,
29
- searchIcon,
30
- searchIconLegacy,
31
- closeIcon,
32
- clearIcon,
33
- ];
34
-
35
19
  export * from './types';
20
+ export { useFrameSize } from './useFrameSize';
package/src/types.tsx CHANGED
@@ -1,6 +1,12 @@
1
+ import type {
2
+ MaterialSymbolProps,
3
+ SFSymbolProps,
4
+ } from '@react-navigation/native';
5
+ import * as React from 'react';
1
6
  import type {
2
7
  Animated,
3
8
  ColorValue,
9
+ ImageSourcePropType,
4
10
  LayoutChangeEvent,
5
11
  StyleProp,
6
12
  TextInputProps,
@@ -325,11 +331,36 @@ export type HeaderButtonProps = {
325
331
  children: React.ReactNode;
326
332
  };
327
333
 
334
+ export type HeaderIcon =
335
+ | {
336
+ type: 'image';
337
+ source: ImageSourcePropType;
338
+ }
339
+ | {
340
+ type: 'sfSymbol';
341
+ name: SFSymbolProps['name'];
342
+ }
343
+ | ({
344
+ type: 'materialSymbol';
345
+ } & Pick<MaterialSymbolProps, 'name' | 'variant' | 'weight'>);
346
+
328
347
  export type HeaderBackButtonProps = Omit<HeaderButtonProps, 'children'> & {
329
348
  /**
330
- * Function which returns a React Element to display custom image in header's back button.
349
+ * Icon to display for the back button.
350
+ *
351
+ * Supported types:
352
+ * - image: custom image source
353
+ * - sfSymbol: SF Symbol icon (iOS only)
354
+ * - materialSymbol: material symbol icon (Android only)
355
+ * - React Node: function that returns a React Element
356
+ *
357
+ * Defaults to back icon image for the platform
358
+ * - A chevron on iOS
359
+ * - An arrow on Android
331
360
  */
332
- backImage?: (props: { tintColor: ColorValue }) => React.ReactNode;
361
+ icon?:
362
+ | HeaderIcon
363
+ | ((props: { tintColor: ColorValue | undefined }) => React.ReactNode);
333
364
  /**
334
365
  * Label text for the button. Usually the title of the previous screen.
335
366
  * By default, this is only shown on iOS.
@@ -1,4 +0,0 @@
1
- <svg viewBox="0 0 12 21" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <path d="M10.527 1.485L1.584 10.5L10.559 19.542" stroke="#0c0000" stroke-width="2.5" stroke-linecap="round"
3
- stroke-linejoin="round" />
4
- </svg>
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -1,4 +0,0 @@
1
- <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <circle cx="9.75" cy="9.75" r="8" stroke="#000" stroke-width="2" />
3
- <path d="M15.5 15.5L22 22" stroke="#000" stroke-width="2" stroke-linecap="round" />
4
- </svg>