react-native-screen-transitions 2.2.1 → 2.3.1

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 (46) hide show
  1. package/lib/commonjs/components/screen-transition-tree.js +34 -0
  2. package/lib/commonjs/components/screen-transition-tree.js.map +1 -0
  3. package/lib/commonjs/configs/presets.js +10 -16
  4. package/lib/commonjs/configs/presets.js.map +1 -1
  5. package/lib/commonjs/hooks/animation/use-associated-style.js +7 -5
  6. package/lib/commonjs/hooks/animation/use-associated-style.js.map +1 -1
  7. package/lib/commonjs/hooks/animation/use-screen-animation.js +18 -3
  8. package/lib/commonjs/hooks/animation/use-screen-animation.js.map +1 -1
  9. package/lib/commonjs/integrations/native-stack/views/NativeStackView.native.js +3 -15
  10. package/lib/commonjs/integrations/native-stack/views/NativeStackView.native.js.map +1 -1
  11. package/lib/commonjs/utils/animation/derivations.js +14 -1
  12. package/lib/commonjs/utils/animation/derivations.js.map +1 -1
  13. package/lib/module/components/screen-transition-tree.js +30 -0
  14. package/lib/module/components/screen-transition-tree.js.map +1 -0
  15. package/lib/module/configs/presets.js +10 -16
  16. package/lib/module/configs/presets.js.map +1 -1
  17. package/lib/module/hooks/animation/use-associated-style.js +7 -5
  18. package/lib/module/hooks/animation/use-associated-style.js.map +1 -1
  19. package/lib/module/hooks/animation/use-screen-animation.js +18 -3
  20. package/lib/module/hooks/animation/use-screen-animation.js.map +1 -1
  21. package/lib/module/integrations/native-stack/views/NativeStackView.native.js +3 -15
  22. package/lib/module/integrations/native-stack/views/NativeStackView.native.js.map +1 -1
  23. package/lib/module/utils/animation/derivations.js +14 -1
  24. package/lib/module/utils/animation/derivations.js.map +1 -1
  25. package/lib/typescript/components/screen-transition-tree.d.ts +11 -0
  26. package/lib/typescript/components/screen-transition-tree.d.ts.map +1 -0
  27. package/lib/typescript/configs/index.d.ts.map +1 -1
  28. package/lib/typescript/configs/presets.d.ts.map +1 -1
  29. package/lib/typescript/hooks/animation/use-associated-style.d.ts +1 -1
  30. package/lib/typescript/hooks/animation/use-associated-style.d.ts.map +1 -1
  31. package/lib/typescript/hooks/animation/use-screen-animation.d.ts +1 -1
  32. package/lib/typescript/hooks/animation/use-screen-animation.d.ts.map +1 -1
  33. package/lib/typescript/index.d.ts.map +1 -1
  34. package/lib/typescript/integrations/native-stack/views/NativeStackView.native.d.ts.map +1 -1
  35. package/lib/typescript/types/animation.d.ts +6 -0
  36. package/lib/typescript/types/animation.d.ts.map +1 -1
  37. package/lib/typescript/utils/animation/derivations.d.ts +3 -0
  38. package/lib/typescript/utils/animation/derivations.d.ts.map +1 -1
  39. package/package.json +1 -1
  40. package/src/components/screen-transition-tree.tsx +33 -0
  41. package/src/configs/presets.ts +9 -25
  42. package/src/hooks/animation/use-associated-style.tsx +12 -7
  43. package/src/hooks/animation/use-screen-animation.tsx +25 -4
  44. package/src/integrations/native-stack/views/NativeStackView.native.tsx +4 -14
  45. package/src/types/animation.ts +6 -0
  46. package/src/utils/animation/derivations.ts +20 -1
@@ -16,16 +16,20 @@ const EMPTY_STYLE = Object.freeze({});
16
16
  /**
17
17
  * This hook is used to get the associated styles for a given styleId / boundTag.
18
18
  */
19
- export const useAssociatedStyles = ({ id, style }: Props = {}) => {
19
+ export const useAssociatedStyles = ({ id }: Props = {}) => {
20
20
  const { stylesMap } = useTransitionStyles();
21
21
  const showAfterFirstFrame = useSharedValue(false);
22
22
 
23
23
  useDerivedValue(() => {
24
24
  "worklet";
25
+
26
+ // If the associated styles have already been shown, return.
27
+
25
28
  if (!id) {
26
29
  showAfterFirstFrame.value = true;
27
30
  return;
28
31
  }
32
+
29
33
  if (!showAfterFirstFrame.value) {
30
34
  requestAnimationFrame(() => {
31
35
  showAfterFirstFrame.value = true;
@@ -39,22 +43,23 @@ export const useAssociatedStyles = ({ id, style }: Props = {}) => {
39
43
  if (!id || !stylesMap) {
40
44
  return EMPTY_STYLE;
41
45
  }
42
- const base =
43
- (stylesMap.value[id] as Record<string, unknown>) || EMPTY_STYLE;
46
+ const base = stylesMap.value[id] || EMPTY_STYLE;
44
47
 
45
48
  let opacity = 1;
46
49
 
47
50
  if ("opacity" in base) {
48
51
  opacity = base.opacity as number;
49
52
  }
50
- if (style && "opacity" in style) {
51
- opacity = style.opacity as number;
52
- }
53
53
 
54
54
  // Only force opacity to 0 during the initial frame; once ready,
55
55
  // return base unchanged so we never override user-provided opacity.
56
56
  if (!showAfterFirstFrame.value) {
57
- return { ...base, opacity: 0 } as Record<string, unknown>;
57
+ return { ...base, opacity: 0 };
58
+ }
59
+
60
+ // Since opacity exists on the base style, we don't need to override it.
61
+ if ("opacity" in base) {
62
+ return base;
58
63
  }
59
64
 
60
65
  return { ...base, opacity };
@@ -106,7 +106,15 @@ export function _useScreenAnimation() {
106
106
  const current =
107
107
  unwrap(currentAnimation, currentDescriptor?.route.key) ?? FALLBACK;
108
108
 
109
- const { progress, focused, activeBoundId, bounds } = derivations({
109
+ const {
110
+ progress,
111
+ focused,
112
+ activeBoundId,
113
+ bounds,
114
+ active,
115
+ isActiveTransitioning,
116
+ isDismissing,
117
+ } = derivations({
110
118
  current,
111
119
  next,
112
120
  previous,
@@ -123,13 +131,26 @@ export function _useScreenAnimation() {
123
131
  activeBoundId,
124
132
  progress,
125
133
  bounds,
134
+ active,
135
+ isActiveTransitioning,
136
+ isDismissing,
126
137
  };
127
138
  },
128
139
  );
129
140
 
130
- const screenStyleInterpolator =
131
- nextDescriptor?.options.screenStyleInterpolator ||
132
- currentDescriptor?.options.screenStyleInterpolator;
141
+ // Prefer the next descriptor's interpolator only when transitions are enabled on it.
142
+ // If the next screen doesn't opt-in to transitions, avoid falling back to the current
143
+ // screen's interpolator to prevent unintended global styles (e.g., scaling previous screens
144
+ // when presenting non-transitioning modals/sheets).
145
+ const nextEnabled = nextDescriptor?.options.enableTransitions;
146
+ const currentEnabled = currentDescriptor?.options.enableTransitions;
147
+
148
+ const nextInterpolator =
149
+ nextEnabled && nextDescriptor?.options.screenStyleInterpolator;
150
+ const currentInterpolator =
151
+ currentEnabled && currentDescriptor?.options.screenStyleInterpolator;
152
+
153
+ const screenStyleInterpolator = nextInterpolator ?? currentInterpolator;
133
154
 
134
155
  return { screenInterpolatorProps, screenStyleInterpolator };
135
156
  }
@@ -32,11 +32,7 @@ import {
32
32
  ScreenStack,
33
33
  ScreenStackItem,
34
34
  } from "react-native-screens";
35
- import { ScreenLifecycleController } from "../../../components/controllers/screen-lifecycle";
36
- import { RootTransitionAware } from "../../../components/root-transition-aware";
37
- import { ScreenGestureProvider } from "../../../providers/gestures";
38
- import { KeysProvider } from "../../../providers/keys";
39
- import { TransitionStylesProvider } from "../../../providers/transition-styles";
35
+ import { ScreenTransitionTree } from "../../../components/screen-transition-tree";
40
36
  import type {
41
37
  NativeStackDescriptor,
42
38
  NativeStackDescriptorMap,
@@ -469,19 +465,13 @@ const SceneView = ({
469
465
  value={isParentHeaderShown || headerShown !== false}
470
466
  >
471
467
  <HeaderBackContext.Provider value={headerBack}>
472
- <KeysProvider
468
+ <ScreenTransitionTree
473
469
  previous={previousDescriptor}
474
470
  current={descriptor}
475
471
  next={nextDescriptor}
476
472
  >
477
- <ScreenGestureProvider>
478
- <ScreenLifecycleController>
479
- <TransitionStylesProvider>
480
- <RootTransitionAware>{render()}</RootTransitionAware>
481
- </TransitionStylesProvider>
482
- </ScreenLifecycleController>
483
- </ScreenGestureProvider>
484
- </KeysProvider>
473
+ {render()}
474
+ </ScreenTransitionTree>
485
475
  </HeaderBackContext.Provider>
486
476
  </HeaderShownContext.Provider>
487
477
  </HeaderHeightContext.Provider>
@@ -41,6 +41,12 @@ export interface ScreenInterpolationProps {
41
41
  progress: number;
42
42
  /** A function that returns a bounds builder for the screen. */
43
43
  bounds: BoundsAccessor;
44
+ /** The active screen between current and next. */
45
+ active: ScreenTransitionState;
46
+ /** Whether the active screen is transitioning. */
47
+ isActiveTransitioning: boolean;
48
+ /** Whether the active screen is dismissing. */
49
+ isDismissing: boolean;
44
50
  }
45
51
 
46
52
  export type ScreenStyleInterpolator = (
@@ -20,11 +20,22 @@ export const derivations = ({
20
20
  dimensions,
21
21
  }: DerivationsParams) => {
22
22
  "worklet";
23
+ // The combined progress
23
24
  const progress = current.progress + (next?.progress ?? 0);
25
+
26
+ // Whether the current screen is focused
24
27
  const focused = !next;
25
28
 
29
+ const active = focused ? current : (next ?? current);
30
+ const isActiveTransitioning = !!(
31
+ active.gesture.isDragging || active.animating
32
+ );
33
+ const isDismissing = !!(active.gesture.isDismissing || active.closing);
34
+
35
+ // The active bound id
26
36
  const activeBoundId = Bounds.getActiveBound(current, next, previous);
27
37
 
38
+ // bounds api
28
39
  const bounds = createBounds({
29
40
  activeBoundId,
30
41
  current,
@@ -34,5 +45,13 @@ export const derivations = ({
34
45
  dimensions,
35
46
  });
36
47
 
37
- return { progress, focused, activeBoundId, bounds };
48
+ return {
49
+ progress,
50
+ focused,
51
+ activeBoundId,
52
+ bounds,
53
+ active,
54
+ isActiveTransitioning,
55
+ isDismissing,
56
+ };
38
57
  };