@lodev09/react-native-true-sheet 4.0.0-beta.24 → 4.0.0-beta.26

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 (88) hide show
  1. package/README.md +2 -0
  2. package/android/src/main/java/com/lodev09/truesheet/TrueSheetModule.kt +13 -0
  3. package/android/src/main/java/com/lodev09/truesheet/TrueSheetOverlayView.kt +12 -1
  4. package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +120 -19
  5. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +103 -27
  6. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +18 -10
  7. package/android/src/main/java/com/lodev09/truesheet/core/RNScreensEventObserver.kt +31 -14
  8. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetBottomSheetBehavior.kt +9 -0
  9. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetBottomSheetView.kt +3 -16
  10. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetCoordinatorLayout.kt +14 -1
  11. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDimView.kt +11 -17
  12. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetGrabberView.kt +2 -4
  13. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetStackManager.kt +29 -38
  14. package/android/src/main/java/com/lodev09/truesheet/utils/ColorUtils.kt +19 -0
  15. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.cpp +6 -2
  16. package/ios/TrueSheetContainerView.h +1 -0
  17. package/ios/TrueSheetContainerView.mm +6 -0
  18. package/ios/TrueSheetContentView.h +1 -0
  19. package/ios/TrueSheetContentView.mm +2 -0
  20. package/ios/TrueSheetFooterView.mm +5 -0
  21. package/ios/TrueSheetModule.mm +11 -2
  22. package/ios/TrueSheetView.h +2 -0
  23. package/ios/TrueSheetView.mm +62 -9
  24. package/ios/TrueSheetViewController.h +14 -0
  25. package/ios/TrueSheetViewController.mm +490 -33
  26. package/ios/core/RNScreensEventObserver.mm +18 -1
  27. package/ios/core/TrueSheetDetentCalculator.h +11 -0
  28. package/ios/core/TrueSheetDetentCalculator.mm +17 -5
  29. package/ios/core/TrueSheetDimView.h +27 -0
  30. package/ios/core/TrueSheetDimView.mm +41 -0
  31. package/ios/core/TrueSheetKeyboardObserver.mm +98 -15
  32. package/lib/module/TrueSheet.js +88 -17
  33. package/lib/module/TrueSheet.js.map +1 -1
  34. package/lib/module/TrueSheet.web.js +150 -37
  35. package/lib/module/TrueSheet.web.js.map +1 -1
  36. package/lib/module/TrueSheetProvider.web.js +13 -9
  37. package/lib/module/TrueSheetProvider.web.js.map +1 -1
  38. package/lib/module/fabric/TrueSheetViewNativeComponent.ts +8 -0
  39. package/lib/module/scrollable.js +28 -0
  40. package/lib/module/scrollable.js.map +1 -0
  41. package/lib/module/web/keyboard.js +69 -0
  42. package/lib/module/web/keyboard.js.map +1 -0
  43. package/lib/module/web/layout.js +1 -1
  44. package/lib/module/web/layout.js.map +1 -1
  45. package/lib/module/web/vaul/context.js.map +1 -1
  46. package/lib/module/web/vaul/index.js +18 -8
  47. package/lib/module/web/vaul/index.js.map +1 -1
  48. package/lib/module/web/vaul/use-snap-points.js +15 -10
  49. package/lib/module/web/vaul/use-snap-points.js.map +1 -1
  50. package/lib/typescript/src/TrueSheet.d.ts +14 -1
  51. package/lib/typescript/src/TrueSheet.d.ts.map +1 -1
  52. package/lib/typescript/src/TrueSheet.types.d.ts +53 -2
  53. package/lib/typescript/src/TrueSheet.types.d.ts.map +1 -1
  54. package/lib/typescript/src/TrueSheet.web.d.ts.map +1 -1
  55. package/lib/typescript/src/TrueSheetProvider.web.d.ts +5 -1
  56. package/lib/typescript/src/TrueSheetProvider.web.d.ts.map +1 -1
  57. package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts +7 -0
  58. package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts.map +1 -1
  59. package/lib/typescript/src/navigation/types.d.ts +1 -1
  60. package/lib/typescript/src/navigation/types.d.ts.map +1 -1
  61. package/lib/typescript/src/scrollable.d.ts +2 -0
  62. package/lib/typescript/src/scrollable.d.ts.map +1 -0
  63. package/lib/typescript/src/web/keyboard.d.ts +15 -0
  64. package/lib/typescript/src/web/keyboard.d.ts.map +1 -0
  65. package/lib/typescript/src/web/layout.d.ts +1 -0
  66. package/lib/typescript/src/web/layout.d.ts.map +1 -1
  67. package/lib/typescript/src/web/vaul/context.d.ts +2 -1
  68. package/lib/typescript/src/web/vaul/context.d.ts.map +1 -1
  69. package/lib/typescript/src/web/vaul/index.d.ts +8 -1
  70. package/lib/typescript/src/web/vaul/index.d.ts.map +1 -1
  71. package/lib/typescript/src/web/vaul/types.d.ts +9 -0
  72. package/lib/typescript/src/web/vaul/types.d.ts.map +1 -1
  73. package/lib/typescript/src/web/vaul/use-snap-points.d.ts +3 -2
  74. package/lib/typescript/src/web/vaul/use-snap-points.d.ts.map +1 -1
  75. package/package.json +1 -1
  76. package/src/TrueSheet.tsx +91 -14
  77. package/src/TrueSheet.types.ts +60 -2
  78. package/src/TrueSheet.web.tsx +170 -41
  79. package/src/TrueSheetProvider.web.tsx +22 -13
  80. package/src/fabric/TrueSheetViewNativeComponent.ts +8 -0
  81. package/src/navigation/types.ts +3 -0
  82. package/src/scrollable.ts +25 -0
  83. package/src/web/keyboard.ts +79 -0
  84. package/src/web/layout.ts +1 -1
  85. package/src/web/vaul/context.ts +2 -1
  86. package/src/web/vaul/index.tsx +20 -5
  87. package/src/web/vaul/types.ts +10 -0
  88. package/src/web/vaul/use-snap-points.ts +19 -9
@@ -284,6 +284,8 @@ using namespace facebook::react;
284
284
 
285
285
  _controller.placement = newProps.placement;
286
286
 
287
+ _controller.foldOptions = newProps.foldOptions;
288
+
287
289
  _controller.grabber = newProps.grabber;
288
290
 
289
291
  // Grabber options - check if any non-default values are set
@@ -317,6 +319,8 @@ using namespace facebook::react;
317
319
  _controller.dismissible = newProps.dismissible;
318
320
  _controller.draggable = newProps.draggable;
319
321
  _controller.dimmed = newProps.dimmed;
322
+ _controller.dimOpacity = newProps.dimOpacity < 0 ? nil : @(newProps.dimOpacity);
323
+ _controller.dimColor = RCTUIColorFromSharedColor(newProps.dimColor);
320
324
 
321
325
  if (newProps.dimmedDetentIndex >= 0) {
322
326
  _controller.dimmedDetentIndex = @(newProps.dimmedDetentIndex);
@@ -419,7 +423,8 @@ using namespace facebook::react;
419
423
  [self setupScrollable];
420
424
 
421
425
  if (_controller.isPresented) {
422
- [self applySheetPropsUpdate];
426
+ _pendingPropsUpdate = YES;
427
+ [self setupSheetDetentsForSizeChange];
423
428
  } else if (_controller.isBeingPresented) {
424
429
  _pendingPropsUpdate = YES;
425
430
  } else if (_initialDetentIndex >= 0) {
@@ -630,6 +635,8 @@ using namespace facebook::react;
630
635
  _controller.peekContentHeight = @([_containerView peekContentHeight]);
631
636
  }
632
637
  _pendingSizeChange = NO;
638
+ // Props queued while the previous presentation dismissed — applied above.
639
+ _pendingPropsUpdate = NO;
633
640
 
634
641
  [self refreshFooterBottomInset];
635
642
  [_controller setupSheetDetents];
@@ -719,6 +726,20 @@ using namespace facebook::react;
719
726
  return;
720
727
  }
721
728
 
729
+ // Still animating in (isPresented flips at viewDidAppear): dismiss once the presentation lands
730
+ id<UIViewControllerTransitionCoordinator> presentCoordinator =
731
+ _controller.isBeingPresented ? _controller.transitionCoordinator : nil;
732
+ if (presentCoordinator) {
733
+ __weak __typeof(self) weakSelf = self;
734
+ [presentCoordinator animateAlongsideTransition:nil
735
+ completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
736
+ dispatch_async(dispatch_get_main_queue(), ^{
737
+ [weakSelf dismissAnimated:animated completion:completion];
738
+ });
739
+ }];
740
+ return;
741
+ }
742
+
722
743
  if (_controller.isBeingDismissed || !_controller.isPresented) {
723
744
  RCTLogWarn(@"TrueSheet: sheet is already dismissed. No need to dismiss it again.");
724
745
 
@@ -768,7 +789,8 @@ using namespace facebook::react;
768
789
  #pragma mark - TrueSheetContainerViewDelegate
769
790
 
770
791
  /**
771
- * Debounced sheet update to handle rapid content/header size changes.
792
+ * Coalesces prop and size changes outside Fabric's mount transaction so
793
+ * the footer's layout can mount inside UIKit's resize animation.
772
794
  */
773
795
  - (void)setupSheetDetentsForSizeChange {
774
796
  // Keep the footer's absorbed inset in sync with the latest measured heights
@@ -784,26 +806,52 @@ using namespace facebook::react;
784
806
  }
785
807
 
786
808
  // Not presented: presentAtIndex measures at present time.
787
- // Dismissing: the sheet is going away — touching detents perturbs the
788
- // presentation stack, visibly glitching the sheet behind.
789
- if (!_controller.isPresented || _controller.isBeingDismissed)
809
+ if (!_controller.isPresented || _isSheetUpdatePending)
790
810
  return;
791
811
 
792
- if (_isSheetUpdatePending)
812
+ // Dismissing: the sheet is going away — touching detents perturbs the
813
+ // presentation stack, visibly glitching the sheet behind. An interactive
814
+ // dismiss can still cancel, so retry once the transition resolves.
815
+ if (_controller.isBeingDismissed) {
816
+ id<UIViewControllerTransitionCoordinator> coordinator = _controller.transitionCoordinator;
817
+ if (coordinator) {
818
+ _isSheetUpdatePending = YES;
819
+
820
+ __weak __typeof(self) weakSelf = self;
821
+ [coordinator animateAlongsideTransition:nil
822
+ completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
823
+ dispatch_async(dispatch_get_main_queue(), ^{
824
+ __typeof(self) strongSelf = weakSelf;
825
+ if (!strongSelf)
826
+ return;
827
+
828
+ strongSelf->_isSheetUpdatePending = NO;
829
+ [strongSelf setupSheetDetentsForSizeChange];
830
+ });
831
+ }];
832
+ }
793
833
  return;
834
+ }
794
835
 
795
836
  _isSheetUpdatePending = YES;
796
837
 
797
838
  dispatch_async(dispatch_get_main_queue(), ^{
798
839
  self->_isSheetUpdatePending = NO;
799
- if (!self->_containerView || self->_controller.isBeingDismissed)
840
+ if (!self->_containerView || !self->_controller.isPresented || self->_controller.isBeingDismissed)
800
841
  return;
801
842
 
802
843
  // Refresh here (not just on peek size events) since the peek's offset
803
844
  // within the content can change without its own size changing.
804
845
  self->_controller.peekContentHeight = @([self->_containerView peekContentHeight]);
805
846
  [self refreshFooterBottomInset];
847
+
848
+ // Size first: the props rebuild refreshes the heights itself, hiding the
849
+ // change from the controller and skipping its post-resize settle.
806
850
  [self->_controller setupSheetDetentsForSizeChange];
851
+ if (self->_pendingPropsUpdate) {
852
+ self->_pendingPropsUpdate = NO;
853
+ [self applySheetPropsUpdate];
854
+ }
807
855
  });
808
856
  }
809
857
 
@@ -820,7 +868,11 @@ using namespace facebook::react;
820
868
  - (void)containerViewFooterDidChangeSize:(CGSize)newSize {
821
869
  [self syncFooterMetrics];
822
870
  [self setupSheetDetentsForSizeChange];
823
- [_controller setupAccessibilityContainer];
871
+ [_controller refreshAccessibilityContainer];
872
+ }
873
+
874
+ - (void)containerViewDidMountTransaction {
875
+ [_controller refreshAccessibilityContainerIfFooterChanged];
824
876
  }
825
877
 
826
878
  - (void)containerViewPeekDidChangeSize:(CGSize)newSize {
@@ -836,11 +888,12 @@ using namespace facebook::react;
836
888
 
837
889
  - (void)viewControllerWillPresentAtIndex:(NSInteger)index position:(CGFloat)position detent:(CGFloat)detent {
838
890
  _controller.activeDetentIndex = index;
891
+ // Before emitting, so an input focused in onWillPresent raises a tracked keyboard
892
+ [_containerView setupKeyboardObserverWithViewController:_controller];
839
893
  [TrueSheetLifecycleEvents emitWillPresent:_eventEmitter index:index position:position detent:detent];
840
894
  }
841
895
 
842
896
  - (void)viewControllerDidPresentAtIndex:(NSInteger)index position:(CGFloat)position detent:(CGFloat)detent {
843
- [_containerView setupKeyboardObserverWithViewController:_controller];
844
897
  [TrueSheetLifecycleEvents emitDidPresent:_eventEmitter index:index position:position detent:detent];
845
898
 
846
899
  if (_pendingPropsUpdate) {
@@ -78,10 +78,13 @@ NS_ASSUME_NONNULL_BEGIN
78
78
  @property (nonatomic, assign) facebook::react::TrueSheetViewAccessibilityOptionsStruct accessibilityOptions;
79
79
  @property (nonatomic, assign) BOOL draggable;
80
80
  @property (nonatomic, assign) BOOL dimmed;
81
+ @property (nonatomic, strong, nullable) UIColor *dimColor;
82
+ @property (nonatomic, strong, nullable) NSNumber *dimOpacity;
81
83
  @property (nonatomic, strong, nullable) NSNumber *dimmedDetentIndex;
82
84
  @property (nonatomic, assign) facebook::react::TrueSheetViewBackgroundBlur backgroundBlur;
83
85
  @property (nonatomic, assign) facebook::react::TrueSheetViewPresentation presentation;
84
86
  @property (nonatomic, assign) facebook::react::TrueSheetViewPlacement placement;
87
+ @property (nonatomic, assign) facebook::react::TrueSheetViewFoldOptionsStruct foldOptions;
85
88
  @property (nonatomic, assign) facebook::react::TrueSheetViewInsetAdjustment insetAdjustment;
86
89
  @property (nonatomic, assign) BOOL scrollingExpandsSheet;
87
90
  @property (nonatomic, assign) CGFloat footerKeyboardOffset;
@@ -107,6 +110,13 @@ NS_ASSUME_NONNULL_BEGIN
107
110
  * announced — ahead of the grow/shrink animation, unlike keyboardSheetGrown.
108
111
  */
109
112
  @property (nonatomic, assign) CGFloat keyboardHeight;
113
+
114
+ /**
115
+ * How far UIKit grows the sheet for the iPadOS minimized keyboard, which it
116
+ * treats as docked. Taken off every detent so the sheet stays put.
117
+ */
118
+ @property (nonatomic, assign) CGFloat minimizedKeyboardOverlap;
119
+
110
120
  @property (nonatomic, readonly) BOOL isTopmostPresentedController;
111
121
  @property (nonatomic, readonly) BOOL isStackedBehindChild;
112
122
  @property (nonatomic, weak, nullable) UIView *accessibilityContentView;
@@ -128,6 +138,9 @@ NS_ASSUME_NONNULL_BEGIN
128
138
  @property (nonatomic, assign) CGFloat appliedFooterBottomInset;
129
139
 
130
140
  - (void)setupAccessibilityContainer;
141
+ - (void)refreshAccessibilityContainer;
142
+ - (void)refreshAccessibilityContainerIfFooterChanged;
143
+
131
144
  - (void)applyActiveDetent;
132
145
  - (void)setupActiveDetentWithIndex:(NSInteger)index;
133
146
  - (void)resizeToDetentIndex:(NSInteger)index;
@@ -136,6 +149,7 @@ NS_ASSUME_NONNULL_BEGIN
136
149
  - (void)setupSheetDetents;
137
150
  - (void)setupSheetDetentsForSizeChange;
138
151
  - (void)setupSheetDetentsForDetentsChange;
152
+ - (void)invalidateDetents;
139
153
  - (void)setupDraggable;
140
154
  - (void)setupAnchorViewInView:(UIView *)parentView;
141
155