react-native-screen-transitions 3.3.0-beta.3 → 3.3.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 (119) hide show
  1. package/README.md +95 -31
  2. package/lib/commonjs/shared/animation/snap-to.js +2 -0
  3. package/lib/commonjs/shared/animation/snap-to.js.map +1 -1
  4. package/lib/commonjs/shared/components/create-transition-aware-component.js +20 -18
  5. package/lib/commonjs/shared/components/create-transition-aware-component.js.map +1 -1
  6. package/lib/commonjs/shared/components/screen-container.js +59 -6
  7. package/lib/commonjs/shared/components/screen-container.js.map +1 -1
  8. package/lib/commonjs/shared/constants.js +8 -1
  9. package/lib/commonjs/shared/constants.js.map +1 -1
  10. package/lib/commonjs/shared/hooks/gestures/use-build-gestures.js +49 -39
  11. package/lib/commonjs/shared/hooks/gestures/use-build-gestures.js.map +1 -1
  12. package/lib/commonjs/shared/hooks/gestures/use-screen-gesture-handlers.js +110 -61
  13. package/lib/commonjs/shared/hooks/gestures/use-screen-gesture-handlers.js.map +1 -1
  14. package/lib/commonjs/shared/hooks/gestures/use-scroll-registry.js +67 -70
  15. package/lib/commonjs/shared/hooks/gestures/use-scroll-registry.js.map +1 -1
  16. package/lib/commonjs/shared/providers/gestures.provider.js +112 -5
  17. package/lib/commonjs/shared/providers/gestures.provider.js.map +1 -1
  18. package/lib/commonjs/shared/types/ownership.types.js +71 -0
  19. package/lib/commonjs/shared/types/ownership.types.js.map +1 -0
  20. package/lib/commonjs/shared/utils/gesture/check-gesture-activation.js +72 -128
  21. package/lib/commonjs/shared/utils/gesture/check-gesture-activation.js.map +1 -1
  22. package/lib/commonjs/shared/utils/gesture/compute-claimed-directions.js +81 -0
  23. package/lib/commonjs/shared/utils/gesture/compute-claimed-directions.js.map +1 -0
  24. package/lib/commonjs/shared/utils/gesture/determine-snap-target.js +1 -1
  25. package/lib/commonjs/shared/utils/gesture/determine-snap-target.js.map +1 -1
  26. package/lib/commonjs/shared/utils/gesture/find-collapse-target.js +48 -0
  27. package/lib/commonjs/shared/utils/gesture/find-collapse-target.js.map +1 -0
  28. package/lib/commonjs/shared/utils/gesture/resolve-ownership.js +87 -0
  29. package/lib/commonjs/shared/utils/gesture/resolve-ownership.js.map +1 -0
  30. package/lib/commonjs/shared/utils/gesture/velocity.js +16 -5
  31. package/lib/commonjs/shared/utils/gesture/velocity.js.map +1 -1
  32. package/lib/module/shared/animation/snap-to.js +1 -0
  33. package/lib/module/shared/animation/snap-to.js.map +1 -1
  34. package/lib/module/shared/components/create-transition-aware-component.js +20 -18
  35. package/lib/module/shared/components/create-transition-aware-component.js.map +1 -1
  36. package/lib/module/shared/components/screen-container.js +59 -7
  37. package/lib/module/shared/components/screen-container.js.map +1 -1
  38. package/lib/module/shared/constants.js +7 -0
  39. package/lib/module/shared/constants.js.map +1 -1
  40. package/lib/module/shared/hooks/gestures/use-build-gestures.js +49 -39
  41. package/lib/module/shared/hooks/gestures/use-build-gestures.js.map +1 -1
  42. package/lib/module/shared/hooks/gestures/use-screen-gesture-handlers.js +112 -63
  43. package/lib/module/shared/hooks/gestures/use-screen-gesture-handlers.js.map +1 -1
  44. package/lib/module/shared/hooks/gestures/use-scroll-registry.js +68 -70
  45. package/lib/module/shared/hooks/gestures/use-scroll-registry.js.map +1 -1
  46. package/lib/module/shared/providers/gestures.provider.js +112 -5
  47. package/lib/module/shared/providers/gestures.provider.js.map +1 -1
  48. package/lib/module/shared/types/ownership.types.js +67 -0
  49. package/lib/module/shared/types/ownership.types.js.map +1 -0
  50. package/lib/module/shared/utils/gesture/check-gesture-activation.js +70 -126
  51. package/lib/module/shared/utils/gesture/check-gesture-activation.js.map +1 -1
  52. package/lib/module/shared/utils/gesture/compute-claimed-directions.js +77 -0
  53. package/lib/module/shared/utils/gesture/compute-claimed-directions.js.map +1 -0
  54. package/lib/module/shared/utils/gesture/determine-snap-target.js +1 -1
  55. package/lib/module/shared/utils/gesture/determine-snap-target.js.map +1 -1
  56. package/lib/module/shared/utils/gesture/find-collapse-target.js +44 -0
  57. package/lib/module/shared/utils/gesture/find-collapse-target.js.map +1 -0
  58. package/lib/module/shared/utils/gesture/resolve-ownership.js +83 -0
  59. package/lib/module/shared/utils/gesture/resolve-ownership.js.map +1 -0
  60. package/lib/module/shared/utils/gesture/velocity.js +16 -5
  61. package/lib/module/shared/utils/gesture/velocity.js.map +1 -1
  62. package/lib/typescript/shared/animation/snap-to.d.ts.map +1 -1
  63. package/lib/typescript/shared/components/create-transition-aware-component.d.ts.map +1 -1
  64. package/lib/typescript/shared/components/screen-container.d.ts.map +1 -1
  65. package/lib/typescript/shared/constants.d.ts +6 -0
  66. package/lib/typescript/shared/constants.d.ts.map +1 -1
  67. package/lib/typescript/shared/hooks/gestures/use-build-gestures.d.ts +15 -3
  68. package/lib/typescript/shared/hooks/gestures/use-build-gestures.d.ts.map +1 -1
  69. package/lib/typescript/shared/hooks/gestures/use-screen-gesture-handlers.d.ts +52 -2
  70. package/lib/typescript/shared/hooks/gestures/use-screen-gesture-handlers.d.ts.map +1 -1
  71. package/lib/typescript/shared/hooks/gestures/use-scroll-registry.d.ts +11 -6
  72. package/lib/typescript/shared/hooks/gestures/use-scroll-registry.d.ts.map +1 -1
  73. package/lib/typescript/shared/hooks/use-backdrop-pointer-events.d.ts +1 -1
  74. package/lib/typescript/shared/hooks/use-backdrop-pointer-events.d.ts.map +1 -1
  75. package/lib/typescript/shared/providers/gestures.provider.d.ts +27 -2
  76. package/lib/typescript/shared/providers/gestures.provider.d.ts.map +1 -1
  77. package/lib/typescript/shared/types/ownership.types.d.ts +52 -0
  78. package/lib/typescript/shared/types/ownership.types.d.ts.map +1 -0
  79. package/lib/typescript/shared/types/screen.types.d.ts +22 -1
  80. package/lib/typescript/shared/types/screen.types.d.ts.map +1 -1
  81. package/lib/typescript/shared/utils/gesture/check-gesture-activation.d.ts +23 -19
  82. package/lib/typescript/shared/utils/gesture/check-gesture-activation.d.ts.map +1 -1
  83. package/lib/typescript/shared/utils/gesture/compute-claimed-directions.d.ts +23 -0
  84. package/lib/typescript/shared/utils/gesture/compute-claimed-directions.d.ts.map +1 -0
  85. package/lib/typescript/shared/utils/gesture/determine-snap-target.d.ts +5 -1
  86. package/lib/typescript/shared/utils/gesture/determine-snap-target.d.ts.map +1 -1
  87. package/lib/typescript/shared/utils/gesture/find-collapse-target.d.ts +17 -0
  88. package/lib/typescript/shared/utils/gesture/find-collapse-target.d.ts.map +1 -0
  89. package/lib/typescript/shared/utils/gesture/resolve-ownership.d.ts +36 -0
  90. package/lib/typescript/shared/utils/gesture/resolve-ownership.d.ts.map +1 -0
  91. package/lib/typescript/shared/utils/gesture/velocity.d.ts.map +1 -1
  92. package/package.json +121 -120
  93. package/src/shared/animation/snap-to.ts +1 -0
  94. package/src/shared/components/create-transition-aware-component.tsx +28 -25
  95. package/src/shared/components/screen-container.tsx +69 -7
  96. package/src/shared/constants.ts +7 -0
  97. package/src/shared/hooks/gestures/use-build-gestures.tsx +80 -44
  98. package/src/shared/hooks/gestures/use-screen-gesture-handlers.ts +147 -71
  99. package/src/shared/hooks/gestures/use-scroll-registry.tsx +94 -86
  100. package/src/shared/hooks/use-backdrop-pointer-events.ts +1 -1
  101. package/src/shared/providers/gestures.provider.tsx +166 -5
  102. package/src/shared/types/ownership.types.ts +77 -0
  103. package/src/shared/types/screen.types.ts +24 -1
  104. package/src/shared/utils/gesture/check-gesture-activation.ts +82 -116
  105. package/src/shared/utils/gesture/compute-claimed-directions.ts +93 -0
  106. package/src/shared/utils/gesture/determine-snap-target.ts +6 -2
  107. package/src/shared/utils/gesture/find-collapse-target.ts +42 -0
  108. package/src/shared/utils/gesture/resolve-ownership.ts +110 -0
  109. package/src/shared/utils/gesture/velocity.ts +16 -6
  110. package/src/shared/__tests__/bounds.store.test.ts +0 -394
  111. package/src/shared/__tests__/derivations.test.ts +0 -156
  112. package/src/shared/__tests__/determine-dismissal.test.ts +0 -111
  113. package/src/shared/__tests__/determine-snap-target.test.ts +0 -268
  114. package/src/shared/__tests__/geometry.test.ts +0 -130
  115. package/src/shared/__tests__/gesture-activation.test.ts +0 -471
  116. package/src/shared/__tests__/gesture.velocity.test.ts +0 -131
  117. package/src/shared/__tests__/history.store.test.ts +0 -550
  118. package/src/shared/__tests__/sync-routes-with-removed.test.ts +0 -137
  119. package/src/shared/__tests__/validate-snap-points.test.ts +0 -125
@@ -0,0 +1,23 @@
1
+ import type { GestureDirection } from "../../types/gesture.types";
2
+ import { type ClaimedDirections } from "../../types/ownership.types";
3
+ /**
4
+ * Computes which directions a screen claims ownership of.
5
+ *
6
+ * A screen claims a direction when:
7
+ * 1. gestureEnabled is true AND
8
+ * 2. gestureDirection includes that direction
9
+ *
10
+ * For snap points, both directions on the axis are claimed automatically.
11
+ * This is because a snap point sheet handles both expand (inverse) and collapse (primary) gestures.
12
+ *
13
+ * @param gestureEnabled - Whether gestures are enabled for this screen
14
+ * @param gestureDirection - The gesture direction(s) configured for this screen
15
+ * @param hasSnapPoints - Whether this screen has snap points configured
16
+ * @returns The claimed directions for this screen
17
+ */
18
+ export declare function computeClaimedDirections(gestureEnabled: boolean, gestureDirection: GestureDirection | GestureDirection[] | undefined, hasSnapPoints: boolean): ClaimedDirections;
19
+ /**
20
+ * Checks if any direction is claimed.
21
+ */
22
+ export declare function claimsAnyDirection(claims: ClaimedDirections): boolean;
23
+ //# sourceMappingURL=compute-claimed-directions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compute-claimed-directions.d.ts","sourceRoot":"","sources":["../../../../../src/shared/utils/gesture/compute-claimed-directions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EACN,KAAK,iBAAiB,EAGtB,MAAM,6BAA6B,CAAC;AAErC;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,CACvC,cAAc,EAAE,OAAO,EACvB,gBAAgB,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,GAAG,SAAS,EACnE,aAAa,EAAE,OAAO,GACpB,iBAAiB,CAsDnB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAOrE"}
@@ -5,7 +5,11 @@ interface DetermineSnapTargetProps {
5
5
  velocity: number;
6
6
  /** Screen dimension along the snap axis (width or height) */
7
7
  dimension: number;
8
- /** How much velocity affects the snap decision (0-1). Default 0.15 */
8
+ /**
9
+ * How much velocity affects the snap decision.
10
+ * Lower values = more deliberate/iOS-like, higher values = more responsive to flicks.
11
+ * @default 0.1
12
+ */
9
13
  velocityFactor?: number;
10
14
  /** Whether dismiss (progress=0) is allowed. Default true */
11
15
  canDismiss?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"determine-snap-target.d.ts","sourceRoot":"","sources":["../../../../../src/shared/utils/gesture/determine-snap-target.ts"],"names":[],"mappings":"AAAA,UAAU,wBAAwB;IACjC,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,yBAAyB;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,EACnC,eAAe,EACf,UAAU,EACV,QAAQ,EACR,SAAS,EACT,cAAqB,EACrB,UAAiB,GACjB,EAAE,wBAAwB,GAAG,yBAAyB,CA0CtD"}
1
+ {"version":3,"file":"determine-snap-target.d.ts","sourceRoot":"","sources":["../../../../../src/shared/utils/gesture/determine-snap-target.ts"],"names":[],"mappings":"AAAA,UAAU,wBAAwB;IACjC,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,yBAAyB;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,EACnC,eAAe,EACf,UAAU,EACV,QAAQ,EACR,SAAS,EACT,cAAoB,EACpB,UAAiB,GACjB,EAAE,wBAAwB,GAAG,yBAAyB,CA0CtD"}
@@ -0,0 +1,17 @@
1
+ interface FindCollapseTargetResult {
2
+ target: number;
3
+ shouldDismiss: boolean;
4
+ }
5
+ /**
6
+ * Finds the next lower snap point for backdrop collapse behavior.
7
+ *
8
+ * - If above min snap: returns next lower snap point
9
+ * - If at or below min snap: returns 0 (dismiss) if canDismiss, else stays at min
10
+ *
11
+ * @param currentProgress - Current animation progress
12
+ * @param snapPoints - Array of snap points
13
+ * @param canDismiss - Whether dismissing is allowed
14
+ */
15
+ export declare function findCollapseTarget(currentProgress: number, snapPoints: number[], canDismiss: boolean): FindCollapseTargetResult;
16
+ export {};
17
+ //# sourceMappingURL=find-collapse-target.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find-collapse-target.d.ts","sourceRoot":"","sources":["../../../../../src/shared/utils/gesture/find-collapse-target.ts"],"names":[],"mappings":"AAEA,UAAU,wBAAwB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CACjC,eAAe,EAAE,MAAM,EACvB,UAAU,EAAE,MAAM,EAAE,EACpB,UAAU,EAAE,OAAO,GACjB,wBAAwB,CAoB1B"}
@@ -0,0 +1,36 @@
1
+ import type { ClaimedDirections } from "../../types/ownership.types";
2
+ import { type DirectionOwnership } from "../../types/ownership.types";
3
+ /**
4
+ * Minimal interface for ancestor context needed for ownership resolution.
5
+ * This allows the function to be used without importing the full GestureContextType.
6
+ */
7
+ export interface AncestorClaimsContext {
8
+ claimedDirections: ClaimedDirections;
9
+ ancestorContext: AncestorClaimsContext | null;
10
+ }
11
+ /**
12
+ * Resolves ownership status for all directions relative to the current screen.
13
+ *
14
+ * For each direction:
15
+ * 1. If the current screen claims it → 'self' (should activate)
16
+ * 2. Else, walk up ancestors looking for a claim → 'ancestor' (should fail to bubble)
17
+ * 3. If no one claims it → 'none' (should fail, no gesture response)
18
+ *
19
+ * This is computed during render (JS thread) and the result can be safely
20
+ * used in worklets since it's a plain object.
21
+ *
22
+ * @param selfClaims - The directions claimed by the current screen
23
+ * @param ancestorContext - The ancestor context chain (can be null if no ancestors)
24
+ * @returns Ownership status for all four directions
25
+ */
26
+ export declare function resolveOwnership(selfClaims: ClaimedDirections, ancestorContext: AncestorClaimsContext | null): DirectionOwnership;
27
+ /**
28
+ * Finds the nearest ancestor (or self if isCurrentOwner) that claims any direction.
29
+ * Used for setting up native gesture relationships.
30
+ *
31
+ * @param selfClaimsAny - Whether the current screen claims any direction
32
+ * @param ancestorContext - The ancestor context chain
33
+ * @returns The nearest context that claims a direction, or null
34
+ */
35
+ export declare function findNearestOwner(selfClaimsAny: boolean, ancestorContext: AncestorClaimsContext | null): AncestorClaimsContext | null;
36
+ //# sourceMappingURL=resolve-ownership.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-ownership.d.ts","sourceRoot":"","sources":["../../../../../src/shared/utils/gesture/resolve-ownership.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAa,MAAM,6BAA6B,CAAC;AAChF,OAAO,EAEN,KAAK,kBAAkB,EAGvB,MAAM,6BAA6B,CAAC;AAErC;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACrC,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,eAAe,EAAE,qBAAqB,GAAG,IAAI,CAAC;CAC9C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC/B,UAAU,EAAE,iBAAiB,EAC7B,eAAe,EAAE,qBAAqB,GAAG,IAAI,GAC3C,kBAAkB,CAYpB;AA4BD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC/B,aAAa,EAAE,OAAO,EACtB,eAAe,EAAE,qBAAqB,GAAG,IAAI,GAC3C,qBAAqB,GAAG,IAAI,CAuB9B"}
@@ -1 +1 @@
1
- {"version":3,"file":"velocity.d.ts","sourceRoot":"","sources":["../../../../../src/shared/utils/gesture/velocity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,uBAAuB,EACvB,6BAA6B,EAC7B,MAAM,8BAA8B,CAAC;AAEtC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEtE,UAAU,sBAAsB;IAC/B,UAAU,EAAE,iBAAiB,CAAC;IAC9B,aAAa,EAAE,OAAO,CAAC;IACvB,KAAK,EAAE,uBAAuB,CAAC,6BAA6B,CAAC,CAAC;IAC9D,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,UAAU,EAAE;QACX,UAAU,EAAE,OAAO,CAAC;QACpB,kBAAkB,EAAE,OAAO,CAAC;QAC5B,QAAQ,EAAE,OAAO,CAAC;QAClB,gBAAgB,EAAE,OAAO,CAAC;KAC1B,CAAC;CACF;AAgID,eAAO,MAAM,QAAQ;yCAvHuB,MAAM,cAAc,MAAM;wCAa3B,MAAM,aAAa,MAAM;uDAU3C,MAAM,0BACN,MAAM;+FAkB5B,sBAAsB;sDAyDL,MAAM,2BACA,MAAM,cACnB,MAAM,kBACF,MAAM;CAuBtB,CAAC"}
1
+ {"version":3,"file":"velocity.d.ts","sourceRoot":"","sources":["../../../../../src/shared/utils/gesture/velocity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,uBAAuB,EACvB,6BAA6B,EAC7B,MAAM,8BAA8B,CAAC;AAGtC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEtE,UAAU,sBAAsB;IAC/B,UAAU,EAAE,iBAAiB,CAAC;IAC9B,aAAa,EAAE,OAAO,CAAC;IACvB,KAAK,EAAE,uBAAuB,CAAC,6BAA6B,CAAC,CAAC;IAC9D,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,UAAU,EAAE;QACX,UAAU,EAAE,OAAO,CAAC;QACpB,kBAAkB,EAAE,OAAO,CAAC;QAC5B,QAAQ,EAAE,OAAO,CAAC;QAClB,gBAAgB,EAAE,OAAO,CAAC;KAC1B,CAAC;CACF;AAyID,eAAO,MAAM,QAAQ;yCAjIuB,MAAM,cAAc,MAAM;wCAa3B,MAAM,aAAa,MAAM;uDAU3C,MAAM,0BACN,MAAM;+FAkB5B,sBAAsB;sDAyDL,MAAM,2BACA,MAAM,cACnB,MAAM,kBACF,MAAM;CAiCtB,CAAC"}
package/package.json CHANGED
@@ -1,122 +1,123 @@
1
1
  {
2
- "name": "react-native-screen-transitions",
3
- "version": "3.3.0-beta.3",
4
- "description": "Easy screen transitions for React Native and Expo",
5
- "author": "Ed",
6
- "license": "MIT",
7
- "repository": {
8
- "type": "git",
9
- "url": "https://github.com/eds2002/react-native-screen-transitions.git",
10
- "directory": "packages/react-native-screen-transitions"
11
- },
12
- "main": "lib/commonjs/shared/index.js",
13
- "module": "lib/module/shared/index.js",
14
- "types": "lib/typescript/shared/index.d.ts",
15
- "react-native": "src/shared/index",
16
- "exports": {
17
- ".": {
18
- "react-native": "./src/shared/index.ts",
19
- "import": "./lib/module/shared/index.js",
20
- "require": "./lib/commonjs/shared/index.js",
21
- "types": "./lib/typescript/shared/index.d.ts"
22
- },
23
- "./native-stack": {
24
- "react-native": "./src/native-stack/index.ts",
25
- "import": "./lib/module/native-stack/index.js",
26
- "require": "./lib/commonjs/native-stack/index.js",
27
- "types": "./lib/typescript/native-stack/index.d.ts"
28
- },
29
- "./blank-stack": {
30
- "react-native": "./src/blank-stack/index.ts",
31
- "import": "./lib/module/blank-stack/index.js",
32
- "require": "./lib/commonjs/blank-stack/index.js",
33
- "types": "./lib/typescript/blank-stack/index.d.ts"
34
- },
35
- "./component-stack": {
36
- "react-native": "./src/component-stack/index.ts",
37
- "import": "./lib/module/component-stack/index.js",
38
- "require": "./lib/commonjs/component-stack/index.js",
39
- "types": "./lib/typescript/component-stack/index.d.ts"
40
- }
41
- },
42
- "scripts": {
43
- "build": "bob build",
44
- "lint": "biome check ./src",
45
- "typecheck": "tsc --noEmit",
46
- "prepublishOnly": "bun run build",
47
- "release": "release-it",
48
- "release:beta": "release-it --preRelease=beta"
49
- },
50
- "keywords": [
51
- "react-native",
52
- "transitions",
53
- "animation",
54
- "react-navigation",
55
- "expo-router",
56
- "reanimated"
57
- ],
58
- "files": [
59
- "lib",
60
- "src",
61
- "README.md",
62
- "LICENSE"
63
- ],
64
- "peerDependencies": {
65
- "@react-navigation/elements": ">=2.0.0",
66
- "@react-navigation/native": ">=6.0.0",
67
- "@react-navigation/native-stack": ">=7.0.0",
68
- "@types/react": "*",
69
- "@types/react-native": "*",
70
- "react": "*",
71
- "react-native": "*",
72
- "react-native-gesture-handler": ">=2.16.1",
73
- "react-native-reanimated": ">=3.16.0 || >=4.0.0-",
74
- "react-native-safe-area-context": "*",
75
- "react-native-screens": ">=4.4.0"
76
- },
77
- "devDependencies": {
78
- "@release-it/conventional-changelog": "^10.0.1",
79
- "@types/react": "~19.1.10",
80
- "react-native-builder-bob": "0.39.0",
81
- "release-it": "^19.0.4",
82
- "typescript": "catalog:"
83
- },
84
- "react-native-builder-bob": {
85
- "source": "src",
86
- "output": "lib",
87
- "targets": [
88
- "commonjs",
89
- "module",
90
- [
91
- "typescript",
92
- {
93
- "project": "tsconfig.build.json"
94
- }
95
- ]
96
- ]
97
- },
98
- "release-it": {
99
- "git": {
100
- "commitMessage": "chore: release ${version}",
101
- "tagName": "v${version}",
102
- "commitArgs": [
103
- "-n"
104
- ]
105
- },
106
- "npm": {
107
- "publish": true
108
- },
109
- "github": {
110
- "release": true
111
- },
112
- "plugins": {
113
- "@release-it/conventional-changelog": {
114
- "preset": {
115
- "name": "angular"
116
- },
117
- "path": "."
118
- }
119
- }
120
- },
121
- "gitHead": "888d4df9936ec0e3b8221bea7cd81115e6301693"
2
+ "name": "react-native-screen-transitions",
3
+ "version": "3.3.0-beta.4",
4
+ "description": "Easy screen transitions for React Native and Expo",
5
+ "author": "Ed",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/eds2002/react-native-screen-transitions.git",
10
+ "directory": "packages/react-native-screen-transitions"
11
+ },
12
+ "main": "lib/commonjs/shared/index.js",
13
+ "module": "lib/module/shared/index.js",
14
+ "types": "lib/typescript/shared/index.d.ts",
15
+ "react-native": "src/shared/index",
16
+ "exports": {
17
+ ".": {
18
+ "react-native": "./src/shared/index.ts",
19
+ "import": "./lib/module/shared/index.js",
20
+ "require": "./lib/commonjs/shared/index.js",
21
+ "types": "./lib/typescript/shared/index.d.ts"
22
+ },
23
+ "./native-stack": {
24
+ "react-native": "./src/native-stack/index.ts",
25
+ "import": "./lib/module/native-stack/index.js",
26
+ "require": "./lib/commonjs/native-stack/index.js",
27
+ "types": "./lib/typescript/native-stack/index.d.ts"
28
+ },
29
+ "./blank-stack": {
30
+ "react-native": "./src/blank-stack/index.ts",
31
+ "import": "./lib/module/blank-stack/index.js",
32
+ "require": "./lib/commonjs/blank-stack/index.js",
33
+ "types": "./lib/typescript/blank-stack/index.d.ts"
34
+ },
35
+ "./component-stack": {
36
+ "react-native": "./src/component-stack/index.ts",
37
+ "import": "./lib/module/component-stack/index.js",
38
+ "require": "./lib/commonjs/component-stack/index.js",
39
+ "types": "./lib/typescript/component-stack/index.d.ts"
40
+ }
41
+ },
42
+ "scripts": {
43
+ "build": "bob build",
44
+ "lint": "biome check ./src",
45
+ "typecheck": "tsc --noEmit",
46
+ "prepublishOnly": "bun run build",
47
+ "release": "release-it",
48
+ "release:beta": "release-it --preRelease=beta"
49
+ },
50
+ "keywords": [
51
+ "react-native",
52
+ "transitions",
53
+ "animation",
54
+ "react-navigation",
55
+ "expo-router",
56
+ "reanimated"
57
+ ],
58
+ "files": [
59
+ "lib",
60
+ "src",
61
+ "!src/**/__tests__",
62
+ "README.md",
63
+ "LICENSE"
64
+ ],
65
+ "peerDependencies": {
66
+ "@react-navigation/elements": ">=2.0.0",
67
+ "@react-navigation/native": ">=6.0.0",
68
+ "@react-navigation/native-stack": ">=7.0.0",
69
+ "@types/react": "*",
70
+ "@types/react-native": "*",
71
+ "react": "*",
72
+ "react-native": "*",
73
+ "react-native-gesture-handler": ">=2.16.1",
74
+ "react-native-reanimated": ">=3.16.0 || >=4.0.0-",
75
+ "react-native-safe-area-context": "*",
76
+ "react-native-screens": ">=4.4.0"
77
+ },
78
+ "devDependencies": {
79
+ "@release-it/conventional-changelog": "^10.0.1",
80
+ "@types/react": "~19.1.10",
81
+ "react-native-builder-bob": "0.39.0",
82
+ "release-it": "^19.0.4",
83
+ "typescript": "catalog:"
84
+ },
85
+ "react-native-builder-bob": {
86
+ "source": "src",
87
+ "output": "lib",
88
+ "targets": [
89
+ "commonjs",
90
+ "module",
91
+ [
92
+ "typescript",
93
+ {
94
+ "project": "tsconfig.build.json"
95
+ }
96
+ ]
97
+ ]
98
+ },
99
+ "release-it": {
100
+ "git": {
101
+ "commitMessage": "chore: release ${version}",
102
+ "tagName": "v${version}",
103
+ "commitArgs": [
104
+ "-n"
105
+ ]
106
+ },
107
+ "npm": {
108
+ "publish": true
109
+ },
110
+ "github": {
111
+ "release": true
112
+ },
113
+ "plugins": {
114
+ "@release-it/conventional-changelog": {
115
+ "preset": {
116
+ "name": "angular"
117
+ },
118
+ "path": "."
119
+ }
120
+ }
121
+ },
122
+ "gitHead": "888d4df9936ec0e3b8221bea7cd81115e6301693"
122
123
  }
@@ -1,3 +1,4 @@
1
+ /** biome-ignore-all lint/style/noNonNullAssertion: <Options always exist> */
1
2
  import { runOnUI } from "react-native-reanimated";
2
3
  import { DefaultSnapSpec } from "../configs/specs";
3
4
  import { AnimationStore } from "../stores/animation.store";
@@ -6,7 +6,6 @@ import { GestureDetector } from "react-native-gesture-handler";
6
6
  import Animated, { runOnUI, useAnimatedRef } from "react-native-reanimated";
7
7
  import { useAssociatedStyles } from "../hooks/animation/use-associated-style";
8
8
  import { useScrollRegistry } from "../hooks/gestures/use-scroll-registry";
9
- import { useGestureContext } from "../providers/gestures.provider";
10
9
  import { RegisterBoundsProvider } from "../providers/register-bounds.provider";
11
10
  import type { TransitionAwareProps } from "../types/screen.types";
12
11
 
@@ -26,33 +25,37 @@ export function createTransitionAwareComponent<P extends object>(
26
25
  React.ComponentRef<typeof Wrapped>,
27
26
  TransitionAwareProps<P>
28
27
  >((props: any, ref) => {
29
- const { nativeGesture } = useGestureContext()!;
30
- const {
31
- scrollHandler,
32
- onContentSizeChange,
33
- onLayout,
34
- onTouchStart,
35
- onTouchEnd,
36
- } = useScrollRegistry({
37
- onScroll: props.onScroll,
38
- onContentSizeChange: props.onContentSizeChange,
39
- onLayout: props.onLayout,
40
- onTouchStart: props.onTouchStart,
41
- onTouchEnd: props.onTouchEnd,
42
- });
28
+ // Determine scroll direction from the horizontal prop (standard ScrollView API)
29
+ const scrollDirection = props.horizontal ? "horizontal" : "vertical";
30
+
31
+ // Get scroll handlers and the gesture owner's nativeGesture for this axis
32
+ const { scrollHandler, onContentSizeChange, onLayout, nativeGesture } =
33
+ useScrollRegistry({
34
+ onScroll: props.onScroll,
35
+ onContentSizeChange: props.onContentSizeChange,
36
+ onLayout: props.onLayout,
37
+ direction: scrollDirection,
38
+ });
39
+
40
+ const scrollableComponent = (
41
+ <AnimatedComponent
42
+ {...(props as any)}
43
+ ref={ref}
44
+ onScroll={scrollHandler}
45
+ onContentSizeChange={onContentSizeChange}
46
+ onLayout={onLayout}
47
+ scrollEventThrottle={props.scrollEventThrottle || 16}
48
+ />
49
+ );
50
+
51
+ // If no gesture owner found for this axis, render without GestureDetector
52
+ if (!nativeGesture) {
53
+ return scrollableComponent;
54
+ }
43
55
 
44
56
  return (
45
57
  <GestureDetector gesture={nativeGesture}>
46
- <AnimatedComponent
47
- {...(props as any)}
48
- ref={ref}
49
- onScroll={scrollHandler}
50
- onContentSizeChange={onContentSizeChange}
51
- onLayout={onLayout}
52
- onTouchStart={onTouchStart}
53
- onTouchEnd={onTouchEnd}
54
- scrollEventThrottle={props.scrollEventThrottle || 16}
55
- />
58
+ {scrollableComponent}
56
59
  </GestureDetector>
57
60
  );
58
61
  });
@@ -1,13 +1,19 @@
1
+ /** biome-ignore-all lint/style/noNonNullAssertion: <Screen gesture is under the gesture context, so this will always exist.> */
1
2
  import { StackActions } from "@react-navigation/native";
2
3
  import { memo, useCallback } from "react";
3
4
  import { Pressable, StyleSheet, View } from "react-native";
4
5
  import { GestureDetector } from "react-native-gesture-handler";
5
- import Animated, { useAnimatedStyle } from "react-native-reanimated";
6
+ import Animated, { runOnUI, useAnimatedStyle } from "react-native-reanimated";
7
+ import { DefaultSnapSpec } from "../configs/specs";
6
8
  import { NO_STYLES } from "../constants";
7
9
  import { useBackdropPointerEvents } from "../hooks/use-backdrop-pointer-events";
8
10
  import { useGestureContext } from "../providers/gestures.provider";
9
11
  import { useKeys } from "../providers/screen/keys.provider";
10
12
  import { useScreenStyles } from "../providers/screen/styles.provider";
13
+ import { AnimationStore } from "../stores/animation.store";
14
+ import { GestureStore } from "../stores/gesture.store";
15
+ import { animateToProgress } from "../utils/animation/animate-to-progress";
16
+ import { findCollapseTarget } from "../utils/gesture/find-collapse-target";
11
17
 
12
18
  type Props = {
13
19
  children: React.ReactNode;
@@ -19,11 +25,67 @@ export const ScreenContainer = memo(({ children }: Props) => {
19
25
  const { pointerEvents, backdropBehavior } = useBackdropPointerEvents();
20
26
  const gestureContext = useGestureContext();
21
27
 
22
- const isDismissable = backdropBehavior === "dismiss";
28
+ const isBackdropActive =
29
+ backdropBehavior === "dismiss" || backdropBehavior === "collapse";
30
+
31
+ const handleDismiss = useCallback(() => {
32
+ const state = current.navigation.getState();
33
+ current.navigation.dispatch({
34
+ ...StackActions.pop(),
35
+ source: current.route.key,
36
+ target: state.key,
37
+ });
38
+ }, [current]);
23
39
 
24
40
  const handleBackdropPress = useCallback(() => {
25
- current.navigation.dispatch(StackActions.pop());
26
- }, [current.navigation]);
41
+ if (backdropBehavior === "dismiss") {
42
+ handleDismiss();
43
+ return;
44
+ }
45
+
46
+ if (backdropBehavior === "collapse") {
47
+ const snapPoints = current.options.snapPoints;
48
+ const canDismiss = current.options.gestureEnabled !== false;
49
+
50
+ // No snap points → fallback to dismiss
51
+ if (!snapPoints || snapPoints.length === 0) {
52
+ handleDismiss();
53
+ return;
54
+ }
55
+
56
+ const animations = AnimationStore.getAll(current.route.key);
57
+ const gestures = GestureStore.getRouteGestures(current.route.key);
58
+ const transitionSpec = current.options.transitionSpec;
59
+
60
+ runOnUI(() => {
61
+ "worklet";
62
+ const { target, shouldDismiss } = findCollapseTarget(
63
+ animations.progress.value,
64
+ snapPoints,
65
+ canDismiss,
66
+ );
67
+
68
+ // If already dismissing, skip
69
+ if (gestures.isDismissing.value) return;
70
+
71
+ gestures.isDismissing.value = shouldDismiss ? 1 : 0;
72
+
73
+ const spec = shouldDismiss
74
+ ? transitionSpec
75
+ : {
76
+ open: transitionSpec?.expand ?? DefaultSnapSpec,
77
+ close: transitionSpec?.collapse ?? DefaultSnapSpec,
78
+ };
79
+
80
+ animateToProgress({
81
+ target,
82
+ spec,
83
+ animations,
84
+ onAnimationFinish: shouldDismiss ? handleDismiss : undefined,
85
+ });
86
+ })();
87
+ }
88
+ }, [backdropBehavior, current, handleDismiss]);
27
89
 
28
90
  const animatedContentStyle = useAnimatedStyle(() => {
29
91
  "worklet";
@@ -41,8 +103,8 @@ export const ScreenContainer = memo(({ children }: Props) => {
41
103
  <View style={styles.container} pointerEvents={pointerEvents}>
42
104
  <Pressable
43
105
  style={StyleSheet.absoluteFillObject}
44
- pointerEvents={isDismissable ? "auto" : "none"}
45
- onPress={isDismissable ? handleBackdropPress : undefined}
106
+ pointerEvents={isBackdropActive ? "auto" : "none"}
107
+ onPress={isBackdropActive ? handleBackdropPress : undefined}
46
108
  >
47
109
  <Animated.View
48
110
  style={[StyleSheet.absoluteFillObject, animatedBackdropStyle]}
@@ -51,7 +113,7 @@ export const ScreenContainer = memo(({ children }: Props) => {
51
113
  <GestureDetector gesture={gestureContext!.panGesture}>
52
114
  <Animated.View
53
115
  style={[styles.content, animatedContentStyle]}
54
- pointerEvents={isDismissable ? "box-none" : pointerEvents}
116
+ pointerEvents={isBackdropActive ? "box-none" : pointerEvents}
55
117
  >
56
118
  {children}
57
119
  </Animated.View>
@@ -93,6 +93,7 @@ export const FULLSCREEN_DIMENSIONS = (
93
93
  * Default gesture config
94
94
  */
95
95
  export const GESTURE_VELOCITY_IMPACT = 0.3;
96
+ export const SNAP_VELOCITY_IMPACT = 0.1;
96
97
  export const DEFAULT_GESTURE_DIRECTION = "horizontal";
97
98
  export const DEFAULT_GESTURE_DRIVES_PROGRESS = true;
98
99
  export const DEFAULT_GESTURE_ACTIVATION_AREA: ActivationArea = "screen";
@@ -106,3 +107,9 @@ export const FALSE = 0;
106
107
  * Small value for floating-point comparisons to handle animation/interpolation imprecision
107
108
  */
108
109
  export const EPSILON = 1e-5;
110
+
111
+ /**
112
+ * Threshold for snapping animations to target when "close enough" (1% of range).
113
+ * Prevents micro-jitter/oscillation near animation endpoints.
114
+ */
115
+ export const ANIMATION_SNAP_THRESHOLD = 0.01;