@lodev09/react-native-true-sheet 3.0.0-beta.1 → 3.0.0-beta.10

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 (59) hide show
  1. package/README.md +7 -21
  2. package/RNTrueSheet.podspec +5 -1
  3. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerView.kt +58 -60
  4. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentView.kt +10 -18
  5. package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterView.kt +76 -20
  6. package/android/src/main/java/com/lodev09/truesheet/TrueSheetHeaderView.kt +38 -0
  7. package/android/src/main/java/com/lodev09/truesheet/TrueSheetHeaderViewManager.kt +21 -0
  8. package/android/src/main/java/com/lodev09/truesheet/TrueSheetPackage.kt +1 -0
  9. package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +104 -146
  10. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +315 -403
  11. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +24 -11
  12. package/android/src/main/java/com/lodev09/truesheet/core/RNScreensFragmentObserver.kt +116 -0
  13. package/android/src/main/java/com/lodev09/truesheet/utils/ScreenUtils.kt +33 -5
  14. package/android/src/main/jni/CMakeLists.txt +87 -0
  15. package/android/src/main/jni/TrueSheetSpec.h +17 -0
  16. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewComponentDescriptor.h +24 -0
  17. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.cpp +46 -0
  18. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.h +28 -0
  19. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewState.cpp +11 -0
  20. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewState.h +42 -0
  21. package/ios/TrueSheetContainerView.h +23 -0
  22. package/ios/TrueSheetContainerView.mm +80 -13
  23. package/ios/TrueSheetContentView.h +9 -1
  24. package/ios/TrueSheetContentView.mm +102 -24
  25. package/ios/TrueSheetFooterView.mm +2 -2
  26. package/ios/TrueSheetHeaderView.h +29 -0
  27. package/ios/TrueSheetHeaderView.mm +60 -0
  28. package/ios/TrueSheetView.h +0 -16
  29. package/ios/TrueSheetView.mm +208 -194
  30. package/ios/TrueSheetViewController.h +4 -3
  31. package/ios/TrueSheetViewController.mm +180 -272
  32. package/ios/utils/ConversionUtil.h +24 -0
  33. package/ios/utils/ConversionUtil.mm +50 -0
  34. package/ios/utils/LayoutUtil.h +11 -1
  35. package/ios/utils/LayoutUtil.mm +32 -1
  36. package/lib/module/TrueSheet.js +30 -33
  37. package/lib/module/TrueSheet.js.map +1 -1
  38. package/lib/module/fabric/TrueSheetContainerViewNativeComponent.ts +1 -1
  39. package/lib/module/fabric/TrueSheetHeaderViewNativeComponent.ts +8 -0
  40. package/lib/module/fabric/TrueSheetViewNativeComponent.ts +6 -8
  41. package/lib/typescript/src/TrueSheet.d.ts +0 -3
  42. package/lib/typescript/src/TrueSheet.d.ts.map +1 -1
  43. package/lib/typescript/src/TrueSheet.types.d.ts +30 -43
  44. package/lib/typescript/src/TrueSheet.types.d.ts.map +1 -1
  45. package/lib/typescript/src/fabric/TrueSheetContainerViewNativeComponent.d.ts.map +1 -1
  46. package/lib/typescript/src/fabric/TrueSheetHeaderViewNativeComponent.d.ts +6 -0
  47. package/lib/typescript/src/fabric/TrueSheetHeaderViewNativeComponent.d.ts.map +1 -0
  48. package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts +3 -6
  49. package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts.map +1 -1
  50. package/package.json +9 -5
  51. package/react-native.config.js +5 -2
  52. package/src/TrueSheet.tsx +34 -31
  53. package/src/TrueSheet.types.ts +47 -61
  54. package/src/fabric/TrueSheetContainerViewNativeComponent.ts +1 -1
  55. package/src/fabric/TrueSheetHeaderViewNativeComponent.ts +8 -0
  56. package/src/fabric/TrueSheetViewNativeComponent.ts +6 -8
  57. package/android/src/main/java/com/lodev09/truesheet/events/SizeChangeEvent.kt +0 -27
  58. package/ios/events/OnSizeChangeEvent.h +0 -28
  59. package/ios/events/OnSizeChangeEvent.mm +0 -30
@@ -22,21 +22,24 @@
22
22
  #import "events/OnDragEndEvent.h"
23
23
  #import "events/OnMountEvent.h"
24
24
  #import "events/OnPositionChangeEvent.h"
25
- #import "events/OnSizeChangeEvent.h"
26
25
  #import "events/OnWillDismissEvent.h"
27
26
  #import "events/OnWillPresentEvent.h"
28
27
  #import "utils/LayoutUtil.h"
29
28
  #import "utils/WindowUtil.h"
30
29
 
31
- #import <react/renderer/components/TrueSheetSpec/ComponentDescriptors.h>
32
30
  #import <react/renderer/components/TrueSheetSpec/EventEmitters.h>
33
31
  #import <react/renderer/components/TrueSheetSpec/Props.h>
34
32
  #import <react/renderer/components/TrueSheetSpec/RCTComponentViewHelpers.h>
33
+ #import <react/renderer/components/TrueSheetSpec/TrueSheetViewComponentDescriptor.h>
34
+ #import <react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.h>
35
+ #import <react/renderer/components/TrueSheetSpec/TrueSheetViewState.h>
35
36
 
36
37
  #import <React/RCTConversions.h>
37
38
  #import <React/RCTFabricComponentsPlugins.h>
39
+ #import <React/RCTLog.h>
38
40
  #import <React/RCTSurfaceTouchHandler.h>
39
41
  #import <React/RCTUtils.h>
42
+ #import <react/renderer/core/State.h>
40
43
 
41
44
  using namespace facebook::react;
42
45
 
@@ -47,26 +50,31 @@ using namespace facebook::react;
47
50
  TrueSheetContainerView *_containerView;
48
51
  TrueSheetViewController *_controller;
49
52
  RCTSurfaceTouchHandler *_touchHandler;
53
+ TrueSheetViewShadowNode::ConcreteState::Shared _state;
54
+ CGSize _lastStateSize;
50
55
  NSInteger _initialDetentIndex;
56
+ BOOL _scrollable;
51
57
  BOOL _initialDetentAnimated;
58
+ BOOL _isSheetUpdatePending;
52
59
  }
53
60
 
61
+ #pragma mark - Initialization
62
+
54
63
  - (instancetype)initWithFrame:(CGRect)frame {
55
64
  if (self = [super initWithFrame:frame]) {
56
65
  static const auto defaultProps = std::make_shared<const TrueSheetViewProps>();
57
66
  _props = defaultProps;
58
67
 
59
- // Initialize controller - persists across container lifecycle
60
68
  _controller = [[TrueSheetViewController alloc] init];
61
69
  _controller.delegate = self;
62
70
 
63
- // Initialize touch handler - will be attached to container when mounted
64
71
  _touchHandler = [[RCTSurfaceTouchHandler alloc] init];
65
-
66
72
  _containerView = nil;
67
-
73
+ _lastStateSize = CGSizeZero;
68
74
  _initialDetentIndex = -1;
69
75
  _initialDetentAnimated = YES;
76
+ _scrollable = NO;
77
+ _isSheetUpdatePending = NO;
70
78
  }
71
79
  return self;
72
80
  }
@@ -74,28 +82,23 @@ using namespace facebook::react;
74
82
  - (void)didMoveToWindow {
75
83
  [super didMoveToWindow];
76
84
 
77
- if (!self.window) {
85
+ if (!self.window)
78
86
  return;
79
- }
80
87
 
81
- // Register this view with the TurboModule when added to window
82
- // This ensures the tag is properly set by the framework
88
+ // Register with TurboModule when tag is set
83
89
  if (self.tag > 0) {
84
90
  [TrueSheetModule registerView:self withTag:@(self.tag)];
85
91
  }
86
92
  }
87
93
 
88
94
  - (void)dealloc {
89
- // Dismiss controller if presented
90
95
  if (_controller && _controller.presentingViewController) {
91
96
  [_controller dismissViewControllerAnimated:NO completion:nil];
92
97
  }
93
98
 
94
- // Clean up controller
95
99
  _controller.delegate = nil;
96
100
  _controller = nil;
97
101
 
98
- // Unregister this view from the TurboModule
99
102
  [TrueSheetModule unregisterViewWithTag:@(self.tag)];
100
103
  }
101
104
 
@@ -105,16 +108,172 @@ using namespace facebook::react;
105
108
  return concreteComponentDescriptorProvider<TrueSheetViewComponentDescriptor>();
106
109
  }
107
110
 
111
+ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps {
112
+ [super updateProps:props oldProps:oldProps];
113
+
114
+ const auto &newProps = *std::static_pointer_cast<TrueSheetViewProps const>(props);
115
+
116
+ // Detents (-1 represents "auto")
117
+ NSMutableArray *detents = [NSMutableArray new];
118
+ for (const auto &detent : newProps.detents) {
119
+ [detents addObject:@(detent)];
120
+ }
121
+ _controller.detents = detents;
122
+
123
+ // Background color
124
+ _controller.backgroundColor =
125
+ newProps.background == 0 ? nil : RCTUIColorFromSharedColor(SharedColor(newProps.background));
126
+
127
+ // Blur tint
128
+ _controller.blurTint = !newProps.blurTint.empty() ? RCTNSStringFromString(newProps.blurTint) : nil;
129
+
130
+ // Corner radius
131
+ _controller.cornerRadius = newProps.cornerRadius < 0 ? nil : @(newProps.cornerRadius);
132
+
133
+ // Max height
134
+ if (newProps.maxHeight != 0.0) {
135
+ _controller.maxHeight = @(newProps.maxHeight);
136
+ }
137
+
138
+ _controller.grabber = newProps.grabber;
139
+ _controller.pageSizing = newProps.pageSizing;
140
+ _controller.modalInPresentation = !newProps.dismissible;
141
+ _controller.dimmed = newProps.dimmed;
142
+
143
+ if (newProps.dimmedDetentIndex >= 0) {
144
+ _controller.dimmedDetentIndex = @(newProps.dimmedDetentIndex);
145
+ }
146
+
147
+ _initialDetentIndex = newProps.initialDetentIndex;
148
+ _initialDetentAnimated = newProps.initialDetentAnimated;
149
+ _scrollable = newProps.scrollable;
150
+
151
+ if (_containerView) {
152
+ _containerView.scrollViewPinningEnabled = _scrollable;
153
+ }
154
+ }
155
+
156
+ - (void)updateState:(const State::Shared &)state oldState:(const State::Shared &)oldState {
157
+ _state = std::static_pointer_cast<TrueSheetViewShadowNode::ConcreteState const>(state);
158
+
159
+ if (_controller) {
160
+ [self updateStateWithSize:_controller.view.frame.size];
161
+ }
162
+ }
163
+
164
+ /**
165
+ * Updates Fabric state with container width for Yoga layout.
166
+ */
167
+ - (void)updateStateWithSize:(CGSize)size {
168
+ if (!_state || size.width <= 0 || size.width == _lastStateSize.width)
169
+ return;
170
+
171
+ _lastStateSize = size;
172
+ _state->updateState([=](TrueSheetViewShadowNode::ConcreteState::Data const &oldData)
173
+ -> TrueSheetViewShadowNode::ConcreteState::SharedData {
174
+ auto newData = oldData;
175
+ newData.containerWidth = static_cast<float>(size.width);
176
+ return std::make_shared<TrueSheetViewShadowNode::ConcreteState::Data const>(newData);
177
+ });
178
+ }
179
+
180
+ - (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask {
181
+ [super finalizeUpdates:updateMask];
182
+
183
+ if (!(updateMask & RNComponentViewUpdateMaskProps) || !_controller)
184
+ return;
185
+
186
+ if (_containerView) {
187
+ [_containerView setupContentScrollViewPinning];
188
+ }
189
+
190
+ if (_controller.isPresented) {
191
+ [_controller.sheetPresentationController animateChanges:^{
192
+ [self->_controller setupSheetProps];
193
+ [self->_controller setupSheetDetents];
194
+ [self->_controller applyActiveDetent];
195
+ }];
196
+ } else if (_initialDetentIndex >= 0) {
197
+ [self presentAtIndex:_initialDetentIndex animated:_initialDetentAnimated completion:nil];
198
+ }
199
+ }
200
+
201
+ - (void)prepareForRecycle {
202
+ [super prepareForRecycle];
203
+
204
+ _lastStateSize = CGSizeZero;
205
+
206
+ if (_controller && _controller.presentingViewController) {
207
+ [_controller dismissViewControllerAnimated:YES completion:nil];
208
+ }
209
+
210
+ [TrueSheetModule unregisterViewWithTag:@(self.tag)];
211
+ }
212
+
213
+ #pragma mark - Child Component Mounting
214
+
215
+ - (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index {
216
+ if (![childComponentView isKindOfClass:[TrueSheetContainerView class]])
217
+ return;
218
+
219
+ if (_containerView != nil) {
220
+ RCTLogWarn(@"TrueSheet: Sheet can only have one container component.");
221
+ return;
222
+ }
223
+
224
+ _containerView = (TrueSheetContainerView *)childComponentView;
225
+ _containerView.delegate = self;
226
+
227
+ [_touchHandler attachToView:_containerView];
228
+ [_controller.view addSubview:_containerView];
229
+ [LayoutUtil pinView:_containerView toParentView:_controller.view edges:UIRectEdgeAll];
230
+ [_controller.view bringSubviewToFront:_containerView];
231
+
232
+ CGFloat contentHeight = [_containerView contentHeight];
233
+ if (contentHeight > 0) {
234
+ _controller.contentHeight = @(contentHeight);
235
+ }
236
+
237
+ CGFloat headerHeight = [_containerView headerHeight];
238
+ if (headerHeight > 0) {
239
+ _controller.headerHeight = @(headerHeight);
240
+ }
241
+
242
+ _containerView.scrollViewPinningEnabled = _scrollable;
243
+ [_containerView setupContentScrollViewPinning];
244
+
245
+ [OnMountEvent emit:_eventEmitter];
246
+ }
247
+
248
+ - (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index {
249
+ if (![childComponentView isKindOfClass:[TrueSheetContainerView class]])
250
+ return;
251
+
252
+ _containerView.delegate = nil;
253
+
254
+ if (_touchHandler) {
255
+ [_touchHandler detachFromView:_containerView];
256
+ }
257
+
258
+ [LayoutUtil unpinView:_containerView fromParentView:nil];
259
+ [_containerView removeFromSuperview];
260
+ _containerView = nil;
261
+ }
262
+
108
263
  #pragma mark - TurboModule Methods
109
264
 
110
265
  - (void)presentAtIndex:(NSInteger)index
111
266
  animated:(BOOL)animated
112
267
  completion:(nullable TrueSheetCompletionBlock)completion {
268
+ if (_controller.isBeingPresented) {
269
+ RCTLogWarn(@"TrueSheet: sheet is being presented. Wait for it to transition before presenting again.");
270
+ return;
271
+ }
272
+
113
273
  if (_controller.isPresented) {
114
274
  [_controller.sheetPresentationController animateChanges:^{
115
275
  [self->_controller setupActiveDetentWithIndex:index];
116
276
  }];
117
-
118
277
  if (completion) {
119
278
  completion(YES, nil);
120
279
  }
@@ -122,30 +281,23 @@ using namespace facebook::react;
122
281
  }
123
282
 
124
283
  UIViewController *presentingViewController = [self findPresentingViewController];
125
-
126
284
  if (!presentingViewController) {
127
285
  NSError *error = [NSError errorWithDomain:@"com.lodev09.TrueSheet"
128
286
  code:1001
129
287
  userInfo:@{NSLocalizedDescriptionKey : @"No presenting view controller found"}];
130
-
131
288
  if (completion) {
132
289
  completion(NO, error);
133
290
  }
134
291
  return;
135
292
  }
136
293
 
137
- // Setup our sheet properties
138
294
  [_controller setupSheetProps];
139
295
  [_controller setupSheetDetents];
140
-
141
- // Set to the given detent index
142
296
  [_controller setupActiveDetentWithIndex:index];
143
297
 
144
- // Present our sheet
145
- [presentingViewController presentViewController:self->_controller
298
+ [presentingViewController presentViewController:_controller
146
299
  animated:animated
147
300
  completion:^{
148
- // Call completion handler
149
301
  if (completion) {
150
302
  completion(YES, nil);
151
303
  }
@@ -153,6 +305,11 @@ using namespace facebook::react;
153
305
  }
154
306
 
155
307
  - (void)dismissAnimated:(BOOL)animated completion:(nullable TrueSheetCompletionBlock)completion {
308
+ if (_controller.isBeingDismissed) {
309
+ RCTLogWarn(@"TrueSheet: sheet is being dismissed. No need to dismiss it again.");
310
+ return;
311
+ }
312
+
156
313
  if (!_controller.isPresented) {
157
314
  if (completion) {
158
315
  completion(YES, nil);
@@ -176,184 +333,47 @@ using namespace facebook::react;
176
333
  }
177
334
  }
178
335
 
179
- - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps {
180
- [super updateProps:props oldProps:oldProps];
181
-
182
- const auto &newProps = *std::static_pointer_cast<TrueSheetViewProps const>(props);
183
-
184
- // Update detents - pass numbers directly (-1 represents "auto")
185
- NSMutableArray *detents = [NSMutableArray new];
186
- for (const auto &detent : newProps.detents) {
187
- [detents addObject:@(detent)];
188
- }
189
-
190
- _controller.detents = detents;
191
-
192
- // Update background color - always set it, even if 0 (which could be a valid color like black)
193
- UIColor *color = RCTUIColorFromSharedColor(SharedColor(newProps.background));
194
- _controller.backgroundColor = color;
195
-
196
- // Update blur tint - always set it to clear when removed
197
- _controller.blurTint = !newProps.blurTint.empty() ? RCTNSStringFromString(newProps.blurTint) : nil;
198
-
199
- // Update corner radius
200
- if (newProps.cornerRadius < 0) {
201
- _controller.cornerRadius = nil;
202
- } else {
203
- _controller.cornerRadius = @(newProps.cornerRadius);
204
- }
205
-
206
- // Update max height
207
- if (newProps.maxHeight != 0.0) {
208
- _controller.maxHeight = @(newProps.maxHeight);
209
- }
210
-
211
- // Update grabber
212
- _controller.grabber = newProps.grabber;
213
-
214
- // Update dismissible
215
- _controller.modalInPresentation = !newProps.dismissible;
216
-
217
- // Update dimmed
218
- _controller.dimmed = newProps.dimmed;
219
-
220
- // Update dimmedIndex
221
- if (newProps.dimmedIndex >= 0) {
222
- _controller.dimmedIndex = @(newProps.dimmedIndex);
223
- }
224
-
225
- // Store initial presentation settings
226
- _initialDetentIndex = newProps.initialDetentIndex;
227
- _initialDetentAnimated = newProps.initialDetentAnimated;
228
- }
229
-
230
- - (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask {
231
- [super finalizeUpdates:updateMask];
232
-
233
- // Apply controller updates after all props and children are updated
234
- if (updateMask & RNComponentViewUpdateMaskProps) {
235
- // Apply changes to presented sheet if needed
236
- if (_controller.isPresented) {
237
- [_controller.sheetPresentationController animateChanges:^{
238
- [self->_controller setupSheetDetents];
239
- [self->_controller applyActiveDetent];
240
- }];
241
- } else {
242
- // Handle initial presentation
243
- if (_initialDetentIndex >= 0 && !_controller.isPresented) {
244
- [self presentAtIndex:_initialDetentIndex animated:_initialDetentAnimated completion:nil];
245
- }
246
- }
247
- }
248
- }
249
-
250
- - (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index {
251
- // Check if it's a container view
252
- if ([childComponentView isKindOfClass:[TrueSheetContainerView class]]) {
253
- if (_containerView != nil) {
254
- NSLog(@"TrueSheet: Sheet can only have one container component.");
255
- return;
256
- }
257
-
258
- _containerView = (TrueSheetContainerView *)childComponentView;
259
-
260
- // Set this view as the container's delegate
261
- _containerView.delegate = self;
262
-
263
- // Attach touch handler to container for touch event handling
264
- [_touchHandler attachToView:_containerView];
265
-
266
- // Add to parent view hierarchy
267
- [_controller.view addSubview:_containerView];
268
-
269
- // Pin container to fill the entire parent view
270
- [LayoutUtil pinView:_containerView toParentView:_controller.view edges:UIRectEdgeAll];
271
-
272
- // Ensure container is above background view
273
- [_controller.view bringSubviewToFront:_containerView];
274
-
275
- // Get initial content height from container
276
- CGFloat contentHeight = [_containerView contentHeight];
277
- if (contentHeight > 0) {
278
- _controller.contentHeight = @(contentHeight);
279
- }
280
-
281
- // Emit onMount event when container is mounted
282
- [OnMountEvent emit:_eventEmitter];
283
- }
284
- }
285
-
286
- - (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index {
287
- if ([childComponentView isKindOfClass:[TrueSheetContainerView class]]) {
288
- _containerView.delegate = nil;
289
-
290
- // Detach touch handler
291
- if (_touchHandler) {
292
- [_touchHandler detachFromView:_containerView];
293
- }
294
-
295
- // Unpin and remove from view hierarchy
296
- [LayoutUtil unpinView:_containerView];
297
- [_containerView removeFromSuperview];
336
+ #pragma mark - TrueSheetContainerViewDelegate
298
337
 
299
- _containerView = nil;
300
- }
301
- }
338
+ /**
339
+ * Debounced sheet update to handle rapid content/header size changes.
340
+ */
341
+ - (void)updateSheetIfNeeded {
342
+ if (!_controller.isPresented || _isSheetUpdatePending)
343
+ return;
302
344
 
303
- - (void)prepareForRecycle {
304
- [super prepareForRecycle];
345
+ _isSheetUpdatePending = YES;
305
346
 
306
- // Dismiss controller if presented
307
- if (_controller && _controller.presentingViewController) {
308
- [_controller dismissViewControllerAnimated:YES completion:nil];
309
- }
347
+ dispatch_async(dispatch_get_main_queue(), ^{
348
+ self->_isSheetUpdatePending = NO;
349
+ self->_controller.layoutTransitioning = YES;
310
350
 
311
- // Unregister from the registry
312
- // Note: Re-registration will happen automatically when the component is reused
313
- [TrueSheetModule unregisterViewWithTag:@(self.tag)];
351
+ [self->_controller.sheetPresentationController animateChanges:^{
352
+ [self->_controller setupSheetDetents];
353
+ }];
354
+ });
314
355
  }
315
356
 
316
- #pragma mark - TrueSheetContainerViewDelegate
317
-
318
357
  - (void)containerViewContentDidChangeSize:(CGSize)newSize {
319
- // Clamp content height to container height to prevent unbounded growth with scrollable content
320
- CGFloat containerHeight = _controller.containerHeight;
321
- CGFloat contentHeight = containerHeight > 0 ? MIN(newSize.height, containerHeight) : newSize.height;
322
-
323
- _controller.contentHeight = @(contentHeight);
324
-
325
- // Update detents if sheet is already presented
326
- if (_controller.isPresented) {
327
- // Tell controller that we are transitioning from layout changes.
328
- // Controller viewDidLayoutSubviews will handle position notification.
329
- _controller.layoutTransitioning = YES;
358
+ _controller.contentHeight = @(newSize.height);
359
+ [self updateSheetIfNeeded];
360
+ }
330
361
 
331
- [_controller.sheetPresentationController animateChanges:^{
332
- [self->_controller setupSheetDetents];
333
- }];
334
- }
362
+ - (void)containerViewHeaderDidChangeSize:(CGSize)newSize {
363
+ _controller.headerHeight = @(newSize.height);
364
+ [self updateSheetIfNeeded];
335
365
  }
336
366
 
337
367
  #pragma mark - TrueSheetViewControllerDelegate
338
368
 
339
369
  - (void)viewControllerWillPresent {
340
370
  NSInteger index = [_controller currentDetentIndex];
341
- CGFloat position = _controller.currentPosition;
342
-
343
371
  _controller.activeDetentIndex = index;
344
-
345
- [OnWillPresentEvent emit:_eventEmitter index:index position:position];
346
-
347
- // Emit onChangeSize event to layout our container on JS
348
- CGSize controllerSize = _controller.view.frame.size;
349
- [OnSizeChangeEvent emit:_eventEmitter width:controllerSize.width height:controllerSize.height];
372
+ [OnWillPresentEvent emit:_eventEmitter index:index position:_controller.currentPosition];
350
373
  }
351
374
 
352
375
  - (void)viewControllerDidPresent {
353
- NSInteger index = [_controller currentDetentIndex];
354
- CGFloat position = _controller.currentPosition;
355
-
356
- [OnDidPresentEvent emit:_eventEmitter index:index position:position];
376
+ [OnDidPresentEvent emit:_eventEmitter index:[_controller currentDetentIndex] position:_controller.currentPosition];
357
377
  }
358
378
 
359
379
  - (void)viewControllerDidDrag:(UIGestureRecognizerState)state index:(NSInteger)index position:(CGFloat)position {
@@ -361,16 +381,13 @@ using namespace facebook::react;
361
381
  case UIGestureRecognizerStateBegan:
362
382
  [OnDragBeginEvent emit:_eventEmitter index:index position:position];
363
383
  break;
364
-
365
384
  case UIGestureRecognizerStateChanged:
366
385
  [OnDragChangeEvent emit:_eventEmitter index:index position:position];
367
386
  break;
368
-
369
387
  case UIGestureRecognizerStateEnded:
370
388
  case UIGestureRecognizerStateCancelled:
371
389
  [OnDragEndEvent emit:_eventEmitter index:index position:position];
372
390
  break;
373
-
374
391
  default:
375
392
  break;
376
393
  }
@@ -382,7 +399,6 @@ using namespace facebook::react;
382
399
 
383
400
  - (void)viewControllerDidDismiss {
384
401
  _controller.activeDetentIndex = -1;
385
-
386
402
  [OnDidDismissEvent emit:_eventEmitter];
387
403
  }
388
404
 
@@ -390,7 +406,6 @@ using namespace facebook::react;
390
406
  if (_controller.activeDetentIndex != index) {
391
407
  _controller.activeDetentIndex = index;
392
408
  }
393
-
394
409
  [OnDetentChangeEvent emit:_eventEmitter index:index position:position];
395
410
  }
396
411
 
@@ -399,29 +414,28 @@ using namespace facebook::react;
399
414
  }
400
415
 
401
416
  - (void)viewControllerDidChangeSize:(CGSize)size {
402
- [OnSizeChangeEvent emit:_eventEmitter width:size.width height:size.height];
417
+ [self updateStateWithSize:size];
403
418
  }
404
419
 
405
420
  #pragma mark - Private Helpers
406
421
 
407
422
  - (UIViewController *)findPresentingViewController {
408
423
  UIWindow *keyWindow = [WindowUtil keyWindow];
409
-
410
- if (!keyWindow) {
424
+ if (!keyWindow)
411
425
  return nil;
412
- }
413
426
 
414
427
  UIViewController *rootViewController = keyWindow.rootViewController;
428
+ if (!rootViewController)
429
+ return nil;
415
430
 
416
- // Find the top-most presented view controller
431
+ // Find topmost presented view controller
417
432
  while (rootViewController.presentedViewController) {
418
433
  UIViewController *presented = rootViewController.presentedViewController;
419
434
 
420
- // Skip TrueSheetViewController if it's being dismissed
435
+ // Skip TrueSheetViewController if being dismissed
421
436
  if ([presented isKindOfClass:[TrueSheetViewController class]] && presented.isBeingDismissed) {
422
437
  break;
423
438
  }
424
-
425
439
  rootViewController = presented;
426
440
  }
427
441
 
@@ -41,12 +41,14 @@ NS_ASSUME_NONNULL_BEGIN
41
41
  @property (nonatomic, strong) NSArray *detents;
42
42
  @property (nonatomic, strong, nullable) NSNumber *maxHeight;
43
43
  @property (nonatomic, strong, nullable) NSNumber *contentHeight;
44
+ @property (nonatomic, strong, nullable) NSNumber *headerHeight;
44
45
  @property (nonatomic, strong, nullable) UIColor *backgroundColor;
45
46
  @property (nonatomic, strong, nullable) NSNumber *cornerRadius;
46
47
  @property (nonatomic, assign) BOOL grabber;
47
48
  @property (nonatomic, assign) BOOL dimmed;
48
- @property (nonatomic, strong, nullable) NSNumber *dimmedIndex;
49
+ @property (nonatomic, strong, nullable) NSNumber *dimmedDetentIndex;
49
50
  @property (nonatomic, copy, nullable) NSString *blurTint;
51
+ @property (nonatomic, assign) BOOL pageSizing;
50
52
  @property (nonatomic, assign) BOOL layoutTransitioning;
51
53
  @property (nonatomic, assign) BOOL isPresented;
52
54
  @property (nonatomic, assign) NSInteger activeDetentIndex;
@@ -57,8 +59,7 @@ NS_ASSUME_NONNULL_BEGIN
57
59
  - (void)setupSheetProps;
58
60
  - (NSInteger)currentDetentIndex;
59
61
  - (CGFloat)currentPosition;
60
- - (CGFloat)currentHeight;
61
- - (CGFloat)containerHeight;
62
+ - (CGFloat)bottomInset;
62
63
 
63
64
  @end
64
65