@lodev09/react-native-true-sheet 3.0.0-beta.6 → 3.0.0-beta.8

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