react-native-screen-transitions 2.1.0 → 2.2.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 (78) hide show
  1. package/lib/commonjs/components/bound-capture.js +7 -2
  2. package/lib/commonjs/components/bound-capture.js.map +1 -1
  3. package/lib/commonjs/components/controllers/screen-lifecycle.js +3 -9
  4. package/lib/commonjs/components/controllers/screen-lifecycle.js.map +1 -1
  5. package/lib/commonjs/components/create-transition-aware-component.js +12 -2
  6. package/lib/commonjs/components/create-transition-aware-component.js.map +1 -1
  7. package/lib/commonjs/components/root-transition-aware.js +3 -1
  8. package/lib/commonjs/components/root-transition-aware.js.map +1 -1
  9. package/lib/commonjs/hooks/animation/use-associated-style.js +41 -6
  10. package/lib/commonjs/hooks/animation/use-associated-style.js.map +1 -1
  11. package/lib/commonjs/hooks/bounds/use-bound-registry.js +9 -16
  12. package/lib/commonjs/hooks/bounds/use-bound-registry.js.map +1 -1
  13. package/lib/commonjs/providers/transition-styles.js +5 -1
  14. package/lib/commonjs/providers/transition-styles.js.map +1 -1
  15. package/lib/commonjs/stores/bounds/_utils.js +118 -0
  16. package/lib/commonjs/stores/bounds/_utils.js.map +1 -0
  17. package/lib/commonjs/stores/bounds/index.js +116 -0
  18. package/lib/commonjs/stores/bounds/index.js.map +1 -0
  19. package/lib/commonjs/stores/utils/reset-stores-for-screen.js +1 -4
  20. package/lib/commonjs/stores/utils/reset-stores-for-screen.js.map +1 -1
  21. package/lib/module/components/bound-capture.js +7 -2
  22. package/lib/module/components/bound-capture.js.map +1 -1
  23. package/lib/module/components/controllers/screen-lifecycle.js +3 -9
  24. package/lib/module/components/controllers/screen-lifecycle.js.map +1 -1
  25. package/lib/module/components/create-transition-aware-component.js +12 -2
  26. package/lib/module/components/create-transition-aware-component.js.map +1 -1
  27. package/lib/module/components/root-transition-aware.js +3 -1
  28. package/lib/module/components/root-transition-aware.js.map +1 -1
  29. package/lib/module/hooks/animation/use-associated-style.js +42 -7
  30. package/lib/module/hooks/animation/use-associated-style.js.map +1 -1
  31. package/lib/module/hooks/bounds/use-bound-registry.js +9 -16
  32. package/lib/module/hooks/bounds/use-bound-registry.js.map +1 -1
  33. package/lib/module/providers/transition-styles.js +5 -1
  34. package/lib/module/providers/transition-styles.js.map +1 -1
  35. package/lib/module/stores/bounds/_utils.js +113 -0
  36. package/lib/module/stores/bounds/_utils.js.map +1 -0
  37. package/lib/module/stores/bounds/index.js +112 -0
  38. package/lib/module/stores/bounds/index.js.map +1 -0
  39. package/lib/module/stores/utils/reset-stores-for-screen.js +1 -4
  40. package/lib/module/stores/utils/reset-stores-for-screen.js.map +1 -1
  41. package/lib/typescript/components/bound-capture.d.ts.map +1 -1
  42. package/lib/typescript/components/create-transition-aware-component.d.ts.map +1 -1
  43. package/lib/typescript/hooks/animation/use-associated-style.d.ts +4 -4
  44. package/lib/typescript/hooks/animation/use-associated-style.d.ts.map +1 -1
  45. package/lib/typescript/hooks/bounds/use-bound-registry.d.ts +0 -1
  46. package/lib/typescript/hooks/bounds/use-bound-registry.d.ts.map +1 -1
  47. package/lib/typescript/index.d.ts +4 -0
  48. package/lib/typescript/index.d.ts.map +1 -1
  49. package/lib/typescript/providers/transition-styles.d.ts +4 -1
  50. package/lib/typescript/providers/transition-styles.d.ts.map +1 -1
  51. package/lib/typescript/stores/bounds/_utils.d.ts +24 -0
  52. package/lib/typescript/stores/bounds/_utils.d.ts.map +1 -0
  53. package/lib/typescript/stores/{bounds.d.ts → bounds/index.d.ts} +3 -13
  54. package/lib/typescript/stores/bounds/index.d.ts.map +1 -0
  55. package/lib/typescript/stores/utils/reset-stores-for-screen.d.ts +1 -3
  56. package/lib/typescript/stores/utils/reset-stores-for-screen.d.ts.map +1 -1
  57. package/lib/typescript/types/core.d.ts +8 -0
  58. package/lib/typescript/types/core.d.ts.map +1 -1
  59. package/package.json +3 -3
  60. package/src/__tests__/bounds.store.test.ts +185 -0
  61. package/src/components/bound-capture.tsx +5 -2
  62. package/src/components/controllers/screen-lifecycle.tsx +3 -3
  63. package/src/components/create-transition-aware-component.tsx +19 -3
  64. package/src/components/root-transition-aware.tsx +1 -1
  65. package/src/hooks/animation/use-associated-style.tsx +42 -7
  66. package/src/hooks/bounds/use-bound-registry.tsx +10 -21
  67. package/src/providers/transition-styles.tsx +8 -2
  68. package/src/stores/bounds/_utils.ts +161 -0
  69. package/src/stores/bounds/index.ts +125 -0
  70. package/src/stores/utils/reset-stores-for-screen.ts +1 -7
  71. package/src/types/core.ts +9 -0
  72. package/LICENSE +0 -21
  73. package/lib/commonjs/stores/bounds.js +0 -205
  74. package/lib/commonjs/stores/bounds.js.map +0 -1
  75. package/lib/module/stores/bounds.js +0 -201
  76. package/lib/module/stores/bounds.js.map +0 -1
  77. package/lib/typescript/stores/bounds.d.ts.map +0 -1
  78. package/src/stores/bounds.ts +0 -227
@@ -1,12 +1,12 @@
1
+ import { type StyleProps } from "react-native-reanimated";
1
2
  type Props = {
2
3
  id?: string;
4
+ style?: StyleProps;
3
5
  };
4
6
  /**
5
- * This hook is used to get the associated styles for a given styleId.
6
- * It is used to get the associated styles for a given styleId.
7
- * It is used to get the associated styles for a given styleId.
7
+ * This hook is used to get the associated styles for a given styleId / boundTag.
8
8
  */
9
- export declare const useAssociatedStyles: ({ id }?: Props) => {
9
+ export declare const useAssociatedStyles: ({ id, style }?: Props) => {
10
10
  associatedStyles: Readonly<{}>;
11
11
  };
12
12
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"use-associated-style.d.ts","sourceRoot":"","sources":["../../../../src/hooks/animation/use-associated-style.tsx"],"names":[],"mappings":"AAGA,KAAK,KAAK,GAAG;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;CACZ,CAAC;AAIF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAAI,SAAQ,KAAU;;CAcrD,CAAC"}
1
+ {"version":3,"file":"use-associated-style.d.ts","sourceRoot":"","sources":["../../../../src/hooks/animation/use-associated-style.tsx"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,UAAU,EAIf,MAAM,yBAAyB,CAAC;AAGjC,KAAK,KAAK,GAAG;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,UAAU,CAAC;CACnB,CAAC;AAIF;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAAI,gBAAe,KAAU;;CA6C5D,CAAC"}
@@ -13,7 +13,6 @@ interface BoundMeasurerHookProps {
13
13
  export declare const useBoundsRegistry: ({ sharedBoundTag, animatedRef, current, style, }: BoundMeasurerHookProps) => {
14
14
  measureBounds: () => void;
15
15
  handleLayout: () => void;
16
- measureOnTouchStart: () => void;
17
16
  };
18
17
  export {};
19
18
  //# sourceMappingURL=use-bound-registry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-bound-registry.d.ts","sourceRoot":"","sources":["../../../../src/hooks/bounds/use-bound-registry.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EACN,KAAK,WAAW,EAEhB,KAAK,UAAU,EAEf,MAAM,yBAAyB,CAAC;AAOjC,UAAU,sBAAsB;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC;IAC/B,OAAO,EAAE;QAAE,KAAK,EAAE;YAAE,GAAG,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IACpC,KAAK,EAAE,UAAU,CAAC;CAClB;AAED,eAAO,MAAM,iBAAiB,GAAI,kDAK/B,sBAAsB;;;;CAwDxB,CAAC"}
1
+ {"version":3,"file":"use-bound-registry.d.ts","sourceRoot":"","sources":["../../../../src/hooks/bounds/use-bound-registry.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EACN,KAAK,WAAW,EAEhB,KAAK,UAAU,EAEf,MAAM,yBAAyB,CAAC;AAMjC,UAAU,sBAAsB;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC;IAC/B,OAAO,EAAE;QAAE,KAAK,EAAE;YAAE,GAAG,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IACpC,KAAK,EAAE,UAAU,CAAC;CAClB;AAED,eAAO,MAAM,iBAAiB,GAAI,kDAK/B,sBAAsB;;;CA8CxB,CAAC"}
@@ -209,6 +209,7 @@ declare const _default: {
209
209
  } & {
210
210
  styleId?: string;
211
211
  sharedBoundTag?: string;
212
+ measureOnLayout?: boolean;
212
213
  } & import("react").RefAttributes<never>>>;
213
214
  Pressable: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<{
214
215
  id?: string | import("react-native-reanimated").SharedValue<string | undefined> | undefined;
@@ -457,6 +458,7 @@ declare const _default: {
457
458
  } & {
458
459
  styleId?: string;
459
460
  sharedBoundTag?: string;
461
+ measureOnLayout?: boolean;
460
462
  } & import("react").RefAttributes<View | import("react").Component<import("react-native").PressableProps & import("react").RefAttributes<View>, any, any>>>>;
461
463
  ScrollView: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<{
462
464
  id?: string | import("react-native-reanimated").SharedValue<string | undefined> | undefined;
@@ -793,6 +795,7 @@ declare const _default: {
793
795
  } & {
794
796
  styleId?: string;
795
797
  sharedBoundTag?: string;
798
+ measureOnLayout?: boolean;
796
799
  } & import("react").RefAttributes<never>>>;
797
800
  FlatList: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<{
798
801
  id?: string | import("react-native-reanimated").SharedValue<string | undefined> | undefined;
@@ -1263,6 +1266,7 @@ declare const _default: {
1263
1266
  } & {
1264
1267
  styleId?: string;
1265
1268
  sharedBoundTag?: string;
1269
+ measureOnLayout?: boolean;
1266
1270
  } & import("react").RefAttributes<never>>>;
1267
1271
  MaskedView: typeof MaskedView;
1268
1272
  presets: {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmC,IAAI,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,8BAA8B,EAAE,MAAM,gDAAgD,CAAC;AAChG,OAAO,UAAU,MAAM,uCAAuC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAgC4iE,CAAC;;;;;;;;;;;AA7B5mE,wBAaE;AAEF,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,0BAA0B,EAAE,MAAM,mEAAmE,CAAC;AAE/G,YAAY,EACX,0BAA0B,EAC1B,sBAAsB,EACtB,2BAA2B,EAC3B,6BAA6B,EAC7B,4BAA4B,EAC5B,yBAAyB,EACzB,yBAAyB,EACzB,sBAAsB,EACtB,sBAAsB,GACtB,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmC,IAAI,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,8BAA8B,EAAE,MAAM,gDAAgD,CAAC;AAChG,OAAO,UAAU,MAAM,uCAAuC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAgC4iE,CAAC;;;;;;;;;;;AA7B5mE,wBAaE;AAEF,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,0BAA0B,EAAE,MAAM,mEAAmE,CAAC;AAE/G,YAAY,EACX,0BAA0B,EAC1B,sBAAsB,EACtB,2BAA2B,EAC3B,6BAA6B,EAC7B,4BAA4B,EAC5B,yBAAyB,EACzB,yBAAyB,EACzB,sBAAsB,EACtB,sBAAsB,GACtB,MAAM,mBAAmB,CAAC"}
@@ -1,8 +1,11 @@
1
+ import { useDerivedValue } from "react-native-reanimated";
1
2
  import type { TransitionInterpolatedStyle } from "../types/animation";
2
3
  type Props = {
3
4
  children: React.ReactNode;
4
5
  };
5
6
  export declare function TransitionStylesProvider({ children }: Props): import("react/jsx-runtime").JSX.Element;
6
- export declare function useTransitionStyles(): import("react-native-reanimated").DerivedValue<TransitionInterpolatedStyle>;
7
+ export declare function useTransitionStyles(): {
8
+ stylesMap: ReturnType<typeof useDerivedValue<TransitionInterpolatedStyle>>;
9
+ };
7
10
  export {};
8
11
  //# sourceMappingURL=transition-styles.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"transition-styles.d.ts","sourceRoot":"","sources":["../../../src/providers/transition-styles.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AAEtE,KAAK,KAAK,GAAG;IACZ,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC1B,CAAC;AAQF,wBAAgB,wBAAwB,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,2CA0B3D;AAED,wBAAgB,mBAAmB,gFAQlC"}
1
+ {"version":3,"file":"transition-styles.d.ts","sourceRoot":"","sources":["../../../src/providers/transition-styles.tsx"],"names":[],"mappings":"AACA,OAAO,EAAqB,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE7E,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AAEtE,KAAK,KAAK,GAAG;IACZ,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC1B,CAAC;AAUF,wBAAgB,wBAAwB,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,2CA8B3D;AAED,wBAAgB,mBAAmB;eApCtB,UAAU,CAAC,OAAO,eAAe,CAAC,2BAA2B,CAAC,CAAC;EA4C3E"}
@@ -0,0 +1,24 @@
1
+ import type { ScreenTransitionState } from "../../types/animation";
2
+ type GetCache = (fromKey: string, toKey: string) => string | null;
3
+ type SetCache = (fromKey: string, toKey: string, id: string) => void;
4
+ type GetRouteActive = (routeKey: string) => string | null;
5
+ interface ResolveActiveBoundParams {
6
+ current: ScreenTransitionState;
7
+ next?: ScreenTransitionState;
8
+ previous?: ScreenTransitionState;
9
+ getPairCache: GetCache;
10
+ setPairCache: SetCache;
11
+ getRouteActive: GetRouteActive;
12
+ }
13
+ export declare function pairKey(fromKey?: string, toKey?: string): string;
14
+ /**
15
+ * Util function to get the active bound id for a given transition state.
16
+ *
17
+ * It will check by ( priority from highest to lowest ):
18
+ * 1. Requested id
19
+ * 2. Cache
20
+ * 3. Intersection
21
+ */
22
+ export declare function resolveActiveBound({ current, next, previous, getPairCache, setPairCache, getRouteActive, }: ResolveActiveBoundParams): string;
23
+ export {};
24
+ //# sourceMappingURL=_utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_utils.d.ts","sourceRoot":"","sources":["../../../../src/stores/bounds/_utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAEnE,KAAK,QAAQ,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;AAClE,KAAK,QAAQ,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;AACrE,KAAK,cAAc,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;AAE1D,UAAU,wBAAwB;IACjC,OAAO,EAAE,qBAAqB,CAAC;IAC/B,IAAI,CAAC,EAAE,qBAAqB,CAAC;IAC7B,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC,YAAY,EAAE,QAAQ,CAAC;IACvB,YAAY,EAAE,QAAQ,CAAC;IACvB,cAAc,EAAE,cAAc,CAAC;CAC/B;AAED,wBAAgB,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,UAGvD;AA2ED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,EAClC,OAAO,EACP,IAAI,EACJ,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,cAAc,GACd,EAAE,wBAAwB,UAoD1B"}
@@ -1,32 +1,22 @@
1
1
  import { type MeasuredDimensions, type StyleProps } from "react-native-reanimated";
2
- import type { ScreenTransitionState } from "../types/animation";
3
- import type { ScreenKey } from "../types/navigator";
2
+ import type { ScreenTransitionState } from "../../types/animation";
3
+ import type { ScreenKey } from "../../types/navigator";
4
4
  declare function setBounds(screenId: string, boundId: string, bounds?: MeasuredDimensions | null, styles?: StyleProps): void;
5
5
  declare function getBounds(screenId: string): Record<string, {
6
6
  bounds: MeasuredDimensions;
7
7
  styles: StyleProps;
8
8
  }>;
9
- declare function setActiveBoundId(boundId: string): void;
10
- declare function getActiveBoundId(): string | null;
11
9
  declare function setRouteActive(routeKey: string, boundId: string): void;
12
10
  declare function getRouteActive(routeKey: string): string;
13
- declare function setTransitionHint(fromKey: string, toKey: string, boundId: string): void;
14
- declare function getTransitionHint(fromKey: string, toKey: string): string | null;
15
11
  declare function clear(routeKey: ScreenKey): void;
16
- declare function clearActive(): void;
17
12
  declare function getActiveBound(current: ScreenTransitionState, next: ScreenTransitionState | undefined, previous: ScreenTransitionState | undefined): string;
18
13
  export declare const Bounds: {
19
14
  setBounds: typeof setBounds;
20
15
  getBounds: typeof getBounds;
21
- setActiveBoundId: typeof setActiveBoundId;
22
- getActiveBoundId: typeof getActiveBoundId;
23
16
  setRouteActive: typeof setRouteActive;
24
17
  getRouteActive: typeof getRouteActive;
25
- setTransitionHint: typeof setTransitionHint;
26
- getTransitionHint: typeof getTransitionHint;
27
18
  clear: typeof clear;
28
- clearActive: typeof clearActive;
29
19
  getActiveBound: typeof getActiveBound;
30
20
  };
31
21
  export {};
32
- //# sourceMappingURL=bounds.d.ts.map
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/stores/bounds/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,kBAAkB,EAEvB,KAAK,UAAU,EACf,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAavD,iBAAS,SAAS,CACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,kBAAkB,GAAG,IAAW,EACxC,MAAM,GAAE,UAAe,QAYvB;AAED,iBAAS,SAAS,CAAC,QAAQ,EAAE,MAAM;YAzBT,kBAAkB;YAAU,UAAU;GA4B/D;AAED,iBAAS,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,QAOxD;AAED,iBAAS,cAAc,CAAC,QAAQ,EAAE,MAAM,UAGvC;AAoBD,iBAAS,KAAK,CAAC,QAAQ,EAAE,SAAS,QAyBjC;AAED,iBAAS,cAAc,CACtB,OAAO,EAAE,qBAAqB,EAC9B,IAAI,EAAE,qBAAqB,GAAG,SAAS,EACvC,QAAQ,EAAE,qBAAqB,GAAG,SAAS,UAW3C;AAED,eAAO,MAAM,MAAM;;;;;;;CAOlB,CAAC"}
@@ -2,7 +2,5 @@ import type { NativeStackDescriptor } from "../../types/navigator";
2
2
  /**
3
3
  * Reset all stores for a given screen
4
4
  */
5
- export declare const resetStoresForScreen: (current: NativeStackDescriptor, options?: {
6
- clearActive?: boolean;
7
- }) => void;
5
+ export declare const resetStoresForScreen: (current: NativeStackDescriptor) => void;
8
6
  //# sourceMappingURL=reset-stores-for-screen.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reset-stores-for-screen.d.ts","sourceRoot":"","sources":["../../../../src/stores/utils/reset-stores-for-screen.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAKnE;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAChC,SAAS,qBAAqB,EAC9B,UAAS;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,SAQvC,CAAC"}
1
+ {"version":3,"file":"reset-stores-for-screen.d.ts","sourceRoot":"","sources":["../../../../src/stores/utils/reset-stores-for-screen.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAKnE;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAAI,SAAS,qBAAqB,SAIlE,CAAC"}
@@ -39,6 +39,14 @@ export type TransitionAwareProps<T extends object> = AnimatedProps<T> & {
39
39
  * </Transition.View>
40
40
  */
41
41
  sharedBoundTag?: string;
42
+ /**
43
+ * Eagerly measure this component on layout and store the result in the
44
+ * Bounds registry. Useful for nested shared elements that may not receive
45
+ * the press event but still need up-to-date measurements at navigation time.
46
+ *
47
+ * Only has an effect when used together with `sharedBoundTag`.
48
+ */
49
+ measureOnLayout?: boolean;
42
50
  };
43
51
  export type TransitionConfig = {
44
52
  open: TransitionSpec;
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../src/types/core.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;AAE1D,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,MAAM,IAAI,aAAa,CAAC,CAAC,CAAC,GAAG;IACvE;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;;;;;;;;;;;;OAcG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC9B,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,cAAc,CAAC;CACtB,CAAC"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../src/types/core.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;AAE1D,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,MAAM,IAAI,aAAa,CAAC,CAAC,CAAC,GAAG;IACvE;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;;;;;;;;;;;;OAcG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC9B,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,cAAc,CAAC;CACtB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-screen-transitions",
3
- "version": "2.1.0",
3
+ "version": "2.2.1",
4
4
  "description": "Easy screen transitions for React Native and Expo",
5
5
  "author": "Ed",
6
6
  "license": "MIT",
@@ -49,7 +49,7 @@
49
49
  "@testing-library/react-native": "^13.2.0",
50
50
  "@types/react": "~19.0.10",
51
51
  "react-native-builder-bob": "0.39.0",
52
- "typescript": "~5.8.3"
52
+ "typescript": "catalog:"
53
53
  },
54
54
  "react-native-builder-bob": {
55
55
  "source": "src",
@@ -65,5 +65,5 @@
65
65
  ]
66
66
  ]
67
67
  },
68
- "gitHead": "92afaa07f6b9c279851d6aef805ecbfefdbcc4df"
68
+ "gitHead": "888d4df9936ec0e3b8221bea7cd81115e6301693"
69
69
  }
@@ -0,0 +1,185 @@
1
+ import { beforeEach, describe, expect, it } from "bun:test";
2
+ import { resolveActiveBound } from "../stores/bounds/_utils";
3
+ import type { ScreenTransitionState } from "../types/animation";
4
+
5
+ type Dim = {
6
+ x: number;
7
+ y: number;
8
+ pageX: number;
9
+ pageY: number;
10
+ width: number;
11
+ height: number;
12
+ };
13
+
14
+ const getDimensions = (x = 0, y = 0, w = 100, h = 100): Dim => ({
15
+ x,
16
+ y,
17
+ pageX: x,
18
+ pageY: y,
19
+ width: w,
20
+ height: h,
21
+ });
22
+
23
+ const mockState = (
24
+ routeKey: string,
25
+ ids: string[] = [],
26
+ ): ScreenTransitionState => {
27
+ const bounds: Record<
28
+ string,
29
+ { bounds: Dim; styles: Record<string, unknown> }
30
+ > = {};
31
+ ids.forEach((id, i) => {
32
+ bounds[id] = { bounds: getDimensions(i * 10, i * 10), styles: {} };
33
+ });
34
+ return {
35
+ progress: 1,
36
+ closing: 0,
37
+ animating: 1,
38
+ gesture: {
39
+ x: 0,
40
+ y: 0,
41
+ normalizedX: 0,
42
+ normalizedY: 0,
43
+ isDismissing: 0,
44
+ isDragging: 0,
45
+ },
46
+ bounds,
47
+ // @ts-expect-error partial route
48
+ route: { key: routeKey },
49
+ };
50
+ };
51
+
52
+ let cache: Record<string, string>;
53
+ let lastActiveByRoute: Record<string, string>;
54
+ beforeEach(() => {
55
+ cache = {};
56
+ lastActiveByRoute = {};
57
+ });
58
+
59
+ const getPairCache = (from: string, to: string) =>
60
+ cache[`${from}|${to}`] ?? null;
61
+ const setPairCache = (from: string, to: string, id: string) => {
62
+ cache[`${from}|${to}`] = id;
63
+ };
64
+ const getRouteActive = (routeKey: string) =>
65
+ lastActiveByRoute[routeKey] ?? null;
66
+
67
+ describe("Bounds.getActiveBound - requested id priority and acceptance", () => {
68
+ it("selects requested id when present only on current (opening)", () => {
69
+ const A = "A-1";
70
+ const B = "B-1";
71
+ const current = mockState(A, ["container"]);
72
+ const previous = mockState(B, ["icon"]);
73
+
74
+ // Opening: fromKey is previous.route.key (B)
75
+ lastActiveByRoute[B] = "container";
76
+ const active = resolveActiveBound({
77
+ current,
78
+ previous,
79
+ getPairCache,
80
+ setPairCache,
81
+ getRouteActive,
82
+ });
83
+
84
+ expect(active).toBe("container");
85
+ expect(getPairCache(B, A)).toBeNull();
86
+ });
87
+
88
+ it("selects requested id when present only on other (closing)", () => {
89
+ const A = "A-2";
90
+ const B = "B-2";
91
+ const current = mockState(A, ["icon"]);
92
+ const next = mockState(B, ["container"]);
93
+
94
+ // Closing: fromKey is current.route.key (A)
95
+ lastActiveByRoute[A] = "container";
96
+ const active = resolveActiveBound({
97
+ current,
98
+ next,
99
+ getPairCache,
100
+ setPairCache,
101
+ getRouteActive,
102
+ });
103
+ expect(active).toBe("container");
104
+ expect(getPairCache(A, B)).toBeNull();
105
+ });
106
+ });
107
+
108
+ describe("Bounds.getActiveBound - hint behavior (guarded writes)", () => {
109
+ it("writes cache only when both sides have the id", () => {
110
+ const A = "A-3";
111
+ const B = "B-3";
112
+ // Both have the same id measured
113
+ const current = mockState(A, ["container"]);
114
+ const previous = mockState(B, ["container"]);
115
+
116
+ // Opening: fromKey is previous.route.key (B)
117
+ lastActiveByRoute[B] = "container";
118
+ const active = resolveActiveBound({
119
+ current,
120
+ previous,
121
+ getPairCache,
122
+ setPairCache,
123
+ getRouteActive,
124
+ });
125
+ expect(active).toBe("container");
126
+ expect(getPairCache(B, A)).toBe("container");
127
+ });
128
+
129
+ it("requested id overrides existing cache and updates it when both sides measured", () => {
130
+ const A = "A-4";
131
+ const B = "B-4";
132
+ // Both sides have icon and container
133
+ // Pre-seed a conflicting cache
134
+ setPairCache(B, A, "icon");
135
+
136
+ const current = mockState(A, ["icon", "container"]);
137
+ const previous = mockState(B, ["icon", "container"]);
138
+
139
+ // Opening: fromKey is previous.route.key (B)
140
+ lastActiveByRoute[B] = "container";
141
+ const active = resolveActiveBound({
142
+ current,
143
+ previous,
144
+ getPairCache,
145
+ setPairCache,
146
+ getRouteActive,
147
+ });
148
+ expect(active).toBe("container");
149
+ expect(getPairCache(B, A)).toBe("container");
150
+ });
151
+ });
152
+
153
+ describe("Bounds.getActiveBound - set intersection and fallbacks", () => {
154
+ it("falls back to intersection when no request or cache", () => {
155
+ const A = "A-5";
156
+ const B = "B-5";
157
+ const current = mockState(A, ["alpha", "beta"]);
158
+ const previous = mockState(B, ["beta", "gamma"]);
159
+
160
+ const active = resolveActiveBound({
161
+ current,
162
+ previous,
163
+ getPairCache,
164
+ setPairCache,
165
+ getRouteActive,
166
+ });
167
+ expect(active).toBe("beta");
168
+ });
169
+
170
+ it("when other has a single bound, selects it (no request/cache)", () => {
171
+ const A = "A-6";
172
+ const B = "B-6";
173
+ const current = mockState(A, ["alpha"]);
174
+ const previous = mockState(B, ["only"]);
175
+
176
+ const active = resolveActiveBound({
177
+ current,
178
+ previous,
179
+ getPairCache,
180
+ setPairCache,
181
+ getRouteActive,
182
+ });
183
+ expect(active).toBe("only");
184
+ });
185
+ });
@@ -1,5 +1,6 @@
1
1
  import { useMemo } from "react";
2
2
  import { Gesture, GestureDetector } from "react-native-gesture-handler";
3
+ import { useKeys } from "../providers/keys";
3
4
  import { Bounds } from "../stores/bounds";
4
5
 
5
6
  interface BoundActivatorProps {
@@ -13,15 +14,17 @@ export const BoundCapture = ({
13
14
  children,
14
15
  measure,
15
16
  }: BoundActivatorProps) => {
17
+ const { current } = useKeys();
18
+ const routeKey = current.route.key;
16
19
  const tapGesture = useMemo(() => {
17
20
  return Gesture.Tap().onStart(() => {
18
21
  "worklet";
19
22
  if (sharedBoundTag) {
20
- Bounds.setActiveBoundId(sharedBoundTag);
23
+ Bounds.setRouteActive(routeKey, sharedBoundTag);
21
24
  measure();
22
25
  }
23
26
  });
24
- }, [sharedBoundTag, measure]);
27
+ }, [sharedBoundTag, measure, routeKey]);
25
28
 
26
29
  if (!sharedBoundTag) return children;
27
30
 
@@ -24,13 +24,13 @@ export const ScreenLifecycleController = ({
24
24
 
25
25
  // Don't run e.preventDefault when the dismissal was on the local root
26
26
  if (requestedDismissOnNavigator) {
27
- resetStoresForScreen(current, { clearActive: true });
27
+ resetStoresForScreen(current);
28
28
  return;
29
29
  }
30
30
 
31
31
  // Don't run e.preventDefault when this is the first screen of the stack
32
32
  if (current.navigation.getState().index === 0) {
33
- resetStoresForScreen(current, { clearActive: true });
33
+ resetStoresForScreen(current);
34
34
  return;
35
35
  }
36
36
 
@@ -41,7 +41,7 @@ export const ScreenLifecycleController = ({
41
41
 
42
42
  // we'll ensure the dispatch is complete before resetting stores
43
43
  requestAnimationFrame(() => {
44
- resetStoresForScreen(current, { clearActive: false });
44
+ resetStoresForScreen(current);
45
45
  });
46
46
  }
47
47
  };
@@ -53,14 +53,22 @@ export function createTransitionAwareComponent<P extends object>(
53
53
  React.ComponentRef<typeof AnimatedComponent>,
54
54
  TransitionAwareProps<P>
55
55
  >((props, ref) => {
56
- const { children, style, sharedBoundTag, styleId, onPress, ...rest } =
57
- props as Any;
56
+ const {
57
+ children,
58
+ style,
59
+ sharedBoundTag,
60
+ styleId,
61
+ onPress,
62
+ measureOnLayout,
63
+ ...rest
64
+ } = props as Any;
58
65
 
59
66
  const animatedRef = useAnimatedRef<View>();
60
67
  const { current } = useKeys();
61
68
 
62
69
  const { associatedStyles } = useAssociatedStyles({
63
70
  id: sharedBoundTag || styleId,
71
+ style,
64
72
  });
65
73
 
66
74
  const { measureBounds, handleLayout } = useBoundsRegistry({
@@ -81,6 +89,14 @@ export function createTransitionAwareComponent<P extends object>(
81
89
  );
82
90
  }
83
91
 
92
+ const onLayoutHandler = runOnUI(() => {
93
+ "worklet";
94
+ handleLayout();
95
+ if (measureOnLayout && sharedBoundTag) {
96
+ measureBounds();
97
+ }
98
+ });
99
+
84
100
  return (
85
101
  <BoundCapture sharedBoundTag={sharedBoundTag} measure={measureBounds}>
86
102
  <AnimatedComponent
@@ -88,7 +104,7 @@ export function createTransitionAwareComponent<P extends object>(
88
104
  ref={animatedRef}
89
105
  style={[style, associatedStyles]}
90
106
  onPress={onPress}
91
- onLayout={runOnUI(handleLayout)}
107
+ onLayout={onLayoutHandler}
92
108
  >
93
109
  {children}
94
110
  </AnimatedComponent>
@@ -13,7 +13,7 @@ type Props = {
13
13
  const EMPTY_STYLE = Object.freeze({} as StyleProps);
14
14
 
15
15
  export const RootTransitionAware = memo(({ children }: Props) => {
16
- const stylesMap = useTransitionStyles();
16
+ const { stylesMap } = useTransitionStyles();
17
17
 
18
18
  const animatedContentStyle = useAnimatedStyle(() => {
19
19
  "worklet";
@@ -1,19 +1,37 @@
1
- import { useAnimatedStyle } from "react-native-reanimated";
1
+ import {
2
+ type StyleProps,
3
+ useAnimatedStyle,
4
+ useDerivedValue,
5
+ useSharedValue,
6
+ } from "react-native-reanimated";
2
7
  import { useTransitionStyles } from "../../providers/transition-styles";
3
8
 
4
9
  type Props = {
5
10
  id?: string;
11
+ style?: StyleProps;
6
12
  };
7
13
 
8
14
  const EMPTY_STYLE = Object.freeze({});
9
15
 
10
16
  /**
11
- * This hook is used to get the associated styles for a given styleId.
12
- * It is used to get the associated styles for a given styleId.
13
- * It is used to get the associated styles for a given styleId.
17
+ * This hook is used to get the associated styles for a given styleId / boundTag.
14
18
  */
15
- export const useAssociatedStyles = ({ id }: Props = {}) => {
16
- const stylesMap = useTransitionStyles();
19
+ export const useAssociatedStyles = ({ id, style }: Props = {}) => {
20
+ const { stylesMap } = useTransitionStyles();
21
+ const showAfterFirstFrame = useSharedValue(false);
22
+
23
+ useDerivedValue(() => {
24
+ "worklet";
25
+ if (!id) {
26
+ showAfterFirstFrame.value = true;
27
+ return;
28
+ }
29
+ if (!showAfterFirstFrame.value) {
30
+ requestAnimationFrame(() => {
31
+ showAfterFirstFrame.value = true;
32
+ });
33
+ }
34
+ });
17
35
 
18
36
  const associatedStyles = useAnimatedStyle(() => {
19
37
  "worklet";
@@ -21,8 +39,25 @@ export const useAssociatedStyles = ({ id }: Props = {}) => {
21
39
  if (!id || !stylesMap) {
22
40
  return EMPTY_STYLE;
23
41
  }
42
+ const base =
43
+ (stylesMap.value[id] as Record<string, unknown>) || EMPTY_STYLE;
44
+
45
+ let opacity = 1;
46
+
47
+ if ("opacity" in base) {
48
+ opacity = base.opacity as number;
49
+ }
50
+ if (style && "opacity" in style) {
51
+ opacity = style.opacity as number;
52
+ }
53
+
54
+ // Only force opacity to 0 during the initial frame; once ready,
55
+ // return base unchanged so we never override user-provided opacity.
56
+ if (!showAfterFirstFrame.value) {
57
+ return { ...base, opacity: 0 } as Record<string, unknown>;
58
+ }
24
59
 
25
- return stylesMap.value[id] || EMPTY_STYLE;
60
+ return { ...base, opacity };
26
61
  });
27
62
 
28
63
  return { associatedStyles };