react-native-screen-transitions 2.3.3 → 2.4.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.
- package/README.md +34 -15
- package/lib/commonjs/__configs__/presets.js +10 -5
- package/lib/commonjs/__configs__/presets.js.map +1 -1
- package/lib/commonjs/components/controllers/screen-lifecycle.js +5 -8
- package/lib/commonjs/components/controllers/screen-lifecycle.js.map +1 -1
- package/lib/commonjs/components/create-transition-aware-component.js +2 -2
- package/lib/commonjs/components/create-transition-aware-component.js.map +1 -1
- package/lib/commonjs/constants.js +2 -1
- package/lib/commonjs/constants.js.map +1 -1
- package/lib/commonjs/hooks/animation/use-screen-animation.js +2 -1
- package/lib/commonjs/hooks/animation/use-screen-animation.js.map +1 -1
- package/lib/commonjs/hooks/bounds/use-bound-registry.js +18 -14
- package/lib/commonjs/hooks/bounds/use-bound-registry.js.map +1 -1
- package/lib/commonjs/hooks/gestures/use-build-gestures.js +17 -10
- package/lib/commonjs/hooks/gestures/use-build-gestures.js.map +1 -1
- package/lib/commonjs/hooks/use-stable-callback-value.js +64 -0
- package/lib/commonjs/hooks/use-stable-callback-value.js.map +1 -0
- package/lib/commonjs/stores/gestures.js +2 -1
- package/lib/commonjs/stores/gestures.js.map +1 -1
- package/lib/commonjs/utils/bounds/_utils/styles.js +58 -0
- package/lib/commonjs/utils/bounds/_utils/styles.js.map +1 -0
- package/lib/commonjs/utils/gesture/reset-gesture-values.js +14 -4
- package/lib/commonjs/utils/gesture/reset-gesture-values.js.map +1 -1
- package/lib/module/__configs__/presets.js +10 -5
- package/lib/module/__configs__/presets.js.map +1 -1
- package/lib/module/components/controllers/screen-lifecycle.js +5 -8
- package/lib/module/components/controllers/screen-lifecycle.js.map +1 -1
- package/lib/module/components/create-transition-aware-component.js +2 -2
- package/lib/module/components/create-transition-aware-component.js.map +1 -1
- package/lib/module/constants.js +2 -1
- package/lib/module/constants.js.map +1 -1
- package/lib/module/hooks/animation/use-screen-animation.js +2 -1
- package/lib/module/hooks/animation/use-screen-animation.js.map +1 -1
- package/lib/module/hooks/bounds/use-bound-registry.js +19 -15
- package/lib/module/hooks/bounds/use-bound-registry.js.map +1 -1
- package/lib/module/hooks/gestures/use-build-gestures.js +18 -11
- package/lib/module/hooks/gestures/use-build-gestures.js.map +1 -1
- package/lib/module/hooks/use-stable-callback-value.js +60 -0
- package/lib/module/hooks/use-stable-callback-value.js.map +1 -0
- package/lib/module/stores/gestures.js +2 -1
- package/lib/module/stores/gestures.js.map +1 -1
- package/lib/module/utils/bounds/_utils/styles.js +54 -0
- package/lib/module/utils/bounds/_utils/styles.js.map +1 -0
- package/lib/module/utils/gesture/reset-gesture-values.js +14 -4
- package/lib/module/utils/gesture/reset-gesture-values.js.map +1 -1
- package/lib/typescript/__configs__/presets.d.ts.map +1 -1
- package/lib/typescript/components/controllers/screen-lifecycle.d.ts.map +1 -1
- package/lib/typescript/constants.d.ts.map +1 -1
- package/lib/typescript/hooks/animation/use-screen-animation.d.ts.map +1 -1
- package/lib/typescript/hooks/bounds/use-bound-registry.d.ts +1 -1
- package/lib/typescript/hooks/bounds/use-bound-registry.d.ts.map +1 -1
- package/lib/typescript/hooks/gestures/use-build-gestures.d.ts.map +1 -1
- package/lib/typescript/hooks/use-stable-callback-value.d.ts +13 -0
- package/lib/typescript/hooks/use-stable-callback-value.d.ts.map +1 -0
- package/lib/typescript/stores/gestures.d.ts +2 -0
- package/lib/typescript/stores/gestures.d.ts.map +1 -1
- package/lib/typescript/types/animation.d.ts +10 -9
- package/lib/typescript/types/animation.d.ts.map +1 -1
- package/lib/typescript/types/gesture.d.ts +4 -0
- package/lib/typescript/types/gesture.d.ts.map +1 -1
- package/lib/typescript/utils/bounds/_utils/styles.d.ts +7 -0
- package/lib/typescript/utils/bounds/_utils/styles.d.ts.map +1 -0
- package/lib/typescript/utils/gesture/reset-gesture-values.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__configs__/presets.ts +23 -7
- package/src/__tests__/determine-dismissal.test.ts +121 -0
- package/src/__tests__/gesture.velocity.test.ts +138 -0
- package/src/components/controllers/screen-lifecycle.tsx +5 -7
- package/src/components/create-transition-aware-component.tsx +2 -2
- package/src/constants.ts +2 -0
- package/src/hooks/animation/use-screen-animation.tsx +1 -0
- package/src/hooks/bounds/use-bound-registry.tsx +23 -23
- package/src/hooks/gestures/use-build-gestures.tsx +21 -37
- package/src/hooks/use-stable-callback-value.tsx +68 -0
- package/src/stores/gestures.ts +5 -0
- package/src/types/animation.ts +10 -9
- package/src/types/gesture.ts +4 -0
- package/src/utils/bounds/_utils/styles.ts +68 -0
- package/src/utils/gesture/reset-gesture-values.ts +22 -4
package/src/stores/gestures.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { makeMutable, type SharedValue } from "react-native-reanimated";
|
|
2
|
+
import type { GestureDirection } from "../types/gesture";
|
|
2
3
|
import type { ScreenKey } from "../types/navigator";
|
|
3
4
|
|
|
4
5
|
export type GestureKey =
|
|
@@ -16,6 +17,7 @@ export type GestureMap = {
|
|
|
16
17
|
normalizedY: SharedValue<number>;
|
|
17
18
|
isDismissing: SharedValue<number>;
|
|
18
19
|
isDragging: SharedValue<number>;
|
|
20
|
+
direction: SharedValue<Omit<GestureDirection, "bidirectional"> | null>;
|
|
19
21
|
};
|
|
20
22
|
|
|
21
23
|
const store: Record<ScreenKey, GestureMap> = {};
|
|
@@ -30,6 +32,9 @@ function ensure(routeKey: ScreenKey): GestureMap {
|
|
|
30
32
|
normalizedY: makeMutable(0),
|
|
31
33
|
isDismissing: makeMutable(0),
|
|
32
34
|
isDragging: makeMutable(0),
|
|
35
|
+
direction: makeMutable<Omit<GestureDirection, "bidirectional"> | null>(
|
|
36
|
+
null,
|
|
37
|
+
),
|
|
33
38
|
};
|
|
34
39
|
store[routeKey] = bag;
|
|
35
40
|
}
|
package/src/types/animation.ts
CHANGED
|
@@ -18,10 +18,11 @@ export type ScreenTransitionState = {
|
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
export interface ScreenInterpolationProps {
|
|
21
|
-
/** Values for the screen that
|
|
21
|
+
/** Values for the screen that came before the current one in the navigation stack. */
|
|
22
22
|
previous: ScreenTransitionState | undefined;
|
|
23
|
+
/** Values for the current screen being interpolated. */
|
|
23
24
|
current: ScreenTransitionState;
|
|
24
|
-
/** Values for the screen
|
|
25
|
+
/** Values for the screen that comes after the current one in the navigation stack. */
|
|
25
26
|
next: ScreenTransitionState | undefined;
|
|
26
27
|
/** Layout measurements for the screen. */
|
|
27
28
|
layouts: {
|
|
@@ -33,19 +34,19 @@ export interface ScreenInterpolationProps {
|
|
|
33
34
|
};
|
|
34
35
|
/** The safe area insets for the screen. */
|
|
35
36
|
insets: EdgeInsets;
|
|
36
|
-
/** The
|
|
37
|
+
/** The ID of the currently active shared bound (e.g., 'a' when Transition.Pressable has sharedBoundTag='a'). */
|
|
37
38
|
activeBoundId: string;
|
|
38
|
-
/** Whether the screen is focused. */
|
|
39
|
+
/** Whether the current screen is the focused (topmost) screen in the stack. */
|
|
39
40
|
focused: boolean;
|
|
40
|
-
/**
|
|
41
|
+
/** Combined progress of current and next screen transitions, ranging from 0-2. */
|
|
41
42
|
progress: number;
|
|
42
|
-
/**
|
|
43
|
+
/** Function that provides access to bounds builders for creating shared element transitions. */
|
|
43
44
|
bounds: BoundsAccessor;
|
|
44
|
-
/** The
|
|
45
|
+
/** The screen state that is currently driving the transition (either current or next, whichever is focused). */
|
|
45
46
|
active: ScreenTransitionState;
|
|
46
|
-
/** Whether the active screen is transitioning. */
|
|
47
|
+
/** Whether the active screen is currently transitioning (either being dragged or animating). */
|
|
47
48
|
isActiveTransitioning: boolean;
|
|
48
|
-
/** Whether the active screen is
|
|
49
|
+
/** Whether the active screen is in the process of being dismissed/closed. */
|
|
49
50
|
isDismissing: boolean;
|
|
50
51
|
}
|
|
51
52
|
|
package/src/types/gesture.ts
CHANGED
|
@@ -49,4 +49,8 @@ export type GestureValues = {
|
|
|
49
49
|
* A flag indicating if the screen is in the process of dismissing.
|
|
50
50
|
*/
|
|
51
51
|
isDismissing: number;
|
|
52
|
+
/**
|
|
53
|
+
* The initial direction that activated the gesture.
|
|
54
|
+
*/
|
|
55
|
+
direction: Omit<GestureDirection, "bidirectional"> | null;
|
|
52
56
|
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { ImageStyle, StyleProp, TextStyle, ViewStyle } from "react-native";
|
|
2
|
+
import { isSharedValue } from "react-native-reanimated";
|
|
3
|
+
|
|
4
|
+
type AnyStyle = ViewStyle | TextStyle | ImageStyle;
|
|
5
|
+
type StyleValue = StyleProp<AnyStyle>;
|
|
6
|
+
type PlainStyleObject = Record<string, any>;
|
|
7
|
+
|
|
8
|
+
function mergeStyleArrays<T extends StyleValue>(style: T): T {
|
|
9
|
+
"worklet";
|
|
10
|
+
|
|
11
|
+
// Early returns for non-objects
|
|
12
|
+
if (style === null || style === undefined || typeof style !== "object") {
|
|
13
|
+
return style;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// If not an array, return as-is
|
|
17
|
+
if (!Array.isArray(style)) {
|
|
18
|
+
return style;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Merge array of styles into single object
|
|
22
|
+
const merged: PlainStyleObject = {};
|
|
23
|
+
for (let i = 0; i < style.length; i++) {
|
|
24
|
+
const currentStyle = mergeStyleArrays(style[i] as StyleValue);
|
|
25
|
+
if (currentStyle && typeof currentStyle === "object") {
|
|
26
|
+
Object.assign(merged, currentStyle);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return merged as T;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function stripNonSerializable<T>(value: T): T | undefined {
|
|
33
|
+
if (isSharedValue(value)) return value;
|
|
34
|
+
|
|
35
|
+
if (Array.isArray(value)) {
|
|
36
|
+
return value.map(stripNonSerializable) as T;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (value && typeof value === "object") {
|
|
40
|
+
const cleaned: PlainStyleObject = {};
|
|
41
|
+
for (const key in value) {
|
|
42
|
+
if (key === "current") continue;
|
|
43
|
+
|
|
44
|
+
const cleanedValue = stripNonSerializable(value[key]);
|
|
45
|
+
if (cleanedValue !== undefined) {
|
|
46
|
+
cleaned[key] = cleanedValue;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return cleaned as T;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (typeof value === "function") {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function prepareStyleForBounds(
|
|
60
|
+
style: StyleValue | undefined,
|
|
61
|
+
): PlainStyleObject {
|
|
62
|
+
if (!style) return {};
|
|
63
|
+
|
|
64
|
+
const flattened = mergeStyleArrays(style);
|
|
65
|
+
const serializable = stripNonSerializable(flattened);
|
|
66
|
+
|
|
67
|
+
return serializable || {};
|
|
68
|
+
}
|
|
@@ -38,11 +38,29 @@ export const resetGestureValues = ({
|
|
|
38
38
|
const vxTowardZero = velocity.calculateRestoreVelocity(nx, vxNorm);
|
|
39
39
|
const vyTowardZero = velocity.calculateRestoreVelocity(ny, vyNorm);
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
gestures.y.value = animate(0, { ...spec, velocity: vyTowardZero });
|
|
41
|
+
let remainingAnimations = 4;
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
const onFinish = (finished: boolean | undefined) => {
|
|
44
|
+
"worklet";
|
|
45
|
+
if (!finished) return;
|
|
46
|
+
remainingAnimations -= 1;
|
|
47
|
+
if (remainingAnimations === 0) {
|
|
48
|
+
gestures.direction.value = null;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
gestures.x.value = animate(0, { ...spec, velocity: vxTowardZero }, onFinish);
|
|
53
|
+
gestures.y.value = animate(0, { ...spec, velocity: vyTowardZero }, onFinish);
|
|
54
|
+
gestures.normalizedX.value = animate(
|
|
55
|
+
0,
|
|
56
|
+
{ ...spec, velocity: vxTowardZero },
|
|
57
|
+
onFinish,
|
|
58
|
+
);
|
|
59
|
+
gestures.normalizedY.value = animate(
|
|
60
|
+
0,
|
|
61
|
+
{ ...spec, velocity: vyTowardZero },
|
|
62
|
+
onFinish,
|
|
63
|
+
);
|
|
46
64
|
gestures.isDragging.value = 0;
|
|
47
65
|
gestures.isDismissing.value = Number(shouldDismiss);
|
|
48
66
|
};
|