react-native-smooth-clip-view 0.4.2 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +74 -0
  3. package/android/src/main/cpp/SmoothClipAndroid.h +1 -1
  4. package/android/src/main/cpp/SmoothClipBindings.cpp +14 -8
  5. package/android/src/main/cpp/SmoothClipRegistry.cpp +6 -6
  6. package/android/src/main/java/com/smoothclipview/ClipGeometryNormalizer.kt +23 -0
  7. package/android/src/main/java/com/smoothclipview/SmoothClipBindings.kt +2 -0
  8. package/android/src/main/java/com/smoothclipview/SmoothClipModule.kt +2 -0
  9. package/android/src/main/java/com/smoothclipview/SmoothClipView.kt +124 -32
  10. package/android/src/main/java/com/smoothclipview/SmoothClipViewManager.kt +16 -0
  11. package/cpp/SmoothClipAnimationCurve.h +13 -10
  12. package/cpp/SmoothClipRegistry.h +2 -0
  13. package/cpp/SmoothClipSharedGeometry.h +20 -0
  14. package/cpp/SmoothClipVelocityTracker.h +6 -0
  15. package/ios/SmoothClipTurboModule.cpp +17 -6
  16. package/ios/SmoothClipTurboModule.h +3 -1
  17. package/ios/SmoothClipView.mm +241 -22
  18. package/lib/module/NativeSmoothClipModule.js.map +1 -1
  19. package/lib/module/SmoothClipView.ios.js +3 -0
  20. package/lib/module/SmoothClipView.ios.js.map +1 -1
  21. package/lib/module/SmoothClipViewNativeComponent.ts +5 -1
  22. package/lib/module/geometry.js +22 -2
  23. package/lib/module/geometry.js.map +1 -1
  24. package/lib/module/presentationCodec.js +5 -3
  25. package/lib/module/presentationCodec.js.map +1 -1
  26. package/lib/typescript/src/NativeSmoothClipModule.d.ts +1 -1
  27. package/lib/typescript/src/NativeSmoothClipModule.d.ts.map +1 -1
  28. package/lib/typescript/src/SmoothClipView.ios.d.ts.map +1 -1
  29. package/lib/typescript/src/SmoothClipViewNativeComponent.d.ts +3 -1
  30. package/lib/typescript/src/SmoothClipViewNativeComponent.d.ts.map +1 -1
  31. package/lib/typescript/src/controllerTypes.d.ts +5 -1
  32. package/lib/typescript/src/controllerTypes.d.ts.map +1 -1
  33. package/lib/typescript/src/geometry.d.ts +9 -0
  34. package/lib/typescript/src/geometry.d.ts.map +1 -1
  35. package/lib/typescript/src/index.d.ts +1 -1
  36. package/lib/typescript/src/index.d.ts.map +1 -1
  37. package/lib/typescript/src/presentationCodec.d.ts +1 -1
  38. package/lib/typescript/src/presentationCodec.d.ts.map +1 -1
  39. package/package.json +5 -4
  40. package/src/NativeSmoothClipModule.ts +3 -1
  41. package/src/SmoothClipView.ios.tsx +3 -0
  42. package/src/SmoothClipViewNativeComponent.ts +5 -1
  43. package/src/controllerTypes.ts +5 -1
  44. package/src/geometry.ts +35 -0
  45. package/src/index.ts +1 -0
  46. package/src/presentationCodec.ts +8 -2
@@ -45,6 +45,36 @@ using namespace facebook::react;
45
45
  return (id<CAAction>)[NSNull null];
46
46
  }
47
47
 
48
+ // UIKit normally hit-tests the target model tree. During native motion, use
49
+ // the visible bounds/transform/opacity instead, including a fade whose target
50
+ // opacity is already zero. These containers have no consumer-owned handlers.
51
+ - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
52
+ CALayer *visible = self.layer.animationKeys.count > 0 ? self.layer.presentationLayer : nil;
53
+ return CGRectContainsPoint(visible != nil ? visible.bounds : self.bounds, point);
54
+ }
55
+
56
+ - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
57
+ CALayer *visible = self.layer.animationKeys.count > 0 ? self.layer.presentationLayer : nil;
58
+ if (self.hidden || !self.userInteractionEnabled ||
59
+ (visible != nil ? visible.opacity : self.layer.opacity) <= 0) return nil;
60
+ if (visible != nil && self.layer.animationKeys.count > 0) {
61
+ CGPoint parentPoint = [self.layer convertPoint:point toLayer:self.layer.superlayer];
62
+ point = [visible convertPoint:parentPoint fromLayer:visible.superlayer];
63
+ }
64
+ if (![self pointInside:point withEvent:event]) return nil;
65
+ for (UIView *child in self.subviews.reverseObjectEnumerator) {
66
+ UIView *hit = [child hitTest:[self convertPoint:point toView:child] withEvent:event];
67
+ if (hit != nil) return hit;
68
+ }
69
+ return self;
70
+ }
71
+
72
+ @end
73
+
74
+ @interface SmoothClipPresentationContainerView : SmoothClipContainerView
75
+ @end
76
+ @implementation SmoothClipPresentationContainerView
77
+ - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { return YES; }
48
78
  @end
49
79
 
50
80
  @interface SmoothClipView () <RCTSmoothClipViewViewProtocol>
@@ -104,6 +134,8 @@ static bool SmoothClipBuildPresentation(
104
134
  double shadowOffsetY,
105
135
  double shadowBlurRadius,
106
136
  double shadowSpreadDistance,
137
+ double rotation,
138
+ double opacity,
107
139
  smoothclip::Presentation *result) {
108
140
  if (result == nullptr || !isfinite(x) || !isfinite(y) ||
109
141
  !isfinite(width) || !isfinite(height) ||
@@ -115,6 +147,7 @@ static bool SmoothClipBuildPresentation(
115
147
  !isfinite(shadowAlpha) ||
116
148
  !isfinite(shadowOffsetX) || !isfinite(shadowOffsetY) ||
117
149
  !isfinite(shadowBlurRadius) || !isfinite(shadowSpreadDistance) ||
150
+ !isfinite(rotation) || !isfinite(opacity) ||
118
151
  contentScale <= 0 || shadowRed < 0 || shadowRed > 1 ||
119
152
  shadowGreen < 0 || shadowGreen > 1 ||
120
153
  shadowBlue < 0 || shadowBlue > 1 ||
@@ -145,7 +178,8 @@ static bool SmoothClipBuildPresentation(
145
178
  shadowBlurRadius,
146
179
  shadowSpreadDistance};
147
180
  *result = {
148
- geometry, contentTranslateX, contentTranslateY, contentScale, shadow};
181
+ geometry, contentTranslateX, contentTranslateY, contentScale, shadow,
182
+ rotation, smoothclip::clamp01(opacity)};
149
183
  return true;
150
184
  }
151
185
 
@@ -320,9 +354,25 @@ static std::array<double, 11> SmoothClipVelocityChannels(
320
354
  contentScale};
321
355
  }
322
356
 
323
- static BOOL SmoothClipRectIntersectsHost(CGRect rect, CGRect host) {
324
- const CGRect intersection = CGRectIntersection(rect, host);
325
- return !CGRectIsNull(intersection) && !CGRectIsEmpty(intersection);
357
+ // Core Animation uses the overdamped physical solution as well as the critical
358
+ // and underdamped ones. This is only a turn-count reference at snapshot time.
359
+ static double SmoothClipCARotationProgress(double elapsed, const smoothclip::SpringAnimation &spring) {
360
+ const double omega = std::sqrt(spring.stiffness / spring.mass);
361
+ const double zeta = spring.damping / (2 * std::sqrt(spring.stiffness * spring.mass));
362
+ if (zeta <= 1) {
363
+ return smoothclip::advanceScalarSpring({0, spring.initialVelocity}, spring, elapsed).position;
364
+ }
365
+ const double root = std::sqrt(zeta * zeta - 1);
366
+ const double slow = -omega / (zeta + root);
367
+ const double fast = -omega * (zeta + root);
368
+ const double a = (spring.initialVelocity + fast) / (slow - fast);
369
+ return 1 + a * std::exp(slow * elapsed) + (-1 - a) * std::exp(fast * elapsed);
370
+ }
371
+
372
+ static BOOL SmoothClipRotatedRectIntersectsHost(CGRect rect, CGRect host, double rotation) {
373
+ return smoothclip::rotatedRectIntersectsHost(rect.origin.x - host.origin.x,
374
+ rect.origin.y - host.origin.y, rect.size.width, rect.size.height, rotation,
375
+ host.size.width, host.size.height);
326
376
  }
327
377
 
328
378
  static smoothclip::Presentation SmoothClipCanonicalSnapshot(
@@ -333,6 +383,19 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
333
383
 
334
384
  @implementation SmoothClipView {
335
385
  CALayer *_shadowLayer;
386
+ SmoothClipPresentationContainerView *_presentationContainer;
387
+ double _requestedRotation;
388
+ double _canonicalRotation;
389
+ double _requestedOpacity;
390
+ double _canonicalOpacity;
391
+ double _animationFromRotation;
392
+ double _animationToRotation;
393
+ BOOL _hasAppearanceAnimation;
394
+ BOOL _hasMaskAnimation;
395
+ BOOL _hasShadowModel;
396
+ SmoothClipCanonicalGeometry _shadowModelGeometry;
397
+ smoothclip::Shadow _shadowModel;
398
+
336
399
  SmoothClipContainerView *_clipContainer;
337
400
  SmoothClipContainerView *_contentContainer;
338
401
  CAShapeLayer *_unequalCornerMask;
@@ -400,6 +463,12 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
400
463
  // intentionally overridden again after every prop update below.
401
464
  self.clipsToBounds = YES;
402
465
 
466
+ _presentationContainer = [[SmoothClipPresentationContainerView alloc] initWithFrame:CGRectZero];
467
+ _presentationContainer.layer.anchorPoint = CGPointZero;
468
+ _presentationContainer.layer.allowsGroupOpacity = YES;
469
+ _presentationContainer.autoresizesSubviews = NO;
470
+ [self addSubview:_presentationContainer];
471
+ _requestedOpacity = _canonicalOpacity = 1;
403
472
  _clipContainer = [[SmoothClipContainerView alloc] initWithFrame:CGRectZero];
404
473
  _clipContainer.layer.masksToBounds = YES;
405
474
  _clipContainer.layer.needsDisplayOnBoundsChange = NO;
@@ -412,7 +481,7 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
412
481
  _contentContainer.layer.needsDisplayOnBoundsChange = NO;
413
482
  _contentContainer.autoresizesSubviews = NO;
414
483
  [_clipContainer addSubview:_contentContainer];
415
- [self addSubview:_clipContainer];
484
+ [_presentationContainer addSubview:_clipContainer];
416
485
 
417
486
  _shadowLayer = nil;
418
487
  // Created lazily so the common clipping-only path owns no shadow layer.
@@ -508,6 +577,8 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
508
577
  presentation.contentTranslateY);
509
578
  _requestedContentScale = presentation.contentScale;
510
579
  _requestedShadow = presentation.shadow;
580
+ _requestedRotation = presentation.rotation;
581
+ _requestedOpacity = smoothclip::clamp01(presentation.opacity);
511
582
  }
512
583
 
513
584
  - (CGColorRef)colorForShadow:(const smoothclip::Shadow &)shadow {
@@ -530,7 +601,7 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
530
601
  @"bounds": [NSNull null],
531
602
  @"position": [NSNull null],
532
603
  };
533
- [self.layer insertSublayer:_shadowLayer below:_clipContainer.layer];
604
+ [_presentationContainer.layer insertSublayer:_shadowLayer below:_clipContainer.layer];
534
605
  return _shadowLayer;
535
606
  }
536
607
 
@@ -545,9 +616,15 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
545
616
  shadowLayer.bounds = self.bounds;
546
617
  shadowLayer.position = CGPointMake(
547
618
  CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
548
- CGPathRef path = SmoothClipCreateShadowPath(geometry, effectiveShadow);
549
- shadowLayer.shadowPath = path;
550
- CGPathRelease(path);
619
+ if (!_hasShadowModel || !SmoothBoxShadowPathInputEqual(
620
+ _shadowModelGeometry, _shadowModel, geometry, effectiveShadow)) {
621
+ CGPathRef path = SmoothClipCreateShadowPath(geometry, effectiveShadow);
622
+ shadowLayer.shadowPath = path;
623
+ CGPathRelease(path);
624
+ }
625
+ _hasShadowModel = YES;
626
+ _shadowModelGeometry = geometry;
627
+ _shadowModel = effectiveShadow;
551
628
  shadowLayer.shadowColor = [self colorForShadow:effectiveShadow];
552
629
  shadowLayer.shadowOpacity = visible ? 1 : 0;
553
630
  shadowLayer.shadowRadius = MAX(0, effectiveShadow.blurRadius) / 2.0;
@@ -603,7 +680,7 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
603
680
  - (void)syncVisibilityForRect:(CGRect)rect {
604
681
  [self setClipContainerHidden:CGRectIsEmpty(rect)];
605
682
  _clipContainer.accessibilityElementsHidden =
606
- !SmoothClipRectIntersectsHost(rect, self.bounds);
683
+ !SmoothClipRotatedRectIntersectsHost(rect, self.bounds, _canonicalRotation) || _canonicalOpacity <= 0;
607
684
  }
608
685
 
609
686
  - (void)configureUnequalCornerMaskForGeometry:
@@ -687,6 +764,50 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
687
764
  #endif
688
765
  }
689
766
 
767
+ - (void)writeAppearanceRotation:(double)rotation opacity:(double)opacity rect:(CGRect)rect {
768
+ CALayer *layer = _presentationContainer.layer;
769
+ // A zero-angle group is identity regardless of pivot. Keep it stationary so
770
+ // existing geometry-only streams do not also dirty the parent layer each frame.
771
+ const CGPoint center = rotation == 0 ? CGPointZero :
772
+ CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
773
+ const CGRect bounds = (CGRect){center, self.bounds.size};
774
+ if (!CGRectEqualToRect(layer.bounds, bounds)) layer.bounds = bounds;
775
+ if (!CGPointEqualToPoint(layer.position, center)) layer.position = center;
776
+ if (_canonicalRotation != rotation) layer.affineTransform = CGAffineTransformMakeRotation(rotation);
777
+ if (_canonicalOpacity != opacity) layer.opacity = smoothclip::clamp01(opacity);
778
+ _canonicalRotation = rotation;
779
+ _canonicalOpacity = opacity;
780
+ }
781
+
782
+ // Matrix decomposition loses complete turns. Use the installed native trajectory
783
+ // to choose the equivalent visible angle, including after a paused spring resumes.
784
+ - (double)visibleRotation {
785
+ CAAnimationGroup *group = (CAAnimationGroup *)[_presentationContainer.layer
786
+ animationForKey:@"smoothClip.appearance"];
787
+ CALayer *visible = _presentationContainer.layer.presentationLayer;
788
+ if (_activeAnimationId == 0 || group == nil || visible == nil) return _canonicalRotation;
789
+ const double elapsed = group.speed == 0 ? group.timeOffset :
790
+ std::clamp([_presentationContainer.layer convertTime:CACurrentMediaTime() fromLayer:nil] - group.beginTime,
791
+ 0.0, group.duration);
792
+ double progress;
793
+ if (_activeAnimationKind == 1) {
794
+ progress = smoothclip::cubicBezier(_timingAnimation.controlPoint1X,
795
+ _timingAnimation.controlPoint1Y, _timingAnimation.controlPoint2X,
796
+ _timingAnimation.controlPoint2Y, group.duration > 0 ? elapsed / group.duration : 1);
797
+ } else {
798
+ progress = SmoothClipCARotationProgress(elapsed, _springAnimation);
799
+ }
800
+ const double expected = _animationFromRotation +
801
+ (_animationToRotation - _animationFromRotation) * progress;
802
+ const CGAffineTransform matrix = visible.affineTransform;
803
+ return smoothclip::unwrapRotation(std::atan2(matrix.b, matrix.a), expected);
804
+ }
805
+
806
+ - (double)visibleOpacity {
807
+ CALayer *layer = _activeAnimationId != 0 ? _presentationContainer.layer.presentationLayer : nil;
808
+ return smoothclip::clamp01(layer == nil ? _canonicalOpacity : layer.opacity);
809
+ }
810
+
690
811
  - (void)writeContentTranslation:(CGPoint)translation
691
812
  scale:(CGFloat)scale {
692
813
  if (CGPointEqualToPoint(_canonicalContentTranslation, translation) &&
@@ -704,7 +825,7 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
704
825
  if (![self canonicalRequestedGeometry:&geometry]) return;
705
826
 
706
827
  const BOOL accessibilityHidden =
707
- !SmoothClipRectIntersectsHost(geometry.rect, self.bounds);
828
+ !SmoothClipRotatedRectIntersectsHost(geometry.rect, self.bounds, _requestedRotation) || _requestedOpacity <= 0;
708
829
  const BOOL visibilityChanged =
709
830
  _clipHidden != CGRectIsEmpty(geometry.rect) ||
710
831
  _clipContainer.accessibilityElementsHidden != accessibilityHidden;
@@ -715,15 +836,23 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
715
836
  CGPointEqualToPoint(
716
837
  _canonicalContentTranslation, _requestedContentTranslation) &&
717
838
  _canonicalContentScale == _requestedContentScale &&
839
+ _canonicalRotation == _requestedRotation && _canonicalOpacity == _requestedOpacity &&
718
840
  SmoothBoxShadowEqual(_canonicalShadow, _requestedShadow) &&
719
841
  !visibilityChanged) {
720
842
  return;
721
843
  }
844
+ const SmoothClipCanonicalGeometry previousGeometry = [self canonicalGeometryValue];
722
845
  [self writeLayerGeometry:geometry
723
846
  hasExplicitRadii:_requestedHasExplicitRadii];
724
847
  [self writeContentTranslation:_requestedContentTranslation
725
848
  scale:_requestedContentScale];
726
- [self writeShadow:_requestedShadow geometry:geometry];
849
+ if (!CGRectEqualToRect(previousGeometry.rect, geometry.rect) ||
850
+ !SmoothClipCornerRadiiEqual(previousGeometry.radii, geometry.radii) ||
851
+ previousGeometry.curve != geometry.curve ||
852
+ !SmoothBoxShadowEqual(_canonicalShadow, _requestedShadow)) {
853
+ [self writeShadow:_requestedShadow geometry:geometry];
854
+ }
855
+ [self writeAppearanceRotation:_requestedRotation opacity:_requestedOpacity rect:geometry.rect];
727
856
  [self syncVisibilityForRect:geometry.rect];
728
857
  }
729
858
 
@@ -833,7 +962,8 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
833
962
  ? (CALayer *)_shadowLayer.presentationLayer
834
963
  : _shadowLayer;
835
964
  if (shadowLayer == nil) return SmoothClipCanonicalSnapshot({
836
- geometry, transform.tx, transform.ty, contentScale, shadow});
965
+ geometry, transform.tx, transform.ty, contentScale, shadow,
966
+ [self visibleRotation], [self visibleOpacity]});
837
967
  shadow.enabled = _canonicalShadow.enabled || shadowLayer.shadowOpacity > 0;
838
968
  shadow.blurRadius = shadowLayer.shadowRadius * 2.0;
839
969
  shadow.offsetX = shadowLayer.shadowOffset.width;
@@ -856,7 +986,8 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
856
986
  CGRectGetMinX(visibleRect) - CGRectGetMinX(shadowBounds);
857
987
  }
858
988
  return SmoothClipCanonicalSnapshot(
859
- {geometry, transform.tx, transform.ty, contentScale, shadow});
989
+ {geometry, transform.tx, transform.ty, contentScale, shadow,
990
+ [self visibleRotation], [self visibleOpacity]});
860
991
  }
861
992
 
862
993
  - (BOOL)smoothClipIsJoinable {
@@ -927,8 +1058,11 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
927
1058
  [_clipContainer.layer removeAnimationForKey:@"smoothClip.geometry"];
928
1059
  [_contentContainer.layer removeAnimationForKey:@"smoothClip.content"];
929
1060
  [_unequalCornerMask removeAnimationForKey:@"smoothClip.mask"];
1061
+ [_presentationContainer.layer removeAnimationForKey:@"smoothClip.appearance"];
930
1062
  [_shadowLayer removeAnimationForKey:@"smoothClip.shadow"];
931
- [self applyStaticCornerRepresentation:[self canonicalGeometryValue]];
1063
+ if (_hasMaskAnimation) {
1064
+ [self applyStaticCornerRepresentation:[self canonicalGeometryValue]];
1065
+ }
932
1066
  _ignoreAnimationCallback = NO;
933
1067
  _activeAnimationId = 0;
934
1068
  _activeAnimationKind = 0;
@@ -987,12 +1121,16 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
987
1121
  fromContentTranslation:(CGPoint)fromContentTranslation
988
1122
  fromContentScale:(CGFloat)fromContentScale
989
1123
  fromShadow:(smoothclip::Shadow)fromShadow
1124
+ fromRotation:(double)fromRotation
1125
+ fromOpacity:(double)fromOpacity
990
1126
  toGeometry:
991
1127
  (SmoothClipCanonicalGeometry)toGeometry
992
1128
  hasExplicitToRadii:(BOOL)hasExplicitToRadii
993
1129
  toContentTranslation:(CGPoint)toContentTranslation
994
1130
  toContentScale:(CGFloat)toContentScale
995
1131
  toShadow:(smoothclip::Shadow)toShadow
1132
+ toRotation:(double)toRotation
1133
+ toOpacity:(double)toOpacity
996
1134
  duration:(CFTimeInterval)duration
997
1135
  sharedBeginTime:(CFTimeInterval)sharedBeginTime {
998
1136
  const int32_t animationId = _activeAnimationId;
@@ -1020,13 +1158,19 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1020
1158
  CGPointMake(
1021
1159
  CGRectGetMidX(toGeometry.rect),
1022
1160
  CGRectGetMidY(toGeometry.rect));
1023
- const BOOL usesMask =
1024
- !SmoothClipCornerRadiiAreUniform(fromGeometry.radii) ||
1025
- !SmoothClipCornerRadiiAreUniform(toGeometry.radii) ||
1161
+ const BOOL changesShape = !CGRectEqualToRect(fromGeometry.rect, toGeometry.rect) ||
1162
+ !SmoothClipCornerRadiiEqual(fromGeometry.radii, toGeometry.radii) ||
1026
1163
  fromGeometry.curve != toGeometry.curve;
1164
+ const BOOL usesMask = changesShape &&
1165
+ (!SmoothClipCornerRadiiAreUniform(fromGeometry.radii) ||
1166
+ !SmoothClipCornerRadiiAreUniform(toGeometry.radii) ||
1167
+ fromGeometry.curve != toGeometry.curve);
1027
1168
  [self writeLayerGeometry:toGeometry
1028
1169
  hasExplicitRadii:hasExplicitToRadii];
1029
1170
  [self writeContentTranslation:toContentTranslation scale:toContentScale];
1171
+ [self writeAppearanceRotation:toRotation opacity:toOpacity rect:toGeometry.rect];
1172
+ _animationFromRotation = fromRotation;
1173
+ _animationToRotation = toRotation;
1030
1174
  _canonicalShadow = toShadow;
1031
1175
  SmoothBoxShadowNormalizeAnimationEndpoints(
1032
1176
  fromGeometry, &fromShadow, toGeometry, &toShadow);
@@ -1087,6 +1231,7 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1087
1231
  ? [CAAnimationGroup animation]
1088
1232
  : nil;
1089
1233
  CAAnimationGroup *maskAnimation = nil;
1234
+ _hasMaskAnimation = usesMask;
1090
1235
  if (_activeAnimationKind == 1) {
1091
1236
  CAMediaTimingFunction *timing = [CAMediaTimingFunction
1092
1237
  functionWithControlPoints:_timingAnimation.controlPoint1X
@@ -1327,6 +1472,36 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1327
1472
  maskAnimation.duration = group.duration;
1328
1473
  }
1329
1474
 
1475
+ CAAnimationGroup *appearanceGroup = [CAAnimationGroup animation];
1476
+ NSMutableArray<CAAnimation *> *appearanceAnimations = [NSMutableArray array];
1477
+ // A zero anchor and moving bounds origin avoid host-size-dependent pivot math.
1478
+ NSArray<NSString *> *keys = @[@"bounds.origin.x", @"bounds.origin.y", @"position.x",
1479
+ @"position.y", @"transform.rotation.z", @"opacity"];
1480
+ NSArray<NSNumber *> *fromValues = @[@(fromPosition.x), @(fromPosition.y), @(fromPosition.x),
1481
+ @(fromPosition.y), @(fromRotation), @(fromOpacity)];
1482
+ NSArray<NSNumber *> *toValues = @[@(toPosition.x), @(toPosition.y), @(toPosition.x),
1483
+ @(toPosition.y), @(toRotation), @(toOpacity)];
1484
+ for (NSUInteger index = 0; index < keys.count; index++) {
1485
+ if ([fromValues[index] isEqual:toValues[index]]) continue;
1486
+ // At zero rotation, origin/position cancel exactly; no pivot animation is needed.
1487
+ if (index < 4 && fromRotation == 0 && toRotation == 0) continue;
1488
+ CAAnimation *animation;
1489
+ if (_activeAnimationKind == 1) {
1490
+ CAMediaTimingFunction *timing = [CAMediaTimingFunction
1491
+ functionWithControlPoints:_timingAnimation.controlPoint1X :_timingAnimation.controlPoint1Y
1492
+ :_timingAnimation.controlPoint2X :_timingAnimation.controlPoint2Y];
1493
+ animation = [self basicAnimationForKeyPath:keys[index] fromValue:fromValues[index]
1494
+ toValue:toValues[index] timingFunction:timing];
1495
+ } else {
1496
+ animation = [self springAnimationForKeyPath:keys[index] fromValue:fromValues[index]
1497
+ toValue:toValues[index] velocity:_springAnimation.initialVelocity duration:group.duration];
1498
+ }
1499
+ [appearanceAnimations addObject:animation];
1500
+ }
1501
+ appearanceGroup.animations = appearanceAnimations;
1502
+ appearanceGroup.duration = group.duration;
1503
+
1504
+
1330
1505
  // An explicit media-time origin is required to pause and resume spring
1331
1506
  // groups without touching the parent layer clock (which would also pause
1332
1507
  // consumer animations in the clipped subtree).
@@ -1337,6 +1512,7 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1337
1512
  // Each layer receives the same absolute media timestamp translated into
1338
1513
  // its local clock. Group participants therefore advance from one epoch
1339
1514
  // even though their animations are installed sequentially.
1515
+ appearanceGroup.beginTime = [_presentationContainer.layer convertTime:sharedBeginTime fromLayer:nil];
1340
1516
  group.beginTime = [layer convertTime:sharedBeginTime fromLayer:nil];
1341
1517
  contentGroup.beginTime = [_contentContainer.layer
1342
1518
  convertTime:sharedBeginTime
@@ -1361,6 +1537,10 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1361
1537
  _springPausedForInactivity = NO;
1362
1538
  _pausedSpringHadMaskAnimation = NO;
1363
1539
  _pausedSpringHadShadowAnimation = NO;
1540
+ _hasAppearanceAnimation = appearanceAnimations.count > 0;
1541
+ if (_hasAppearanceAnimation) {
1542
+ [_presentationContainer.layer addAnimation:appearanceGroup forKey:@"smoothClip.appearance"];
1543
+ }
1364
1544
  [layer addAnimation:group forKey:@"smoothClip.geometry"];
1365
1545
  [_contentContainer.layer addAnimation:contentGroup
1366
1546
  forKey:@"smoothClip.content"];
@@ -1405,11 +1585,15 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1405
1585
  current.contentTranslateY)
1406
1586
  fromContentScale:current.contentScale
1407
1587
  fromShadow:current.shadow
1588
+ fromRotation:current.rotation
1589
+ fromOpacity:current.opacity
1408
1590
  toGeometry:target
1409
1591
  hasExplicitToRadii:_requestedHasExplicitRadii
1410
1592
  toContentTranslation:_requestedContentTranslation
1411
1593
  toContentScale:_requestedContentScale
1412
1594
  toShadow:_requestedShadow
1595
+ toRotation:_requestedRotation
1596
+ toOpacity:_requestedOpacity
1413
1597
  duration:duration
1414
1598
  sharedBeginTime:sharedBeginTime];
1415
1599
  return YES;
@@ -1496,7 +1680,8 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1496
1680
  [geometryLayer animationForKey:@"smoothClip.geometry"];
1497
1681
  CAAnimation *installedContent =
1498
1682
  [contentLayer animationForKey:@"smoothClip.content"];
1499
- if (installedGeometry == nil || installedContent == nil) return NO;
1683
+ CAAnimation *installedAppearance = [_presentationContainer.layer animationForKey:@"smoothClip.appearance"];
1684
+ if ((_hasAppearanceAnimation && installedAppearance == nil) || installedGeometry == nil || installedContent == nil) return NO;
1500
1685
 
1501
1686
  auto pausedCopy = ^CAAnimation *(CALayer *layer, CAAnimation *installed) {
1502
1687
  if (installed == nil) return (CAAnimation *)nil;
@@ -1513,6 +1698,7 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1513
1698
  return paused;
1514
1699
  };
1515
1700
 
1701
+ CAAnimation *appearance = pausedCopy(_presentationContainer.layer, installedAppearance);
1516
1702
  CAAnimation *geometry = pausedCopy(geometryLayer, installedGeometry);
1517
1703
  CAAnimation *content = pausedCopy(contentLayer, installedContent);
1518
1704
  CAAnimation *installedMask =
@@ -1527,6 +1713,7 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1527
1713
  [geometryLayer removeAnimationForKey:@"smoothClip.geometry"];
1528
1714
  [contentLayer removeAnimationForKey:@"smoothClip.content"];
1529
1715
  [_unequalCornerMask removeAnimationForKey:@"smoothClip.mask"];
1716
+ [_presentationContainer.layer removeAnimationForKey:@"smoothClip.appearance"];
1530
1717
  [_shadowLayer removeAnimationForKey:@"smoothClip.shadow"];
1531
1718
 
1532
1719
  _animationDelegate = [SmoothClipAnimationDelegate new];
@@ -1534,6 +1721,9 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1534
1721
  _animationDelegate.driverId = _driverId;
1535
1722
  _animationDelegate.animationId = animationId;
1536
1723
  geometry.delegate = _animationDelegate;
1724
+ if (appearance != nil) {
1725
+ [_presentationContainer.layer addAnimation:appearance forKey:@"smoothClip.appearance"];
1726
+ }
1537
1727
  [geometryLayer addAnimation:geometry forKey:@"smoothClip.geometry"];
1538
1728
  [contentLayer addAnimation:content forKey:@"smoothClip.content"];
1539
1729
  if (mask != nil) {
@@ -1567,7 +1757,8 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1567
1757
  [_unequalCornerMask animationForKey:@"smoothClip.mask"];
1568
1758
  CAAnimation *installedShadow =
1569
1759
  [_shadowLayer animationForKey:@"smoothClip.shadow"];
1570
- if (installedGeometry == nil || installedContent == nil ||
1760
+ CAAnimation *installedAppearance = [_presentationContainer.layer animationForKey:@"smoothClip.appearance"];
1761
+ if ((_hasAppearanceAnimation && installedAppearance == nil) || installedGeometry == nil || installedContent == nil ||
1571
1762
  (_pausedSpringHadMaskAnimation && installedMask == nil) ||
1572
1763
  (_pausedSpringHadShadowAnimation && installedShadow == nil)) {
1573
1764
  return NO;
@@ -1587,6 +1778,7 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1587
1778
  return resumed;
1588
1779
  };
1589
1780
 
1781
+ CAAnimation *appearance = resumedCopy(_presentationContainer.layer, installedAppearance);
1590
1782
  CAAnimation *geometry = resumedCopy(geometryLayer, installedGeometry);
1591
1783
  CAAnimation *content = resumedCopy(contentLayer, installedContent);
1592
1784
  CAAnimation *mask = resumedCopy(_unequalCornerMask, installedMask);
@@ -1597,6 +1789,7 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1597
1789
  [geometryLayer removeAnimationForKey:@"smoothClip.geometry"];
1598
1790
  [contentLayer removeAnimationForKey:@"smoothClip.content"];
1599
1791
  [_unequalCornerMask removeAnimationForKey:@"smoothClip.mask"];
1792
+ [_presentationContainer.layer removeAnimationForKey:@"smoothClip.appearance"];
1600
1793
  [_shadowLayer removeAnimationForKey:@"smoothClip.shadow"];
1601
1794
 
1602
1795
  _animationDelegate = [SmoothClipAnimationDelegate new];
@@ -1604,6 +1797,9 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1604
1797
  _animationDelegate.driverId = _driverId;
1605
1798
  _animationDelegate.animationId = animationId;
1606
1799
  geometry.delegate = _animationDelegate;
1800
+ if (appearance != nil) {
1801
+ [_presentationContainer.layer addAnimation:appearance forKey:@"smoothClip.appearance"];
1802
+ }
1607
1803
  [geometryLayer addAnimation:geometry forKey:@"smoothClip.geometry"];
1608
1804
  [contentLayer addAnimation:content forKey:@"smoothClip.content"];
1609
1805
  if (mask != nil) {
@@ -1621,6 +1817,8 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1621
1817
 
1622
1818
  - (BOOL)smoothClipHasInstalledAnimation:(int32_t)animationId {
1623
1819
  return _activeAnimationId == animationId &&
1820
+ (!_hasAppearanceAnimation ||
1821
+ [_presentationContainer.layer animationForKey:@"smoothClip.appearance"] != nil) &&
1624
1822
  [_clipContainer.layer animationForKey:@"smoothClip.geometry"] != nil &&
1625
1823
  [_contentContainer.layer animationForKey:@"smoothClip.content"] != nil &&
1626
1824
  (!_springPausedForInactivity ||
@@ -1642,8 +1840,11 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1642
1840
  _pausedSpringHadMaskAnimation = NO;
1643
1841
  _pausedSpringHadShadowAnimation = NO;
1644
1842
  [_unequalCornerMask removeAnimationForKey:@"smoothClip.mask"];
1843
+ [_presentationContainer.layer removeAnimationForKey:@"smoothClip.appearance"];
1645
1844
  [_shadowLayer removeAnimationForKey:@"smoothClip.shadow"];
1646
- [self applyStaticCornerRepresentation:[self canonicalGeometryValue]];
1845
+ if (_hasMaskAnimation) {
1846
+ [self applyStaticCornerRepresentation:[self canonicalGeometryValue]];
1847
+ }
1647
1848
  [self writeShadow:_requestedShadow
1648
1849
  geometry:[self canonicalGeometryValue]];
1649
1850
  [self syncVisibilityForRect:_canonicalClip];
@@ -1685,6 +1886,8 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1685
1886
  newProps.initialClipBoxShadowOffsetY,
1686
1887
  newProps.initialClipBoxShadowBlurRadius,
1687
1888
  newProps.initialClipBoxShadowSpreadDistance,
1889
+ newProps.initialRotation,
1890
+ newProps.initialOpacity,
1688
1891
  &initial)) {
1689
1892
  // The initial presentation is atomic. Never apply a valid subset when one
1690
1893
  // field rejects.
@@ -1706,6 +1909,7 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1706
1909
  }
1707
1910
 
1708
1911
  - (void)layoutContentContainer {
1912
+ [self writeAppearanceRotation:_canonicalRotation opacity:_canonicalOpacity rect:_canonicalClip];
1709
1913
  _contentContainer.layer.bounds = CGRectMake(
1710
1914
  0, 0, MAX(0, self.bounds.size.width), MAX(0, self.bounds.size.height));
1711
1915
  _contentContainer.layer.position = CGPointMake(
@@ -1733,6 +1937,12 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1733
1937
  const CGRect clip = _activeAnimationId != 0
1734
1938
  ? [self presentationRectWithRadii:&radii]
1735
1939
  : _canonicalClip;
1940
+ if ([self visibleOpacity] <= 0) return NO;
1941
+ const double rotation = [self visibleRotation];
1942
+ const CGPoint center = CGPointMake(CGRectGetMidX(clip), CGRectGetMidY(clip));
1943
+ const double dx = point.x - center.x, dy = point.y - center.y;
1944
+ point = CGPointMake(center.x + cos(rotation) * dx + sin(rotation) * dy,
1945
+ center.y - sin(rotation) * dx + cos(rotation) * dy);
1736
1946
  if (CGRectIsEmpty(clip) || !CGRectContainsPoint(clip, point)) return NO;
1737
1947
  CGPathRef path = nil;
1738
1948
  if (_clipContainer.layer.mask == _unequalCornerMask) {
@@ -1775,7 +1985,9 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1775
1985
  shadowOffsetX:(double)shadowOffsetX
1776
1986
  shadowOffsetY:(double)shadowOffsetY
1777
1987
  shadowBlurRadius:(double)shadowBlurRadius
1778
- shadowSpreadDistance:(double)shadowSpreadDistance {
1988
+ shadowSpreadDistance:(double)shadowSpreadDistance
1989
+ rotation:(double)rotation
1990
+ opacity:(double)opacity {
1779
1991
  smoothclip::Presentation presentation{};
1780
1992
  if (!SmoothClipBuildPresentation(
1781
1993
  x,
@@ -1799,6 +2011,8 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1799
2011
  shadowOffsetY,
1800
2012
  shadowBlurRadius,
1801
2013
  shadowSpreadDistance,
2014
+ rotation,
2015
+ opacity,
1802
2016
  &presentation)) {
1803
2017
  return;
1804
2018
  }
@@ -1830,6 +2044,10 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1830
2044
  _canonicalContentScale = 1;
1831
2045
  _requestedShadow = {};
1832
2046
  _canonicalShadow = {};
2047
+ _requestedRotation = _canonicalRotation = 0;
2048
+ _requestedOpacity = _canonicalOpacity = 1;
2049
+ _presentationContainer.layer.affineTransform = CGAffineTransformIdentity;
2050
+ _presentationContainer.layer.opacity = 1;
1833
2051
  _hasLayout = NO;
1834
2052
  _commandIsAuthoritative = NO;
1835
2053
 
@@ -1841,6 +2059,7 @@ static smoothclip::Presentation SmoothClipCanonicalSnapshot(
1841
2059
  layer.mask = nil;
1842
2060
  _unequalCornerMask.path = nil;
1843
2061
  _contentContainer.layer.affineTransform = CGAffineTransformIdentity;
2062
+ _hasShadowModel = NO;
1844
2063
  _shadowLayer.shadowPath = nil;
1845
2064
  _shadowLayer.shadowOpacity = 0;
1846
2065
  _shadowLayer.shadowRadius = 0;
@@ -1 +1 @@
1
- {"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeSmoothClipModule.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;AA+HlD,eAAeA,mBAAmB,CAACC,YAAY,CAAO,wBAAwB,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeSmoothClipModule.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;AAiIlD,eAAeA,mBAAmB,CAACC,YAAY,CAAO,wBAAwB,CAAC","ignoreList":[]}
@@ -4,6 +4,7 @@
4
4
  import { forwardRef, useEffect } from 'react';
5
5
  import { StyleSheet } from 'react-native';
6
6
  import { getControllerRef, unwrapSmoothClipRef } from "./controllerInternals.js";
7
+ import { rotationRadians } from "./geometry.js";
7
8
  import NativeSmoothClipView from './SmoothClipViewNativeComponent';
8
9
  import { jsx as _jsx } from "react/jsx-runtime";
9
10
  let reportedIndependentShadow = false;
@@ -94,6 +95,8 @@ export function renderSmoothClipView({
94
95
  initialContentTranslateX: canonical.contentTranslateX,
95
96
  initialContentTranslateY: canonical.contentTranslateY,
96
97
  initialContentScale: canonical.contentScale,
98
+ initialRotation: rotationRadians(canonical.rotation),
99
+ initialOpacity: canonical.opacity,
97
100
  initialClipBoxShadowEnabled: shadow !== undefined,
98
101
  initialClipBoxShadowRed: (color >>> 24 & 0xff) / 255,
99
102
  initialClipBoxShadowGreen: (color >>> 16 & 0xff) / 255,
@@ -1 +1 @@
1
- {"version":3,"names":["forwardRef","useEffect","StyleSheet","getControllerRef","unwrapSmoothClipRef","NativeSmoothClipView","jsx","_jsx","reportedIndependentShadow","mountedControllers","WeakMap","useSingleControllerHost","controller","mounted","get","__DEV__","Error","set","current","delete","filterContainsDropShadow","filter","test","Array","isArray","some","entry","removeDropShadowFilter","remaining","replace","trim","undefined","length","sanitizeSmoothClipStyle","style","flat","flatten","hasIndependentShadow","boxShadow","shadowColor","shadowOffset","shadowOpacity","shadowRadius","elevation","console","error","sanitized","renderSmoothClipView","children","viewProps","forwardedRef","ref","initialFrame","canonical","driverId","id","clip","shadow","color","nativeProps","initialClipX","x","initialClipY","y","initialClipWidth","width","initialClipHeight","height","initialClipTopLeftRadius","topLeftRadius","initialClipTopRightRadius","topRightRadius","initialClipBottomRightRadius","bottomRightRadius","initialClipBottomLeftRadius","bottomLeftRadius","initialClipCurve","curve","initialContentTranslateX","contentTranslateX","initialContentTranslateY","contentTranslateY","initialContentScale","contentScale","initialClipBoxShadowEnabled","initialClipBoxShadowRed","initialClipBoxShadowGreen","initialClipBoxShadowBlue","initialClipBoxShadowAlpha","initialClipBoxShadowOffsetX","offsetX","initialClipBoxShadowOffsetY","offsetY","initialClipBoxShadowBlurRadius","blurRadius","initialClipBoxShadowSpreadDistance","spreadDistance","SmoothClipView","SmoothClipViewComponent","props"],"sourceRoot":"../../src","sources":["SmoothClipView.ios.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["forwardRef","useEffect","StyleSheet","getControllerRef","unwrapSmoothClipRef","rotationRadians","NativeSmoothClipView","jsx","_jsx","reportedIndependentShadow","mountedControllers","WeakMap","useSingleControllerHost","controller","mounted","get","__DEV__","Error","set","current","delete","filterContainsDropShadow","filter","test","Array","isArray","some","entry","removeDropShadowFilter","remaining","replace","trim","undefined","length","sanitizeSmoothClipStyle","style","flat","flatten","hasIndependentShadow","boxShadow","shadowColor","shadowOffset","shadowOpacity","shadowRadius","elevation","console","error","sanitized","renderSmoothClipView","children","viewProps","forwardedRef","ref","initialFrame","canonical","driverId","id","clip","shadow","color","nativeProps","initialClipX","x","initialClipY","y","initialClipWidth","width","initialClipHeight","height","initialClipTopLeftRadius","topLeftRadius","initialClipTopRightRadius","topRightRadius","initialClipBottomRightRadius","bottomRightRadius","initialClipBottomLeftRadius","bottomLeftRadius","initialClipCurve","curve","initialContentTranslateX","contentTranslateX","initialContentTranslateY","contentTranslateY","initialContentScale","contentScale","initialRotation","rotation","initialOpacity","opacity","initialClipBoxShadowEnabled","initialClipBoxShadowRed","initialClipBoxShadowGreen","initialClipBoxShadowBlue","initialClipBoxShadowAlpha","initialClipBoxShadowOffsetX","offsetX","initialClipBoxShadowOffsetY","offsetY","initialClipBoxShadowBlurRadius","blurRadius","initialClipBoxShadowSpreadDistance","spreadDistance","SmoothClipView","SmoothClipViewComponent","props"],"sourceRoot":"../../src","sources":["SmoothClipView.ios.tsx"],"mappings":"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","ignoreList":[]}
@@ -20,6 +20,8 @@ export interface NativeProps extends ViewProps {
20
20
  initialContentTranslateX: CodegenTypes.Double;
21
21
  initialContentTranslateY: CodegenTypes.Double;
22
22
  initialContentScale: CodegenTypes.Double;
23
+ initialRotation: CodegenTypes.Double;
24
+ initialOpacity?: CodegenTypes.WithDefault<CodegenTypes.Double, 1>;
23
25
  initialClipBoxShadowEnabled: boolean;
24
26
  initialClipBoxShadowRed: CodegenTypes.Double;
25
27
  initialClipBoxShadowGreen: CodegenTypes.Double;
@@ -54,7 +56,9 @@ interface NativeCommands {
54
56
  shadowOffsetX: CodegenTypes.Double,
55
57
  shadowOffsetY: CodegenTypes.Double,
56
58
  shadowBlurRadius: CodegenTypes.Double,
57
- shadowSpreadDistance: CodegenTypes.Double
59
+ shadowSpreadDistance: CodegenTypes.Double,
60
+ rotation: CodegenTypes.Double,
61
+ opacity: CodegenTypes.Double
58
62
  ) => void;
59
63
  }
60
64