react-native-morph-card 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/android/src/main/java/com/melivalesca/morphcard/MorphCardSourceManager.kt +8 -0
- package/android/src/main/java/com/melivalesca/morphcard/MorphCardSourceView.kt +47 -5
- package/android/src/main/java/com/melivalesca/morphcard/MorphCardTargetView.kt +16 -0
- package/ios/Fabric/RNCMorphCardSourceComponentView.mm +96 -9
- package/lib/commonjs/MorphCardSource.js +4 -0
- package/lib/commonjs/MorphCardSource.js.map +1 -1
- package/lib/commonjs/specs/NativeMorphCardSource.js.map +1 -1
- package/lib/module/MorphCardSource.js +4 -0
- package/lib/module/MorphCardSource.js.map +1 -1
- package/lib/module/specs/NativeMorphCardSource.js.map +1 -1
- package/lib/typescript/src/MorphCardSource.d.ts +5 -1
- package/lib/typescript/src/MorphCardSource.d.ts.map +1 -1
- package/lib/typescript/src/specs/NativeMorphCardSource.d.ts +2 -0
- package/lib/typescript/src/specs/NativeMorphCardSource.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/MorphCardSource.tsx +7 -1
- package/src/specs/NativeMorphCardSource.ts +2 -0
package/README.md
CHANGED
|
@@ -111,6 +111,8 @@ Wraps the card content on the list/grid screen. Captures a snapshot and drives t
|
|
|
111
111
|
| `duration` | `number` | `300` | Default animation duration in ms (used for both expand and collapse if specific durations are not set) |
|
|
112
112
|
| `expandDuration` | `number` | — | Duration of the expand animation in ms. Overrides `duration` for expand. |
|
|
113
113
|
| `resizeMode` | `'cover' \| 'contain' \| 'stretch'` | `'cover'` | How the snapshot scales during animation. When set, the bitmap is kept after expand (no live children). **Recommended when wrapping an `<Image>` — without it, the image may not scale properly during the animation.** |
|
|
114
|
+
| `rotations` | `number` | `0` | Number of full 360° rotations during the expand animation |
|
|
115
|
+
| `rotationEndAngle`| `number` | `0` | Final rotation angle in degrees after expand (e.g. `45` to end tilted). Collapse reverses it back to 0 |
|
|
114
116
|
| `onPress` | `(sourceTag: number) => void` | — | Called on tap with the native view tag. Use this to navigate to the detail screen. |
|
|
115
117
|
|
|
116
118
|
### `<MorphCardTarget>`
|
|
@@ -38,6 +38,14 @@ class MorphCardSourceManager :
|
|
|
38
38
|
view.borderRadiusDp = value.toFloat()
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
override fun setRotations(view: MorphCardSourceView, value: Double) {
|
|
42
|
+
view.rotations = value
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
override fun setRotationEndAngle(view: MorphCardSourceView, value: Double) {
|
|
46
|
+
view.rotationEndAngle = value
|
|
47
|
+
}
|
|
48
|
+
|
|
41
49
|
companion object {
|
|
42
50
|
const val REACT_CLASS = "RNCMorphCardSource"
|
|
43
51
|
}
|
|
@@ -33,6 +33,8 @@ class MorphCardSourceView(context: Context) : ReactViewGroup(context) {
|
|
|
33
33
|
var expandDuration: Double = 0.0
|
|
34
34
|
var scaleMode: String = "aspectFill"
|
|
35
35
|
var borderRadiusDp: Float = 0f
|
|
36
|
+
var rotations: Double = 0.0
|
|
37
|
+
var rotationEndAngle: Double = 0.0
|
|
36
38
|
|
|
37
39
|
// ── Target config (set by module, in dp from JS) ──
|
|
38
40
|
var pendingTargetWidth: Float = 0f
|
|
@@ -527,6 +529,8 @@ class MorphCardSourceView(context: Context) : ReactViewGroup(context) {
|
|
|
527
529
|
imageFrameForScaleMode(scaleMode, cardWidth, cardHeight, targetWidthPx, targetHeightPx)
|
|
528
530
|
} else null
|
|
529
531
|
|
|
532
|
+
val totalAngle = (rotations * 360.0 + rotationEndAngle).toFloat()
|
|
533
|
+
|
|
530
534
|
val animator = ValueAnimator.ofFloat(0f, 1f)
|
|
531
535
|
animator.duration = dur
|
|
532
536
|
animator.interpolator = springInterpolator
|
|
@@ -541,6 +545,7 @@ class MorphCardSourceView(context: Context) : ReactViewGroup(context) {
|
|
|
541
545
|
lp.height = lerp(cardHeight, targetHeightPx, t).toInt()
|
|
542
546
|
cardWrapper.layoutParams = lp
|
|
543
547
|
setRoundedCorners(cardWrapper, lerp(cardCornerRadiusPx, targetCornerRadiusPx, t))
|
|
548
|
+
cardWrapper.rotation = lerp(0f, totalAngle, t)
|
|
544
549
|
|
|
545
550
|
if (content != null) {
|
|
546
551
|
if (hasWrapper) {
|
|
@@ -591,6 +596,11 @@ class MorphCardSourceView(context: Context) : ReactViewGroup(context) {
|
|
|
591
596
|
}
|
|
592
597
|
this@MorphCardSourceView.alpha = 1f
|
|
593
598
|
|
|
599
|
+
// Apply end rotation to target view
|
|
600
|
+
if (rotationEndAngle != 0.0) {
|
|
601
|
+
targetView?.rotation = rotationEndAngle.toFloat()
|
|
602
|
+
}
|
|
603
|
+
|
|
594
604
|
transferSnapshotToTarget(decorView, wrapper, targetView,
|
|
595
605
|
targetWidthPx, targetHeightPx, targetCornerRadiusPx, 200L)
|
|
596
606
|
|
|
@@ -718,6 +728,7 @@ class MorphCardSourceView(context: Context) : ReactViewGroup(context) {
|
|
|
718
728
|
var wrapper = overlayContainer
|
|
719
729
|
if (wrapper == null) {
|
|
720
730
|
val target = targetView as? MorphCardTargetView
|
|
731
|
+
// Read position BEFORE clearing rotation — visual position depends on rotation
|
|
721
732
|
val targetLoc = if (targetView != null) getLocationInWindow(targetView) else intArrayOf(cardLeft.toInt(), cardTop.toInt())
|
|
722
733
|
val twPx = if (pendingTargetWidth > 0) pendingTargetWidth * d else cardWidth
|
|
723
734
|
val thPx = if (pendingTargetHeight > 0) pendingTargetHeight * d else cardHeight
|
|
@@ -728,13 +739,15 @@ class MorphCardSourceView(context: Context) : ReactViewGroup(context) {
|
|
|
728
739
|
val cardImage = captureSnapshot()
|
|
729
740
|
alpha = 0f
|
|
730
741
|
|
|
731
|
-
// Clear the snapshot
|
|
732
|
-
// don't show behind the animating collapse overlay
|
|
742
|
+
// Clear the snapshot from the target
|
|
733
743
|
target?.clearSnapshot()
|
|
734
|
-
|
|
744
|
+
|
|
745
|
+
// Use target view's actual size if available for exact match
|
|
746
|
+
val wrapW = if (targetView != null && targetView.width > 0) targetView.width.toFloat() else twPx
|
|
747
|
+
val wrapH = if (targetView != null && targetView.height > 0) targetView.height.toFloat() else thPx
|
|
735
748
|
|
|
736
749
|
wrapper = FrameLayout(context)
|
|
737
|
-
wrapper.layoutParams = FrameLayout.LayoutParams(
|
|
750
|
+
wrapper.layoutParams = FrameLayout.LayoutParams(wrapW.toInt(), wrapH.toInt())
|
|
738
751
|
wrapper.x = targetLoc[0].toFloat()
|
|
739
752
|
wrapper.y = targetLoc[1].toFloat()
|
|
740
753
|
wrapper.clipChildren = true
|
|
@@ -764,8 +777,23 @@ class MorphCardSourceView(context: Context) : ReactViewGroup(context) {
|
|
|
764
777
|
}
|
|
765
778
|
|
|
766
779
|
wrapper.addView(content)
|
|
780
|
+
wrapper.translationZ = 1000f
|
|
781
|
+
|
|
782
|
+
// Match the target's exact rotation center by reading its actual size
|
|
783
|
+
val actualW = targetView?.width?.toFloat() ?: wrapW
|
|
784
|
+
val actualH = targetView?.height?.toFloat() ?: wrapH
|
|
785
|
+
// Clear target rotation first so getLocationInWindow gives un-rotated pos
|
|
786
|
+
// then position wrapper at same un-rotated pos with same rotation
|
|
787
|
+
targetView?.rotation = 0f
|
|
788
|
+
val unrotatedLoc = if (targetView != null) getLocationInWindow(targetView) else targetLoc
|
|
789
|
+
wrapper.x = unrotatedLoc[0].toFloat()
|
|
790
|
+
wrapper.y = unrotatedLoc[1].toFloat()
|
|
791
|
+
wrapper.layoutParams = FrameLayout.LayoutParams(actualW.toInt(), actualH.toInt())
|
|
792
|
+
wrapper.rotation = rotationEndAngle.toFloat()
|
|
793
|
+
|
|
767
794
|
decorView.addView(wrapper)
|
|
768
795
|
overlayContainer = wrapper
|
|
796
|
+
targetView?.visibility = View.INVISIBLE
|
|
769
797
|
}
|
|
770
798
|
|
|
771
799
|
// Show source screen underneath
|
|
@@ -786,9 +814,18 @@ class MorphCardSourceView(context: Context) : ReactViewGroup(context) {
|
|
|
786
814
|
val startImgW = content?.layoutParams?.width?.toFloat() ?: cardWidth
|
|
787
815
|
val startImgH = content?.layoutParams?.height?.toFloat() ?: cardHeight
|
|
788
816
|
|
|
817
|
+
// Lock pivot to center so rotation stays stable as size changes
|
|
818
|
+
if (rotationEndAngle != 0.0) {
|
|
819
|
+
wrapper.pivotX = startWidth / 2f
|
|
820
|
+
wrapper.pivotY = startHeight / 2f
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
// Match iOS collapse curve: cubic bezier (0.25, 1.0, 0.5, 1.0)
|
|
824
|
+
val collapseInterpolator = PathInterpolator(0.25f, 1.0f, 0.5f, 1.0f)
|
|
825
|
+
|
|
789
826
|
val animator = ValueAnimator.ofFloat(0f, 1f)
|
|
790
827
|
animator.duration = dur
|
|
791
|
-
animator.interpolator =
|
|
828
|
+
animator.interpolator = collapseInterpolator
|
|
792
829
|
|
|
793
830
|
animator.addUpdateListener { anim ->
|
|
794
831
|
val t = anim.animatedValue as Float
|
|
@@ -799,6 +836,11 @@ class MorphCardSourceView(context: Context) : ReactViewGroup(context) {
|
|
|
799
836
|
lp.height = lerp(startHeight, cardHeight, t).toInt()
|
|
800
837
|
wrapper.layoutParams = lp
|
|
801
838
|
setRoundedCorners(wrapper, lerp(startCr, cardCornerRadiusPx, t))
|
|
839
|
+
if (rotationEndAngle != 0.0) {
|
|
840
|
+
wrapper.rotation = lerp(rotationEndAngle.toFloat(), 0f, t)
|
|
841
|
+
wrapper.pivotX = lp.width / 2f
|
|
842
|
+
wrapper.pivotY = lp.height / 2f
|
|
843
|
+
}
|
|
802
844
|
|
|
803
845
|
if (content != null) {
|
|
804
846
|
if (hasWrapper) {
|
|
@@ -40,6 +40,8 @@ class MorphCardTargetView(context: Context) : ReactViewGroup(context) {
|
|
|
40
40
|
screenContainer.visibility = View.INVISIBLE
|
|
41
41
|
Log.d(TAG, "TargetView: set screen INVISIBLE")
|
|
42
42
|
}
|
|
43
|
+
// Hide children until snapshot is in place to avoid flash of un-rotated content
|
|
44
|
+
hideChildren()
|
|
43
45
|
}
|
|
44
46
|
}
|
|
45
47
|
|
|
@@ -118,6 +120,18 @@ class MorphCardTargetView(context: Context) : ReactViewGroup(context) {
|
|
|
118
120
|
invalidate()
|
|
119
121
|
}
|
|
120
122
|
|
|
123
|
+
fun showChildren() {
|
|
124
|
+
for (i in 0 until childCount) {
|
|
125
|
+
getChildAt(i).alpha = 1f
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
fun hideChildren() {
|
|
130
|
+
for (i in 0 until childCount) {
|
|
131
|
+
getChildAt(i).alpha = 0f
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
121
135
|
fun fadeOutSnapshot() {
|
|
122
136
|
if (snapshotBitmap == null) return
|
|
123
137
|
// Only fade out if there are React children underneath to reveal.
|
|
@@ -129,6 +143,8 @@ class MorphCardTargetView(context: Context) : ReactViewGroup(context) {
|
|
|
129
143
|
snapshotAlpha = it.animatedValue as Float
|
|
130
144
|
invalidate()
|
|
131
145
|
}
|
|
146
|
+
// Show children before snapshot fades so they're visible underneath
|
|
147
|
+
showChildren()
|
|
132
148
|
anim.addListener(object : android.animation.AnimatorListenerAdapter() {
|
|
133
149
|
override fun onAnimationEnd(animation: android.animation.Animator) {
|
|
134
150
|
clearSnapshot()
|
|
@@ -92,6 +92,8 @@ static CGRect imageFrameForScaleMode(UIViewContentMode mode,
|
|
|
92
92
|
__weak UIView *_targetView;
|
|
93
93
|
__weak UIView *_sourceScreenContainer;
|
|
94
94
|
__weak UIView *_targetScreenContainer;
|
|
95
|
+
CGFloat _rotations;
|
|
96
|
+
CGFloat _rotationEndAngle;
|
|
95
97
|
UIView *_wrapperView;
|
|
96
98
|
UIImageView *_snapshot;
|
|
97
99
|
}
|
|
@@ -124,6 +126,8 @@ static CGRect imageFrameForScaleMode(UIViewContentMode mode,
|
|
|
124
126
|
} else {
|
|
125
127
|
_scaleMode = UIViewContentModeScaleAspectFill;
|
|
126
128
|
}
|
|
129
|
+
_rotations = newProps.rotations;
|
|
130
|
+
_rotationEndAngle = newProps.rotationEndAngle;
|
|
127
131
|
[super updateProps:props oldProps:oldProps];
|
|
128
132
|
}
|
|
129
133
|
|
|
@@ -293,17 +297,37 @@ static CGRect imageFrameForScaleMode(UIViewContentMode mode,
|
|
|
293
297
|
? (targetFrame.size.height - contentSize.height) / 2.0
|
|
294
298
|
: contentOffsetY;
|
|
295
299
|
|
|
300
|
+
// Use bounds/center instead of frame so rotation transforms work correctly
|
|
301
|
+
CGFloat totalAngleDeg = _rotations * 360.0 + _rotationEndAngle;
|
|
302
|
+
CGFloat totalAngleRad = totalAngleDeg * M_PI / 180.0;
|
|
303
|
+
wrapper.bounds = CGRectMake(0, 0, _cardFrame.size.width, _cardFrame.size.height);
|
|
304
|
+
wrapper.center = CGPointMake(CGRectGetMidX(_cardFrame), CGRectGetMidY(_cardFrame));
|
|
305
|
+
|
|
296
306
|
UIViewPropertyAnimator *animator = [[UIViewPropertyAnimator alloc]
|
|
297
307
|
initWithDuration:dur
|
|
298
308
|
dampingRatio:0.85
|
|
299
309
|
animations:^{
|
|
300
|
-
wrapper.
|
|
310
|
+
wrapper.bounds = CGRectMake(0, 0, targetFrame.size.width, targetFrame.size.height);
|
|
311
|
+
wrapper.center = CGPointMake(CGRectGetMidX(targetFrame), CGRectGetMidY(targetFrame));
|
|
301
312
|
wrapper.layer.cornerRadius = targetCornerRadius;
|
|
302
313
|
content.frame = CGRectMake(targetCx, targetCy,
|
|
303
314
|
contentSize.width,
|
|
304
315
|
contentSize.height);
|
|
305
316
|
}];
|
|
306
317
|
|
|
318
|
+
// Use CABasicAnimation for rotation — UIViewPropertyAnimator takes the
|
|
319
|
+
// shortest path and can't do multiple full spins.
|
|
320
|
+
if (totalAngleRad != 0) {
|
|
321
|
+
CABasicAnimation *rotAnim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
|
|
322
|
+
rotAnim.fromValue = @(0);
|
|
323
|
+
rotAnim.toValue = @(totalAngleRad);
|
|
324
|
+
rotAnim.duration = dur;
|
|
325
|
+
rotAnim.timingFunction = [CAMediaTimingFunction functionWithControlPoints:0.25 :1.0 :0.5 :1.0];
|
|
326
|
+
rotAnim.fillMode = kCAFillModeForwards;
|
|
327
|
+
rotAnim.removedOnCompletion = NO;
|
|
328
|
+
[wrapper.layer addAnimation:rotAnim forKey:@"morphRotation"];
|
|
329
|
+
}
|
|
330
|
+
|
|
307
331
|
// Hide the target view itself so it doesn't double-render over the morph overlay.
|
|
308
332
|
if (targetView) {
|
|
309
333
|
targetView.hidden = YES;
|
|
@@ -345,7 +369,13 @@ static CGRect imageFrameForScaleMode(UIViewContentMode mode,
|
|
|
345
369
|
[target fadeOutSnapshot];
|
|
346
370
|
});
|
|
347
371
|
}
|
|
348
|
-
if (targetView) {
|
|
372
|
+
if (targetView) {
|
|
373
|
+
targetView.hidden = NO;
|
|
374
|
+
CGFloat endAngleRad = self->_rotationEndAngle * M_PI / 180.0;
|
|
375
|
+
if (endAngleRad != 0) {
|
|
376
|
+
targetView.transform = CGAffineTransformMakeRotation(endAngleRad);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
349
379
|
self.alpha = 1;
|
|
350
380
|
UIView *ts = self->_targetScreenContainer;
|
|
351
381
|
if (ts) { ts.alpha = 1; }
|
|
@@ -363,7 +393,9 @@ static CGRect imageFrameForScaleMode(UIViewContentMode mode,
|
|
|
363
393
|
UIViewContentMode scaleMode = _scaleMode;
|
|
364
394
|
CGSize imageSize = cardImage.size;
|
|
365
395
|
|
|
366
|
-
UIView *container = [[UIView alloc] initWithFrame:
|
|
396
|
+
UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
|
|
397
|
+
container.bounds = CGRectMake(0, 0, _cardFrame.size.width, _cardFrame.size.height);
|
|
398
|
+
container.center = CGPointMake(CGRectGetMidX(_cardFrame), CGRectGetMidY(_cardFrame));
|
|
367
399
|
container.clipsToBounds = YES;
|
|
368
400
|
container.layer.cornerRadius = _cardCornerRadius;
|
|
369
401
|
|
|
@@ -388,15 +420,31 @@ static CGRect imageFrameForScaleMode(UIViewContentMode mode,
|
|
|
388
420
|
CGRect targetImageFrame = imageFrameForScaleMode(
|
|
389
421
|
scaleMode, imageSize, targetFrame.size);
|
|
390
422
|
|
|
423
|
+
CGFloat totalAngleDegNoWrap = _rotations * 360.0 + _rotationEndAngle;
|
|
424
|
+
CGFloat totalAngleRadNoWrap = totalAngleDegNoWrap * M_PI / 180.0;
|
|
425
|
+
|
|
391
426
|
UIViewPropertyAnimator *animator = [[UIViewPropertyAnimator alloc]
|
|
392
427
|
initWithDuration:dur
|
|
393
428
|
dampingRatio:0.85
|
|
394
429
|
animations:^{
|
|
395
|
-
container.
|
|
430
|
+
container.bounds = CGRectMake(0, 0, targetFrame.size.width, targetFrame.size.height);
|
|
431
|
+
container.center = CGPointMake(CGRectGetMidX(targetFrame), CGRectGetMidY(targetFrame));
|
|
396
432
|
container.layer.cornerRadius = targetCornerRadius;
|
|
397
433
|
snapshot.frame = targetImageFrame;
|
|
398
434
|
}];
|
|
399
435
|
|
|
436
|
+
// Use CABasicAnimation for rotation — supports multiple full spins
|
|
437
|
+
if (totalAngleRadNoWrap != 0) {
|
|
438
|
+
CABasicAnimation *rotAnim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
|
|
439
|
+
rotAnim.fromValue = @(0);
|
|
440
|
+
rotAnim.toValue = @(totalAngleRadNoWrap);
|
|
441
|
+
rotAnim.duration = dur;
|
|
442
|
+
rotAnim.timingFunction = [CAMediaTimingFunction functionWithControlPoints:0.25 :1.0 :0.5 :1.0];
|
|
443
|
+
rotAnim.fillMode = kCAFillModeForwards;
|
|
444
|
+
rotAnim.removedOnCompletion = NO;
|
|
445
|
+
[container.layer addAnimation:rotAnim forKey:@"morphRotation"];
|
|
446
|
+
}
|
|
447
|
+
|
|
400
448
|
// Start fading in screen content early (at 15% of the animation).
|
|
401
449
|
__weak RNCMorphCardSourceComponentView *weakSelf2 = self;
|
|
402
450
|
dispatch_after(
|
|
@@ -427,7 +475,13 @@ static CGRect imageFrameForScaleMode(UIViewContentMode mode,
|
|
|
427
475
|
[target fadeOutSnapshot];
|
|
428
476
|
});
|
|
429
477
|
}
|
|
430
|
-
if (targetView) {
|
|
478
|
+
if (targetView) {
|
|
479
|
+
targetView.hidden = NO;
|
|
480
|
+
CGFloat endAngleRad = self->_rotationEndAngle * M_PI / 180.0;
|
|
481
|
+
if (endAngleRad != 0) {
|
|
482
|
+
targetView.transform = CGAffineTransformMakeRotation(endAngleRad);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
431
485
|
self.alpha = 1;
|
|
432
486
|
UIView *ts = self->_targetScreenContainer;
|
|
433
487
|
if (ts) { ts.alpha = 1; }
|
|
@@ -464,6 +518,7 @@ static CGRect imageFrameForScaleMode(UIViewContentMode mode,
|
|
|
464
518
|
if (targetView && [targetView isKindOfClass:[RNCMorphCardTargetComponentView class]]) {
|
|
465
519
|
[(RNCMorphCardTargetComponentView *)targetView clearSnapshot];
|
|
466
520
|
targetView.hidden = YES;
|
|
521
|
+
targetView.transform = CGAffineTransformIdentity;
|
|
467
522
|
}
|
|
468
523
|
|
|
469
524
|
CGFloat collapseDur = 0;
|
|
@@ -493,7 +548,9 @@ static CGRect imageFrameForScaleMode(UIViewContentMode mode,
|
|
|
493
548
|
? (targetFrame.size.height - contentSize.height) / 2.0
|
|
494
549
|
: contentOffsetY;
|
|
495
550
|
|
|
496
|
-
wrapper = [[UIView alloc] initWithFrame:
|
|
551
|
+
wrapper = [[UIView alloc] initWithFrame:CGRectZero];
|
|
552
|
+
wrapper.bounds = CGRectMake(0, 0, targetFrame.size.width, targetFrame.size.height);
|
|
553
|
+
wrapper.center = CGPointMake(CGRectGetMidX(targetFrame), CGRectGetMidY(targetFrame));
|
|
497
554
|
wrapper.backgroundColor = self.backgroundColor;
|
|
498
555
|
wrapper.layer.cornerRadius = targetCornerRadius;
|
|
499
556
|
wrapper.clipsToBounds = YES;
|
|
@@ -522,13 +579,27 @@ static CGRect imageFrameForScaleMode(UIViewContentMode mode,
|
|
|
522
579
|
initWithDuration:dur
|
|
523
580
|
timingParameters:timing];
|
|
524
581
|
[animator addAnimations:^{
|
|
525
|
-
wrapper.
|
|
582
|
+
wrapper.bounds = CGRectMake(0, 0, self->_cardFrame.size.width, self->_cardFrame.size.height);
|
|
583
|
+
wrapper.center = CGPointMake(CGRectGetMidX(self->_cardFrame), CGRectGetMidY(self->_cardFrame));
|
|
526
584
|
wrapper.layer.cornerRadius = self->_cardCornerRadius;
|
|
527
585
|
if (content) {
|
|
528
586
|
content.frame = (CGRect){CGPointZero, content.frame.size};
|
|
529
587
|
}
|
|
530
588
|
}];
|
|
531
589
|
|
|
590
|
+
// Animate rotation back to 0
|
|
591
|
+
CGFloat collapseStartAngle = _rotationEndAngle * M_PI / 180.0;
|
|
592
|
+
if (collapseStartAngle != 0) {
|
|
593
|
+
CABasicAnimation *rotAnim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
|
|
594
|
+
rotAnim.fromValue = @(collapseStartAngle);
|
|
595
|
+
rotAnim.toValue = @(0);
|
|
596
|
+
rotAnim.duration = dur;
|
|
597
|
+
rotAnim.timingFunction = [CAMediaTimingFunction functionWithControlPoints:0.25 :1.0 :0.5 :1.0];
|
|
598
|
+
rotAnim.fillMode = kCAFillModeForwards;
|
|
599
|
+
rotAnim.removedOnCompletion = NO;
|
|
600
|
+
[wrapper.layer addAnimation:rotAnim forKey:@"morphRotation"];
|
|
601
|
+
}
|
|
602
|
+
|
|
532
603
|
// Fade out target screen
|
|
533
604
|
[self scheduleScreenFadeOut:targetScreen duration:dur];
|
|
534
605
|
|
|
@@ -556,7 +627,9 @@ static CGRect imageFrameForScaleMode(UIViewContentMode mode,
|
|
|
556
627
|
CGRect imageFrame = imageFrameForScaleMode(
|
|
557
628
|
_scaleMode, imageSize, targetFrame.size);
|
|
558
629
|
|
|
559
|
-
container = [[UIView alloc] initWithFrame:
|
|
630
|
+
container = [[UIView alloc] initWithFrame:CGRectZero];
|
|
631
|
+
container.bounds = CGRectMake(0, 0, targetFrame.size.width, targetFrame.size.height);
|
|
632
|
+
container.center = CGPointMake(CGRectGetMidX(targetFrame), CGRectGetMidY(targetFrame));
|
|
560
633
|
container.clipsToBounds = YES;
|
|
561
634
|
container.layer.cornerRadius = targetCornerRadius;
|
|
562
635
|
|
|
@@ -582,11 +655,25 @@ static CGRect imageFrameForScaleMode(UIViewContentMode mode,
|
|
|
582
655
|
initWithDuration:dur
|
|
583
656
|
timingParameters:timing];
|
|
584
657
|
[animator addAnimations:^{
|
|
585
|
-
container.
|
|
658
|
+
container.bounds = CGRectMake(0, 0, self->_cardFrame.size.width, self->_cardFrame.size.height);
|
|
659
|
+
container.center = CGPointMake(CGRectGetMidX(self->_cardFrame), CGRectGetMidY(self->_cardFrame));
|
|
586
660
|
container.layer.cornerRadius = self->_cardCornerRadius;
|
|
587
661
|
snapshot.frame = (CGRect){CGPointZero, self->_cardFrame.size};
|
|
588
662
|
}];
|
|
589
663
|
|
|
664
|
+
// Animate rotation back to 0
|
|
665
|
+
CGFloat collapseStartAngleNW = _rotationEndAngle * M_PI / 180.0;
|
|
666
|
+
if (collapseStartAngleNW != 0) {
|
|
667
|
+
CABasicAnimation *rotAnim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
|
|
668
|
+
rotAnim.fromValue = @(collapseStartAngleNW);
|
|
669
|
+
rotAnim.toValue = @(0);
|
|
670
|
+
rotAnim.duration = dur;
|
|
671
|
+
rotAnim.timingFunction = [CAMediaTimingFunction functionWithControlPoints:0.25 :1.0 :0.5 :1.0];
|
|
672
|
+
rotAnim.fillMode = kCAFillModeForwards;
|
|
673
|
+
rotAnim.removedOnCompletion = NO;
|
|
674
|
+
[container.layer addAnimation:rotAnim forKey:@"morphRotation"];
|
|
675
|
+
}
|
|
676
|
+
|
|
590
677
|
// Fade out target screen
|
|
591
678
|
[self scheduleScreenFadeOut:targetScreen duration:dur];
|
|
592
679
|
|
|
@@ -25,6 +25,8 @@ const MorphCardSource = ({
|
|
|
25
25
|
borderRadius,
|
|
26
26
|
backgroundColor,
|
|
27
27
|
resizeMode,
|
|
28
|
+
rotations,
|
|
29
|
+
rotationEndAngle,
|
|
28
30
|
onPress,
|
|
29
31
|
ref
|
|
30
32
|
}) => {
|
|
@@ -76,6 +78,8 @@ const MorphCardSource = ({
|
|
|
76
78
|
expandDuration: expandDuration,
|
|
77
79
|
scaleMode: resizeMode === 'contain' ? 'aspectFit' : resizeMode === 'stretch' ? 'stretch' : 'aspectFill',
|
|
78
80
|
cardBorderRadius: borderRadius,
|
|
81
|
+
rotations: rotations,
|
|
82
|
+
rotationEndAngle: rotationEndAngle,
|
|
79
83
|
style: style,
|
|
80
84
|
onLayout: handleLayout,
|
|
81
85
|
children: children
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","_interopRequireWildcard","require","_reactNative","_NativeMorphCardModule","_interopRequireDefault","_NativeMorphCardSource","_MorphChildrenRegistry","_jsxRuntime","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","NativeSourceView","NativeSourceViewSpec","View","MorphCardSource","children","duration","expandDuration","width","height","borderRadius","backgroundColor","resizeMode","onPress","ref","nativeRef","useRef","useImperativeHandle","current","useEffect","tag","findNodeHandle","setSourceEntry","clearSourceEntry","style","overflow","handleLayout","useCallback","lw","lh","nativeEvent","layout","setSourceLayout","handlePress","NativeMorphCardModule","prepareExpand","requestAnimationFrame","content","jsx","scaleMode","cardBorderRadius","onLayout","Pressable","exports","getViewTag","viewRef","morphExpand","sourceRef","targetRef","sourceTag","targetTag","expand","morphCollapse","collapse"],"sourceRoot":"../../src","sources":["MorphCardSource.tsx"],"mappings":";;;;;;;;;AAAA,IAAAA,KAAA,GAAAC,uBAAA,CAAAC,OAAA;AACA,IAAAC,YAAA,GAAAD,OAAA;AAQA,IAAAE,sBAAA,GAAAC,sBAAA,CAAAH,OAAA;AACA,IAAAI,sBAAA,GAAAD,sBAAA,CAAAH,OAAA;AACA,IAAAK,sBAAA,GAAAL,OAAA;AAA4F,IAAAM,WAAA,GAAAN,OAAA;AAAA,SAAAG,uBAAAI,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,SAAAR,wBAAAQ,CAAA,EAAAG,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAZ,uBAAA,YAAAA,CAAAQ,CAAA,EAAAG,CAAA,SAAAA,CAAA,IAAAH,CAAA,IAAAA,CAAA,CAAAC,UAAA,SAAAD,CAAA,MAAAO,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAR,OAAA,EAAAF,CAAA,iBAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,SAAAS,CAAA,MAAAF,CAAA,GAAAJ,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAE,CAAA,CAAAI,GAAA,CAAAX,CAAA,UAAAO,CAAA,CAAAK,GAAA,CAAAZ,CAAA,GAAAO,CAAA,CAAAM,GAAA,CAAAb,CAAA,EAAAS,CAAA,gBAAAN,CAAA,IAAAH,CAAA,gBAAAG,CAAA,OAAAW,cAAA,CAAAC,IAAA,CAAAf,CAAA,EAAAG,CAAA,OAAAK,CAAA,IAAAD,CAAA,GAAAS,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAG,CAAA,OAAAK,CAAA,CAAAI,GAAA,IAAAJ,CAAA,CAAAK,GAAA,IAAAN,CAAA,CAAAE,CAAA,EAAAN,CAAA,EAAAK,CAAA,IAAAC,CAAA,CAAAN,CAAA,IAAAH,CAAA,CAAAG,CAAA,WAAAM,CAAA,KAAAT,CAAA,EAAAG,CAAA;AAE5F,MAAMgB,gBAAgB,GAAGC,8BAAoB,IAAIC,iBAAI;
|
|
1
|
+
{"version":3,"names":["React","_interopRequireWildcard","require","_reactNative","_NativeMorphCardModule","_interopRequireDefault","_NativeMorphCardSource","_MorphChildrenRegistry","_jsxRuntime","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","NativeSourceView","NativeSourceViewSpec","View","MorphCardSource","children","duration","expandDuration","width","height","borderRadius","backgroundColor","resizeMode","rotations","rotationEndAngle","onPress","ref","nativeRef","useRef","useImperativeHandle","current","useEffect","tag","findNodeHandle","setSourceEntry","clearSourceEntry","style","overflow","handleLayout","useCallback","lw","lh","nativeEvent","layout","setSourceLayout","handlePress","NativeMorphCardModule","prepareExpand","requestAnimationFrame","content","jsx","scaleMode","cardBorderRadius","onLayout","Pressable","exports","getViewTag","viewRef","morphExpand","sourceRef","targetRef","sourceTag","targetTag","expand","morphCollapse","collapse"],"sourceRoot":"../../src","sources":["MorphCardSource.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_codegenNativeComponent","_interopRequireDefault","require","e","__esModule","default","_default","exports","codegenNativeComponent"],"sourceRoot":"../../../src","sources":["specs/NativeMorphCardSource.ts"],"mappings":";;;;;;AAMA,IAAAA,uBAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA6F,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,
|
|
1
|
+
{"version":3,"names":["_codegenNativeComponent","_interopRequireDefault","require","e","__esModule","default","_default","exports","codegenNativeComponent"],"sourceRoot":"../../../src","sources":["specs/NativeMorphCardSource.ts"],"mappings":";;;;;;AAMA,IAAAA,uBAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA6F,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAc9E,IAAAG,+BAAsB,EACnC,oBACF,CAAC","ignoreList":[]}
|
|
@@ -16,6 +16,8 @@ export const MorphCardSource = ({
|
|
|
16
16
|
borderRadius,
|
|
17
17
|
backgroundColor,
|
|
18
18
|
resizeMode,
|
|
19
|
+
rotations,
|
|
20
|
+
rotationEndAngle,
|
|
19
21
|
onPress,
|
|
20
22
|
ref
|
|
21
23
|
}) => {
|
|
@@ -67,6 +69,8 @@ export const MorphCardSource = ({
|
|
|
67
69
|
expandDuration: expandDuration,
|
|
68
70
|
scaleMode: resizeMode === 'contain' ? 'aspectFit' : resizeMode === 'stretch' ? 'stretch' : 'aspectFill',
|
|
69
71
|
cardBorderRadius: borderRadius,
|
|
72
|
+
rotations: rotations,
|
|
73
|
+
rotationEndAngle: rotationEndAngle,
|
|
70
74
|
style: style,
|
|
71
75
|
onLayout: handleLayout,
|
|
72
76
|
children: children
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","Pressable","View","findNodeHandle","NativeMorphCardModule","NativeSourceViewSpec","setSourceEntry","setSourceLayout","clearSourceEntry","jsx","_jsx","NativeSourceView","MorphCardSource","children","duration","expandDuration","width","height","borderRadius","backgroundColor","resizeMode","onPress","ref","nativeRef","useRef","useImperativeHandle","current","useEffect","tag","style","overflow","handleLayout","useCallback","e","lw","lh","nativeEvent","layout","handlePress","prepareExpand","requestAnimationFrame","content","scaleMode","cardBorderRadius","onLayout","getViewTag","viewRef","morphExpand","sourceRef","targetRef","sourceTag","targetTag","expand","morphCollapse","collapse"],"sourceRoot":"../../src","sources":["MorphCardSource.tsx"],"mappings":";;AAAA,OAAO,KAAKA,KAAK,MAAM,OAAO;AAC9B,SACEC,SAAS,EAITC,IAAI,EACJC,cAAc,QACT,cAAc;AACrB,OAAOC,qBAAqB,MAAM,+BAA+B;AACjE,OAAOC,oBAAoB,MAAM,+BAA+B;AAChE,SAASC,cAAc,EAAEC,eAAe,EAAEC,gBAAgB,QAAQ,yBAAyB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAE5F,MAAMC,gBAAgB,GAAGN,oBAAoB,IAAIH,IAAI;
|
|
1
|
+
{"version":3,"names":["React","Pressable","View","findNodeHandle","NativeMorphCardModule","NativeSourceViewSpec","setSourceEntry","setSourceLayout","clearSourceEntry","jsx","_jsx","NativeSourceView","MorphCardSource","children","duration","expandDuration","width","height","borderRadius","backgroundColor","resizeMode","rotations","rotationEndAngle","onPress","ref","nativeRef","useRef","useImperativeHandle","current","useEffect","tag","style","overflow","handleLayout","useCallback","e","lw","lh","nativeEvent","layout","handlePress","prepareExpand","requestAnimationFrame","content","scaleMode","cardBorderRadius","onLayout","getViewTag","viewRef","morphExpand","sourceRef","targetRef","sourceTag","targetTag","expand","morphCollapse","collapse"],"sourceRoot":"../../src","sources":["MorphCardSource.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["codegenNativeComponent"],"sourceRoot":"../../../src","sources":["specs/NativeMorphCardSource.ts"],"mappings":";;AAMA,OAAOA,sBAAsB,MAAM,yDAAyD;
|
|
1
|
+
{"version":3,"names":["codegenNativeComponent"],"sourceRoot":"../../../src","sources":["specs/NativeMorphCardSource.ts"],"mappings":";;AAMA,OAAOA,sBAAsB,MAAM,yDAAyD;AAc5F,eAAeA,sBAAsB,CACnC,oBACF,CAAC","ignoreList":[]}
|
|
@@ -11,10 +11,14 @@ export interface MorphCardSourceProps {
|
|
|
11
11
|
backgroundColor?: string;
|
|
12
12
|
/** How the snapshot scales in no-wrapper mode (no backgroundColor). Default: 'cover' */
|
|
13
13
|
resizeMode?: ResizeMode;
|
|
14
|
+
/** Number of full 360° rotations during expand animation. Default: 0 */
|
|
15
|
+
rotations?: number;
|
|
16
|
+
/** Final rotation angle in degrees after expand. Default: 0 */
|
|
17
|
+
rotationEndAngle?: number;
|
|
14
18
|
onPress?: (sourceTag: number) => void;
|
|
15
19
|
children: React.ReactNode;
|
|
16
20
|
}
|
|
17
|
-
export declare const MorphCardSource: ({ children, duration, expandDuration, width, height, borderRadius, backgroundColor, resizeMode, onPress, ref, }: MorphCardSourceProps) => React.JSX.Element;
|
|
21
|
+
export declare const MorphCardSource: ({ children, duration, expandDuration, width, height, borderRadius, backgroundColor, resizeMode, rotations, rotationEndAngle, onPress, ref, }: MorphCardSourceProps) => React.JSX.Element;
|
|
18
22
|
/**
|
|
19
23
|
* Get the native view tag from a ref. Useful for passing sourceTag
|
|
20
24
|
* to the detail screen via navigation params.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MorphCardSource.d.ts","sourceRoot":"","sources":["../../../src/MorphCardSource.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAGL,KAAK,cAAc,EAIpB,MAAM,cAAc,CAAC;AAOtB,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AAEzD,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wFAAwF;IACxF,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,eAAO,MAAM,eAAe,GAAI,
|
|
1
|
+
{"version":3,"file":"MorphCardSource.d.ts","sourceRoot":"","sources":["../../../src/MorphCardSource.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAGL,KAAK,cAAc,EAIpB,MAAM,cAAc,CAAC;AAOtB,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AAEzD,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wFAAwF;IACxF,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,eAAO,MAAM,eAAe,GAAI,8IAa7B,oBAAoB,sBAuDtB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,MAAM,GAAG,IAAI,CAEvE;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,EAC/B,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,GAC9B,OAAO,CAAC,OAAO,CAAC,CAKlB;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAEvE"}
|
|
@@ -8,6 +8,8 @@ export interface NativeMorphCardSourceProps extends ViewProps {
|
|
|
8
8
|
expandDuration?: Double;
|
|
9
9
|
scaleMode?: WithDefault<'aspectFill' | 'aspectFit' | 'stretch', 'aspectFill'>;
|
|
10
10
|
cardBorderRadius?: Double;
|
|
11
|
+
rotations?: Double;
|
|
12
|
+
rotationEndAngle?: Double;
|
|
11
13
|
}
|
|
12
14
|
declare const _default: import("react-native/Libraries/Utilities/codegenNativeComponent").NativeComponentType<NativeMorphCardSourceProps>;
|
|
13
15
|
export default _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeMorphCardSource.d.ts","sourceRoot":"","sources":["../../../../src/specs/NativeMorphCardSource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EACV,kBAAkB,EAClB,MAAM,EACN,WAAW,EACZ,MAAM,2CAA2C,CAAC;AAGnD,MAAM,WAAW,0BAA2B,SAAQ,SAAS;IAC3D,YAAY,CAAC,EAAE,kBAAkB,CAAC,EAAE,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,kBAAkB,CAAC,EAAE,CAAC,CAAC;IACzC,iBAAiB,CAAC,EAAE,kBAAkB,CAAC,EAAE,CAAC,CAAC;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,WAAW,CAAC,YAAY,GAAG,WAAW,GAAG,SAAS,EAAE,YAAY,CAAC,CAAC;IAC9E,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;;AAED,wBAEE"}
|
|
1
|
+
{"version":3,"file":"NativeMorphCardSource.d.ts","sourceRoot":"","sources":["../../../../src/specs/NativeMorphCardSource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EACV,kBAAkB,EAClB,MAAM,EACN,WAAW,EACZ,MAAM,2CAA2C,CAAC;AAGnD,MAAM,WAAW,0BAA2B,SAAQ,SAAS;IAC3D,YAAY,CAAC,EAAE,kBAAkB,CAAC,EAAE,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,kBAAkB,CAAC,EAAE,CAAC,CAAC;IACzC,iBAAiB,CAAC,EAAE,kBAAkB,CAAC,EAAE,CAAC,CAAC;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,WAAW,CAAC,YAAY,GAAG,WAAW,GAAG,SAAS,EAAE,YAAY,CAAC,CAAC;IAC9E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;;AAED,wBAEE"}
|
package/package.json
CHANGED
package/src/MorphCardSource.tsx
CHANGED
|
@@ -25,6 +25,10 @@ export interface MorphCardSourceProps {
|
|
|
25
25
|
backgroundColor?: string;
|
|
26
26
|
/** How the snapshot scales in no-wrapper mode (no backgroundColor). Default: 'cover' */
|
|
27
27
|
resizeMode?: ResizeMode;
|
|
28
|
+
/** Number of full 360° rotations during expand animation. Default: 0 */
|
|
29
|
+
rotations?: number;
|
|
30
|
+
/** Final rotation angle in degrees after expand. Default: 0 */
|
|
31
|
+
rotationEndAngle?: number;
|
|
28
32
|
onPress?: (sourceTag: number) => void;
|
|
29
33
|
children: React.ReactNode;
|
|
30
34
|
}
|
|
@@ -38,6 +42,8 @@ export const MorphCardSource = ({
|
|
|
38
42
|
borderRadius,
|
|
39
43
|
backgroundColor,
|
|
40
44
|
resizeMode,
|
|
45
|
+
rotations,
|
|
46
|
+
rotationEndAngle,
|
|
41
47
|
onPress,
|
|
42
48
|
ref,
|
|
43
49
|
}: MorphCardSourceProps) => {
|
|
@@ -85,7 +91,7 @@ export const MorphCardSource = ({
|
|
|
85
91
|
}, [onPress]);
|
|
86
92
|
|
|
87
93
|
const content = (
|
|
88
|
-
<NativeSourceView ref={nativeRef} duration={duration} expandDuration={expandDuration} scaleMode={resizeMode === 'contain' ? 'aspectFit' : resizeMode === 'stretch' ? 'stretch' : 'aspectFill'} cardBorderRadius={borderRadius} style={style} onLayout={handleLayout}>
|
|
94
|
+
<NativeSourceView ref={nativeRef} duration={duration} expandDuration={expandDuration} scaleMode={resizeMode === 'contain' ? 'aspectFit' : resizeMode === 'stretch' ? 'stretch' : 'aspectFill'} cardBorderRadius={borderRadius} rotations={rotations} rotationEndAngle={rotationEndAngle} style={style} onLayout={handleLayout}>
|
|
89
95
|
{children}
|
|
90
96
|
</NativeSourceView>
|
|
91
97
|
);
|
|
@@ -14,6 +14,8 @@ export interface NativeMorphCardSourceProps extends ViewProps {
|
|
|
14
14
|
expandDuration?: Double;
|
|
15
15
|
scaleMode?: WithDefault<'aspectFill' | 'aspectFit' | 'stretch', 'aspectFill'>;
|
|
16
16
|
cardBorderRadius?: Double;
|
|
17
|
+
rotations?: Double;
|
|
18
|
+
rotationEndAngle?: Double;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
export default codegenNativeComponent<NativeMorphCardSourceProps>(
|