react-native-screen-transitions 1.0.3 → 1.1.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/dist/index.js CHANGED
@@ -34,18 +34,52 @@ __export(index_exports, {
34
34
  useScreenAnimation: () => useScreenAnimation
35
35
  });
36
36
  module.exports = __toCommonJS(index_exports);
37
+ var import_react_native5 = require("react-native");
38
+
39
+ // src/components/create-transition-aware-component.tsx
40
+ var import_react7 = require("react");
37
41
  var import_react_native3 = require("react-native");
42
+ var import_react_native_reanimated8 = __toESM(require("react-native-reanimated"));
38
43
 
39
- // src/configs/presets.ts
40
- var presets_exports = {};
41
- __export(presets_exports, {
42
- DraggableCard: () => DraggableCard,
43
- ElasticCard: () => ElasticCard,
44
- SlideFromBottom: () => SlideFromBottom,
45
- SlideFromTop: () => SlideFromTop,
46
- ZoomIn: () => ZoomIn
47
- });
44
+ // src/components/transition-gesture-handler-provider.tsx
45
+ var import_react4 = require("react");
46
+ var import_react_native_gesture_handler3 = require("react-native-gesture-handler");
47
+ var import_react_native_reanimated5 = require("react-native-reanimated");
48
+
49
+ // src/contexts/gesture.ts
50
+ var import_react = require("react");
51
+ var import_react_native_gesture_handler = require("react-native-gesture-handler");
48
52
  var import_react_native_reanimated = require("react-native-reanimated");
53
+ var GestureContext = (0, import_react.createContext)(
54
+ void 0
55
+ );
56
+ var useGestureContext = () => {
57
+ const context = (0, import_react.useContext)(GestureContext);
58
+ const scrollProgressFallback = (0, import_react_native_reanimated.useSharedValue)({
59
+ x: 0,
60
+ y: 0,
61
+ contentHeight: 0,
62
+ contentWidth: 0,
63
+ layoutHeight: 0,
64
+ layoutWidth: 0
65
+ });
66
+ if (!context) {
67
+ return {
68
+ panGesture: import_react_native_gesture_handler.Gesture.Pan(),
69
+ nativeGesture: import_react_native_gesture_handler.Gesture.Native(),
70
+ scrollProgress: scrollProgressFallback,
71
+ isPlaceholder: true
72
+ };
73
+ }
74
+ return context;
75
+ };
76
+
77
+ // src/hooks/use-build-gestures.tsx
78
+ var import_native3 = require("@react-navigation/native");
79
+ var import_react3 = require("react");
80
+ var import_react_native = require("react-native");
81
+ var import_react_native_gesture_handler2 = require("react-native-gesture-handler");
82
+ var import_react_native_reanimated4 = require("react-native-reanimated");
49
83
 
50
84
  // src/configs/specs.ts
51
85
  var specs_exports = {};
@@ -60,179 +94,12 @@ var DefaultSpec = {
60
94
  restSpeedThreshold: 0.01
61
95
  };
62
96
 
63
- // src/configs/presets.ts
64
- var SlideFromTop = (config = {}) => {
65
- return {
66
- gestureEnabled: true,
67
- gestureDirection: "vertical-inverted",
68
- screenStyleInterpolator: ({
69
- current,
70
- next,
71
- layouts: {
72
- screen: { height }
73
- }
74
- }) => {
75
- "worklet";
76
- const progress = current.progress.value + (next?.progress.value ?? 0);
77
- const y = (0, import_react_native_reanimated.interpolate)(progress, [0, 1, 2], [-height, 0, height]);
78
- return {
79
- contentStyle: {
80
- transform: [{ translateY: y }]
81
- }
82
- };
83
- },
84
- transitionSpec: {
85
- open: DefaultSpec,
86
- close: DefaultSpec
87
- },
88
- ...config
89
- };
90
- };
91
- var ZoomIn = (config = {}) => {
92
- return {
93
- gestureEnabled: false,
94
- screenStyleInterpolator: ({ current, next }) => {
95
- "worklet";
96
- const progress = current.progress.value + (next?.progress.value ?? 0);
97
- const scale = (0, import_react_native_reanimated.interpolate)(
98
- progress,
99
- [0, 1, 2],
100
- [0.5, 1, 0.5],
101
- import_react_native_reanimated.Extrapolation.CLAMP
102
- );
103
- const opacity = (0, import_react_native_reanimated.interpolate)(
104
- progress,
105
- [0, 1, 2],
106
- [0, 1, 0],
107
- import_react_native_reanimated.Extrapolation.CLAMP
108
- );
109
- return {
110
- contentStyle: {
111
- transform: [{ scale }],
112
- opacity
113
- }
114
- };
115
- },
116
- transitionSpec: {
117
- open: DefaultSpec,
118
- close: DefaultSpec
119
- },
120
- ...config
121
- };
122
- };
123
- var SlideFromBottom = (config = {}) => {
124
- return {
125
- gestureEnabled: true,
126
- gestureDirection: "vertical",
127
- screenStyleInterpolator: ({
128
- current,
129
- next,
130
- layouts: {
131
- screen: { height }
132
- }
133
- }) => {
134
- "worklet";
135
- const progress = current.progress.value + (next?.progress.value ?? 0);
136
- const y = (0, import_react_native_reanimated.interpolate)(progress, [0, 1, 2], [height, 0, -height]);
137
- return {
138
- contentStyle: {
139
- transform: [{ translateY: y }]
140
- }
141
- };
142
- },
143
- transitionSpec: {
144
- open: DefaultSpec,
145
- close: DefaultSpec
146
- },
147
- ...config
148
- };
149
- };
150
- var DraggableCard = (config = {}) => {
151
- return {
152
- gestureEnabled: true,
153
- gestureDirection: ["horizontal", "vertical"],
154
- screenStyleInterpolator: ({ current, next, layouts: { screen } }) => {
155
- "worklet";
156
- const progress = current.progress.value + (next?.progress.value ?? 0);
157
- const scale = (0, import_react_native_reanimated.interpolate)(progress, [0, 1, 2], [0, 1, 0.75]);
158
- const translateY = (0, import_react_native_reanimated.interpolate)(
159
- current.gesture.normalizedY.value,
160
- [-1, 1],
161
- [-screen.height * 0.5, screen.height * 0.5],
162
- "clamp"
163
- );
164
- const translateX = (0, import_react_native_reanimated.interpolate)(
165
- current.gesture.normalizedX.value,
166
- [-1, 1],
167
- [-screen.width * 0.5, screen.width * 0.5],
168
- "clamp"
169
- );
170
- return {
171
- contentStyle: {
172
- transform: [{ scale }, { translateY }, { translateX }]
173
- }
174
- };
175
- },
176
- transitionSpec: {
177
- open: DefaultSpec,
178
- close: DefaultSpec
179
- },
180
- ...config
181
- };
182
- };
183
- var ElasticCard = (config = { elasticFactor: 0.5 }) => {
184
- return {
185
- gestureEnabled: true,
186
- gestureDirection: "bidirectional",
187
- screenStyleInterpolator: ({ current, next, layouts: { screen } }) => {
188
- "worklet";
189
- const progress = current.progress.value + (next?.progress.value ?? 0);
190
- const scale = (0, import_react_native_reanimated.interpolate)(progress, [0, 1, 2], [0, 1, 0.8]);
191
- const maxElasticityX = screen.width * (config.elasticFactor ?? 0.5);
192
- const maxElasticityY = screen.height * (config.elasticFactor ?? 0.5);
193
- const translateX = (0, import_react_native_reanimated.interpolate)(
194
- current.gesture.normalizedX.value,
195
- [-1, 0, 1],
196
- [-maxElasticityX, 0, maxElasticityX],
197
- "clamp"
198
- );
199
- const translateY = (0, import_react_native_reanimated.interpolate)(
200
- current.gesture.normalizedY.value,
201
- [-1, 0, 1],
202
- [-maxElasticityY, 0, maxElasticityY],
203
- "clamp"
204
- );
205
- const overlayColor = (0, import_react_native_reanimated.interpolateColor)(
206
- next?.progress.value || 0,
207
- [0, 1],
208
- ["rgba(0,0,0,0)", "rgba(0,0,0,0.5)"]
209
- );
210
- return {
211
- contentStyle: {
212
- transform: [{ scale }, { translateX }, { translateY }]
213
- },
214
- overlayStyle: {
215
- backgroundColor: overlayColor
216
- }
217
- };
218
- },
219
- ...config
220
- };
221
- };
222
-
223
- // src/hooks/use-screen-animation.tsx
224
- var import_native3 = require("@react-navigation/native");
225
- var import_react2 = require("react");
226
- var import_react_native = require("react-native");
227
- var import_react_native_reanimated5 = require("react-native-reanimated");
228
- var import_react_native_safe_area_context = require("react-native-safe-area-context");
229
-
230
97
  // src/animation-engine.ts
231
98
  var import_react_native_reanimated3 = require("react-native-reanimated");
232
99
 
233
100
  // src/store/utils/create-vanilla-store.ts
234
101
  var import_immer = require("immer");
235
- var import_react = require("react");
102
+ var import_react2 = require("react");
236
103
  function createVanillaStore(initialState) {
237
104
  let state = initialState;
238
105
  const listeners = /* @__PURE__ */ new Set();
@@ -262,7 +129,7 @@ function createVanillaStore(initialState) {
262
129
  return unsubscribe;
263
130
  };
264
131
  function useStore(selector) {
265
- return (0, import_react.useSyncExternalStore)(subscribe, () => selector(getState()));
132
+ return (0, import_react2.useSyncExternalStore)(subscribe, () => selector(getState()));
266
133
  }
267
134
  Object.assign(useStore, {
268
135
  setState,
@@ -378,7 +245,8 @@ var animationValues = {
378
245
  gestureY: {},
379
246
  normalizedGestureX: {},
380
247
  normalizedGestureY: {},
381
- gestureDragging: {}
248
+ gestureDragging: {},
249
+ isDismissing: {}
382
250
  };
383
251
  var triggerAnimation = (screen) => {
384
252
  "worklet";
@@ -428,9 +296,72 @@ ScreenStore.use.subscribeWithSelector(
428
296
  }
429
297
  );
430
298
 
431
- // src/utils/gesture/build-gesture-detector.ts
432
- var import_react_native_gesture_handler = require("react-native-gesture-handler");
433
- var import_react_native_reanimated4 = require("react-native-reanimated");
299
+ // src/utils/create-config.ts
300
+ var createConfig = ({
301
+ navigation: reactNavigation,
302
+ route,
303
+ ...config
304
+ }) => {
305
+ return {
306
+ focus: (e) => {
307
+ const parentNavigatorKey = reactNavigation.getParent()?.getState?.()?.key;
308
+ const navigatorKey = reactNavigation.getState().key;
309
+ ScreenStore.updateScreen(e.target, {
310
+ id: e.target,
311
+ name: route.name,
312
+ status: 1,
313
+ closing: false,
314
+ navigatorKey,
315
+ parentNavigatorKey,
316
+ ...config
317
+ });
318
+ },
319
+ beforeRemove: (e) => {
320
+ const shouldSkipPreventDefault2 = ScreenStore.shouldSkipPreventDefault(
321
+ e.target,
322
+ reactNavigation.getState()
323
+ );
324
+ if (shouldSkipPreventDefault2) {
325
+ ScreenStore.removeScreen(e.target);
326
+ return;
327
+ }
328
+ e.preventDefault();
329
+ const handleFinish = (finished) => {
330
+ if (!finished) return;
331
+ if (reactNavigation.canGoBack()) {
332
+ reactNavigation.dispatch(e.data?.action);
333
+ ScreenStore.removeScreen(e.target);
334
+ }
335
+ };
336
+ ScreenStore.updateScreen(e.target, {
337
+ status: 0,
338
+ closing: true,
339
+ onAnimationFinish: handleFinish
340
+ });
341
+ }
342
+ };
343
+ };
344
+ var createScreenConfig = (config) => {
345
+ return {
346
+ listeners: (l) => createConfig({ ...l, ...config || {} })
347
+ };
348
+ };
349
+
350
+ // src/utils/default-screen-options.ts
351
+ var defaultScreenOptions = () => ({
352
+ presentation: "containedTransparentModal",
353
+ headerShown: false,
354
+ animation: "none"
355
+ });
356
+
357
+ // src/utils/noop-interpolator.ts
358
+ var noopinterpolator = () => {
359
+ "worklet";
360
+ return {
361
+ contentStyle: {},
362
+ overlayStyle: {}
363
+ };
364
+ };
434
365
 
435
366
  // src/utils/gesture/apply-gesture-activation-criteria.ts
436
367
  var applyGestureActivationCriteria = ({
@@ -516,153 +447,329 @@ var mapGestureToProgress = (translation, dimension) => {
516
447
  return Math.max(0, Math.min(1, rawProgress));
517
448
  };
518
449
 
519
- // src/utils/gesture/build-gesture-detector.ts
450
+ // src/hooks/use-key.tsx
451
+ var import_native2 = require("@react-navigation/native");
452
+ var useKey = () => (0, import_native2.useRoute)().key;
453
+
454
+ // src/hooks/use-build-gestures.tsx
520
455
  var GESTURE_VELOCITY_IMPACT = 0.3;
521
456
  var DEFAULT_GESTURE_RESPONSE_DISTANCE = 50;
522
- var buildGestureDetector = ({
523
- key,
524
- progress,
525
- screenState,
526
- width,
527
- height,
528
- handleDismiss
457
+ var DEFAULT_GESTURE_DIRECTION = "horizontal";
458
+ var DEFAULT_GESTURE_ENABLED = false;
459
+ var useBuildGestures = ({
460
+ scrollProgress
529
461
  }) => {
530
- const _translateX = animationValues.gestureX[key];
531
- const _translateY = animationValues.gestureY[key];
532
- const _normalizedGestureX = animationValues.normalizedGestureX[key];
533
- const _normalizedGestureY = animationValues.normalizedGestureY[key];
534
- const _isDragging = animationValues.gestureDragging[key];
535
- const {
536
- gestureDirection = "horizontal",
537
- gestureEnabled = false,
538
- transitionSpec,
539
- gestureVelocityImpact = GESTURE_VELOCITY_IMPACT,
540
- gestureResponseDistance = DEFAULT_GESTURE_RESPONSE_DISTANCE
541
- } = screenState;
462
+ const key = useKey();
463
+ const dimensions = (0, import_react_native.useWindowDimensions)();
464
+ const navigation = (0, import_native3.useNavigation)();
465
+ const currentScreen = ScreenStore.use(
466
+ (0, import_react3.useCallback)((state) => state.screens[key], [key])
467
+ );
468
+ const handleDismiss = (0, import_react3.useCallback)(
469
+ (screenBeingDismissed) => {
470
+ ScreenStore.handleScreenDismiss(screenBeingDismissed, navigation);
471
+ },
472
+ [navigation]
473
+ );
474
+ const initialTouch = (0, import_react_native_reanimated4.useSharedValue)({
475
+ x: 0,
476
+ y: 0
477
+ });
478
+ const translateX = animationValues.gestureX[key];
479
+ const translateY = animationValues.gestureY[key];
480
+ const normalizedGestureX = animationValues.normalizedGestureX[key];
481
+ const normalizedGestureY = animationValues.normalizedGestureY[key];
482
+ const isDragging = animationValues.gestureDragging[key];
483
+ const isDismissing = animationValues.isDismissing[key];
484
+ const progress = animationValues.screenProgress[key] || 0;
485
+ const {
486
+ gestureDirection = DEFAULT_GESTURE_DIRECTION,
487
+ gestureEnabled = DEFAULT_GESTURE_ENABLED,
488
+ transitionSpec = {
489
+ open: DefaultSpec,
490
+ close: DefaultSpec
491
+ },
492
+ gestureVelocityImpact = GESTURE_VELOCITY_IMPACT,
493
+ gestureResponseDistance = DEFAULT_GESTURE_RESPONSE_DISTANCE
494
+ } = currentScreen ?? {};
542
495
  const directions = Array.isArray(gestureDirection) ? gestureDirection : [gestureDirection];
543
- const panGesture = import_react_native_gesture_handler.Gesture.Pan().enabled(gestureEnabled).onStart(() => {
544
- "worklet";
545
- _isDragging.value = 1;
546
- }).onUpdate((event) => {
547
- "worklet";
548
- let gestureProgress = 0;
549
- _translateX.value = event.translationX;
550
- _translateY.value = event.translationY;
551
- _normalizedGestureX.value = (0, import_react_native_reanimated4.interpolate)(
552
- event.translationX,
553
- [-width, width],
554
- [-1, 1],
555
- "clamp"
556
- );
557
- _normalizedGestureY.value = (0, import_react_native_reanimated4.interpolate)(
558
- event.translationY,
559
- [-height, height],
560
- [-1, 1],
561
- "clamp"
562
- );
563
- if (directions.includes("bidirectional")) {
564
- const distance = Math.sqrt(
565
- event.translationX ** 2 + event.translationY ** 2
566
- );
567
- gestureProgress = mapGestureToProgress(distance, width);
568
- } else {
569
- let maxProgress = 0;
570
- const allowedDown = directions.includes("vertical");
571
- const allowedUp = directions.includes("vertical-inverted");
572
- const allowedRight = directions.includes("horizontal");
573
- const allowedLeft = directions.includes("horizontal-inverted");
574
- if (allowedRight || allowedLeft) {
575
- const absX = Math.abs(event.translationX);
576
- const currentProgress = mapGestureToProgress(absX, width);
577
- maxProgress = Math.max(maxProgress, currentProgress);
496
+ const nativeGesture = import_react_native_gesture_handler2.Gesture.Native();
497
+ const onTouchesDown = (0, import_react3.useCallback)(
498
+ (e) => {
499
+ "worklet";
500
+ const firstTouch = e.changedTouches[0];
501
+ initialTouch.value = { x: firstTouch.x, y: firstTouch.y };
502
+ },
503
+ [initialTouch]
504
+ );
505
+ const onTouchesMove = (0, import_react3.useCallback)(
506
+ (e, manager) => {
507
+ "worklet";
508
+ const touch = e.changedTouches[0];
509
+ const deltaX = touch.x - initialTouch.value.x;
510
+ const deltaY = touch.y - initialTouch.value.y;
511
+ const isVerticalSwipe = Math.abs(deltaY) > Math.abs(deltaX);
512
+ const isHorizontalSwipe = Math.abs(deltaX) > Math.abs(deltaY);
513
+ const isSwipingDown = isVerticalSwipe && deltaY > 0;
514
+ const isSwipingUp = isVerticalSwipe && deltaY < 0;
515
+ const isSwipingRight = isHorizontalSwipe && deltaX > 0;
516
+ const isSwipingLeft = isHorizontalSwipe && deltaX < 0;
517
+ const minMovement = 5;
518
+ const hasEnoughMovement = Math.abs(deltaX) > minMovement || Math.abs(deltaY) > minMovement;
519
+ if (!hasEnoughMovement) return;
520
+ if (isDragging.value) {
521
+ manager.activate();
522
+ return;
523
+ }
524
+ let shouldActivate = false;
525
+ for (const direction of directions) {
526
+ switch (direction) {
527
+ case "vertical":
528
+ if (isSwipingDown) {
529
+ shouldActivate = scrollProgress.value.y <= 0;
530
+ }
531
+ break;
532
+ case "vertical-inverted":
533
+ if (isSwipingUp) {
534
+ const maxScrollableY = scrollProgress.value.contentHeight - scrollProgress.value.layoutHeight;
535
+ shouldActivate = scrollProgress.value.y >= maxScrollableY;
536
+ }
537
+ break;
538
+ case "horizontal":
539
+ if (isSwipingRight) {
540
+ shouldActivate = scrollProgress.value.x <= 0;
541
+ }
542
+ break;
543
+ case "horizontal-inverted":
544
+ if (isSwipingLeft) {
545
+ const maxProgress = scrollProgress.value.contentWidth - scrollProgress.value.layoutWidth;
546
+ shouldActivate = scrollProgress.value.x >= maxProgress;
547
+ }
548
+ break;
549
+ case "bidirectional":
550
+ if (isSwipingDown) {
551
+ shouldActivate = scrollProgress.value.y <= 0;
552
+ } else if (isSwipingUp) {
553
+ shouldActivate = scrollProgress.value.y <= 0;
554
+ } else if (isSwipingRight || isSwipingLeft) {
555
+ shouldActivate = true;
556
+ }
557
+ break;
558
+ }
559
+ if (shouldActivate) break;
578
560
  }
579
- if (allowedUp || allowedDown) {
580
- const absY = Math.abs(event.translationY);
581
- const currentProgress = mapGestureToProgress(absY, height);
582
- maxProgress = Math.max(maxProgress, currentProgress);
561
+ if ((shouldActivate || isDragging.value) && !isDismissing.value) {
562
+ manager.activate();
563
+ } else {
564
+ manager.fail();
583
565
  }
584
- gestureProgress = maxProgress;
585
- }
586
- progress.value = 1 - gestureProgress;
587
- }).onEnd((event) => {
566
+ },
567
+ [initialTouch, directions, scrollProgress, isDragging, isDismissing]
568
+ );
569
+ const onStart = (0, import_react3.useCallback)(() => {
588
570
  "worklet";
589
- const { translationX, translationY, velocityX, velocityY } = event;
590
- let shouldDismiss = false;
591
- const dismissThreshold = 0.5;
592
- if (directions.includes("bidirectional")) {
593
- const finalX = Math.abs(
594
- translationX + velocityX * gestureVelocityImpact
571
+ isDragging.value = 1;
572
+ isDismissing.value = 0;
573
+ }, [isDragging, isDismissing]);
574
+ const onUpdate = (0, import_react3.useCallback)(
575
+ (event) => {
576
+ "worklet";
577
+ let gestureProgress = 0;
578
+ translateX.value = event.translationX;
579
+ translateY.value = event.translationY;
580
+ normalizedGestureX.value = (0, import_react_native_reanimated4.interpolate)(
581
+ event.translationX,
582
+ [-dimensions.width, dimensions.width],
583
+ [-1, 1],
584
+ "clamp"
595
585
  );
596
- const finalY = Math.abs(
597
- translationY + velocityY * gestureVelocityImpact
586
+ normalizedGestureY.value = (0, import_react_native_reanimated4.interpolate)(
587
+ event.translationY,
588
+ [-dimensions.height, dimensions.height],
589
+ [-1, 1],
590
+ "clamp"
598
591
  );
599
- const finalDistance = Math.sqrt(finalX ** 2 + finalY ** 2);
600
- shouldDismiss = finalDistance > width * dismissThreshold;
601
- } else {
602
- const allowedDown = directions.includes("vertical");
603
- const allowedUp = directions.includes("vertical-inverted");
604
- const allowedRight = directions.includes("horizontal");
605
- const allowedLeft = directions.includes("horizontal-inverted");
606
- if (allowedRight && translationX + velocityX * gestureVelocityImpact > width * dismissThreshold) {
607
- shouldDismiss = true;
608
- } else if (allowedLeft && -translationX - velocityX * gestureVelocityImpact > width * dismissThreshold) {
609
- shouldDismiss = true;
610
- } else if (allowedDown && translationY + velocityY * gestureVelocityImpact > height * dismissThreshold) {
611
- shouldDismiss = true;
612
- } else if (allowedUp && -translationY - velocityY * gestureVelocityImpact > height * dismissThreshold) {
613
- shouldDismiss = true;
592
+ if (directions.includes("bidirectional")) {
593
+ const distance = Math.sqrt(
594
+ event.translationX ** 2 + event.translationY ** 2
595
+ );
596
+ gestureProgress = mapGestureToProgress(distance, dimensions.width);
597
+ } else {
598
+ let maxProgress = 0;
599
+ const allowedDown = directions.includes("vertical");
600
+ const allowedUp = directions.includes("vertical-inverted");
601
+ const allowedRight = directions.includes("horizontal");
602
+ const allowedLeft = directions.includes("horizontal-inverted");
603
+ if (allowedRight && event.translationX > 0) {
604
+ const currentProgress = mapGestureToProgress(
605
+ event.translationX,
606
+ dimensions.width
607
+ );
608
+ maxProgress = Math.max(maxProgress, currentProgress);
609
+ }
610
+ if (allowedLeft && event.translationX < 0) {
611
+ const currentProgress = mapGestureToProgress(
612
+ -event.translationX,
613
+ dimensions.width
614
+ );
615
+ maxProgress = Math.max(maxProgress, currentProgress);
616
+ }
617
+ if (allowedDown && event.translationY > 0) {
618
+ const currentProgress = mapGestureToProgress(
619
+ event.translationY,
620
+ dimensions.height
621
+ );
622
+ maxProgress = Math.max(maxProgress, currentProgress);
623
+ }
624
+ if (allowedUp && event.translationY < 0) {
625
+ const currentProgress = mapGestureToProgress(
626
+ -event.translationY,
627
+ dimensions.height
628
+ );
629
+ maxProgress = Math.max(maxProgress, currentProgress);
630
+ }
631
+ gestureProgress = maxProgress;
614
632
  }
615
- }
616
- const finalProgress = shouldDismiss ? 0 : 1;
617
- const spec = shouldDismiss ? transitionSpec?.close : transitionSpec?.open;
618
- const onFinish = shouldDismiss ? (isFinished) => {
633
+ progress.value = 1 - gestureProgress;
634
+ },
635
+ [
636
+ dimensions,
637
+ directions,
638
+ translateX,
639
+ translateY,
640
+ normalizedGestureX,
641
+ normalizedGestureY,
642
+ progress
643
+ ]
644
+ );
645
+ const onEnd = (0, import_react3.useCallback)(
646
+ (event) => {
619
647
  "worklet";
620
- if (isFinished) (0, import_react_native_reanimated4.runOnJS)(handleDismiss)(screenState.id);
621
- } : void 0;
622
- progress.value = animate(finalProgress, spec, onFinish);
623
- _translateX.value = animate(0, spec);
624
- _translateY.value = animate(0, spec);
625
- _normalizedGestureX.value = animate(0, spec);
626
- _normalizedGestureY.value = animate(0, spec);
627
- });
648
+ const { translationX, translationY, velocityX, velocityY } = event;
649
+ const dismissThreshold = 0.5;
650
+ if (directions.includes("bidirectional")) {
651
+ const finalX = Math.abs(
652
+ translationX + velocityX * gestureVelocityImpact
653
+ );
654
+ const finalY = Math.abs(
655
+ translationY + velocityY * gestureVelocityImpact
656
+ );
657
+ const finalDistance = Math.sqrt(finalX ** 2 + finalY ** 2);
658
+ isDismissing.value = Number(
659
+ finalDistance > dimensions.width * dismissThreshold
660
+ );
661
+ } else {
662
+ const allowedDown = directions.includes("vertical");
663
+ const allowedUp = directions.includes("vertical-inverted");
664
+ const allowedRight = directions.includes("horizontal");
665
+ const allowedLeft = directions.includes("horizontal-inverted");
666
+ if (allowedRight && translationX + velocityX * gestureVelocityImpact > dimensions.width * dismissThreshold) {
667
+ isDismissing.value = 1;
668
+ } else if (allowedLeft && -translationX - velocityX * gestureVelocityImpact > dimensions.width * dismissThreshold) {
669
+ isDismissing.value = 1;
670
+ } else if (allowedDown && translationY + velocityY * gestureVelocityImpact > dimensions.height * dismissThreshold) {
671
+ isDismissing.value = 1;
672
+ } else if (allowedUp && -translationY - velocityY * gestureVelocityImpact > dimensions.height * dismissThreshold) {
673
+ isDismissing.value = 1;
674
+ }
675
+ }
676
+ const finalProgress = isDismissing.value ? 0 : 1;
677
+ const spec = isDismissing.value ? transitionSpec?.close : transitionSpec?.open;
678
+ const onFinish = isDismissing.value ? (isFinished) => {
679
+ "worklet";
680
+ if (isFinished) (0, import_react_native_reanimated4.runOnJS)(handleDismiss)(currentScreen?.id);
681
+ } : void 0;
682
+ progress.value = animate(finalProgress, spec, onFinish);
683
+ translateX.value = animate(0, spec);
684
+ translateY.value = animate(0, spec);
685
+ normalizedGestureX.value = animate(0, spec);
686
+ normalizedGestureY.value = animate(0, spec);
687
+ isDragging.value = 0;
688
+ },
689
+ [
690
+ dimensions,
691
+ directions,
692
+ translateX,
693
+ translateY,
694
+ normalizedGestureX,
695
+ normalizedGestureY,
696
+ progress,
697
+ handleDismiss,
698
+ currentScreen?.id,
699
+ transitionSpec?.close,
700
+ transitionSpec?.open,
701
+ gestureVelocityImpact,
702
+ isDragging,
703
+ isDismissing
704
+ ]
705
+ );
706
+ const panGesture = (0, import_react3.useMemo)(
707
+ () => import_react_native_gesture_handler2.Gesture.Pan().enabled(gestureEnabled).manualActivation(true).onTouchesDown(onTouchesDown).onTouchesMove(onTouchesMove).onStart(onStart).onUpdate(onUpdate).onEnd(onEnd).blocksExternalGesture(nativeGesture),
708
+ [
709
+ gestureEnabled,
710
+ nativeGesture,
711
+ onTouchesDown,
712
+ onTouchesMove,
713
+ onStart,
714
+ onUpdate,
715
+ onEnd
716
+ ]
717
+ );
628
718
  applyGestureActivationCriteria({
629
719
  gestureDirection,
630
720
  gestureResponseDistance,
631
721
  panGesture
632
722
  });
633
- return panGesture;
723
+ return { panGesture, nativeGesture };
634
724
  };
635
725
 
636
- // src/utils/noop-interpolator.ts
637
- var noopinterpolator = () => {
638
- "worklet";
639
- return {
640
- contentStyle: {},
641
- overlayStyle: {}
642
- };
726
+ // src/components/transition-gesture-handler-provider.tsx
727
+ var import_jsx_runtime = require("react/jsx-runtime");
728
+ var TransitionGestureHandlerProvider = ({
729
+ children
730
+ }) => {
731
+ const scrollProgress = (0, import_react_native_reanimated5.useSharedValue)({
732
+ x: 0,
733
+ y: 0,
734
+ contentHeight: 0,
735
+ contentWidth: 0,
736
+ layoutHeight: 0,
737
+ layoutWidth: 0
738
+ });
739
+ const { panGesture, nativeGesture } = useBuildGestures({
740
+ scrollProgress
741
+ });
742
+ const value = (0, import_react4.useMemo)(() => {
743
+ return {
744
+ panGesture,
745
+ scrollProgress,
746
+ nativeGesture
747
+ };
748
+ }, [panGesture, scrollProgress, nativeGesture]);
749
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GestureContext.Provider, { value, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native_gesture_handler3.GestureDetector, { gesture: panGesture, children }) });
643
750
  };
644
751
 
645
- // src/hooks/use-key.tsx
646
- var import_native2 = require("@react-navigation/native");
647
- var useKey = () => (0, import_native2.useRoute)().key;
648
-
649
752
  // src/hooks/use-screen-animation.tsx
753
+ var import_react5 = require("react");
754
+ var import_react_native2 = require("react-native");
755
+ var import_react_native_reanimated6 = require("react-native-reanimated");
756
+ var import_react_native_safe_area_context = require("react-native-safe-area-context");
650
757
  var useAnimationBuilder = () => {
651
758
  const key = useKey();
652
- const dimensions = (0, import_react_native.useWindowDimensions)();
759
+ const dimensions = (0, import_react_native2.useWindowDimensions)();
653
760
  const insets = (0, import_react_native_safe_area_context.useSafeAreaInsets)();
654
- const navigation = (0, import_native3.useNavigation)();
655
- const progressFallback = (0, import_react_native_reanimated5.useSharedValue)(0);
656
- const gestureDraggingFallback = (0, import_react_native_reanimated5.useSharedValue)(0);
657
- const gestureXFallback = (0, import_react_native_reanimated5.useSharedValue)(0);
658
- const gestureYFallback = (0, import_react_native_reanimated5.useSharedValue)(0);
659
- const normalizedGestureXFallback = (0, import_react_native_reanimated5.useSharedValue)(0);
660
- const normalizedGestureYFallback = (0, import_react_native_reanimated5.useSharedValue)(0);
761
+ const progressFallback = (0, import_react_native_reanimated6.useSharedValue)(0);
762
+ const gestureDraggingFallback = (0, import_react_native_reanimated6.useSharedValue)(0);
763
+ const gestureXFallback = (0, import_react_native_reanimated6.useSharedValue)(0);
764
+ const gestureYFallback = (0, import_react_native_reanimated6.useSharedValue)(0);
765
+ const normalizedGestureXFallback = (0, import_react_native_reanimated6.useSharedValue)(0);
766
+ const normalizedGestureYFallback = (0, import_react_native_reanimated6.useSharedValue)(0);
767
+ const isDismissingFallback = (0, import_react_native_reanimated6.useSharedValue)(0);
661
768
  const currentScreen = ScreenStore.use(
662
- (0, import_react2.useCallback)((state) => state.screens[key], [key])
769
+ (0, import_react5.useCallback)((state) => state.screens[key], [key])
663
770
  );
664
771
  const actualNextScreen = ScreenStore.use(
665
- (0, import_react2.useCallback)(
772
+ (0, import_react5.useCallback)(
666
773
  (state) => {
667
774
  const current = state.screens[key];
668
775
  if (!current) return void 0;
@@ -674,26 +781,7 @@ var useAnimationBuilder = () => {
674
781
  [key]
675
782
  )
676
783
  );
677
- const panGesture = (0, import_react2.useMemo)(
678
- () => buildGestureDetector({
679
- key,
680
- progress: animationValues.screenProgress[key],
681
- screenState: currentScreen || {
682
- id: key,
683
- name: key,
684
- index: 0,
685
- status: 0,
686
- closing: false
687
- },
688
- width: dimensions.width,
689
- height: dimensions.height,
690
- handleDismiss: (screenBeingDismissed) => {
691
- ScreenStore.handleScreenDismiss(screenBeingDismissed, navigation);
692
- }
693
- }),
694
- [key, currentScreen, dimensions, navigation]
695
- );
696
- const getAnimationValuesForScreen = (0, import_react2.useCallback)(
784
+ const getAnimationValuesForScreen = (0, import_react5.useCallback)(
697
785
  (screenId) => ({
698
786
  progress: animationValues.screenProgress[screenId] || progressFallback,
699
787
  gesture: {
@@ -701,7 +789,8 @@ var useAnimationBuilder = () => {
701
789
  x: animationValues.gestureX[screenId] || gestureXFallback,
702
790
  y: animationValues.gestureY[screenId] || gestureYFallback,
703
791
  normalizedX: animationValues.normalizedGestureX[screenId] || normalizedGestureXFallback,
704
- normalizedY: animationValues.normalizedGestureY[screenId] || normalizedGestureYFallback
792
+ normalizedY: animationValues.normalizedGestureY[screenId] || normalizedGestureYFallback,
793
+ isDismissing: animationValues.isDismissing[screenId] || isDismissingFallback
705
794
  }
706
795
  }),
707
796
  [
@@ -710,18 +799,18 @@ var useAnimationBuilder = () => {
710
799
  gestureXFallback,
711
800
  gestureYFallback,
712
801
  normalizedGestureXFallback,
713
- normalizedGestureYFallback
802
+ normalizedGestureYFallback,
803
+ isDismissingFallback
714
804
  ]
715
805
  );
716
- return (0, import_react2.useMemo)(() => {
806
+ return (0, import_react5.useMemo)(() => {
717
807
  return {
718
808
  current: getAnimationValuesForScreen(key),
719
809
  next: actualNextScreen ? getAnimationValuesForScreen(actualNextScreen.id) : void 0,
720
810
  layouts: { screen: dimensions },
721
811
  insets,
722
812
  closing: currentScreen?.closing || false,
723
- screenStyleInterpolator: actualNextScreen?.screenStyleInterpolator || currentScreen?.screenStyleInterpolator || noopinterpolator,
724
- gestureDetector: panGesture
813
+ screenStyleInterpolator: actualNextScreen?.screenStyleInterpolator || currentScreen?.screenStyleInterpolator || noopinterpolator
725
814
  };
726
815
  }, [
727
816
  key,
@@ -729,7 +818,6 @@ var useAnimationBuilder = () => {
729
818
  actualNextScreen,
730
819
  dimensions,
731
820
  insets,
732
- panGesture,
733
821
  getAnimationValuesForScreen
734
822
  ]);
735
823
  };
@@ -737,78 +825,22 @@ var _useScreenAnimation = () => {
737
825
  return useAnimationBuilder();
738
826
  };
739
827
  var useScreenAnimation = () => {
740
- const {
741
- screenStyleInterpolator: _,
742
- gestureDetector: __,
743
- ...animationProps
744
- } = useAnimationBuilder();
828
+ const { screenStyleInterpolator: _, ...animationProps } = useAnimationBuilder();
745
829
  return animationProps;
746
830
  };
747
831
 
748
- // src/utils/create-config.ts
749
- var createConfig = ({
750
- navigation: reactNavigation,
751
- route,
752
- ...config
753
- }) => {
754
- return {
755
- focus: (e) => {
756
- const parentNavigatorKey = reactNavigation.getParent()?.getState?.()?.key;
757
- const navigatorKey = reactNavigation.getState().key;
758
- ScreenStore.updateScreen(e.target, {
759
- id: e.target,
760
- name: route.name,
761
- status: 1,
762
- closing: false,
763
- navigatorKey,
764
- parentNavigatorKey,
765
- ...config
766
- });
767
- },
768
- beforeRemove: (e) => {
769
- const shouldSkipPreventDefault2 = ScreenStore.shouldSkipPreventDefault(
770
- e.target,
771
- reactNavigation.getState()
772
- );
773
- if (shouldSkipPreventDefault2) {
774
- ScreenStore.removeScreen(e.target);
775
- return;
776
- }
777
- e.preventDefault();
778
- const handleFinish = (finished) => {
779
- if (!finished) return;
780
- if (reactNavigation.canGoBack()) {
781
- reactNavigation.dispatch(e.data?.action);
782
- ScreenStore.removeScreen(e.target);
783
- }
784
- };
785
- ScreenStore.updateScreen(e.target, {
786
- status: 0,
787
- closing: true,
788
- onAnimationFinish: handleFinish
789
- });
790
- }
791
- };
792
- };
793
-
794
- // src/utils/create-transition-component.tsx
795
- var import_react4 = require("react");
796
- var import_react_native2 = require("react-native");
797
- var import_react_native_gesture_handler2 = require("react-native-gesture-handler");
798
- var import_react_native_reanimated7 = __toESM(require("react-native-reanimated"));
799
-
800
832
  // src/hooks/use-skip-first-frame.tsx
801
- var import_react3 = require("react");
802
- var import_react_native_reanimated6 = require("react-native-reanimated");
833
+ var import_react6 = require("react");
834
+ var import_react_native_reanimated7 = require("react-native-reanimated");
803
835
  var useSkipFirstFrame = () => {
804
- const opacity = (0, import_react_native_reanimated6.useSharedValue)(0);
805
- const style = (0, import_react_native_reanimated6.useAnimatedStyle)(() => {
836
+ const opacity = (0, import_react_native_reanimated7.useSharedValue)(0);
837
+ const style = (0, import_react_native_reanimated7.useAnimatedStyle)(() => {
806
838
  "worklet";
807
839
  return {
808
840
  opacity: opacity.value
809
841
  };
810
842
  });
811
- (0, import_react3.useEffect)(() => {
843
+ (0, import_react6.useEffect)(() => {
812
844
  requestAnimationFrame(() => {
813
845
  opacity.value = 1;
814
846
  });
@@ -816,29 +848,32 @@ var useSkipFirstFrame = () => {
816
848
  return { style };
817
849
  };
818
850
 
819
- // src/utils/create-transition-component.tsx
820
- var import_jsx_runtime = require("react/jsx-runtime");
821
- function createTransitionComponent(Wrapped) {
822
- const AnimatedComponent = import_react_native_reanimated7.default.createAnimatedComponent(Wrapped);
823
- const Inner = (0, import_react4.forwardRef)(
851
+ // src/components/create-transition-aware-component.tsx
852
+ var import_jsx_runtime2 = require("react/jsx-runtime");
853
+ function createTransitionAwareComponent(Wrapped) {
854
+ const AnimatedComponent = import_react_native_reanimated8.default.createAnimatedComponent(Wrapped);
855
+ const Inner = (0, import_react7.forwardRef)(
824
856
  (props, ref) => {
825
857
  const { children, style, ...rest } = props;
826
- const {
827
- screenStyleInterpolator,
828
- gestureDetector,
829
- ...screenInterpolationProps
830
- } = _useScreenAnimation();
831
- const screenContainerStyle = (0, import_react_native_reanimated7.useAnimatedStyle)(() => {
858
+ const { screenStyleInterpolator, ...screenInterpolationProps } = _useScreenAnimation();
859
+ const screenContainerStyle = (0, import_react_native_reanimated8.useAnimatedStyle)(() => {
832
860
  "worklet";
833
861
  return screenStyleInterpolator(screenInterpolationProps).contentStyle || {};
834
862
  });
835
- const overlayStyle = (0, import_react_native_reanimated7.useAnimatedStyle)(() => {
863
+ const overlayStyle = (0, import_react_native_reanimated8.useAnimatedStyle)(() => {
836
864
  "worklet";
837
865
  return screenStyleInterpolator(screenInterpolationProps).overlayStyle || {};
838
866
  });
839
867
  const { style: flickerFixStyle } = useSkipFirstFrame();
840
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native_reanimated7.default.View, { style: [{ flex: 1 }, flickerFixStyle], children: [
841
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native_gesture_handler2.GestureDetector, { gesture: gestureDetector, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
868
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(TransitionGestureHandlerProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native_reanimated8.default.View, { style: [{ flex: 1 }, flickerFixStyle], children: [
869
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
870
+ import_react_native_reanimated8.default.View,
871
+ {
872
+ style: [import_react_native3.StyleSheet.absoluteFillObject, overlayStyle],
873
+ pointerEvents: "none"
874
+ }
875
+ ),
876
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
842
877
  AnimatedComponent,
843
878
  {
844
879
  ...rest,
@@ -850,41 +885,282 @@ function createTransitionComponent(Wrapped) {
850
885
  ],
851
886
  children
852
887
  }
853
- ) }),
854
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
855
- import_react_native_reanimated7.default.View,
856
- {
857
- style: [
858
- import_react_native2.StyleSheet.absoluteFillObject,
859
- overlayStyle,
860
- { zIndex: 1e4 }
861
- ],
862
- pointerEvents: "none"
863
- }
864
888
  )
865
- ] });
889
+ ] }) });
866
890
  }
867
891
  );
868
892
  Inner.displayName = `Transition(${Wrapped.displayName || Wrapped.name || "Component"})`;
869
- return (0, import_react4.memo)(Inner);
893
+ return (0, import_react7.memo)(Inner);
870
894
  }
871
895
 
872
- // src/utils/default-screen-options.ts
873
- var defaultScreenOptions = () => ({
874
- presentation: "containedTransparentModal",
875
- headerShown: false,
876
- animation: "none"
896
+ // src/components/create-transition-aware-scrollable.tsx
897
+ var import_react9 = require("react");
898
+ var import_react_native4 = require("react-native");
899
+ var import_react_native_gesture_handler4 = require("react-native-gesture-handler");
900
+ var import_react_native_reanimated10 = __toESM(require("react-native-reanimated"));
901
+
902
+ // src/hooks/use-scroll-progress.tsx
903
+ var import_react8 = require("react");
904
+ var import_react_native_reanimated9 = require("react-native-reanimated");
905
+ var useScrollProgress = (props) => {
906
+ const { scrollProgress } = useGestureContext();
907
+ const scrollHandler = (0, import_react_native_reanimated9.useAnimatedScrollHandler)({
908
+ onScroll: (event) => {
909
+ scrollProgress.modify((value) => {
910
+ "worklet";
911
+ return {
912
+ ...value,
913
+ x: event.contentOffset.x,
914
+ y: event.contentOffset.y,
915
+ layoutHeight: event.layoutMeasurement.height,
916
+ layoutWidth: event.layoutMeasurement.width,
917
+ contentHeight: event.contentSize.height,
918
+ contentWidth: event.contentSize.width
919
+ };
920
+ });
921
+ }
922
+ });
923
+ const onContentSizeChange = (0, import_react8.useCallback)(
924
+ (width, height) => {
925
+ props.onContentSizeChange?.(width, height);
926
+ scrollProgress.modify((value) => {
927
+ "worklet";
928
+ return {
929
+ ...value,
930
+ contentWidth: width,
931
+ contentHeight: height
932
+ };
933
+ });
934
+ },
935
+ [scrollProgress, props.onContentSizeChange]
936
+ );
937
+ return {
938
+ scrollHandler,
939
+ onContentSizeChange
940
+ };
941
+ };
942
+
943
+ // src/components/create-transition-aware-scrollable.tsx
944
+ var import_jsx_runtime3 = require("react/jsx-runtime");
945
+ function createTransitionAwareScrollable(ScrollableComponent) {
946
+ const WithTransitionAwareness = createTransitionAwareComponent(import_react_native4.View);
947
+ const AnimatedScrollableComponent = import_react_native_reanimated10.default.createAnimatedComponent(ScrollableComponent);
948
+ const WithScrollAwareness = (0, import_react9.forwardRef)((props, ref) => {
949
+ const { nativeGesture } = useGestureContext();
950
+ const { scrollHandler, onContentSizeChange } = useScrollProgress({
951
+ onScroll: props.onScroll,
952
+ onContentSizeChange: props.onContentSizeChange
953
+ });
954
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_gesture_handler4.GestureDetector, { gesture: nativeGesture, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
955
+ AnimatedScrollableComponent,
956
+ {
957
+ ...props,
958
+ ref,
959
+ onScroll: scrollHandler,
960
+ onContentSizeChange,
961
+ scrollEventThrottle: props.scrollEventThrottle || 16
962
+ }
963
+ ) });
964
+ });
965
+ const Wrapped = (0, import_react9.forwardRef)((props, ref) => {
966
+ const { isPlaceholder } = useGestureContext();
967
+ if (isPlaceholder) {
968
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(WithTransitionAwareness, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(WithScrollAwareness, { ...props, ref }) });
969
+ }
970
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(WithScrollAwareness, { ...props, ref });
971
+ });
972
+ WithScrollAwareness.displayName = `Transition(${ScrollableComponent.displayName || ScrollableComponent.name || "Component"})`;
973
+ return (0, import_react9.memo)(Wrapped);
974
+ }
975
+
976
+ // src/configs/presets.ts
977
+ var presets_exports = {};
978
+ __export(presets_exports, {
979
+ DraggableCard: () => DraggableCard,
980
+ ElasticCard: () => ElasticCard,
981
+ SlideFromBottom: () => SlideFromBottom,
982
+ SlideFromTop: () => SlideFromTop,
983
+ ZoomIn: () => ZoomIn
877
984
  });
985
+ var import_react_native_reanimated11 = require("react-native-reanimated");
986
+ var SlideFromTop = (config = {}) => {
987
+ return {
988
+ gestureEnabled: true,
989
+ gestureDirection: "vertical-inverted",
990
+ screenStyleInterpolator: ({
991
+ current,
992
+ next,
993
+ layouts: {
994
+ screen: { height }
995
+ }
996
+ }) => {
997
+ "worklet";
998
+ const progress = current.progress.value + (next?.progress.value ?? 0);
999
+ const y = (0, import_react_native_reanimated11.interpolate)(progress, [0, 1, 2], [-height, 0, height]);
1000
+ return {
1001
+ contentStyle: {
1002
+ transform: [{ translateY: y }]
1003
+ }
1004
+ };
1005
+ },
1006
+ transitionSpec: {
1007
+ open: DefaultSpec,
1008
+ close: DefaultSpec
1009
+ },
1010
+ ...config
1011
+ };
1012
+ };
1013
+ var ZoomIn = (config = {}) => {
1014
+ return {
1015
+ gestureEnabled: false,
1016
+ screenStyleInterpolator: ({ current, next }) => {
1017
+ "worklet";
1018
+ const progress = current.progress.value + (next?.progress.value ?? 0);
1019
+ const scale = (0, import_react_native_reanimated11.interpolate)(
1020
+ progress,
1021
+ [0, 1, 2],
1022
+ [0.5, 1, 0.5],
1023
+ import_react_native_reanimated11.Extrapolation.CLAMP
1024
+ );
1025
+ const opacity = (0, import_react_native_reanimated11.interpolate)(
1026
+ progress,
1027
+ [0, 1, 2],
1028
+ [0, 1, 0],
1029
+ import_react_native_reanimated11.Extrapolation.CLAMP
1030
+ );
1031
+ return {
1032
+ contentStyle: {
1033
+ transform: [{ scale }],
1034
+ opacity
1035
+ }
1036
+ };
1037
+ },
1038
+ transitionSpec: {
1039
+ open: DefaultSpec,
1040
+ close: DefaultSpec
1041
+ },
1042
+ ...config
1043
+ };
1044
+ };
1045
+ var SlideFromBottom = (config = {}) => {
1046
+ return {
1047
+ gestureEnabled: true,
1048
+ gestureDirection: "vertical",
1049
+ screenStyleInterpolator: ({
1050
+ current,
1051
+ next,
1052
+ layouts: {
1053
+ screen: { height }
1054
+ }
1055
+ }) => {
1056
+ "worklet";
1057
+ const progress = current.progress.value + (next?.progress.value ?? 0);
1058
+ const y = (0, import_react_native_reanimated11.interpolate)(progress, [0, 1, 2], [height, 0, -height]);
1059
+ return {
1060
+ contentStyle: {
1061
+ transform: [{ translateY: y }]
1062
+ }
1063
+ };
1064
+ },
1065
+ transitionSpec: {
1066
+ open: DefaultSpec,
1067
+ close: DefaultSpec
1068
+ },
1069
+ ...config
1070
+ };
1071
+ };
1072
+ var DraggableCard = (config = {}) => {
1073
+ return {
1074
+ gestureEnabled: true,
1075
+ gestureDirection: ["horizontal", "vertical"],
1076
+ screenStyleInterpolator: ({ current, next, layouts: { screen } }) => {
1077
+ "worklet";
1078
+ const progress = current.progress.value + (next?.progress.value ?? 0);
1079
+ const scale = (0, import_react_native_reanimated11.interpolate)(progress, [0, 1, 2], [0, 1, 0.75]);
1080
+ const translateY = (0, import_react_native_reanimated11.interpolate)(
1081
+ current.gesture.normalizedY.value,
1082
+ [-1, 1],
1083
+ [-screen.height * 0.5, screen.height * 0.5],
1084
+ "clamp"
1085
+ );
1086
+ const translateX = (0, import_react_native_reanimated11.interpolate)(
1087
+ current.gesture.normalizedX.value,
1088
+ [-1, 1],
1089
+ [-screen.width * 0.5, screen.width * 0.5],
1090
+ "clamp"
1091
+ );
1092
+ return {
1093
+ contentStyle: {
1094
+ transform: [{ scale }, { translateY }, { translateX }]
1095
+ }
1096
+ };
1097
+ },
1098
+ transitionSpec: {
1099
+ open: DefaultSpec,
1100
+ close: DefaultSpec
1101
+ },
1102
+ ...config
1103
+ };
1104
+ };
1105
+ var ElasticCard = (config = { elasticFactor: 0.5 }) => {
1106
+ return {
1107
+ gestureEnabled: true,
1108
+ gestureDirection: "bidirectional",
1109
+ screenStyleInterpolator: ({ current, next, layouts: { screen } }) => {
1110
+ "worklet";
1111
+ const progress = current.progress.value + (next?.progress.value ?? 0);
1112
+ const scale = (0, import_react_native_reanimated11.interpolate)(progress, [0, 1, 2], [0, 1, 0.8]);
1113
+ const maxElasticityX = screen.width * (config.elasticFactor ?? 0.5);
1114
+ const maxElasticityY = screen.height * (config.elasticFactor ?? 0.5);
1115
+ const translateX = (0, import_react_native_reanimated11.interpolate)(
1116
+ current.gesture.normalizedX.value,
1117
+ [-1, 0, 1],
1118
+ [-maxElasticityX, 0, maxElasticityX],
1119
+ "clamp"
1120
+ );
1121
+ const translateY = (0, import_react_native_reanimated11.interpolate)(
1122
+ current.gesture.normalizedY.value,
1123
+ [-1, 0, 1],
1124
+ [-maxElasticityY, 0, maxElasticityY],
1125
+ "clamp"
1126
+ );
1127
+ const overlayColor = (0, import_react_native_reanimated11.interpolateColor)(
1128
+ next?.progress.value || 0,
1129
+ [0, 1],
1130
+ ["rgba(0,0,0,0)", "rgba(0,0,0,0.5)"]
1131
+ );
1132
+ return {
1133
+ contentStyle: {
1134
+ transform: [{ scale }, { translateX }, { translateY }]
1135
+ },
1136
+ overlayStyle: {
1137
+ backgroundColor: overlayColor
1138
+ }
1139
+ };
1140
+ },
1141
+ ...config
1142
+ };
1143
+ };
878
1144
 
879
1145
  // src/index.ts
880
1146
  var index_default = {
881
- createTransitionComponent,
882
- View: createTransitionComponent(import_react_native3.View),
883
- Pressable: createTransitionComponent(import_react_native3.Pressable),
1147
+ View: createTransitionAwareComponent(import_react_native5.View),
1148
+ Pressable: createTransitionAwareComponent(import_react_native5.Pressable),
1149
+ ScrollView: createTransitionAwareScrollable(import_react_native5.ScrollView),
1150
+ FlatList: createTransitionAwareScrollable(import_react_native5.FlatList),
884
1151
  createConfig,
1152
+ createScreenConfig,
885
1153
  defaultScreenOptions,
886
1154
  presets: presets_exports,
887
- specs: specs_exports
1155
+ specs: specs_exports,
1156
+ /**
1157
+ * Create a transition aware component
1158
+ */
1159
+ createTransitionAwareComponent,
1160
+ /**
1161
+ * Create a transition aware scrollable component
1162
+ */
1163
+ createTransitionAwareScrollable
888
1164
  };
889
1165
  // Annotate the CommonJS export names for ESM import in node:
890
1166
  0 && (module.exports = {