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