react-native-screens 4.0.0-beta.2 → 4.0.0-beta.4

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 (52) hide show
  1. package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +35 -3
  2. package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +0 -3
  3. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +11 -12
  4. package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +6 -1
  5. package/ios/RNSConvert.mm +0 -1
  6. package/ios/RNSScreen.h +1 -0
  7. package/ios/RNSScreen.mm +27 -3
  8. package/lib/commonjs/components/Screen.js +49 -7
  9. package/lib/commonjs/components/Screen.js.map +1 -1
  10. package/lib/commonjs/components/ScreenContentWrapper.web.js +3 -2
  11. package/lib/commonjs/components/ScreenContentWrapper.web.js.map +1 -1
  12. package/lib/commonjs/components/ScreenFooter.web.js +11 -0
  13. package/lib/commonjs/components/ScreenFooter.web.js.map +1 -0
  14. package/lib/commonjs/fabric/ModalScreenNativeComponent.js.map +1 -1
  15. package/lib/commonjs/fabric/ScreenNativeComponent.js.map +1 -1
  16. package/lib/commonjs/native-stack/views/NativeStackView.js +4 -4
  17. package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -1
  18. package/lib/module/components/Screen.js +49 -7
  19. package/lib/module/components/Screen.js.map +1 -1
  20. package/lib/module/components/ScreenContentWrapper.web.js +2 -1
  21. package/lib/module/components/ScreenContentWrapper.web.js.map +1 -1
  22. package/lib/module/components/ScreenFooter.web.js +5 -0
  23. package/lib/module/components/ScreenFooter.web.js.map +1 -0
  24. package/lib/module/fabric/ModalScreenNativeComponent.js.map +1 -1
  25. package/lib/module/fabric/ScreenNativeComponent.js.map +1 -1
  26. package/lib/module/native-stack/views/NativeStackView.js +4 -4
  27. package/lib/module/native-stack/views/NativeStackView.js.map +1 -1
  28. package/lib/typescript/components/Screen.d.ts +5 -1
  29. package/lib/typescript/components/Screen.d.ts.map +1 -1
  30. package/lib/typescript/components/ScreenContentWrapper.web.d.ts +2 -1
  31. package/lib/typescript/components/ScreenContentWrapper.web.d.ts.map +1 -1
  32. package/lib/typescript/components/ScreenFooter.web.d.ts +5 -0
  33. package/lib/typescript/components/ScreenFooter.web.d.ts.map +1 -0
  34. package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts +1 -0
  35. package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts.map +1 -1
  36. package/lib/typescript/fabric/ScreenNativeComponent.d.ts +1 -1
  37. package/lib/typescript/fabric/ScreenNativeComponent.d.ts.map +1 -1
  38. package/lib/typescript/native-stack/types.d.ts +2 -3
  39. package/lib/typescript/native-stack/types.d.ts.map +1 -1
  40. package/lib/typescript/types.d.ts +26 -9
  41. package/lib/typescript/types.d.ts.map +1 -1
  42. package/native-stack/README.md +3 -2
  43. package/package.json +1 -1
  44. package/src/components/Screen.tsx +81 -12
  45. package/src/components/ScreenContentWrapper.web.tsx +3 -1
  46. package/src/components/ScreenFooter.web.tsx +6 -0
  47. package/src/fabric/ModalScreenNativeComponent.ts +1 -0
  48. package/src/fabric/ScreenNativeComponent.ts +0 -1
  49. package/src/native-stack/types.tsx +2 -3
  50. package/src/native-stack/views/NativeStackView.tsx +4 -4
  51. package/src/types.tsx +29 -13
  52. package/windows/RNScreens/Screen.h +0 -1
@@ -287,9 +287,11 @@ Defaults to system default.
287
287
 
288
288
  #### `sheetInitialDetent`
289
289
 
290
- Initial detent for the sheet.
290
+ Index of the detent the sheet should expand to after being opened.
291
291
  Works only when `presentation` is set to `formSheet`.
292
292
 
293
+ Defaults to `0` - which represents first detent in the detents array.
294
+
293
295
  #### `sheetGrabberVisible` (iOS only)
294
296
 
295
297
  Boolean indicating whether the sheet shows a grabber at the top.
@@ -326,7 +328,6 @@ How the given screen should appear/disappear when pushed or popped at the top of
326
328
  - `slide_from_bottom` – performs a slide from bottom animation
327
329
  - `slide_from_right` - slide in the new screen from right to left (Android only, resolves to default transition on iOS)
328
330
  - `slide_from_left` - slide in the new screen from left to right
329
- - `"ios"` - @deprecated iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS) (will be removed in v4.0.0 in favor of `ios_from_right`)
330
331
  - `"ios_from_right"` - iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS)
331
332
  - `"ios_from_left"` - iOS like slide in animation. pushes in the new screen from left to right (Android only, resolves to default transition on iOS)
332
333
  - `none` - the screen appears/disappears without an animation.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-screens",
3
- "version": "4.0.0-beta.2",
3
+ "version": "4.0.0-beta.4",
4
4
  "description": "Native navigation primitives for your React Native app.",
5
5
  "scripts": {
6
6
  "submodules": "git submodule update --init --recursive && (cd react-navigation && yarn)",
@@ -17,11 +17,19 @@ import {
17
17
  import ScreenNativeComponent from '../fabric/ScreenNativeComponent';
18
18
  import ModalScreenNativeComponent from '../fabric/ModalScreenNativeComponent';
19
19
 
20
- export const NativeScreen: React.ComponentType<ScreenProps> =
21
- ScreenNativeComponent as React.ComponentType<ScreenProps>;
20
+ type NativeScreenProps = Omit<
21
+ ScreenProps,
22
+ 'sheetInitialDetentIndex' | 'sheetLargestUndimmedDetentIndex'
23
+ > & {
24
+ sheetInitialDetent: number;
25
+ sheetLargestUndimmedDetent: number;
26
+ };
27
+
28
+ export const NativeScreen: React.ComponentType<NativeScreenProps> =
29
+ ScreenNativeComponent as React.ComponentType<NativeScreenProps>;
22
30
  const AnimatedNativeScreen = Animated.createAnimatedComponent(NativeScreen);
23
31
  const AnimatedNativeModalScreen = Animated.createAnimatedComponent(
24
- ModalScreenNativeComponent as React.ComponentType<ScreenProps>,
32
+ ModalScreenNativeComponent as React.ComponentType<NativeScreenProps>,
25
33
  );
26
34
 
27
35
  // Incomplete type, all accessible properties available at:
@@ -52,12 +60,31 @@ const SHEET_COMPAT_ALL = [0.5, 1.0];
52
60
  const SHEET_DIMMED_ALWAYS = -1;
53
61
  // const SHEET_DIMMED_NEVER = 9999;
54
62
 
63
+ function assertDetentsArrayIsSorted(array: number[]) {
64
+ for (let i = 1; i < array.length; i++) {
65
+ if (array[i - 1] > array[i]) {
66
+ throw new Error(
67
+ '[RNScreens] The detent array is not sorted in ascending order!',
68
+ );
69
+ }
70
+ }
71
+ }
72
+
55
73
  // These exist to transform old 'legacy' values used by the formsheet API to the new API shape.
56
74
  // We can get rid of it, once we get rid of support for legacy values: 'large', 'medium', 'all'.
57
75
  function resolveSheetAllowedDetents(
58
76
  allowedDetentsCompat: ScreenProps['sheetAllowedDetents'],
59
77
  ): number[] {
60
78
  if (Array.isArray(allowedDetentsCompat)) {
79
+ if (__DEV__) {
80
+ assertDetentsArrayIsSorted(allowedDetentsCompat);
81
+ if (Platform.OS === 'android' && allowedDetentsCompat.length > 3) {
82
+ console.warn(
83
+ '[RNScreens] Sheets API on Android do accept only up to 3 values. Any surplus value are ignored.',
84
+ );
85
+ allowedDetentsCompat = allowedDetentsCompat.slice(0, 3);
86
+ }
87
+ }
61
88
  return allowedDetentsCompat;
62
89
  } else if (allowedDetentsCompat === 'fitToContents') {
63
90
  return SHEET_FIT_TO_CONTENTS;
@@ -74,13 +101,22 @@ function resolveSheetAllowedDetents(
74
101
  }
75
102
 
76
103
  function resolveSheetLargestUndimmedDetent(
77
- lud: ScreenProps['sheetLargestUndimmedDetent'],
78
- largestDetentIndex: number,
104
+ lud: ScreenProps['sheetLargestUndimmedDetentIndex'],
105
+ lastDetentIndex: number,
79
106
  ): number {
80
107
  if (typeof lud === 'number') {
108
+ if (!isIndexInClosedRange(lud, SHEET_DIMMED_ALWAYS, lastDetentIndex)) {
109
+ if (__DEV__) {
110
+ throw new Error(
111
+ "[RNScreens] Provided value of 'sheetLargestUndimmedDetentIndex' prop is out of bounds of 'sheetAllowedDetents' array.",
112
+ );
113
+ }
114
+ // Return default in production
115
+ return SHEET_DIMMED_ALWAYS;
116
+ }
81
117
  return lud;
82
- } else if (lud === 'largest') {
83
- return largestDetentIndex;
118
+ } else if (lud === 'last') {
119
+ return lastDetentIndex;
84
120
  } else if (lud === 'none' || lud === 'all') {
85
121
  return SHEET_DIMMED_ALWAYS;
86
122
  } else if (lud === 'large') {
@@ -93,6 +129,36 @@ function resolveSheetLargestUndimmedDetent(
93
129
  }
94
130
  }
95
131
 
132
+ function resolveSheetInitialDetentIndex(
133
+ index: ScreenProps['sheetInitialDetentIndex'],
134
+ lastDetentIndex: number,
135
+ ): number {
136
+ if (index === 'last') {
137
+ index = lastDetentIndex;
138
+ } else if (index == null) {
139
+ // Intentional check for undefined & null ^
140
+ index = 0;
141
+ }
142
+ if (!isIndexInClosedRange(index, 0, lastDetentIndex)) {
143
+ if (__DEV__) {
144
+ throw new Error(
145
+ "[RNScreens] Provided value of 'sheetInitialDetentIndex' prop is out of bounds of 'sheetAllowedDetents' array.",
146
+ );
147
+ }
148
+ // Return default in production
149
+ return 0;
150
+ }
151
+ return index;
152
+ }
153
+
154
+ function isIndexInClosedRange(
155
+ value: number,
156
+ lowerBound: number,
157
+ upperBound: number,
158
+ ): boolean {
159
+ return Number.isInteger(value) && value >= lowerBound && value <= upperBound;
160
+ }
161
+
96
162
  export const InnerScreen = React.forwardRef<View, ScreenProps>(
97
163
  function InnerScreen(props, ref) {
98
164
  const innerRef = React.useRef<ViewConfig | null>(null);
@@ -118,13 +184,12 @@ export const InnerScreen = React.forwardRef<View, ScreenProps>(
118
184
  const {
119
185
  // formSheet presentation related props
120
186
  sheetAllowedDetents = [1.0],
121
- sheetLargestUndimmedDetent = SHEET_DIMMED_ALWAYS,
187
+ sheetLargestUndimmedDetentIndex = SHEET_DIMMED_ALWAYS,
122
188
  sheetGrabberVisible = false,
123
189
  sheetCornerRadius = -1.0,
124
190
  sheetExpandsWhenScrolledToEdge = true,
125
191
  sheetElevation = 24,
126
- sheetInitialDetent = 0,
127
-
192
+ sheetInitialDetentIndex = 0,
128
193
  // Other
129
194
  stackPresentation,
130
195
  } = rest;
@@ -134,9 +199,13 @@ export const InnerScreen = React.forwardRef<View, ScreenProps>(
134
199
  resolveSheetAllowedDetents(sheetAllowedDetents);
135
200
  const resolvedSheetLargestUndimmedDetent =
136
201
  resolveSheetLargestUndimmedDetent(
137
- sheetLargestUndimmedDetent,
202
+ sheetLargestUndimmedDetentIndex,
138
203
  resolvedSheetAllowedDetents.length - 1,
139
204
  );
205
+ const resolvedSheetInitialDetentIndex = resolveSheetInitialDetentIndex(
206
+ sheetInitialDetentIndex,
207
+ resolvedSheetAllowedDetents.length - 1,
208
+ );
140
209
  // Due to how Yoga resolves layout, we need to have different components for modal nad non-modal screens
141
210
  const AnimatedScreen =
142
211
  Platform.OS === 'android' ||
@@ -200,7 +269,7 @@ export const InnerScreen = React.forwardRef<View, ScreenProps>(
200
269
  sheetGrabberVisible={sheetGrabberVisible}
201
270
  sheetCornerRadius={sheetCornerRadius}
202
271
  sheetExpandsWhenScrolledToEdge={sheetExpandsWhenScrolledToEdge}
203
- sheetInitialDetent={sheetInitialDetent}
272
+ sheetInitialDetent={resolvedSheetInitialDetentIndex}
204
273
  gestureResponseDistance={{
205
274
  start: gestureResponseDistance?.start ?? -1,
206
275
  end: gestureResponseDistance?.end ?? -1,
@@ -1,4 +1,6 @@
1
1
  import { View } from 'react-native';
2
2
 
3
3
  export const NativeScreenContentWrapper = View;
4
- export const ScreenContentWrapper = View;
4
+
5
+ const ScreenContentWrapper = View;
6
+ export default ScreenContentWrapper;
@@ -0,0 +1,6 @@
1
+ import { View } from 'react-native';
2
+
3
+ export const NativeScreenFooter = View;
4
+
5
+ const ScreenFooter = View;
6
+ export default ScreenFooter;
@@ -75,6 +75,7 @@ export interface NativeProps extends ViewProps {
75
75
  sheetGrabberVisible?: WithDefault<boolean, false>;
76
76
  sheetCornerRadius?: WithDefault<Float, -1.0>;
77
77
  sheetExpandsWhenScrolledToEdge?: WithDefault<boolean, false>;
78
+ sheetInitialDetent?: WithDefault<Int32, 0>;
78
79
  customAnimationOnSwipe?: boolean;
79
80
  fullScreenSwipeEnabled?: boolean;
80
81
  fullScreenSwipeShadowEnabled?: boolean;
@@ -58,7 +58,6 @@ type StackAnimation =
58
58
  | 'slide_from_left'
59
59
  | 'slide_from_bottom'
60
60
  | 'fade_from_bottom'
61
- | 'ios'
62
61
  | 'ios_from_right'
63
62
  | 'ios_from_left';
64
63
 
@@ -418,7 +418,7 @@ export type NativeStackNavigationOptions = {
418
418
  *
419
419
  * Defaults to `0` - which represents first detent in the detents array.
420
420
  */
421
- sheetInitialDetent?: ScreenProps['sheetInitialDetent'];
421
+ sheetInitialDetentIndex?: ScreenProps['sheetInitialDetentIndex'];
422
422
  /**
423
423
  * The largest sheet detent for which a view underneath won't be dimmed.
424
424
  * Works only when `stackPresentation` is set to `formSheet`.
@@ -436,7 +436,7 @@ export type NativeStackNavigationOptions = {
436
436
  *
437
437
  * Defaults to `none`, indicating that the dimming view should be always present.
438
438
  */
439
- sheetLargestUndimmedDetent?: ScreenProps['sheetLargestUndimmedDetent'];
439
+ sheetLargestUndimmedDetentIndex?: ScreenProps['sheetLargestUndimmedDetentIndex'];
440
440
  /**
441
441
  * How the screen should appear/disappear when pushed or popped at the top of the stack.
442
442
  * The following values are currently supported:
@@ -448,7 +448,6 @@ export type NativeStackNavigationOptions = {
448
448
  * - "slide_from_bottom" – performs a slide from bottom animation
449
449
  * - "slide_from_right" - slide in the new screen from right to left (Android only, resolves to default transition on iOS)
450
450
  * - "slide_from_left" - slide in the new screen from left to right
451
- * - "ios" - @deprecated iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS) (will be removed in v4.0.0 in favor of `ios_from_right`)
452
451
  * - "ios_from_right" - iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS)
453
452
  * - "ios_from_left" - iOS like slide in animation. pushes in the new screen from left to right (Android only, resolves to default transition on iOS)
454
453
  * - "none" – the screen appears/dissapears without an animation
@@ -195,12 +195,12 @@ const RouteView = ({
195
195
  headerShown,
196
196
  hideKeyboardOnSwipe,
197
197
  homeIndicatorHidden,
198
- sheetLargestUndimmedDetent = 'none',
198
+ sheetLargestUndimmedDetentIndex = 'none',
199
199
  sheetGrabberVisible = false,
200
200
  sheetCornerRadius = -1.0,
201
201
  sheetElevation = 24,
202
202
  sheetExpandsWhenScrolledToEdge = true,
203
- sheetInitialDetent = 0,
203
+ sheetInitialDetentIndex = 0,
204
204
  nativeBackButtonDismissalEnabled = false,
205
205
  navigationBarColor,
206
206
  navigationBarTranslucent,
@@ -318,9 +318,9 @@ const RouteView = ({
318
318
  hasLargeHeader={hasLargeHeader}
319
319
  style={[StyleSheet.absoluteFill, unstable_screenStyle]}
320
320
  sheetAllowedDetents={sheetAllowedDetents}
321
- sheetLargestUndimmedDetent={sheetLargestUndimmedDetent}
321
+ sheetLargestUndimmedDetentIndex={sheetLargestUndimmedDetentIndex}
322
322
  sheetGrabberVisible={sheetGrabberVisible}
323
- sheetInitialDetent={sheetInitialDetent}
323
+ sheetInitialDetentIndex={sheetInitialDetentIndex}
324
324
  sheetCornerRadius={sheetCornerRadius}
325
325
  sheetElevation={sheetElevation}
326
326
  sheetExpandsWhenScrolledToEdge={sheetExpandsWhenScrolledToEdge}
package/src/types.tsx CHANGED
@@ -39,7 +39,6 @@ export type StackAnimationTypes =
39
39
  | 'slide_from_bottom'
40
40
  | 'slide_from_right'
41
41
  | 'slide_from_left'
42
- | 'ios'
43
42
  | 'ios_from_right'
44
43
  | 'ios_from_left';
45
44
  export type BlurEffectTypes =
@@ -290,13 +289,19 @@ export interface ScreenProps extends ViewProps {
290
289
  unstable_screenStyle?: Pick<ViewStyle, 'backgroundColor'>;
291
290
  /**
292
291
  * Describes heights where a sheet can rest.
293
- * Works only when `stackPresentation` is set to `formSheet`.
292
+ * Works only when `presentation` is set to `formSheet`.
294
293
  *
295
294
  * Heights should be described as fraction (a number from `[0, 1]` interval) of screen height / maximum detent height.
296
- * There is also possibility to specify `[-1]` literal array with single element, which intets to set the sheet height
295
+ * You can pass an array of ascending values each defining allowed sheet detent. iOS accepts any number of detents,
296
+ * while **Android is limited to three**.
297
+ *
298
+ * There is also possibility to specify `fitToContents` literal, which intents to set the sheet height
297
299
  * to the height of its contents.
298
300
  *
299
- * Please note that the array **must** be sorted in ascending order.
301
+ * Please note that the array **must** be sorted in ascending order. This invariant is verified only in developement mode,
302
+ * where violation results in error.
303
+ *
304
+ * **Android is limited to up 3 values in the array** -- any surplus values, beside first three are ignored.
300
305
  *
301
306
  * There are also legacy & **deprecated** options available:
302
307
  *
@@ -304,7 +309,9 @@ export interface ScreenProps extends ViewProps {
304
309
  * * 'large' - corresponds to `[1.0]` detent value, maximum height,
305
310
  * * 'all' - corresponds to `[0.5, 1.0]` value, the name is deceiving due to compatibility reasons.
306
311
  *
307
- * Defaults to `[1.0]` literal.
312
+ * These are provided solely for **temporary** backward compatibility and are destined for removal in future versions.
313
+ *
314
+ * Defaults to `[1.0]`.
308
315
  */
309
316
  sheetAllowedDetents?: number[] | 'fitToContents' | 'medium' | 'large' | 'all';
310
317
  /**
@@ -351,30 +358,40 @@ export interface ScreenProps extends ViewProps {
351
358
  * This prop can be set to an number, which indicates index of detent in `sheetAllowedDetents` array for which
352
359
  * there won't be a dimming view beneath the sheet.
353
360
  *
361
+ * If the specified index is out of bounds of `sheetAllowedDetents` array, in dev environment mode error will be thrown,
362
+ * in production the value will be reset to default value.
363
+ *
354
364
  * Additionaly there are following options available:
355
365
  *
356
366
  * * `none` - there will be dimming view for all detents levels,
357
- * * `largest` - there won't be a dimming view for any detent level.
367
+ * * `last` - there won't be a dimming view for any detent level.
358
368
  *
359
369
  * There also legacy & **deprecated** prop values available: `medium`, `large` (don't confuse with `largest`), `all`, which work in tandem with
360
370
  * corresponding legacy prop values for `sheetAllowedDetents` prop.
361
371
  *
372
+ * These are provided solely for **temporary** backward compatibility and are destined for removal in future versions.
373
+ *
362
374
  * Defaults to `none`, indicating that the dimming view should be always present.
363
375
  */
364
- sheetLargestUndimmedDetent?:
376
+ sheetLargestUndimmedDetentIndex?:
365
377
  | number
366
378
  | 'none'
367
- | 'largest'
368
- | 'medium'
369
- | 'large'
370
- | 'all';
379
+ | 'last'
380
+ | 'medium' // deprecated
381
+ | 'large' // deprecated
382
+ | 'all'; // deprecated
371
383
  /**
372
384
  * Index of the detent the sheet should expand to after being opened.
373
385
  * Works only when `stackPresentation` is set to `formSheet`.
374
386
  *
387
+ * If the specified index is out of bounds of `sheetAllowedDetents` array, in dev environment more error will be thrown,
388
+ * in production the value will be reset to default value.
389
+ *
390
+ * Additionaly there is `last` value available, when set the sheet will expand initially to last (largest) detent.
391
+ *
375
392
  * Defaults to `0` - which represents first detent in the detents array.
376
393
  */
377
- sheetInitialDetent?: number;
394
+ sheetInitialDetentIndex?: number | 'last';
378
395
  /**
379
396
  * How the screen should appear/disappear when pushed or popped at the top of the stack.
380
397
  * The following values are currently supported:
@@ -386,7 +403,6 @@ export interface ScreenProps extends ViewProps {
386
403
  * - `slide_from_bottom` – performs a slide from bottom animation
387
404
  * - "slide_from_right" - slide in the new screen from right to left (Android only, resolves to default transition on iOS)
388
405
  * - "slide_from_left" - slide in the new screen from left to right
389
- * - "ios" - @deprecated iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS) (will be removed in v4.0.0 in favor of `ios_from_right`)
390
406
  * - "ios_from_right" - iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS)
391
407
  * - "ios_from_left" - iOS like slide in animation. pushes in the new screen from left to right (Android only, resolves to default transition on iOS)
392
408
  * - "none" – the screen appears/dissapears without an animation
@@ -11,7 +11,6 @@ enum class StackAnimation {
11
11
  SIMPLE_FROM_BOTTOM,
12
12
  SLIDE_FROM_RIGHT,
13
13
  SLIDE_FROM_LEFT,
14
- IOS,
15
14
  IOS_FROM_RIGHT,
16
15
  IOS_FROM_LEFT
17
16
  };