react-native-screen-transitions 2.0.2 → 2.0.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 (77) hide show
  1. package/lib/commonjs/utils/bounds/constants.js +3 -3
  2. package/lib/commonjs/utils/bounds/constants.js.map +1 -1
  3. package/lib/commonjs/utils/bounds/get-bounds.js +3 -3
  4. package/lib/commonjs/utils/bounds/get-bounds.js.map +1 -1
  5. package/lib/module/utils/bounds/constants.js +3 -3
  6. package/lib/module/utils/bounds/constants.js.map +1 -1
  7. package/lib/module/utils/bounds/get-bounds.js +3 -3
  8. package/lib/module/utils/bounds/get-bounds.js.map +1 -1
  9. package/lib/typescript/utils/bounds/_types/get-bounds.d.ts +2 -2
  10. package/lib/typescript/utils/bounds/_types/get-bounds.d.ts.map +1 -1
  11. package/lib/typescript/utils/bounds/constants.d.ts +4 -4
  12. package/lib/typescript/utils/bounds/constants.d.ts.map +1 -1
  13. package/lib/typescript/utils/bounds/get-bounds.d.ts +2 -2
  14. package/lib/typescript/utils/bounds/get-bounds.d.ts.map +1 -1
  15. package/lib/typescript/utils/bounds/index.d.ts +1 -1
  16. package/lib/typescript/utils/bounds/index.d.ts.map +1 -1
  17. package/package.json +4 -2
  18. package/src/__tests__/geometry.test.ts +127 -0
  19. package/src/components/bounds-activator.tsx +29 -0
  20. package/src/components/controllers/screen-lifecycle.tsx +72 -0
  21. package/src/components/create-transition-aware-component.tsx +99 -0
  22. package/src/components/root-transition-aware.tsx +56 -0
  23. package/src/configs/index.ts +2 -0
  24. package/src/configs/presets.ts +227 -0
  25. package/src/configs/specs.ts +9 -0
  26. package/src/hooks/animation/use-associated-style.tsx +28 -0
  27. package/src/hooks/animation/use-screen-animation.tsx +142 -0
  28. package/src/hooks/bounds/use-bound-measurer.tsx +71 -0
  29. package/src/hooks/gestures/use-build-gestures.tsx +369 -0
  30. package/src/hooks/gestures/use-scroll-progress.tsx +60 -0
  31. package/src/hooks/use-stable-callback.tsx +15 -0
  32. package/src/index.ts +32 -0
  33. package/src/integrations/native-stack/navigators/createNativeStackNavigator.tsx +112 -0
  34. package/src/integrations/native-stack/utils/debounce.tsx +14 -0
  35. package/src/integrations/native-stack/utils/getModalRoutesKeys.ts +21 -0
  36. package/src/integrations/native-stack/utils/useAnimatedHeaderHeight.tsx +18 -0
  37. package/src/integrations/native-stack/utils/useDismissedRouteError.tsx +30 -0
  38. package/src/integrations/native-stack/utils/useInvalidPreventRemoveError.tsx +31 -0
  39. package/src/integrations/native-stack/views/FontProcessor.native.tsx +12 -0
  40. package/src/integrations/native-stack/views/FontProcessor.tsx +5 -0
  41. package/src/integrations/native-stack/views/FooterComponent.tsx +10 -0
  42. package/src/integrations/native-stack/views/NativeStackView.native.tsx +657 -0
  43. package/src/integrations/native-stack/views/NativeStackView.tsx +214 -0
  44. package/src/integrations/native-stack/views/useHeaderConfigProps.tsx +295 -0
  45. package/src/providers/gestures.tsx +89 -0
  46. package/src/providers/keys.tsx +38 -0
  47. package/src/stores/animations.ts +45 -0
  48. package/src/stores/bounds.ts +71 -0
  49. package/src/stores/gestures.ts +55 -0
  50. package/src/stores/navigator-dismiss-state.ts +17 -0
  51. package/src/stores/utils/reset-stores-for-screen.ts +14 -0
  52. package/src/types/animation.ts +76 -0
  53. package/src/types/bounds.ts +82 -0
  54. package/src/types/core.ts +50 -0
  55. package/src/types/gesture.ts +33 -0
  56. package/src/types/navigator.ts +744 -0
  57. package/src/types/utils.ts +3 -0
  58. package/src/utils/animation/animate.ts +28 -0
  59. package/src/utils/animation/run-transition.ts +49 -0
  60. package/src/utils/bounds/_types/builder.ts +35 -0
  61. package/src/utils/bounds/_types/geometry.ts +17 -0
  62. package/src/utils/bounds/_types/get-bounds.ts +10 -0
  63. package/src/utils/bounds/build-bound-styles.ts +184 -0
  64. package/src/utils/bounds/constants.ts +25 -0
  65. package/src/utils/bounds/flatten-styles.ts +21 -0
  66. package/src/utils/bounds/geometry.ts +113 -0
  67. package/src/utils/bounds/get-bounds.ts +56 -0
  68. package/src/utils/bounds/index.ts +46 -0
  69. package/src/utils/bounds/style-composers.ts +172 -0
  70. package/src/utils/gesture/apply-gesture-activation-criteria.ts +109 -0
  71. package/src/utils/gesture/map-gesture-to-progress.ts +11 -0
  72. package/src/utils/gesture/normalize-gesture-translation.ts +20 -0
  73. package/src/utils/index.ts +1 -0
  74. package/lib/commonjs/__tests__ /geometry.test.js +0 -178
  75. package/lib/commonjs/__tests__ /geometry.test.js.map +0 -1
  76. package/lib/module/__tests__ /geometry.test.js +0 -178
  77. package/lib/module/__tests__ /geometry.test.js.map +0 -1
@@ -0,0 +1,3 @@
1
+ export type Any = any;
2
+
3
+ export type Complete<T> = { [K in keyof T]-?: Exclude<T[K], undefined> };
@@ -0,0 +1,28 @@
1
+ import {
2
+ type WithSpringConfig,
3
+ type WithTimingConfig,
4
+ withSpring,
5
+ withTiming,
6
+ } from "react-native-reanimated";
7
+ import type {
8
+ AnimatableValue,
9
+ AnimationCallback,
10
+ } from "react-native-reanimated/lib/typescript/commonTypes";
11
+
12
+ export const animate = <T extends AnimatableValue>(
13
+ toValue: T,
14
+ config?: WithSpringConfig | WithTimingConfig,
15
+ callback?: AnimationCallback,
16
+ ) => {
17
+ "worklet";
18
+ const isSpring =
19
+ typeof config === "object" &&
20
+ !("duration" in config) &&
21
+ !("easing" in config);
22
+
23
+ if (!isSpring) {
24
+ return withTiming(toValue, config, callback);
25
+ }
26
+
27
+ return withSpring(toValue, config, callback);
28
+ };
@@ -0,0 +1,49 @@
1
+ import { runOnJS } from "react-native-reanimated";
2
+ import type { AnimationMap } from "../../stores/animations";
3
+ import type { TransitionSpec } from "../../types/animation";
4
+ import { animate } from "./animate";
5
+
6
+ interface RunTransitionProps {
7
+ target: "open" | "close";
8
+ spec?: TransitionSpec;
9
+ onFinish?: (finished: boolean) => void;
10
+ animations: AnimationMap;
11
+ }
12
+
13
+ export const runTransition = ({
14
+ target,
15
+ spec,
16
+ onFinish,
17
+ animations,
18
+ }: RunTransitionProps) => {
19
+ "worklet";
20
+ const value = target === "open" ? 1 : 0;
21
+ const config = target === "open" ? spec?.open : spec?.close;
22
+
23
+ const { progress, animating, closing } = animations;
24
+
25
+ if (target === "close") {
26
+ closing.value = 1;
27
+ }
28
+
29
+ if (!config) {
30
+ animating.value = 0;
31
+ progress.value = value;
32
+
33
+ if (onFinish) {
34
+ runOnJS(onFinish)(true);
35
+ }
36
+ return;
37
+ }
38
+
39
+ animating.value = 1;
40
+ progress.value = animate(value, config, (finished) => {
41
+ "worklet";
42
+ if (finished) {
43
+ animating.value = 0;
44
+ if (onFinish) {
45
+ runOnJS(onFinish)(finished);
46
+ }
47
+ }
48
+ });
49
+ };
@@ -0,0 +1,35 @@
1
+ import type { ScaledSize } from "react-native";
2
+ import type { ScreenTransitionState } from "../../../types/animation";
3
+ import type { BoundsMethod } from "../../../types/bounds";
4
+
5
+ /**
6
+ * Params passed to the builder initializer. No method required here.
7
+ */
8
+ export type BoundsBuilderInitParams = {
9
+ id: string | null;
10
+ previous?: ScreenTransitionState;
11
+ current: ScreenTransitionState;
12
+ next?: ScreenTransitionState;
13
+ progress: number;
14
+ dimensions: ScaledSize;
15
+ };
16
+
17
+ /**
18
+ * Params used internally for final computation. Method is required.
19
+ */
20
+ export type BoundsComputeParams = BoundsBuilderInitParams & {
21
+ method: BoundsMethod;
22
+ };
23
+
24
+ /**
25
+ * Builder options that affect how math is applied.
26
+ * Method is not an option; it's tracked separately by the builder.
27
+ */
28
+ export type BoundsBuilderOptions = {
29
+ gestures?: { x?: number; y?: number };
30
+ toFullscreen?: boolean;
31
+ absolute?: boolean;
32
+ relative?: boolean;
33
+ method?: BoundsMethod;
34
+ contentScaleMode?: "aspectFill" | "aspectFit" | "auto";
35
+ };
@@ -0,0 +1,17 @@
1
+ export type GeometryBase = {
2
+ ranges: readonly [number, number];
3
+ entering: boolean;
4
+ };
5
+
6
+ export type RelativeGeometry = GeometryBase & {
7
+ dx: number;
8
+ dy: number;
9
+ scaleX: number;
10
+ scaleY: number;
11
+ };
12
+
13
+ export type ContentTransformGeometry = GeometryBase & {
14
+ tx: number;
15
+ ty: number;
16
+ s: number;
17
+ };
@@ -0,0 +1,10 @@
1
+ import type { ScreenPhase } from '../../../types/core';
2
+ import type { ScreenTransitionState } from '../../../types/animation';
3
+
4
+ export type GetBoundsParams = {
5
+ id: string | null;
6
+ phase?: ScreenPhase;
7
+ previous?: ScreenTransitionState;
8
+ current: ScreenTransitionState;
9
+ next?: ScreenTransitionState;
10
+ };
@@ -0,0 +1,184 @@
1
+ import type { ScaledSize } from "react-native";
2
+ import { interpolate, type MeasuredDimensions } from "react-native-reanimated";
3
+ import type { ScreenTransitionState } from "../../types/animation";
4
+ import type { BoundsBuilder } from "../../types/bounds";
5
+ import type { ScreenPhase } from "../../types/core";
6
+ import type {
7
+ BoundsBuilderInitParams,
8
+ BoundsBuilderOptions,
9
+ } from "./_types/builder";
10
+ import { DEFAULT_BUILDER_OPTIONS, FULLSCREEN_DIMENSIONS } from "./constants";
11
+ import {
12
+ computeContentTransformGeometry,
13
+ computeRelativeGeometry,
14
+ } from "./geometry";
15
+ import {
16
+ composeContentStyle,
17
+ composeSizeAbsolute,
18
+ composeSizeRelative,
19
+ composeTransformAbsolute,
20
+ composeTransformRelative,
21
+ type ElementComposeParams,
22
+ } from "./style-composers";
23
+
24
+ function resolveBounds(props: {
25
+ id: string;
26
+ previous?: ScreenTransitionState;
27
+ current?: ScreenTransitionState;
28
+ next?: ScreenTransitionState;
29
+ toRect?: Partial<MeasuredDimensions>;
30
+ dimensions: ScaledSize;
31
+ computeOptions: BoundsBuilderOptions;
32
+ }) {
33
+ "worklet";
34
+ const entering = !props.next;
35
+
36
+ const fullscreen = FULLSCREEN_DIMENSIONS(props.dimensions);
37
+
38
+ const startPhase: ScreenPhase = entering ? "previous" : "current";
39
+ const endPhase: ScreenPhase = entering ? "current" : "next";
40
+
41
+ const resolve = (phase?: ScreenPhase) => {
42
+ "worklet";
43
+ if (phase === "previous") return props.previous?.bounds?.[props.id]?.bounds;
44
+ if (phase === "current") return props.current?.bounds?.[props.id]?.bounds;
45
+ if (phase === "next") return props.next?.bounds?.[props.id]?.bounds;
46
+ return null;
47
+ };
48
+
49
+ const start = resolve(startPhase);
50
+ let end = resolve(endPhase);
51
+
52
+ if (props.computeOptions.toFullscreen) {
53
+ end = fullscreen;
54
+ }
55
+
56
+ return {
57
+ start,
58
+ end,
59
+ entering,
60
+ };
61
+ }
62
+
63
+ const computeBoundStyles = (
64
+ {
65
+ id,
66
+ previous,
67
+ current,
68
+ next,
69
+ progress,
70
+ dimensions,
71
+ }: BoundsBuilderInitParams,
72
+ computeOptions: BoundsBuilderOptions = {},
73
+ ) => {
74
+ "worklet";
75
+ if (!id) return {};
76
+
77
+ const { start, end, entering } = resolveBounds({
78
+ id,
79
+ previous,
80
+ current,
81
+ next,
82
+ computeOptions: computeOptions,
83
+ dimensions,
84
+ });
85
+
86
+ if (!start || !end) return {};
87
+
88
+ const relativeGeometry = computeRelativeGeometry({ start, end, entering });
89
+
90
+ const interp = (a: number, b: number) =>
91
+ interpolate(progress, relativeGeometry.ranges, [a, b]);
92
+
93
+ const common: ElementComposeParams = {
94
+ start,
95
+ end,
96
+ interp,
97
+ geometry: relativeGeometry,
98
+ computeOptions,
99
+ };
100
+
101
+ const isSize = computeOptions.method === "size";
102
+ const isAbs = !!computeOptions.absolute;
103
+
104
+ if (computeOptions.method === "content") {
105
+ const contentGeometry = computeContentTransformGeometry({
106
+ start,
107
+ end,
108
+ entering,
109
+ dimensions,
110
+ contentScaleMode: computeOptions.contentScaleMode ?? "auto",
111
+ });
112
+
113
+ return composeContentStyle({
114
+ ...common,
115
+ geometry: contentGeometry,
116
+ computeOptions,
117
+ });
118
+ }
119
+
120
+ return isSize
121
+ ? isAbs
122
+ ? composeSizeAbsolute(common)
123
+ : composeSizeRelative(common)
124
+ : isAbs
125
+ ? composeTransformAbsolute(common)
126
+ : composeTransformRelative(common);
127
+ };
128
+
129
+ export function buildBoundStyles(
130
+ params: BoundsBuilderInitParams,
131
+ ): BoundsBuilder {
132
+ "worklet";
133
+
134
+ const cfg: { options: BoundsBuilderOptions } = {
135
+ options: { ...DEFAULT_BUILDER_OPTIONS },
136
+ };
137
+
138
+ const builder = (): BoundsBuilder => ({
139
+ gestures: (options) => {
140
+ cfg.options.gestures = options;
141
+ return builder();
142
+ },
143
+ toFullscreen: () => {
144
+ cfg.options.toFullscreen = true;
145
+ return builder();
146
+ },
147
+ absolute: () => {
148
+ cfg.options.absolute = true;
149
+ cfg.options.relative = false;
150
+ return builder();
151
+ },
152
+ relative: () => {
153
+ cfg.options.relative = true;
154
+ cfg.options.absolute = false;
155
+ return builder();
156
+ },
157
+ transform: () => {
158
+ cfg.options.method = "transform";
159
+ return builder();
160
+ },
161
+ size: () => {
162
+ cfg.options.method = "size";
163
+ return builder();
164
+ },
165
+ content: () => {
166
+ cfg.options.method = "content";
167
+ return builder();
168
+ },
169
+ contentFill: () => {
170
+ cfg.options.contentScaleMode = "aspectFill";
171
+ return builder();
172
+ },
173
+ contentFit: () => {
174
+ cfg.options.contentScaleMode = "aspectFit";
175
+ return builder();
176
+ },
177
+
178
+ build: () => {
179
+ return computeBoundStyles(params, cfg.options);
180
+ },
181
+ });
182
+
183
+ return builder();
184
+ }
@@ -0,0 +1,25 @@
1
+ import type { ScaledSize } from 'react-native';
2
+ import type { MeasuredDimensions } from 'react-native-reanimated';
3
+ import type { Complete } from '../../types/utils';
4
+ import type { BoundsBuilderOptions } from './_types/builder';
5
+
6
+ export const FULLSCREEN_DIMENSIONS = (dimensions: ScaledSize): MeasuredDimensions => {
7
+ 'worklet';
8
+ return {
9
+ x: 0,
10
+ y: 0,
11
+ pageX: 0,
12
+ pageY: 0,
13
+ width: dimensions.width,
14
+ height: dimensions.height,
15
+ };
16
+ };
17
+
18
+ export const DEFAULT_BUILDER_OPTIONS: Complete<BoundsBuilderOptions> = Object.freeze({
19
+ gestures: { x: 0, y: 0 },
20
+ toFullscreen: false,
21
+ absolute: false,
22
+ relative: true,
23
+ method: 'transform',
24
+ contentScaleMode: 'auto',
25
+ });
@@ -0,0 +1,21 @@
1
+ export function flattenStyle<TStyleProp>(style: TStyleProp): TStyleProp {
2
+ "worklet";
3
+ if (style === null || typeof style !== "object") {
4
+ return style;
5
+ }
6
+
7
+ if (!Array.isArray(style)) {
8
+ return style;
9
+ }
10
+
11
+ const result: { [key: string]: TStyleProp } = {};
12
+ for (let i = 0, styleLength = style.length; i < styleLength; ++i) {
13
+ const computedStyle = flattenStyle(style[i]);
14
+ if (computedStyle) {
15
+ for (const key in computedStyle) {
16
+ result[key] = computedStyle[key];
17
+ }
18
+ }
19
+ }
20
+ return result as TStyleProp;
21
+ }
@@ -0,0 +1,113 @@
1
+ import type { ScaledSize } from "react-native";
2
+ import type { MeasuredDimensions } from "react-native-reanimated";
3
+ import type { BoundsBuilderOptions } from "./_types/builder";
4
+ import type {
5
+ ContentTransformGeometry,
6
+ RelativeGeometry,
7
+ } from "./_types/geometry";
8
+
9
+ /**
10
+ * Relative geometry between start/end bounds.
11
+ */
12
+ export function computeRelativeGeometry({
13
+ start,
14
+ end,
15
+ entering,
16
+ }: {
17
+ start: MeasuredDimensions;
18
+ end: MeasuredDimensions;
19
+ entering: boolean;
20
+ }): RelativeGeometry {
21
+ "worklet";
22
+ const startCenterX = start.pageX + start.width / 2;
23
+ const startCenterY = start.pageY + start.height / 2;
24
+ const endCenterX = end.pageX + end.width / 2;
25
+ const endCenterY = end.pageY + end.height / 2;
26
+
27
+ const dx = startCenterX - endCenterX;
28
+ const dy = startCenterY - endCenterY;
29
+
30
+ const scaleX = start.width / end.width;
31
+ const scaleY = start.height / end.height;
32
+
33
+ const ranges: readonly [number, number] = entering ? [0, 1] : [1, 2];
34
+
35
+ return { dx, dy, scaleX, scaleY, ranges, entering };
36
+ }
37
+ /**
38
+ * Computes the transform to apply to the entire destination screen so that
39
+ * its bound (end) matches the source bound (start) at progress start.
40
+ */
41
+ export function computeContentTransformGeometry({
42
+ start,
43
+ end,
44
+ entering,
45
+ dimensions,
46
+ contentScaleMode,
47
+ }: {
48
+ start: MeasuredDimensions;
49
+ end: MeasuredDimensions;
50
+ entering: boolean;
51
+ dimensions: ScaledSize;
52
+ contentScaleMode: BoundsBuilderOptions["contentScaleMode"];
53
+ }): ContentTransformGeometry {
54
+ "worklet";
55
+
56
+ const parent = {
57
+ x: 0,
58
+ y: 0,
59
+ width: dimensions.width,
60
+ height: dimensions.height,
61
+ };
62
+
63
+ const startCenterX = start.pageX + start.width / 2;
64
+ const startCenterY = start.pageY + start.height / 2;
65
+
66
+ const childCenterX = end.pageX + end.width / 2;
67
+ const childCenterY = end.pageY + end.height / 2;
68
+
69
+ const parentCenterX = parent.x + parent.width / 2;
70
+ const parentCenterY = parent.y + parent.height / 2;
71
+
72
+ const safe = (v: number) => (v === 0 ? 1e-6 : v);
73
+
74
+ const sx = safe(start.width) / safe(end.width);
75
+ const sy = safe(start.height) / safe(end.height);
76
+
77
+ let s: number;
78
+
79
+ if (contentScaleMode === "aspectFit") {
80
+ s = Math.min(sx, sy);
81
+ } else if (contentScaleMode === "aspectFill") {
82
+ s = Math.max(sx, sy);
83
+ } else {
84
+ const startAspect = start.width / start.height;
85
+ const endAspect = end.width / end.height;
86
+ const aspectDifference = Math.abs(startAspect - endAspect);
87
+
88
+ if (aspectDifference < 0.1) {
89
+ s = Math.max(sx, sy);
90
+ } else {
91
+ s = Math.min(sx, sy);
92
+ }
93
+ }
94
+
95
+ const offsetX = startCenterX - parentCenterX;
96
+ const offsetY = startCenterY - parentCenterY;
97
+
98
+ const centerOffsetX = (parentCenterX - childCenterX) * s;
99
+ const centerOffsetY = (parentCenterY - childCenterY) * s;
100
+
101
+ const tx = offsetX + centerOffsetX;
102
+ const ty = offsetY + centerOffsetY;
103
+
104
+ const ranges: readonly [number, number] = entering ? [0, 1] : [1, 2];
105
+
106
+ return {
107
+ tx,
108
+ ty,
109
+ s,
110
+ ranges,
111
+ entering,
112
+ };
113
+ }
@@ -0,0 +1,56 @@
1
+ import type { BoundEntry } from '../../types/bounds';
2
+
3
+ import type { GetBoundsParams } from './_types/get-bounds';
4
+
5
+ const fallbackBounds = {
6
+ bounds: {
7
+ width: 0,
8
+ height: 0,
9
+ x: 0,
10
+ y: 0,
11
+ pageX: 0,
12
+ pageY: 0,
13
+ },
14
+ styles: {},
15
+ };
16
+
17
+ export const getBounds = (props: GetBoundsParams): BoundEntry => {
18
+ 'worklet';
19
+ const boundId = props.id;
20
+ const phase = props.phase;
21
+
22
+ if (phase && boundId) {
23
+ let phaseBounds = null;
24
+
25
+ if (phase === 'current') {
26
+ phaseBounds = props.current?.bounds[boundId];
27
+ } else if (phase === 'next') {
28
+ phaseBounds = props.next?.bounds[boundId];
29
+ } else {
30
+ phaseBounds = props.previous?.bounds[boundId];
31
+ }
32
+
33
+ if (!phaseBounds) {
34
+ return fallbackBounds;
35
+ }
36
+
37
+ return {
38
+ bounds: phaseBounds.bounds,
39
+ styles: phaseBounds?.styles,
40
+ };
41
+ }
42
+
43
+ if (!props.next && boundId) {
44
+ const previousBounds = props.previous?.bounds[boundId];
45
+
46
+ return previousBounds || fallbackBounds;
47
+ }
48
+
49
+ if (boundId) {
50
+ const nextBounds = props.next?.bounds[boundId];
51
+
52
+ return nextBounds || fallbackBounds;
53
+ }
54
+
55
+ return fallbackBounds;
56
+ };
@@ -0,0 +1,46 @@
1
+ import type { ScaledSize } from "react-native";
2
+ import type { ScreenPhase } from "../../types/core";
3
+ import type { ScreenTransitionState } from "../../types/animation";
4
+ import { buildBoundStyles } from "./build-bound-styles";
5
+ import { getBounds } from "./get-bounds";
6
+
7
+ export interface BuildBoundsAccessorParams {
8
+ activeBoundId: string | null;
9
+ current: ScreenTransitionState;
10
+ previous?: ScreenTransitionState;
11
+ next?: ScreenTransitionState;
12
+ progress: number;
13
+ dimensions: ScaledSize;
14
+ }
15
+
16
+ export const buildBoundsAccessor = ({
17
+ activeBoundId,
18
+ current,
19
+ previous,
20
+ next,
21
+ progress,
22
+ dimensions,
23
+ }: BuildBoundsAccessorParams) => {
24
+ "worklet";
25
+
26
+ const bounds = (id?: string) =>
27
+ buildBoundStyles({
28
+ id: id ?? activeBoundId,
29
+ previous,
30
+ current,
31
+ next,
32
+ progress,
33
+ dimensions,
34
+ });
35
+
36
+ return Object.assign(bounds, {
37
+ get: (id?: string, phase?: ScreenPhase) =>
38
+ getBounds({
39
+ id: id ?? activeBoundId,
40
+ phase,
41
+ current,
42
+ previous,
43
+ next,
44
+ }),
45
+ });
46
+ };