@react-navigation/stack 7.4.4 → 7.4.6

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 (32) hide show
  1. package/lib/module/views/Stack/Card.js +65 -81
  2. package/lib/module/views/Stack/Card.js.map +1 -1
  3. package/lib/module/views/Stack/CardA11yWrapper.js +44 -0
  4. package/lib/module/views/Stack/CardA11yWrapper.js.map +1 -0
  5. package/lib/module/views/Stack/CardContainer.js +71 -70
  6. package/lib/module/views/Stack/CardContainer.js.map +1 -1
  7. package/lib/module/views/Stack/{CardSheet.js → CardContent.js} +5 -13
  8. package/lib/module/views/Stack/CardContent.js.map +1 -0
  9. package/lib/module/views/Stack/CardStack.js +26 -21
  10. package/lib/module/views/Stack/CardStack.js.map +1 -1
  11. package/lib/module/views/Stack/StackView.js +2 -2
  12. package/lib/module/views/Stack/StackView.js.map +1 -1
  13. package/lib/typescript/src/views/Stack/Card.d.ts +5 -5
  14. package/lib/typescript/src/views/Stack/Card.d.ts.map +1 -1
  15. package/lib/typescript/src/views/Stack/CardA11yWrapper.d.ts +15 -0
  16. package/lib/typescript/src/views/Stack/CardA11yWrapper.d.ts.map +1 -0
  17. package/lib/typescript/src/views/Stack/CardContainer.d.ts.map +1 -1
  18. package/lib/typescript/src/views/Stack/CardContent.d.ts +13 -0
  19. package/lib/typescript/src/views/Stack/CardContent.d.ts.map +1 -0
  20. package/lib/typescript/src/views/Stack/CardStack.d.ts +2 -1
  21. package/lib/typescript/src/views/Stack/CardStack.d.ts.map +1 -1
  22. package/package.json +5 -5
  23. package/src/views/Stack/Card.tsx +96 -111
  24. package/src/views/Stack/CardA11yWrapper.tsx +65 -0
  25. package/src/views/Stack/CardContainer.tsx +92 -98
  26. package/src/views/Stack/CardContent.tsx +92 -0
  27. package/src/views/Stack/CardStack.tsx +51 -42
  28. package/src/views/Stack/StackView.tsx +2 -2
  29. package/lib/module/views/Stack/CardSheet.js.map +0 -1
  30. package/lib/typescript/src/views/Stack/CardSheet.d.ts +0 -14
  31. package/lib/typescript/src/views/Stack/CardSheet.d.ts.map +0 -1
  32. package/src/views/Stack/CardSheet.tsx +0 -106
@@ -40,9 +40,9 @@ import type {
40
40
  Scene,
41
41
  StackAnimationName,
42
42
  StackCardStyleInterpolator,
43
- StackDescriptor,
44
43
  StackDescriptorMap,
45
44
  StackHeaderMode,
45
+ StackNavigationOptions,
46
46
  TransitionPreset,
47
47
  } from '../../types';
48
48
  import { findLastIndex } from '../../utils/findLastIndex';
@@ -198,24 +198,20 @@ const getHeaderHeights = (
198
198
 
199
199
  const getDistanceFromOptions = (
200
200
  layout: Layout,
201
- descriptor: StackDescriptor | undefined,
201
+ options: StackNavigationOptions | undefined,
202
202
  isRTL: boolean
203
203
  ) => {
204
- if (descriptor?.options.gestureDirection) {
205
- return getDistanceForDirection(
206
- layout,
207
- descriptor?.options.gestureDirection,
208
- isRTL
209
- );
204
+ if (options?.gestureDirection) {
205
+ return getDistanceForDirection(layout, options.gestureDirection, isRTL);
210
206
  }
211
207
 
212
208
  const defaultGestureDirection =
213
- descriptor?.options.presentation === 'modal'
209
+ options?.presentation === 'modal'
214
210
  ? ModalTransition.gestureDirection
215
211
  : DefaultTransition.gestureDirection;
216
212
 
217
- const gestureDirection = descriptor?.options.animation
218
- ? NAMED_TRANSITIONS_PRESETS[descriptor?.options.animation]?.gestureDirection
213
+ const gestureDirection = options?.animation
214
+ ? NAMED_TRANSITIONS_PRESETS[options?.animation]?.gestureDirection
219
215
  : defaultGestureDirection;
220
216
 
221
217
  return getDistanceForDirection(layout, gestureDirection, isRTL);
@@ -224,7 +220,7 @@ const getDistanceFromOptions = (
224
220
  const getProgressFromGesture = (
225
221
  gesture: Animated.Value,
226
222
  layout: Layout,
227
- descriptor: StackDescriptor | undefined,
223
+ options: StackNavigationOptions | undefined,
228
224
  isRTL: boolean
229
225
  ) => {
230
226
  const distance = getDistanceFromOptions(
@@ -234,7 +230,7 @@ const getProgressFromGesture = (
234
230
  width: Math.max(1, layout.width),
235
231
  height: Math.max(1, layout.height),
236
232
  },
237
- descriptor,
233
+ options,
238
234
  isRTL
239
235
  );
240
236
 
@@ -251,6 +247,20 @@ const getProgressFromGesture = (
251
247
  });
252
248
  };
253
249
 
250
+ function getDefaultAnimation(animation: StackAnimationName | undefined) {
251
+ // Disable screen transition animation by default on web, windows and macos to match the native behavior
252
+ const excludedPlatforms =
253
+ Platform.OS !== 'web' &&
254
+ Platform.OS !== 'windows' &&
255
+ Platform.OS !== 'macos';
256
+
257
+ return animation ?? (excludedPlatforms ? 'default' : 'none');
258
+ }
259
+
260
+ export function getAnimationEnabled(animation: StackAnimationName | undefined) {
261
+ return getDefaultAnimation(animation) !== 'none';
262
+ }
263
+
254
264
  export class CardStack extends React.Component<Props, State> {
255
265
  static getDerivedStateFromProps(
256
266
  props: Props,
@@ -274,11 +284,12 @@ export class CardStack extends React.Component<Props, State> {
274
284
  acc[curr.key] =
275
285
  state.gestures[curr.key] ||
276
286
  new Animated.Value(
277
- (props.openingRouteKeys.includes(curr.key) && animation !== 'none') ||
287
+ (props.openingRouteKeys.includes(curr.key) &&
288
+ getAnimationEnabled(animation)) ||
278
289
  props.state.preloadedRoutes.includes(curr)
279
290
  ? getDistanceFromOptions(
280
291
  state.layout,
281
- descriptor,
292
+ descriptor?.options,
282
293
  props.direction === 'rtl'
283
294
  )
284
295
  : 0
@@ -317,15 +328,19 @@ export class CardStack extends React.Component<Props, State> {
317
328
  state.descriptors[route.key] ||
318
329
  (oldScene ? oldScene.descriptor : FALLBACK_DESCRIPTOR);
319
330
 
320
- const nextDescriptor =
331
+ const nextOptions =
321
332
  nextRoute &&
322
- (props.descriptors[nextRoute?.key] ||
323
- state.descriptors[nextRoute?.key]);
333
+ (
334
+ props.descriptors[nextRoute?.key] ||
335
+ state.descriptors[nextRoute?.key]
336
+ )?.options;
324
337
 
325
- const previousDescriptor =
338
+ const previousOptions =
326
339
  previousRoute &&
327
- (props.descriptors[previousRoute?.key] ||
328
- state.descriptors[previousRoute?.key]);
340
+ (
341
+ props.descriptors[previousRoute?.key] ||
342
+ state.descriptors[previousRoute?.key]
343
+ )?.options;
329
344
 
330
345
  // When a screen is not the last, it should use next screen's transition config
331
346
  // Many transitions also animate the previous screen, so using 2 different transitions doesn't look right
@@ -335,25 +350,20 @@ export class CardStack extends React.Component<Props, State> {
335
350
  // but the majority of the transitions look alright
336
351
  const optionsForTransitionConfig =
337
352
  index !== self.length - 1 &&
338
- nextDescriptor &&
339
- nextDescriptor.options.presentation !== 'transparentModal'
340
- ? nextDescriptor.options
353
+ nextOptions &&
354
+ nextOptions?.presentation !== 'transparentModal'
355
+ ? nextOptions
341
356
  : descriptor.options;
342
357
 
343
358
  // Assume modal if there are already modal screens in the stack
344
359
  // or current screen is a modal when no presentation is specified
345
360
  const isModal = modalRouteKeys.includes(route.key);
346
361
 
347
- // Disable screen transition animation by default on web, windows and macos to match the native behavior
348
- const excludedPlatforms =
349
- Platform.OS !== 'web' &&
350
- Platform.OS !== 'windows' &&
351
- Platform.OS !== 'macos';
362
+ const animation = getDefaultAnimation(
363
+ optionsForTransitionConfig.animation
364
+ );
352
365
 
353
- const animation =
354
- optionsForTransitionConfig.animation ??
355
- (excludedPlatforms ? 'default' : 'none');
356
- const isAnimationEnabled = animation !== 'none';
366
+ const isAnimationEnabled = getAnimationEnabled(animation);
357
367
 
358
368
  const transitionPreset =
359
369
  animation !== 'default'
@@ -382,8 +392,8 @@ export class CardStack extends React.Component<Props, State> {
382
392
  (!(
383
393
  optionsForTransitionConfig.presentation === 'modal' ||
384
394
  optionsForTransitionConfig.presentation === 'transparentModal' ||
385
- nextDescriptor?.options.presentation === 'modal' ||
386
- nextDescriptor?.options.presentation === 'transparentModal' ||
395
+ nextOptions?.presentation === 'modal' ||
396
+ nextOptions?.presentation === 'transparentModal' ||
387
397
  getIsModalPresentation(cardStyleInterpolator)
388
398
  ) &&
389
399
  Platform.OS === 'ios' &&
@@ -413,16 +423,15 @@ export class CardStack extends React.Component<Props, State> {
413
423
  current: getProgressFromGesture(
414
424
  currentGesture,
415
425
  state.layout,
416
- descriptor,
426
+ descriptor.options,
417
427
  isRTL
418
428
  ),
419
429
  next:
420
- nextGesture &&
421
- nextDescriptor?.options.presentation !== 'transparentModal'
430
+ nextGesture && nextOptions?.presentation !== 'transparentModal'
422
431
  ? getProgressFromGesture(
423
432
  nextGesture,
424
433
  state.layout,
425
- nextDescriptor,
434
+ nextOptions,
426
435
  isRTL
427
436
  )
428
437
  : undefined,
@@ -430,7 +439,7 @@ export class CardStack extends React.Component<Props, State> {
430
439
  ? getProgressFromGesture(
431
440
  previousGesture,
432
441
  state.layout,
433
- previousDescriptor,
442
+ previousOptions,
434
443
  isRTL
435
444
  )
436
445
  : undefined,
@@ -438,8 +447,8 @@ export class CardStack extends React.Component<Props, State> {
438
447
  __memo: [
439
448
  state.layout,
440
449
  descriptor,
441
- nextDescriptor,
442
- previousDescriptor,
450
+ nextOptions,
451
+ previousOptions,
443
452
  currentGesture,
444
453
  nextGesture,
445
454
  previousGesture,
@@ -27,7 +27,7 @@ import {
27
27
  HeaderContainer,
28
28
  type Props as HeaderContainerProps,
29
29
  } from '../Header/HeaderContainer';
30
- import { CardStack } from './CardStack';
30
+ import { CardStack, getAnimationEnabled } from './CardStack';
31
31
 
32
32
  type Props = StackNavigationConfig & {
33
33
  direction: LocaleDirection;
@@ -142,7 +142,7 @@ export class StackView extends React.Component<Props, State> {
142
142
  const isAnimationEnabled = (key: string) => {
143
143
  const descriptor = props.descriptors[key] || state.descriptors[key];
144
144
 
145
- return descriptor ? descriptor.options.animation !== 'none' : true;
145
+ return getAnimationEnabled(descriptor?.options.animation);
146
146
  };
147
147
 
148
148
  const getAnimationTypeForReplace = (key: string) => {
@@ -1 +0,0 @@
1
- {"version":3,"names":["React","StyleSheet","View","jsx","_jsx","CardSheet","forwardRef","enabled","layout","style","rest","ref","fill","setFill","useState","pointerEvents","setPointerEvents","useImperativeHandle","useEffect","document","body","width","clientWidth","height","clientHeight","isFullHeight","id","unsubscribe","navigator","maxTouchPoints","getElementById","createElement","updateStyle","vh","window","innerHeight","textContent","join","head","contains","appendChild","addEventListener","removeEventListener","remove","styles","page","card","create","minHeight","flex","overflow"],"sourceRoot":"../../../../src","sources":["views/Stack/CardSheet.tsx"],"mappings":"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","ignoreList":[]}
@@ -1,14 +0,0 @@
1
- import * as React from 'react';
2
- import { type ViewProps } from 'react-native';
3
- export type CardSheetRef = {
4
- setPointerEvents: React.Dispatch<ViewProps['pointerEvents']>;
5
- };
6
- export declare const CardSheet: React.ForwardRefExoticComponent<ViewProps & {
7
- enabled: boolean;
8
- layout: {
9
- width: number;
10
- height: number;
11
- };
12
- children: React.ReactNode;
13
- } & React.RefAttributes<CardSheetRef>>;
14
- //# sourceMappingURL=CardSheet.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"CardSheet.d.ts","sourceRoot":"","sources":["../../../../../src/views/Stack/CardSheet.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAQhE,MAAM,MAAM,YAAY,GAAG;IACzB,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC;CAC9D,CAAC;AAMF,eAAO,MAAM,SAAS;aAbX,OAAO;YACR;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;cAC/B,KAAK,CAAC,SAAS;sCAyF1B,CAAC"}
@@ -1,106 +0,0 @@
1
- import * as React from 'react';
2
- import { StyleSheet, View, type ViewProps } from 'react-native';
3
-
4
- type Props = ViewProps & {
5
- enabled: boolean;
6
- layout: { width: number; height: number };
7
- children: React.ReactNode;
8
- };
9
-
10
- export type CardSheetRef = {
11
- setPointerEvents: React.Dispatch<ViewProps['pointerEvents']>;
12
- };
13
-
14
- // This component will render a page which overflows the screen
15
- // if the container fills the body by comparing the size
16
- // This lets the document.body handle scrolling of the content
17
- // It's necessary for mobile browsers to be able to hide address bar on scroll
18
- export const CardSheet = React.forwardRef<CardSheetRef, Props>(
19
- function CardSheet({ enabled, layout, style, ...rest }, ref) {
20
- const [fill, setFill] = React.useState(false);
21
- // To avoid triggering a rerender in Card during animation we had to move
22
- // the state to CardSheet. The `setPointerEvents` is then hoisted back to the Card.
23
- const [pointerEvents, setPointerEvents] =
24
- React.useState<ViewProps['pointerEvents']>('auto');
25
-
26
- React.useImperativeHandle(ref, () => {
27
- return { setPointerEvents };
28
- });
29
-
30
- React.useEffect(() => {
31
- if (typeof document === 'undefined' || !document.body) {
32
- // Only run when DOM is available
33
- return;
34
- }
35
-
36
- const width = document.body.clientWidth;
37
- const height = document.body.clientHeight;
38
-
39
- // Workaround for mobile Chrome, necessary when a navigation happens
40
- // when the address bar has already collapsed, which resulted in an
41
- // empty space at the bottom of the page (matching the height of the
42
- // address bar). To fix this, it's necessary to update the height of
43
- // the DOM with the current height of the window.
44
- // See https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
45
- const isFullHeight = height === layout.height;
46
- const id = '__react-navigation-stack-mobile-chrome-viewport-fix';
47
-
48
- let unsubscribe: (() => void) | undefined;
49
-
50
- if (isFullHeight && navigator.maxTouchPoints > 0) {
51
- const style =
52
- document.getElementById(id) ?? document.createElement('style');
53
-
54
- style.id = id;
55
-
56
- const updateStyle = () => {
57
- const vh = window.innerHeight * 0.01;
58
-
59
- style.textContent = [
60
- `:root { --vh: ${vh}px; }`,
61
- `body { height: calc(var(--vh, 1vh) * 100); }`,
62
- ].join('\n');
63
- };
64
-
65
- updateStyle();
66
-
67
- if (!document.head.contains(style)) {
68
- document.head.appendChild(style);
69
- }
70
-
71
- window.addEventListener('resize', updateStyle);
72
-
73
- unsubscribe = () => {
74
- window.removeEventListener('resize', updateStyle);
75
- };
76
- } else {
77
- // Remove the workaround if the stack does not occupy the whole
78
- // height of the page
79
- document.getElementById(id)?.remove();
80
- }
81
-
82
- // eslint-disable-next-line @eslint-react/hooks-extra/no-direct-set-state-in-use-effect
83
- setFill(width === layout.width && height === layout.height);
84
-
85
- return unsubscribe;
86
- }, [layout.height, layout.width]);
87
-
88
- return (
89
- <View
90
- {...rest}
91
- pointerEvents={pointerEvents}
92
- style={[enabled && fill ? styles.page : styles.card, style]}
93
- />
94
- );
95
- }
96
- );
97
-
98
- const styles = StyleSheet.create({
99
- page: {
100
- minHeight: '100%',
101
- },
102
- card: {
103
- flex: 1,
104
- overflow: 'hidden',
105
- },
106
- });