react-native-screens 3.9.0 → 3.11.0

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 (102) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +47 -7
  3. package/android/build.gradle +1 -2
  4. package/android/src/main/java/com/swmansion/rnscreens/CustomSearchView.kt +71 -0
  5. package/android/src/main/java/com/swmansion/rnscreens/CustomToolbar.kt +7 -0
  6. package/android/src/main/java/com/swmansion/rnscreens/FragmentBackPressOverrider.kt +29 -0
  7. package/android/src/main/java/com/swmansion/rnscreens/RNScreensPackage.kt +2 -1
  8. package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +35 -52
  9. package/android/src/main/java/com/swmansion/rnscreens/ScreenContainer.kt +1 -1
  10. package/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.kt +83 -34
  11. package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +38 -33
  12. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +77 -42
  13. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +25 -9
  14. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.kt +8 -0
  15. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubview.kt +7 -1
  16. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubviewManager.kt +1 -0
  17. package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +10 -0
  18. package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +72 -11
  19. package/android/src/main/java/com/swmansion/rnscreens/SearchBarManager.kt +107 -0
  20. package/android/src/main/java/com/swmansion/rnscreens/SearchBarView.kt +155 -0
  21. package/android/src/main/java/com/swmansion/rnscreens/SearchViewFormatter.kt +67 -0
  22. package/android/src/main/res/anim/rns_default_enter_in.xml +18 -0
  23. package/android/src/main/res/anim/rns_default_enter_out.xml +19 -0
  24. package/android/src/main/res/anim/rns_default_exit_in.xml +17 -0
  25. package/android/src/main/res/anim/rns_default_exit_out.xml +18 -0
  26. package/android/src/main/res/anim/rns_fade_in.xml +7 -0
  27. package/android/src/main/res/anim/rns_fade_out.xml +7 -0
  28. package/android/src/main/res/anim/rns_no_animation_20.xml +6 -0
  29. package/createNativeStackNavigator/README.md +12 -0
  30. package/ios/RNSScreen.h +10 -0
  31. package/ios/RNSScreen.m +38 -0
  32. package/ios/RNSScreenContainer.m +5 -0
  33. package/ios/RNSScreenStack.m +29 -13
  34. package/ios/RNSScreenStackAnimator.m +45 -14
  35. package/ios/RNSScreenStackHeaderConfig.m +4 -1
  36. package/ios/RNSScreenWindowTraits.h +1 -0
  37. package/ios/RNSScreenWindowTraits.m +20 -0
  38. package/ios/UIViewController+RNScreens.m +10 -0
  39. package/lib/commonjs/index.js +17 -1
  40. package/lib/commonjs/index.js.map +1 -1
  41. package/lib/commonjs/index.native.js +66 -18
  42. package/lib/commonjs/index.native.js.map +1 -1
  43. package/lib/commonjs/native-stack/utils/useBackPressSubscription.js +67 -0
  44. package/lib/commonjs/native-stack/utils/useBackPressSubscription.js.map +1 -0
  45. package/lib/commonjs/native-stack/views/HeaderConfig.js +46 -4
  46. package/lib/commonjs/native-stack/views/HeaderConfig.js.map +1 -1
  47. package/lib/commonjs/native-stack/views/NativeStackView.js +33 -4
  48. package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -1
  49. package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js +60 -0
  50. package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js.map +1 -0
  51. package/lib/commonjs/reanimated/ReanimatedScreen.js +7 -79
  52. package/lib/commonjs/reanimated/ReanimatedScreen.js.map +1 -1
  53. package/lib/commonjs/reanimated/ReanimatedScreenProvider.js +61 -0
  54. package/lib/commonjs/reanimated/ReanimatedScreenProvider.js.map +1 -0
  55. package/lib/commonjs/reanimated/index.js +2 -2
  56. package/lib/commonjs/reanimated/index.js.map +1 -1
  57. package/lib/commonjs/utils.js +20 -0
  58. package/lib/commonjs/utils.js.map +1 -0
  59. package/lib/module/index.js +1 -0
  60. package/lib/module/index.js.map +1 -1
  61. package/lib/module/index.native.js +65 -19
  62. package/lib/module/index.native.js.map +1 -1
  63. package/lib/module/native-stack/utils/useBackPressSubscription.js +50 -0
  64. package/lib/module/native-stack/utils/useBackPressSubscription.js.map +1 -0
  65. package/lib/module/native-stack/views/HeaderConfig.js +46 -5
  66. package/lib/module/native-stack/views/HeaderConfig.js.map +1 -1
  67. package/lib/module/native-stack/views/NativeStackView.js +33 -4
  68. package/lib/module/native-stack/views/NativeStackView.js.map +1 -1
  69. package/lib/module/reanimated/ReanimatedNativeStackScreen.js +40 -0
  70. package/lib/module/reanimated/ReanimatedNativeStackScreen.js.map +1 -0
  71. package/lib/module/reanimated/ReanimatedScreen.js +6 -73
  72. package/lib/module/reanimated/ReanimatedScreen.js.map +1 -1
  73. package/lib/module/reanimated/ReanimatedScreenProvider.js +49 -0
  74. package/lib/module/reanimated/ReanimatedScreenProvider.js.map +1 -0
  75. package/lib/module/reanimated/index.js +1 -1
  76. package/lib/module/reanimated/index.js.map +1 -1
  77. package/lib/module/utils.js +8 -0
  78. package/lib/module/utils.js.map +1 -0
  79. package/lib/typescript/index.d.ts +1 -0
  80. package/lib/typescript/native-stack/types.d.ts +34 -2
  81. package/lib/typescript/native-stack/utils/useBackPressSubscription.d.ts +16 -0
  82. package/lib/typescript/reanimated/ReanimatedNativeStackScreen.d.ts +5 -0
  83. package/lib/typescript/reanimated/ReanimatedScreen.d.ts +5 -2
  84. package/lib/typescript/reanimated/ReanimatedScreenProvider.d.ts +2 -0
  85. package/lib/typescript/reanimated/index.d.ts +1 -1
  86. package/lib/typescript/types.d.ts +101 -1
  87. package/lib/typescript/utils.d.ts +2 -0
  88. package/native-stack/README.md +70 -8
  89. package/package.json +2 -1
  90. package/reanimated/package.json +6 -0
  91. package/src/index.native.tsx +94 -36
  92. package/src/index.tsx +4 -0
  93. package/src/native-stack/types.tsx +34 -2
  94. package/src/native-stack/utils/useBackPressSubscription.tsx +66 -0
  95. package/src/native-stack/views/HeaderConfig.tsx +46 -3
  96. package/src/native-stack/views/NativeStackView.tsx +33 -4
  97. package/src/reanimated/ReanimatedNativeStackScreen.tsx +61 -0
  98. package/src/reanimated/ReanimatedScreen.tsx +6 -84
  99. package/src/reanimated/ReanimatedScreenProvider.tsx +42 -0
  100. package/src/reanimated/index.tsx +1 -1
  101. package/src/types.tsx +101 -1
  102. package/src/utils.ts +12 -0
@@ -0,0 +1,66 @@
1
+ import React from 'react';
2
+ import { BackHandler, NativeEventSubscription } from 'react-native';
3
+
4
+ interface Args {
5
+ onBackPress: () => boolean;
6
+ isDisabled: boolean;
7
+ }
8
+
9
+ interface UseBackPressSubscription {
10
+ handleAttached: () => void;
11
+ handleDetached: () => void;
12
+ createSubscription: () => void;
13
+ clearSubscription: () => void;
14
+ }
15
+
16
+ /**
17
+ * This hook is an abstraction for keeping back press subscription
18
+ * logic in one place.
19
+ */
20
+ export function useBackPressSubscription({
21
+ onBackPress,
22
+ isDisabled,
23
+ }: Args): UseBackPressSubscription {
24
+ const [isActive, setIsActive] = React.useState(false);
25
+ const subscription = React.useRef<NativeEventSubscription | undefined>();
26
+
27
+ const clearSubscription = React.useCallback((shouldSetActive = true) => {
28
+ subscription.current?.remove();
29
+ subscription.current = undefined;
30
+ if (shouldSetActive) setIsActive(false);
31
+ }, []);
32
+
33
+ const createSubscription = React.useCallback(() => {
34
+ if (!isDisabled) {
35
+ subscription.current?.remove();
36
+ subscription.current = BackHandler.addEventListener(
37
+ 'hardwareBackPress',
38
+ onBackPress
39
+ );
40
+ setIsActive(true);
41
+ }
42
+ }, [isDisabled, onBackPress]);
43
+
44
+ const handleAttached = React.useCallback(() => {
45
+ if (isActive) {
46
+ createSubscription();
47
+ }
48
+ }, [createSubscription, isActive]);
49
+
50
+ const handleDetached = React.useCallback(() => {
51
+ clearSubscription(false);
52
+ }, [clearSubscription]);
53
+
54
+ React.useEffect(() => {
55
+ if (isDisabled) {
56
+ clearSubscription();
57
+ }
58
+ }, [isDisabled, clearSubscription]);
59
+
60
+ return {
61
+ handleAttached,
62
+ handleDetached,
63
+ createSubscription,
64
+ clearSubscription,
65
+ };
66
+ }
@@ -9,8 +9,12 @@ import {
9
9
  ScreenStackHeaderRightView,
10
10
  ScreenStackHeaderSearchBarView,
11
11
  SearchBar,
12
+ SearchBarProps,
13
+ isSearchBarAvailableForCurrentPlatform,
14
+ executeNativeBackPress,
12
15
  } from 'react-native-screens';
13
16
  import { NativeStackNavigationOptions } from '../types';
17
+ import { useBackPressSubscription } from '../utils/useBackPressSubscription';
14
18
  import { processFonts } from './FontProcessor';
15
19
 
16
20
  type Props = NativeStackNavigationOptions & {
@@ -48,6 +52,19 @@ export default function HeaderConfig({
48
52
  const { colors } = useTheme();
49
53
  const tintColor = headerTintColor ?? colors.primary;
50
54
 
55
+ // We need to use back press subscription here to override back button behavior on JS side.
56
+ // Because screens are usually used with react-navigation and this library overrides back button
57
+ // we need to handle it first in case when search bar is open
58
+ const {
59
+ handleAttached,
60
+ handleDetached,
61
+ clearSubscription,
62
+ createSubscription,
63
+ } = useBackPressSubscription({
64
+ onBackPress: executeNativeBackPress,
65
+ isDisabled: !searchBar || !!searchBar.disableBackButtonOverride,
66
+ });
67
+
51
68
  const [
52
69
  backTitleFontFamily,
53
70
  largeTitleFontFamily,
@@ -58,6 +75,29 @@ export default function HeaderConfig({
58
75
  headerTitleStyle.fontFamily,
59
76
  ]);
60
77
 
78
+ // We want to clear clearSubscription only when components unmounts or search bar changes
79
+ React.useEffect(() => clearSubscription, [searchBar]);
80
+
81
+ const processedSearchBarOptions = React.useMemo(() => {
82
+ if (
83
+ Platform.OS === 'android' &&
84
+ searchBar &&
85
+ !searchBar.disableBackButtonOverride
86
+ ) {
87
+ const onFocus: SearchBarProps['onFocus'] = (...args) => {
88
+ createSubscription();
89
+ searchBar.onFocus?.(...args);
90
+ };
91
+ const onClose: SearchBarProps['onClose'] = (...args) => {
92
+ clearSubscription();
93
+ searchBar.onClose?.(...args);
94
+ };
95
+
96
+ return { ...searchBar, onFocus, onClose };
97
+ }
98
+ return searchBar;
99
+ }, [searchBar, createSubscription, clearSubscription]);
100
+
61
101
  return (
62
102
  <ScreenStackHeaderConfig
63
103
  backButtonInCustomView={backButtonInCustomView}
@@ -99,7 +139,9 @@ export default function HeaderConfig({
99
139
  titleFontSize={headerTitleStyle.fontSize}
100
140
  titleFontWeight={headerTitleStyle.fontWeight}
101
141
  topInsetEnabled={headerTopInsetEnabled}
102
- translucent={headerTranslucent === true}>
142
+ translucent={headerTranslucent === true}
143
+ onAttached={handleAttached}
144
+ onDetached={handleDetached}>
103
145
  {headerRight !== undefined ? (
104
146
  <ScreenStackHeaderRightView>
105
147
  {headerRight({ tintColor })}
@@ -121,9 +163,10 @@ export default function HeaderConfig({
121
163
  {headerCenter({ tintColor })}
122
164
  </ScreenStackHeaderCenterView>
123
165
  ) : null}
124
- {Platform.OS === 'ios' && searchBar !== undefined ? (
166
+ {isSearchBarAvailableForCurrentPlatform &&
167
+ processedSearchBarOptions !== undefined ? (
125
168
  <ScreenStackHeaderSearchBarView>
126
- <SearchBar {...searchBar} />
169
+ <SearchBar {...processedSearchBarOptions} />
127
170
  </ScreenStackHeaderSearchBarView>
128
171
  ) : null}
129
172
  </ScreenStackHeaderConfig>
@@ -149,22 +149,46 @@ const RouteView = ({
149
149
  }) => {
150
150
  const { options, render: renderScene } = descriptors[route.key];
151
151
  const {
152
- customAnimationOnSwipe,
153
- fullScreenSwipeEnabled,
154
152
  gestureEnabled,
155
153
  headerShown,
154
+ homeIndicatorHidden,
156
155
  nativeBackButtonDismissalEnabled = false,
156
+ navigationBarColor,
157
+ navigationBarHidden,
157
158
  replaceAnimation = 'pop',
158
159
  screenOrientation,
159
- stackAnimation,
160
160
  statusBarAnimation,
161
161
  statusBarColor,
162
162
  statusBarHidden,
163
163
  statusBarStyle,
164
164
  statusBarTranslucent,
165
+ swipeDirection = 'horizontal',
166
+ transitionDuration,
167
+ } = options;
168
+
169
+ let {
170
+ customAnimationOnSwipe,
171
+ fullScreenSwipeEnabled,
172
+ stackAnimation,
173
+ stackPresentation = 'push',
165
174
  } = options;
166
175
 
167
- let { stackPresentation = 'push' } = options;
176
+ if (swipeDirection === 'vertical') {
177
+ // for `vertical` direction to work, we need to set `fullScreenSwipeEnabled` to `true`
178
+ // so the screen can be dismissed from any point on screen.
179
+ // `customAnimationOnSwipe` needs to be set to `true` so the `stackAnimation` set by user can be used,
180
+ // otherwise `simple_push` will be used.
181
+ // Also, the default animation for this direction seems to be `slide_from_bottom`.
182
+ if (fullScreenSwipeEnabled === undefined) {
183
+ fullScreenSwipeEnabled = true;
184
+ }
185
+ if (customAnimationOnSwipe === undefined) {
186
+ customAnimationOnSwipe = true;
187
+ }
188
+ if (stackAnimation === undefined) {
189
+ stackAnimation = 'slide_from_bottom';
190
+ }
191
+ }
168
192
 
169
193
  if (index === 0) {
170
194
  // first screen should always be treated as `push`, it resolves problems with no header animation
@@ -194,8 +218,11 @@ const RouteView = ({
194
218
  style={StyleSheet.absoluteFill}
195
219
  customAnimationOnSwipe={customAnimationOnSwipe}
196
220
  fullScreenSwipeEnabled={fullScreenSwipeEnabled}
221
+ homeIndicatorHidden={homeIndicatorHidden}
197
222
  gestureEnabled={isAndroid ? false : gestureEnabled}
198
223
  nativeBackButtonDismissalEnabled={nativeBackButtonDismissalEnabled}
224
+ navigationBarColor={navigationBarColor}
225
+ navigationBarHidden={navigationBarHidden}
199
226
  replaceAnimation={replaceAnimation}
200
227
  screenOrientation={screenOrientation}
201
228
  stackAnimation={stackAnimation}
@@ -205,6 +232,8 @@ const RouteView = ({
205
232
  statusBarHidden={statusBarHidden}
206
233
  statusBarStyle={statusBarStyle}
207
234
  statusBarTranslucent={statusBarTranslucent}
235
+ swipeDirection={swipeDirection}
236
+ transitionDuration={transitionDuration}
208
237
  onHeaderBackButtonClicked={() => {
209
238
  navigation.dispatch({
210
239
  ...StackActions.pop(),
@@ -0,0 +1,61 @@
1
+ import React from 'react';
2
+ import { Platform } from 'react-native';
3
+ import {
4
+ Screen,
5
+ ScreenProps,
6
+ TransitionProgressEventType,
7
+ } from 'react-native-screens';
8
+
9
+ // @ts-ignore file to be used only if `react-native-reanimated` available in the project
10
+ import Animated, { useEvent, useSharedValue } from 'react-native-reanimated';
11
+ import ReanimatedTransitionProgressContext from './ReanimatedTransitionProgressContext';
12
+
13
+ const AnimatedScreen = Animated.createAnimatedComponent(
14
+ (Screen as unknown) as React.ComponentClass
15
+ );
16
+
17
+ const ReanimatedNativeStackScreen = React.forwardRef<
18
+ typeof AnimatedScreen,
19
+ ScreenProps
20
+ >((props, ref) => {
21
+ const { children, ...rest } = props;
22
+
23
+ const progress = useSharedValue(0);
24
+ const closing = useSharedValue(0);
25
+ const goingForward = useSharedValue(0);
26
+
27
+ return (
28
+ <AnimatedScreen
29
+ // @ts-ignore some problems with ref and onTransitionProgressReanimated being "fake" prop for parsing of `useEvent` return value
30
+ ref={ref}
31
+ onTransitionProgressReanimated={useEvent(
32
+ (event: TransitionProgressEventType) => {
33
+ 'worklet';
34
+ progress.value = event.progress;
35
+ closing.value = event.closing;
36
+ goingForward.value = event.goingForward;
37
+ },
38
+ [
39
+ // This should not be necessary, but is not properly managed by `react-native-reanimated`
40
+ // @ts-ignore wrong type
41
+ Platform.OS === 'android'
42
+ ? 'onTransitionProgress'
43
+ : 'topTransitionProgress',
44
+ ]
45
+ )}
46
+ {...rest}>
47
+ <ReanimatedTransitionProgressContext.Provider
48
+ value={{
49
+ progress: progress,
50
+ closing: closing,
51
+ goingForward: goingForward,
52
+ }}>
53
+ {children}
54
+ </ReanimatedTransitionProgressContext.Provider>
55
+ </AnimatedScreen>
56
+ );
57
+ });
58
+
59
+ ReanimatedNativeStackScreen.displayName = 'ReanimatedNativeStackScreen';
60
+
61
+ export default ReanimatedNativeStackScreen;
@@ -1,103 +1,25 @@
1
- import React, { PropsWithChildren } from 'react';
2
- import { Platform, View } from 'react-native';
3
- import {
4
- Screen,
5
- ScreenProps,
6
- ScreenContext,
7
- TransitionProgressEventType,
8
- } from 'react-native-screens';
1
+ import React from 'react';
2
+ import { Screen, ScreenProps } from 'react-native-screens';
9
3
 
10
4
  // @ts-ignore file to be used only if `react-native-reanimated` available in the project
11
- import Animated, { useEvent, useSharedValue } from 'react-native-reanimated';
12
- import ReanimatedTransitionProgressContext from './ReanimatedTransitionProgressContext';
5
+ import Animated from 'react-native-reanimated';
13
6
 
14
7
  const AnimatedScreen = Animated.createAnimatedComponent(
15
8
  (Screen as unknown) as React.ComponentClass
16
9
  );
17
10
 
18
- class ReanimatedScreenWrapper extends React.Component<ScreenProps> {
19
- private ref: React.ElementRef<typeof View> | null = null;
20
-
21
- setNativeProps(props: ScreenProps): void {
22
- this.ref?.setNativeProps(props);
23
- }
24
-
25
- setRef = (ref: React.ElementRef<typeof View> | null): void => {
26
- this.ref = ref;
27
- this.props.onComponentRef?.(ref);
28
- };
29
-
30
- render() {
31
- return (
32
- <ReanimatedScreen
33
- {...this.props}
34
- // @ts-ignore some problems with ref
35
- ref={this.setRef}
36
- />
37
- );
38
- }
39
- }
40
-
41
11
  const ReanimatedScreen = React.forwardRef<typeof AnimatedScreen, ScreenProps>(
42
12
  (props, ref) => {
43
- const { children, ...rest } = props;
44
-
45
- const progress = useSharedValue(0);
46
- const closing = useSharedValue(0);
47
- const goingForward = useSharedValue(0);
48
-
49
13
  return (
50
14
  <AnimatedScreen
51
15
  // @ts-ignore some problems with ref and onTransitionProgressReanimated being "fake" prop for parsing of `useEvent` return value
52
16
  ref={ref}
53
- // ReanimatedScreen.tsx should only be used by Screens of native-stack, but it always better to check
54
- onTransitionProgressReanimated={
55
- !props.isNativeStack
56
- ? undefined
57
- : useEvent(
58
- (event: TransitionProgressEventType) => {
59
- 'worklet';
60
- progress.value = event.progress;
61
- closing.value = event.closing;
62
- goingForward.value = event.goingForward;
63
- },
64
- [
65
- // This should not be necessary, but is not properly managed by `react-native-reanimated`
66
- // @ts-ignore wrong type
67
- Platform.OS === 'android'
68
- ? 'onTransitionProgress'
69
- : 'topTransitionProgress',
70
- ]
71
- )
72
- }
73
- {...rest}>
74
- {!props.isNativeStack ? ( // see comment of this prop in types.tsx for information why it is needed
75
- children
76
- ) : (
77
- <ReanimatedTransitionProgressContext.Provider
78
- value={{
79
- progress: progress,
80
- closing: closing,
81
- goingForward: goingForward,
82
- }}>
83
- {children}
84
- </ReanimatedTransitionProgressContext.Provider>
85
- )}
86
- </AnimatedScreen>
17
+ {...props}
18
+ />
87
19
  );
88
20
  }
89
21
  );
90
22
 
91
- // used to silence error "Component definition is missing display name"
92
23
  ReanimatedScreen.displayName = 'ReanimatedScreen';
93
24
 
94
- export default function ReanimatedScreenProvider(
95
- props: PropsWithChildren<unknown>
96
- ) {
97
- return (
98
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
99
- <ScreenContext.Provider value={ReanimatedScreenWrapper as any}>
100
- {props.children}
101
- </ScreenContext.Provider>
102
- );
103
- }
25
+ export default ReanimatedScreen;
@@ -0,0 +1,42 @@
1
+ import React, { PropsWithChildren } from 'react';
2
+ import { View } from 'react-native';
3
+ import { ScreenProps, ScreenContext } from 'react-native-screens';
4
+ import ReanimatedNativeStackScreen from './ReanimatedNativeStackScreen';
5
+ import AnimatedScreen from './ReanimatedScreen';
6
+
7
+ class ReanimatedScreenWrapper extends React.Component<ScreenProps> {
8
+ private ref: React.ElementRef<typeof View> | null = null;
9
+
10
+ setNativeProps(props: ScreenProps): void {
11
+ this.ref?.setNativeProps(props);
12
+ }
13
+
14
+ setRef = (ref: React.ElementRef<typeof View> | null): void => {
15
+ this.ref = ref;
16
+ this.props.onComponentRef?.(ref);
17
+ };
18
+
19
+ render() {
20
+ const ReanimatedScreen = this.props.isNativeStack
21
+ ? ReanimatedNativeStackScreen
22
+ : AnimatedScreen;
23
+ return (
24
+ <ReanimatedScreen
25
+ {...this.props}
26
+ // @ts-ignore some problems with ref
27
+ ref={this.setRef}
28
+ />
29
+ );
30
+ }
31
+ }
32
+
33
+ export default function ReanimatedScreenProvider(
34
+ props: PropsWithChildren<unknown>
35
+ ) {
36
+ return (
37
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
+ <ScreenContext.Provider value={ReanimatedScreenWrapper as any}>
39
+ {props.children}
40
+ </ScreenContext.Provider>
41
+ );
42
+ }
@@ -1,2 +1,2 @@
1
- export { default as ReanimatedScreenProvider } from './ReanimatedScreen';
1
+ export { default as ReanimatedScreenProvider } from './ReanimatedScreenProvider';
2
2
  export { default as useReanimatedTransitionProgress } from './useReanimatedTransitionProgress';
package/src/types.tsx CHANGED
@@ -47,6 +47,7 @@ export type BlurEffectTypes =
47
47
  | 'systemThickMaterialDark'
48
48
  | 'systemChromeMaterialDark';
49
49
  export type ScreenReplaceTypes = 'push' | 'pop';
50
+ export type SwipeDirectionTypes = 'vertical' | 'horizontal';
50
51
  export type ScreenOrientationTypes =
51
52
  | 'default'
52
53
  | 'all'
@@ -101,6 +102,12 @@ export interface ScreenProps extends ViewProps {
101
102
  * @platform ios
102
103
  */
103
104
  gestureEnabled?: boolean;
105
+ /**
106
+ * Whether the home indicator should be hidden on this screen. Defaults to `false`.
107
+ *
108
+ * @platform ios
109
+ */
110
+ homeIndicatorHidden?: boolean;
104
111
  /**
105
112
  * Boolean indicating whether, when the Android default back button is clicked, the `pop` action should be performed on the native side or on the JS side to be able to prevent it.
106
113
  * Unfortunately the same behavior is not available on iOS since the behavior of native back button cannot be changed there.
@@ -109,6 +116,18 @@ export interface ScreenProps extends ViewProps {
109
116
  * @platform android
110
117
  */
111
118
  nativeBackButtonDismissalEnabled?: boolean;
119
+ /**
120
+ * Sets the navigation bar color. Defaults to initial status bar color.
121
+ *
122
+ * @platform android
123
+ */
124
+ navigationBarColor?: string;
125
+ /**
126
+ * Sets the visibility of the navigation bar. Defaults to `false`.
127
+ *
128
+ * @platform android
129
+ */
130
+ navigationBarHidden?: boolean;
112
131
  /**
113
132
  * A callback that gets called when the current screen appears.
114
133
  */
@@ -214,6 +233,23 @@ export interface ScreenProps extends ViewProps {
214
233
  * @platform android
215
234
  */
216
235
  statusBarTranslucent?: boolean;
236
+ /**
237
+ * Sets the direction in which you should swipe to dismiss the screen.
238
+ * When using `vertical` option, options `fullScreenSwipeEnabled: true`, `customAnimationOnSwipe: true` and `stackAnimation: 'slide_from_bottom'` are set by default.
239
+ * The following values are supported:
240
+ * - `vertical` – dismiss screen vertically
241
+ * - `horizontal` – dismiss screen horizontally (default)
242
+ *
243
+ * @platform ios
244
+ */
245
+ swipeDirection?: SwipeDirectionTypes;
246
+ /**
247
+ * Changes the duration (in milliseconds) of `slide_from_bottom`, `fade_from_bottom`, `fade` and `simple_push` transitions on iOS. Defaults to `350`.
248
+ * The duration of `default` and `flip` transitions isn't customizable.
249
+ *
250
+ * @platform ios
251
+ */
252
+ transitionDuration?: number;
217
253
  }
218
254
 
219
255
  export interface ScreenContainerProps extends ViewProps {
@@ -331,6 +367,14 @@ export interface ScreenStackHeaderConfigProps extends ViewProps {
331
367
  * Boolean that allows for disabling drop shadow under navigation header when the edge of any scrollable content reaches the matching edge of the navigation bar.
332
368
  */
333
369
  largeTitleHideShadow?: boolean;
370
+ /**
371
+ * Callback which is executed when screen header is attached
372
+ */
373
+ onAttached?: () => void;
374
+ /**
375
+ * Callback which is executed when screen header is detached
376
+ */
377
+ onDetached?: () => void;
334
378
  /**
335
379
  * String that can be displayed in the header as a fallback for `headerTitle`.
336
380
  */
@@ -371,24 +415,47 @@ export interface SearchBarProps {
371
415
  * The auto-capitalization behavior
372
416
  */
373
417
  autoCapitalize?: 'none' | 'words' | 'sentences' | 'characters';
418
+ /**
419
+ * Automatically focuses search bar on mount
420
+ *
421
+ * @platform android
422
+ */
423
+ autoFocus?: boolean;
374
424
  /**
375
425
  * The search field background color
376
426
  */
377
427
  barTintColor?: string;
378
428
  /**
379
429
  * The text to be used instead of default `Cancel` button text
430
+ *
431
+ * @platform ios
380
432
  */
381
433
  cancelButtonText?: string;
382
-
434
+ /**
435
+ * Specifies whether the back button should close search bar's text input or not.
436
+ *
437
+ * @platform android
438
+ */
439
+ disableBackButtonOverride?: boolean;
383
440
  /**
384
441
  * Indicates whether to hide the navigation bar
442
+ *
443
+ * @platform ios
385
444
  */
386
445
  hideNavigationBar?: boolean;
387
446
  /**
388
447
  * Indicates whether to hide the search bar when scrolling
448
+ *
449
+ * @platform ios
389
450
  */
390
451
  hideWhenScrolling?: boolean;
391
452
 
453
+ /**
454
+ * Sets type of the input. Defaults to `text`.
455
+ *
456
+ * @platform android
457
+ */
458
+ inputType?: 'text' | 'phone' | 'number' | 'email';
392
459
  /**
393
460
  * Indicates whether to to obscure the underlying content
394
461
  */
@@ -399,6 +466,8 @@ export interface SearchBarProps {
399
466
  onBlur?: (e: NativeSyntheticEvent<TargetedEvent>) => void;
400
467
  /**
401
468
  * A callback that gets called when the cancel button is pressed
469
+ *
470
+ * @platform ios
402
471
  */
403
472
  onCancelButtonPress?: (e: NativeSyntheticEvent<TargetedEvent>) => void;
404
473
 
@@ -407,10 +476,22 @@ export interface SearchBarProps {
407
476
  */
408
477
  onChangeText?: (e: NativeSyntheticEvent<TextInputFocusEventData>) => void;
409
478
 
479
+ /**
480
+ * A callback that gets called when search bar is closed
481
+ *
482
+ * @platform android
483
+ */
484
+ onClose?: () => void;
410
485
  /**
411
486
  * A callback that gets called when search bar has received focus
412
487
  */
413
488
  onFocus?: (e: NativeSyntheticEvent<TargetedEvent>) => void;
489
+ /**
490
+ * A callback that gets called when search bar is opened
491
+ *
492
+ * @platform android
493
+ */
494
+ onOpen?: () => void;
414
495
  /**
415
496
  * A callback that gets called when the search button is pressed. It receives the current text value of the search bar.
416
497
  */
@@ -425,4 +506,23 @@ export interface SearchBarProps {
425
506
  * The search field text color
426
507
  */
427
508
  textColor?: string;
509
+ /**
510
+ * The search hint text color
511
+ *
512
+ * @plaform android
513
+ */
514
+ hintTextColor?: string;
515
+ /**
516
+ * The search and close icon color shown in the header
517
+ *
518
+ * @plaform android
519
+ */
520
+ headerIconColor?: string;
521
+ /**
522
+ * Show the search hint icon when search bar is focused
523
+ *
524
+ * @plaform android
525
+ * @default true
526
+ */
527
+ shouldShowHintSearchIcon?: boolean;
428
528
  }
package/src/utils.ts ADDED
@@ -0,0 +1,12 @@
1
+ import { BackHandler, Platform } from 'react-native';
2
+
3
+ export const isSearchBarAvailableForCurrentPlatform = [
4
+ 'ios',
5
+ 'android',
6
+ ].includes(Platform.OS);
7
+
8
+ export function executeNativeBackPress() {
9
+ // This function invokes the native back press event
10
+ BackHandler.exitApp();
11
+ return true;
12
+ }