@react-navigation/elements 3.0.0-alpha.3 → 3.0.0-alpha.31

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 (177) hide show
  1. package/lib/module/ActivityView.js +90 -0
  2. package/lib/module/ActivityView.js.map +1 -0
  3. package/lib/module/ActivityView.native.js +67 -0
  4. package/lib/module/ActivityView.native.js.map +1 -0
  5. package/lib/module/Badge.js +5 -4
  6. package/lib/module/Badge.js.map +1 -1
  7. package/lib/module/Button.js +91 -13
  8. package/lib/module/Button.js.map +1 -1
  9. package/lib/module/Color.js +552 -4
  10. package/lib/module/Color.js.map +1 -1
  11. package/lib/module/Container.js +11 -1
  12. package/lib/module/Container.js.map +1 -1
  13. package/lib/module/Header/Header.js +26 -11
  14. package/lib/module/Header/Header.js.map +1 -1
  15. package/lib/module/Header/HeaderBackButton.js +27 -13
  16. package/lib/module/Header/HeaderBackButton.js.map +1 -1
  17. package/lib/module/Header/HeaderButton.js +4 -5
  18. package/lib/module/Header/HeaderButton.js.map +1 -1
  19. package/lib/module/Header/HeaderIcon.js +29 -10
  20. package/lib/module/Header/HeaderIcon.js.map +1 -1
  21. package/lib/module/Header/HeaderSearchBar.js +31 -24
  22. package/lib/module/Header/HeaderSearchBar.js.map +1 -1
  23. package/lib/module/Header/getHeaderTitle.js.map +1 -1
  24. package/lib/module/Header/useHeaderHeight.js +1 -1
  25. package/lib/module/Header/useHeaderHeight.js.map +1 -1
  26. package/lib/module/Label/getLabel.js.map +1 -1
  27. package/lib/module/PlatformColor.js +1 -0
  28. package/lib/module/PlatformColor.js.map +1 -1
  29. package/lib/module/PlatformColor.native.js +1 -1
  30. package/lib/module/PlatformColor.native.js.map +1 -1
  31. package/lib/module/PlatformPressable.js +14 -5
  32. package/lib/module/PlatformPressable.js.map +1 -1
  33. package/lib/module/SafeAreaProviderCompat.js +1 -1
  34. package/lib/module/SafeAreaProviderCompat.js.map +1 -1
  35. package/lib/module/Screen.js +31 -18
  36. package/lib/module/Screen.js.map +1 -1
  37. package/lib/module/index.js +1 -7
  38. package/lib/module/index.js.map +1 -1
  39. package/lib/module/internal.js +1 -1
  40. package/lib/module/internal.js.map +1 -1
  41. package/lib/module/useFrameSize.js +1 -1
  42. package/lib/module/useFrameSize.js.map +1 -1
  43. package/lib/typescript/src/ActivityView.d.ts +31 -0
  44. package/lib/typescript/src/ActivityView.d.ts.map +1 -0
  45. package/lib/typescript/src/ActivityView.native.d.ts +3 -0
  46. package/lib/typescript/src/ActivityView.native.d.ts.map +1 -0
  47. package/lib/typescript/src/Badge.d.ts +3 -3
  48. package/lib/typescript/src/Badge.d.ts.map +1 -1
  49. package/lib/typescript/src/Button.d.ts +35 -4
  50. package/lib/typescript/src/Button.d.ts.map +1 -1
  51. package/lib/typescript/src/Color.d.ts +4 -4
  52. package/lib/typescript/src/Color.d.ts.map +1 -1
  53. package/lib/typescript/src/Container.d.ts +7 -4
  54. package/lib/typescript/src/Container.d.ts.map +1 -1
  55. package/lib/typescript/src/Header/Header.d.ts +2 -2
  56. package/lib/typescript/src/Header/Header.d.ts.map +1 -1
  57. package/lib/typescript/src/Header/HeaderBackButton.d.ts +1 -1
  58. package/lib/typescript/src/Header/HeaderBackButton.d.ts.map +1 -1
  59. package/lib/typescript/src/Header/HeaderBackground.d.ts +3 -3
  60. package/lib/typescript/src/Header/HeaderBackground.d.ts.map +1 -1
  61. package/lib/typescript/src/Header/HeaderButton.d.ts +6 -1
  62. package/lib/typescript/src/Header/HeaderButton.d.ts.map +1 -1
  63. package/lib/typescript/src/Header/HeaderIcon.d.ts +8 -4
  64. package/lib/typescript/src/Header/HeaderIcon.d.ts.map +1 -1
  65. package/lib/typescript/src/Header/HeaderSearchBar.d.ts +9 -6
  66. package/lib/typescript/src/Header/HeaderSearchBar.d.ts.map +1 -1
  67. package/lib/typescript/src/Header/HeaderTitle.d.ts +3 -3
  68. package/lib/typescript/src/Header/HeaderTitle.d.ts.map +1 -1
  69. package/lib/typescript/src/Header/getHeaderTitle.d.ts +1 -1
  70. package/lib/typescript/src/Header/getHeaderTitle.d.ts.map +1 -1
  71. package/lib/typescript/src/Label/getLabel.d.ts +2 -2
  72. package/lib/typescript/src/Label/getLabel.d.ts.map +1 -1
  73. package/lib/typescript/src/PlatformColor.d.ts +1 -0
  74. package/lib/typescript/src/PlatformColor.d.ts.map +1 -1
  75. package/lib/typescript/src/PlatformColor.native.d.ts +1 -1
  76. package/lib/typescript/src/PlatformColor.native.d.ts.map +1 -1
  77. package/lib/typescript/src/PlatformPressable.d.ts +12 -15
  78. package/lib/typescript/src/PlatformPressable.d.ts.map +1 -1
  79. package/lib/typescript/src/Screen.d.ts +6 -6
  80. package/lib/typescript/src/Screen.d.ts.map +1 -1
  81. package/lib/typescript/src/index.d.ts +1 -2
  82. package/lib/typescript/src/index.d.ts.map +1 -1
  83. package/lib/typescript/src/internal.d.ts +1 -1
  84. package/lib/typescript/src/internal.d.ts.map +1 -1
  85. package/lib/typescript/src/types.d.ts +119 -69
  86. package/lib/typescript/src/types.d.ts.map +1 -1
  87. package/package.json +20 -20
  88. package/src/ActivityView.native.tsx +90 -0
  89. package/src/ActivityView.tsx +129 -0
  90. package/src/Badge.tsx +9 -7
  91. package/src/Button.tsx +151 -14
  92. package/src/Color.tsx +726 -8
  93. package/src/Container.tsx +20 -4
  94. package/src/Header/Header.tsx +43 -20
  95. package/src/Header/HeaderBackButton.tsx +31 -17
  96. package/src/Header/HeaderBackground.tsx +3 -3
  97. package/src/Header/HeaderButton.tsx +16 -18
  98. package/src/Header/HeaderIcon.tsx +49 -9
  99. package/src/Header/HeaderSearchBar.tsx +50 -44
  100. package/src/Header/HeaderTitle.tsx +3 -3
  101. package/src/Header/getHeaderTitle.tsx +4 -1
  102. package/src/Header/useHeaderHeight.tsx +1 -1
  103. package/src/Label/getLabel.tsx +1 -1
  104. package/src/PlatformColor.native.tsx +1 -1
  105. package/src/PlatformColor.tsx +4 -0
  106. package/src/PlatformPressable.tsx +40 -29
  107. package/src/SafeAreaProviderCompat.tsx +1 -1
  108. package/src/Screen.tsx +40 -27
  109. package/src/index.tsx +1 -16
  110. package/src/internal.tsx +1 -1
  111. package/src/types.tsx +153 -76
  112. package/src/useFrameSize.tsx +1 -1
  113. package/lib/module/Lazy.js +0 -42
  114. package/lib/module/Lazy.js.map +0 -1
  115. package/lib/module/assets/back-icon.ios.svg +0 -4
  116. package/lib/module/assets/back-icon@1x.android.png +0 -0
  117. package/lib/module/assets/back-icon@1x.ios.png +0 -0
  118. package/lib/module/assets/back-icon@2x.android.png +0 -0
  119. package/lib/module/assets/back-icon@2x.ios.png +0 -0
  120. package/lib/module/assets/back-icon@3x.android.png +0 -0
  121. package/lib/module/assets/back-icon@3x.ios.png +0 -0
  122. package/lib/module/assets/back-icon@4x.android.png +0 -0
  123. package/lib/module/assets/back-icon@4x.ios.png +0 -0
  124. package/lib/module/assets/clear-icon@1x.png +0 -0
  125. package/lib/module/assets/clear-icon@2x.png +0 -0
  126. package/lib/module/assets/clear-icon@3x.png +0 -0
  127. package/lib/module/assets/clear-icon@4x.png +0 -0
  128. package/lib/module/assets/close-icon@1x.png +0 -0
  129. package/lib/module/assets/close-icon@2x.png +0 -0
  130. package/lib/module/assets/close-icon@3x.png +0 -0
  131. package/lib/module/assets/close-icon@4x.png +0 -0
  132. package/lib/module/assets/search-icon-legacy@1x.ios.png +0 -0
  133. package/lib/module/assets/search-icon-legacy@2x.ios.png +0 -0
  134. package/lib/module/assets/search-icon-legacy@3x.ios.png +0 -0
  135. package/lib/module/assets/search-icon-legacy@4x.ios.png +0 -0
  136. package/lib/module/assets/search-icon.ios.svg +0 -4
  137. package/lib/module/assets/search-icon@1x.android.png +0 -0
  138. package/lib/module/assets/search-icon@1x.ios.png +0 -0
  139. package/lib/module/assets/search-icon@2x.android.png +0 -0
  140. package/lib/module/assets/search-icon@2x.ios.png +0 -0
  141. package/lib/module/assets/search-icon@3x.android.png +0 -0
  142. package/lib/module/assets/search-icon@3x.ios.png +0 -0
  143. package/lib/module/assets/search-icon@4x.android.png +0 -0
  144. package/lib/module/assets/search-icon@4x.ios.png +0 -0
  145. package/lib/typescript/src/Lazy.d.ts +0 -31
  146. package/lib/typescript/src/Lazy.d.ts.map +0 -1
  147. package/src/Lazy.tsx +0 -59
  148. package/src/assets/back-icon.ios.svg +0 -4
  149. package/src/assets/back-icon@1x.android.png +0 -0
  150. package/src/assets/back-icon@1x.ios.png +0 -0
  151. package/src/assets/back-icon@2x.android.png +0 -0
  152. package/src/assets/back-icon@2x.ios.png +0 -0
  153. package/src/assets/back-icon@3x.android.png +0 -0
  154. package/src/assets/back-icon@3x.ios.png +0 -0
  155. package/src/assets/back-icon@4x.android.png +0 -0
  156. package/src/assets/back-icon@4x.ios.png +0 -0
  157. package/src/assets/clear-icon@1x.png +0 -0
  158. package/src/assets/clear-icon@2x.png +0 -0
  159. package/src/assets/clear-icon@3x.png +0 -0
  160. package/src/assets/clear-icon@4x.png +0 -0
  161. package/src/assets/close-icon@1x.png +0 -0
  162. package/src/assets/close-icon@2x.png +0 -0
  163. package/src/assets/close-icon@3x.png +0 -0
  164. package/src/assets/close-icon@4x.png +0 -0
  165. package/src/assets/search-icon-legacy@1x.ios.png +0 -0
  166. package/src/assets/search-icon-legacy@2x.ios.png +0 -0
  167. package/src/assets/search-icon-legacy@3x.ios.png +0 -0
  168. package/src/assets/search-icon-legacy@4x.ios.png +0 -0
  169. package/src/assets/search-icon.ios.svg +0 -4
  170. package/src/assets/search-icon@1x.android.png +0 -0
  171. package/src/assets/search-icon@1x.ios.png +0 -0
  172. package/src/assets/search-icon@2x.android.png +0 -0
  173. package/src/assets/search-icon@2x.ios.png +0 -0
  174. package/src/assets/search-icon@3x.android.png +0 -0
  175. package/src/assets/search-icon@3x.ios.png +0 -0
  176. package/src/assets/search-icon@4x.android.png +0 -0
  177. package/src/assets/search-icon@4x.ios.png +0 -0
package/src/Container.tsx CHANGED
@@ -1,18 +1,33 @@
1
1
  import { Platform, View, type ViewStyle } from 'react-native';
2
2
 
3
3
  export type Props = {
4
- inert?: boolean;
5
- style?: React.CSSProperties & ViewStyle;
4
+ ref?: React.Ref<HTMLDivElement | View> | undefined;
5
+ inert?: boolean | undefined;
6
+ style?:
7
+ | (ViewStyle &
8
+ Omit<React.CSSProperties, 'backgroundColor'> & {
9
+ backgroundColor?: ViewStyle['backgroundColor'] | undefined;
10
+ })
11
+ | undefined;
6
12
  children: React.ReactNode;
7
13
  };
8
14
 
9
- export function Container({ inert, children, style }: Props) {
15
+ export function Container({ ref, inert, children, style }: Props) {
10
16
  if (Platform.OS === 'web') {
17
+ const { backgroundColor, ...rest } = style ?? {};
18
+
11
19
  return (
12
20
  <div
21
+ ref={ref as React.Ref<HTMLDivElement> | undefined}
13
22
  inert={inert}
14
23
  aria-hidden={inert}
15
- style={{ ...DEFAULT_STYLE, ...style }}
24
+ style={{
25
+ ...DEFAULT_STYLE,
26
+ ...rest,
27
+ backgroundColor:
28
+ // In practice we only get string on web instead of OpaqueValue
29
+ typeof backgroundColor === 'string' ? backgroundColor : undefined,
30
+ }}
16
31
  >
17
32
  {children}
18
33
  </div>
@@ -21,6 +36,7 @@ export function Container({ inert, children, style }: Props) {
21
36
 
22
37
  return (
23
38
  <View
39
+ ref={ref as React.Ref<View> | undefined}
24
40
  aria-hidden={inert}
25
41
  style={[{ pointerEvents: inert ? 'none' : 'box-none' }, style]}
26
42
  collapsable={false}
@@ -1,4 +1,8 @@
1
- import { useNavigation, useTheme } from '@react-navigation/native';
1
+ import {
2
+ UNSTABLE_CornerInset,
3
+ useNavigation,
4
+ useTheme,
5
+ } from '@react-navigation/native';
2
6
  import * as React from 'react';
3
7
  import {
4
8
  Animated,
@@ -30,20 +34,22 @@ type Props = HeaderOptions & {
30
34
  /**
31
35
  * Options for the back button.
32
36
  */
33
- back?: {
34
- /**
35
- * Title of the previous screen.
36
- */
37
- title: string | undefined;
38
- /**
39
- * The `href` to use for the anchor tag on web
40
- */
41
- href: string | undefined;
42
- };
37
+ back?:
38
+ | {
39
+ /**
40
+ * Title of the previous screen.
41
+ */
42
+ title: string | undefined;
43
+ /**
44
+ * The `href` to use for the anchor tag on web
45
+ */
46
+ href: string | undefined;
47
+ }
48
+ | undefined;
43
49
  /**
44
50
  * Whether the header is in a modal
45
51
  */
46
- modal?: boolean;
52
+ modal?: boolean | undefined;
47
53
  /**
48
54
  * Title text for the header.
49
55
  */
@@ -79,7 +85,7 @@ export function Header(props: Props) {
79
85
  const { colors } = useTheme();
80
86
 
81
87
  const navigation = useNavigation();
82
- const isParentHeaderShown = React.useContext(HeaderShownContext);
88
+ const isParentHeaderShown = React.use(HeaderShownContext);
83
89
 
84
90
  const [searchBarVisible, setSearchBarVisible] = React.useState(false);
85
91
 
@@ -321,21 +327,21 @@ export function Header(props: Props) {
321
327
  return;
322
328
  }
323
329
 
324
- Animated.timing(searchBarVisibleAnim, {
330
+ const animation = Animated.timing(searchBarVisibleAnim, {
325
331
  toValue: searchBarVisible ? 1 : 0,
326
332
  duration: 150,
327
333
  useNativeDriver,
328
334
  easing: Easing.in(Easing.linear),
329
- }).start(({ finished }) => {
335
+ });
336
+
337
+ animation.start(({ finished }) => {
330
338
  if (finished) {
331
339
  setSearchBarRendered(searchBarVisible);
332
340
  searchBarVisibleRef.current = searchBarVisible;
333
341
  }
334
342
  });
335
343
 
336
- return () => {
337
- searchBarVisibleAnim.stopAnimation();
338
- };
344
+ return () => animation.stop();
339
345
  }, [searchBarVisible, searchBarVisibleAnim]);
340
346
 
341
347
  const headerOpacity = searchBarVisibleAnim.interpolate({
@@ -402,6 +408,7 @@ export function Header(props: Props) {
402
408
  },
403
409
  ]}
404
410
  >
411
+ <UNSTABLE_CornerInset direction="horizontal" edge="left" />
405
412
  <View
406
413
  style={[
407
414
  styles.start,
@@ -458,7 +465,23 @@ export function Header(props: Props) {
458
465
  headerSearchBarOptions?.onOpen?.();
459
466
  }}
460
467
  >
461
- <HeaderIcon source={searchIcon} tintColor={iconTintColor} />
468
+ <HeaderIcon
469
+ icon={Platform.select({
470
+ android: {
471
+ type: 'materialSymbol',
472
+ name: 'search',
473
+ },
474
+ ios: {
475
+ type: 'sfSymbol',
476
+ name: 'magnifyingglass',
477
+ },
478
+ default: {
479
+ type: 'image',
480
+ source: searchIcon,
481
+ },
482
+ })}
483
+ color={iconTintColor}
484
+ />
462
485
  </HeaderButton>
463
486
  ) : null}
464
487
  </HeaderButtonBackground>
@@ -540,7 +563,7 @@ const styles = StyleSheet.create({
540
563
  maxWidth: '50%',
541
564
  },
542
565
  background: {
543
- ...StyleSheet.absoluteFillObject,
566
+ ...StyleSheet.absoluteFill,
544
567
  pointerEvents: 'box-none',
545
568
  },
546
569
  });
@@ -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
+ Icon,
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<Icon>({
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 = () => {
@@ -105,11 +119,11 @@ function HeaderBackLabel({
105
119
  truncatedLabel,
106
120
  onMeasureMinimal,
107
121
  }: {
108
- allowFontScaling?: boolean;
122
+ allowFontScaling?: boolean | undefined;
109
123
  displayMode: HeaderBackButtonDisplayMode;
110
124
  label: string | undefined;
111
- labelStyle?: Animated.WithAnimatedValue<StyleProp<TextStyle>>;
112
- tintColor?: ColorValue;
125
+ labelStyle?: Animated.WithAnimatedValue<StyleProp<TextStyle>> | undefined;
126
+ tintColor?: ColorValue | undefined;
113
127
  truncatedLabel: string | undefined;
114
128
  onMeasureMinimal: () => void;
115
129
  }) {
@@ -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;
@@ -12,9 +12,9 @@ import { BlurEffectBackground } from '../BlurEffectBackground';
12
12
  import { type BlurEffectType } from '../getBlurBackgroundColor';
13
13
 
14
14
  type Props = Omit<ViewProps, 'style'> & {
15
- blurEffect?: BlurEffectType | 'none';
16
- style?: StyleProp<ViewStyle>;
17
- children?: React.ReactNode;
15
+ blurEffect?: BlurEffectType | 'none' | undefined;
16
+ style?: StyleProp<ViewStyle> | undefined;
17
+ children?: React.ReactNode | undefined;
18
18
  };
19
19
 
20
20
  export function HeaderBackground({
@@ -4,20 +4,22 @@ import { Platform, StyleSheet } from 'react-native';
4
4
  import { PlatformPressable } from '../PlatformPressable';
5
5
  import type { HeaderButtonProps } from '../types';
6
6
 
7
- function HeaderButtonInternal(
8
- {
9
- disabled,
10
- onPress,
11
- pressColor,
12
- pressOpacity,
13
- accessibilityLabel,
14
- testID,
15
- style,
16
- href,
17
- children,
18
- }: HeaderButtonProps,
19
- ref: React.Ref<React.ComponentRef<typeof PlatformPressable>>
20
- ) {
7
+ type Props = HeaderButtonProps & {
8
+ ref?: React.Ref<React.ComponentRef<typeof PlatformPressable>>;
9
+ };
10
+
11
+ export function HeaderButton({
12
+ disabled,
13
+ onPress,
14
+ pressColor,
15
+ pressOpacity,
16
+ accessibilityLabel,
17
+ testID,
18
+ style,
19
+ href,
20
+ children,
21
+ ref,
22
+ }: Props) {
21
23
  return (
22
24
  <PlatformPressable
23
25
  ref={ref}
@@ -40,10 +42,6 @@ function HeaderButtonInternal(
40
42
  );
41
43
  }
42
44
 
43
- export const HeaderButton = React.forwardRef(HeaderButtonInternal);
44
-
45
- HeaderButton.displayName = 'HeaderButton';
46
-
47
45
  export const BUTTON_SIZE = Platform.OS === 'ios' ? 44 : 48;
48
46
  export const BUTTON_SPACING = Platform.OS === 'ios' ? 10 : 8;
49
47
 
@@ -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 { Icon } from '../types';
11
+
12
+ type Props = Omit<ImageProps, 'source'> & {
13
+ icon: Icon;
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,
@@ -34,11 +30,12 @@ import { HeaderIcon } from './HeaderIcon';
34
30
  type Props = Omit<HeaderSearchBarOptions, 'ref'> & {
35
31
  visible: boolean;
36
32
  onClose: () => void;
37
- tintColor?: ColorValue;
38
- pressColor?: ColorValue;
39
- pressOpacity?: number;
33
+ tintColor?: ColorValue | undefined;
34
+ pressColor?: ColorValue | undefined;
35
+ pressOpacity?: number | undefined;
40
36
  statusBarHeight: number;
41
- style?: Animated.WithAnimatedValue<StyleProp<ViewStyle>>;
37
+ style?: Animated.WithAnimatedValue<StyleProp<ViewStyle>> | undefined;
38
+ ref?: React.Ref<HeaderSearchBarRef>;
42
39
  };
43
40
 
44
41
  const INPUT_TYPE_TO_MODE = {
@@ -50,26 +47,24 @@ const INPUT_TYPE_TO_MODE = {
50
47
 
51
48
  const useNativeDriver = Platform.OS !== 'web';
52
49
 
53
- function HeaderSearchBarInternal(
54
- {
55
- visible,
56
- inputType,
57
- autoFocus = true,
58
- autoCapitalize,
59
- placeholder = 'Search',
60
- enterKeyHint = 'search',
61
- cancelButtonText = 'Cancel',
62
- onChange,
63
- onClose,
64
- tintColor,
65
- pressColor,
66
- pressOpacity,
67
- statusBarHeight,
68
- style,
69
- ...rest
70
- }: Props,
71
- ref: React.ForwardedRef<HeaderSearchBarRef>
72
- ) {
50
+ export function HeaderSearchBar({
51
+ visible,
52
+ inputType,
53
+ autoFocus = true,
54
+ autoCapitalize,
55
+ placeholder = 'Search',
56
+ enterKeyHint = 'search',
57
+ cancelButtonText = 'Cancel',
58
+ onChange,
59
+ onClose,
60
+ tintColor,
61
+ pressColor,
62
+ pressOpacity,
63
+ statusBarHeight,
64
+ style,
65
+ ref,
66
+ ...rest
67
+ }: Props) {
73
68
  const navigation = useNavigation();
74
69
  const { dark, colors, fonts } = useTheme();
75
70
  const [value, setValue] = React.useState('');
@@ -210,9 +205,10 @@ function HeaderSearchBarInternal(
210
205
  ) : null}
211
206
  <HeaderButtonBackground style={styles.searchbarContainer}>
212
207
  {Platform.OS === 'ios' ? (
213
- <HeaderIcon
214
- source={isLiquidGlassSupported ? searchIcon : searchIconLegacy}
215
- tintColor={textColor}
208
+ <SFSymbol
209
+ name="magnifyingglass"
210
+ size={SEARCH_ICON_SIZE}
211
+ color={textColor}
216
212
  style={[
217
213
  styles.inputSearchIconIos,
218
214
  !isLiquidGlassSupported && styles.inputSearchIconIosLegacy,
@@ -263,10 +259,10 @@ function HeaderSearchBarInternal(
263
259
  !isLiquidGlassSupported && styles.clearButtonIosLegacy,
264
260
  ]}
265
261
  >
266
- <Image
267
- source={clearIcon}
268
- resizeMode="contain"
269
- tintColor={textColor}
262
+ <SFSymbol
263
+ name="xmark.circle.fill"
264
+ size={CLEAR_ICON_SIZE}
265
+ color={textColor}
270
266
  style={styles.clearIconIos}
271
267
  />
272
268
  </PlatformPressable>
@@ -278,7 +274,19 @@ function HeaderSearchBarInternal(
278
274
  onPress={onClear}
279
275
  style={[styles.closeButton, { opacity: clearVisibleAnim }]}
280
276
  >
281
- <HeaderIcon source={closeIcon} tintColor={textColor} />
277
+ <HeaderIcon
278
+ icon={Platform.select({
279
+ android: {
280
+ type: 'materialSymbol',
281
+ name: 'close',
282
+ },
283
+ default: {
284
+ type: 'image',
285
+ source: closeIcon,
286
+ },
287
+ })}
288
+ color={textColor}
289
+ />
282
290
  </HeaderButton>
283
291
  ) : null}
284
292
  {Platform.OS === 'ios' ? (
@@ -288,7 +296,7 @@ function HeaderSearchBarInternal(
288
296
  accessibilityLabel={cancelButtonText}
289
297
  onPress={cancelSearch}
290
298
  >
291
- <HeaderIcon source={closeIcon} tintColor={textColor} />
299
+ <SFSymbol name="xmark" color={textColor} />
292
300
  </HeaderButton>
293
301
  </HeaderButtonBackground>
294
302
  ) : (
@@ -332,14 +340,14 @@ const styles = StyleSheet.create({
332
340
  },
333
341
  inputSearchIconIos: {
334
342
  position: 'absolute',
335
- opacity: 0.5,
336
- top: SEARCHBAR_ICON_SPACING,
337
- left: SEARCHBAR_ICON_SPACING,
343
+ top: '50%',
344
+ left: BUTTON_SPACING + SEARCHBAR_ICON_SPACING / 2,
345
+ marginTop: -SEARCH_ICON_SIZE / 2,
338
346
  height: SEARCH_ICON_SIZE,
339
347
  width: SEARCH_ICON_SIZE,
340
348
  },
341
349
  inputSearchIconIosLegacy: {
342
- top: SEARCHBAR_LEGACY_VERTICAL_OFFSET_IOS,
350
+ top: SEARCHBAR_ICON_SPACING,
343
351
  },
344
352
  backButton: {
345
353
  alignSelf: 'center',
@@ -417,5 +425,3 @@ const styles = StyleSheet.create({
417
425
  }),
418
426
  },
419
427
  });
420
-
421
- export const HeaderSearchBar = React.forwardRef(HeaderSearchBarInternal);
@@ -10,9 +10,9 @@ import {
10
10
  } from 'react-native';
11
11
 
12
12
  type Props = Omit<TextProps, 'style'> & {
13
- tintColor?: ColorValue;
14
- children?: string;
15
- style?: Animated.WithAnimatedValue<StyleProp<TextStyle>>;
13
+ tintColor?: ColorValue | undefined;
14
+ children?: string | undefined;
15
+ style?: Animated.WithAnimatedValue<StyleProp<TextStyle>> | undefined;
16
16
  };
17
17
 
18
18
  export function HeaderTitle({ tintColor, style, ...rest }: Props) {
@@ -1,7 +1,10 @@
1
1
  import type { HeaderOptions } from '../types';
2
2
 
3
3
  export function getHeaderTitle(
4
- options: { title?: string; headerTitle?: HeaderOptions['headerTitle'] },
4
+ options: {
5
+ title?: string | undefined;
6
+ headerTitle?: HeaderOptions['headerTitle'];
7
+ },
5
8
  fallback: string
6
9
  ): string {
7
10
  return typeof options.headerTitle === 'string'
@@ -3,7 +3,7 @@ import * as React from 'react';
3
3
  import { HeaderHeightContext } from './HeaderHeightContext';
4
4
 
5
5
  export function useHeaderHeight() {
6
- const height = React.useContext(HeaderHeightContext);
6
+ const height = React.use(HeaderHeightContext);
7
7
 
8
8
  if (height === undefined) {
9
9
  throw new Error(
@@ -1,5 +1,5 @@
1
1
  export function getLabel(
2
- options: { label?: string; title?: string },
2
+ options: { label?: string | undefined; title?: string | undefined },
3
3
  fallback: string
4
4
  ): string {
5
5
  return options.label !== undefined
@@ -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;