@lodev09/react-native-true-sheet 3.1.0-beta.6 → 3.1.0-beta.7

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.
@@ -223,7 +223,7 @@ using namespace facebook::react;
223
223
  [self->_controller setupSheetDetents];
224
224
  [self->_controller applyActiveDetent];
225
225
  }];
226
- [_controller updateDraggable];
226
+ [_controller setupDraggable];
227
227
  } else if (_initialDetentIndex >= 0) {
228
228
  [self presentAtIndex:_initialDetentIndex animated:_initialDetentAnimated completion:nil];
229
229
  }
@@ -361,7 +361,7 @@ using namespace facebook::react;
361
361
  /**
362
362
  * Debounced sheet update to handle rapid content/header size changes.
363
363
  */
364
- - (void)updateSheetIfNeeded {
364
+ - (void)setupSheetDetentsForSizeChange {
365
365
  if (!_controller.isPresented || _isSheetUpdatePending)
366
366
  return;
367
367
 
@@ -371,19 +371,19 @@ using namespace facebook::react;
371
371
  self->_isSheetUpdatePending = NO;
372
372
 
373
373
  [self->_controller.sheetPresentationController animateChanges:^{
374
- [self->_controller setupSheetDetents];
374
+ [self->_controller setupSheetDetentsForSizeChange];
375
375
  }];
376
376
  });
377
377
  }
378
378
 
379
379
  - (void)containerViewContentDidChangeSize:(CGSize)newSize {
380
380
  _controller.contentHeight = @(newSize.height);
381
- [self updateSheetIfNeeded];
381
+ [self setupSheetDetentsForSizeChange];
382
382
  }
383
383
 
384
384
  - (void)containerViewHeaderDidChangeSize:(CGSize)newSize {
385
385
  _controller.headerHeight = @(newSize.height);
386
- [self updateSheetIfNeeded];
386
+ [self setupSheetDetentsForSizeChange];
387
387
  }
388
388
 
389
389
  #pragma mark - TrueSheetViewControllerDelegate
@@ -69,9 +69,10 @@ NS_ASSUME_NONNULL_BEGIN
69
69
  - (void)applyActiveDetent;
70
70
  - (void)setupActiveDetentWithIndex:(NSInteger)index;
71
71
  - (void)resizeToDetentIndex:(NSInteger)index;
72
- - (void)setupSheetDetents;
73
72
  - (void)setupSheetProps;
74
- - (void)updateDraggable;
73
+ - (void)setupSheetDetents;
74
+ - (void)setupSheetDetentsForSizeChange;
75
+ - (void)setupDraggable;
75
76
 
76
77
  @end
77
78
 
@@ -22,13 +22,15 @@
22
22
 
23
23
  @implementation TrueSheetViewController {
24
24
  CGFloat _lastPosition;
25
- BOOL _isDragging;
26
25
  NSInteger _pendingDetentIndex;
26
+ BOOL _pendingContentSizeChange;
27
27
 
28
- // Transitioning tracker
28
+ // Position tracking
29
29
  CADisplayLink *_transitioningTimer;
30
30
  UIView *_transitionFakeView;
31
+ BOOL _isDragging;
31
32
  BOOL _isTransitioning;
33
+ BOOL _isTrackingPositionFromLayout;
32
34
 
33
35
  // Reference to parent TrueSheetViewController (if presented from another sheet)
34
36
  __weak TrueSheetViewController *_parentSheetController;
@@ -61,10 +63,13 @@
61
63
  _lastPosition = 0;
62
64
  _isDragging = NO;
63
65
  _isPresented = NO;
66
+ _pendingContentSizeChange = NO;
64
67
  _activeDetentIndex = -1;
65
68
  _pendingDetentIndex = -1;
69
+
66
70
  _isTransitioning = NO;
67
71
  _transitionFakeView = [UIView new];
72
+ _isTrackingPositionFromLayout = NO;
68
73
 
69
74
  _blurInteraction = YES;
70
75
  _resolvedDetentPositions = [NSMutableArray array];
@@ -200,6 +205,9 @@
200
205
  if ([self.delegate respondsToSelector:@selector(viewControllerDidFocus)]) {
201
206
  [self.delegate viewControllerDidFocus];
202
207
  }
208
+
209
+ // Emit correct position after presentation
210
+ [self emitChangePositionDelegateWithPosition:self.currentPosition realtime:NO debug:@"did present"];
203
211
  });
204
212
 
205
213
  [self setupGestureRecognizer];
@@ -264,6 +272,31 @@
264
272
  }
265
273
  }
266
274
 
275
+ - (void)viewWillLayoutSubviews {
276
+ [super viewWillLayoutSubviews];
277
+
278
+ if (!_isTransitioning) {
279
+ _isTrackingPositionFromLayout = YES;
280
+
281
+ UIViewController *presented = self.presentedViewController;
282
+
283
+ // Not realtime when another controller is presented that triggers our layout
284
+ BOOL hasPresentedController = presented != nil && !presented.isBeingPresented && !presented.isBeingDismissed;
285
+
286
+ BOOL realtime = !hasPresentedController;
287
+
288
+ if (_pendingContentSizeChange) {
289
+ _pendingContentSizeChange = NO;
290
+ realtime = NO;
291
+
292
+ // Store resolved position after content size changes
293
+ [self storeResolvedPositionForIndex:self.currentDetentIndex];
294
+ }
295
+
296
+ [self emitChangePositionDelegateWithPosition:self.currentPosition realtime:realtime debug:@"layout"];
297
+ }
298
+ }
299
+
267
300
  - (void)viewDidLayoutSubviews {
268
301
  [super viewDidLayoutSubviews];
269
302
 
@@ -271,15 +304,6 @@
271
304
  [self.delegate viewControllerDidChangeSize:self.view.frame.size];
272
305
  }
273
306
 
274
- UIViewController *presented = self.presentedViewController;
275
- BOOL hasPresentedController = presented != nil && !presented.isBeingPresented && !presented.isBeingDismissed;
276
-
277
- if (!_isDragging && !_isTransitioning) {
278
- // Update stored position for current detent (handles content size changes)
279
- [self storeResolvedPositionForIndex:self.currentDetentIndex];
280
- [self emitChangePositionDelegateWithPosition:self.currentPosition realtime:hasPresentedController];
281
- }
282
-
283
307
  // Emit pending detent change after programmatic resize settles
284
308
  if (_pendingDetentIndex >= 0) {
285
309
  NSInteger pendingIndex = _pendingDetentIndex;
@@ -289,9 +313,14 @@
289
313
  if ([self.delegate respondsToSelector:@selector(viewControllerDidChangeDetent:position:detent:)]) {
290
314
  CGFloat detent = [self detentValueForIndex:pendingIndex];
291
315
  [self.delegate viewControllerDidChangeDetent:pendingIndex position:self.currentPosition detent:detent];
316
+
317
+ // Emit position for the final position
318
+ [self emitChangePositionDelegateWithPosition:self.currentPosition realtime:NO debug:@"pending detent change"];
292
319
  }
293
320
  });
294
321
  }
322
+
323
+ _isTrackingPositionFromLayout = NO;
295
324
  }
296
325
 
297
326
  #pragma mark - Presentation Tracking (for RN Screens integration)
@@ -402,7 +431,7 @@
402
431
  }
403
432
  }
404
433
 
405
- - (void)updateDraggable {
434
+ - (void)setupDraggable {
406
435
  UIView *presentedView = self.presentedView;
407
436
  if (!presentedView)
408
437
  return;
@@ -432,7 +461,9 @@
432
461
  _isDragging = YES;
433
462
  break;
434
463
  case UIGestureRecognizerStateChanged:
435
- [self emitChangePositionDelegateWithPosition:self.currentPosition realtime:YES];
464
+ if (!_isTrackingPositionFromLayout) {
465
+ [self emitChangePositionDelegateWithPosition:self.currentPosition realtime:YES debug:@"drag change"];
466
+ }
436
467
  break;
437
468
  case UIGestureRecognizerStateEnded:
438
469
  case UIGestureRecognizerStateCancelled: {
@@ -440,7 +471,9 @@
440
471
  dispatch_async(dispatch_get_main_queue(), ^{
441
472
  // Store resolved position when drag ends
442
473
  [self storeResolvedPositionForIndex:self.currentDetentIndex];
443
- [self emitChangePositionDelegateWithPosition:self.currentPosition realtime:NO];
474
+
475
+ // Emit the correct position after dragging
476
+ [self emitChangePositionDelegateWithPosition:self.currentPosition realtime:NO debug:@"drag end"];
444
477
  });
445
478
  }
446
479
 
@@ -461,7 +494,7 @@
461
494
  _isTransitioning = YES;
462
495
 
463
496
  CGRect dismissedFrame = CGRectMake(0, self.screenHeight, 0, 0);
464
- CGRect presentedFrame = CGRectMake(0, self.presentedView.frame.origin.y, 0, 0);
497
+ CGRect presentedFrame = CGRectMake(0, self.currentPosition, 0, 0);
465
498
 
466
499
  // Set starting fake view position
467
500
  _transitionFakeView.frame = self.isDismissing ? presentedFrame : dismissedFrame;
@@ -470,7 +503,7 @@
470
503
  auto animation = ^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
471
504
  [[context containerView] addSubview:self->_transitionFakeView];
472
505
 
473
- // Set the fake view target position
506
+ // Set ending fake view position
474
507
  self->_transitionFakeView.frame = self.isDismissing ? dismissedFrame : presentedFrame;
475
508
 
476
509
  self->_transitioningTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleTransitionTracker)];
@@ -495,16 +528,17 @@
495
528
 
496
529
  if (self.currentPosition >= self.screenHeight) {
497
530
  // Dismissing position
498
- [self emitChangePositionDelegateWithPosition:layerPosition realtime:YES];
531
+ CGFloat position = fmax(_lastPosition, layerPosition);
532
+ [self emitChangePositionDelegateWithPosition:position realtime:YES debug:@"transition out"];
499
533
  } else {
500
534
  // Presenting position
501
535
  CGFloat position = fmax(self.currentPosition, layerPosition);
502
- [self emitChangePositionDelegateWithPosition:position realtime:YES];
536
+ [self emitChangePositionDelegateWithPosition:position realtime:YES debug:@"transition in"];
503
537
  }
504
538
  }
505
539
  }
506
540
 
507
- - (void)emitChangePositionDelegateWithPosition:(CGFloat)position realtime:(BOOL)realtime {
541
+ - (void)emitChangePositionDelegateWithPosition:(CGFloat)position realtime:(BOOL)realtime debug:(NSString *)debug {
508
542
  // Use epsilon comparison to avoid missing updates due to floating point precision
509
543
  if (fabs(_lastPosition - position) > 0.01) {
510
544
  _lastPosition = position;
@@ -514,6 +548,9 @@
514
548
  if ([self.delegate respondsToSelector:@selector(viewControllerDidChangePosition:position:detent:realtime:)]) {
515
549
  [self.delegate viewControllerDidChangePosition:index position:position detent:detent realtime:realtime];
516
550
  }
551
+
552
+ // Debug position tracking
553
+ // NSLog(@"position from %@: %f, realtime: %i", debug, position, realtime);
517
554
  }
518
555
  }
519
556
 
@@ -658,6 +695,11 @@
658
695
 
659
696
  #pragma mark - Sheet Configuration
660
697
 
698
+ - (void)setupSheetDetentsForSizeChange {
699
+ _pendingContentSizeChange = YES;
700
+ [self setupSheetDetents];
701
+ }
702
+
661
703
  - (void)setupSheetDetents {
662
704
  UISheetPresentationController *sheet = self.sheetPresentationController;
663
705
  if (!sheet)
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- import { createContext, useContext, useMemo } from 'react';
3
+ import { createContext, useContext } from 'react';
4
4
  import { useWindowDimensions } from 'react-native';
5
5
  import { useSharedValue } from 'react-native-reanimated';
6
6
  import { jsx as _jsx } from "react/jsx-runtime";
@@ -31,11 +31,11 @@ export const ReanimatedTrueSheetProvider = ({
31
31
  const animatedPosition = useSharedValue(height);
32
32
  const animatedIndex = useSharedValue(-1);
33
33
  const animatedDetent = useSharedValue(0);
34
- const value = useMemo(() => ({
34
+ const value = {
35
35
  animatedPosition,
36
36
  animatedIndex,
37
37
  animatedDetent
38
- }), [animatedPosition, animatedIndex, animatedDetent]);
38
+ };
39
39
  return /*#__PURE__*/_jsx(ReanimatedTrueSheetContext.Provider, {
40
40
  value: value,
41
41
  children: children
@@ -1 +1 @@
1
- {"version":3,"names":["createContext","useContext","useMemo","useWindowDimensions","useSharedValue","jsx","_jsx","ReanimatedTrueSheetContext","ReanimatedTrueSheetProvider","children","height","animatedPosition","animatedIndex","animatedDetent","value","Provider","useReanimatedTrueSheet","context","Error"],"sourceRoot":"../../../src","sources":["reanimated/ReanimatedTrueSheetProvider.tsx"],"mappings":";;AAAA,SAASA,aAAa,EAAEC,UAAU,EAAEC,OAAO,QAAwB,OAAO;AAC1E,SAASC,mBAAmB,QAAQ,cAAc;AAClD,SAASC,cAAc,QAA0B,yBAAyB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAmB3E,MAAMC,0BAA0B,gBAAGP,aAAa,CAAyC,IAAI,CAAC;AAM9F;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMQ,2BAA2B,GAAGA,CAAC;EAAEC;AAA2C,CAAC,KAAK;EAC7F,MAAM;IAAEC;EAAO,CAAC,GAAGP,mBAAmB,CAAC,CAAC;EACxC,MAAMQ,gBAAgB,GAAGP,cAAc,CAACM,MAAM,CAAC;EAC/C,MAAME,aAAa,GAAGR,cAAc,CAAC,CAAC,CAAC,CAAC;EACxC,MAAMS,cAAc,GAAGT,cAAc,CAAC,CAAC,CAAC;EAExC,MAAMU,KAAK,GAAGZ,OAAO,CACnB,OAAO;IACLS,gBAAgB;IAChBC,aAAa;IACbC;EACF,CAAC,CAAC,EACF,CAACF,gBAAgB,EAAEC,aAAa,EAAEC,cAAc,CAClD,CAAC;EAED,oBACEP,IAAA,CAACC,0BAA0B,CAACQ,QAAQ;IAACD,KAAK,EAAEA,KAAM;IAAAL,QAAA,EAC/CA;EAAQ,CAC0B,CAAC;AAE1C,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMO,sBAAsB,GAAGA,CAAA,KAAuC;EAC3E,MAAMC,OAAO,GAAGhB,UAAU,CAACM,0BAA0B,CAAC;EAEtD,IAAI,CAACU,OAAO,EAAE;IACZ,MAAM,IAAIC,KAAK,CACb,4EAA4E,GAC1E,2EACJ,CAAC;EACH;EAEA,OAAOD,OAAO;AAChB,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["createContext","useContext","useWindowDimensions","useSharedValue","jsx","_jsx","ReanimatedTrueSheetContext","ReanimatedTrueSheetProvider","children","height","animatedPosition","animatedIndex","animatedDetent","value","Provider","useReanimatedTrueSheet","context","Error"],"sourceRoot":"../../../src","sources":["reanimated/ReanimatedTrueSheetProvider.tsx"],"mappings":";;AAAA,SAASA,aAAa,EAAEC,UAAU,QAAwB,OAAO;AACjE,SAASC,mBAAmB,QAAQ,cAAc;AAClD,SAASC,cAAc,QAA0B,yBAAyB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAmB3E,MAAMC,0BAA0B,gBAAGN,aAAa,CAAyC,IAAI,CAAC;AAM9F;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMO,2BAA2B,GAAGA,CAAC;EAAEC;AAA2C,CAAC,KAAK;EAC7F,MAAM;IAAEC;EAAO,CAAC,GAAGP,mBAAmB,CAAC,CAAC;EACxC,MAAMQ,gBAAgB,GAAGP,cAAc,CAACM,MAAM,CAAC;EAC/C,MAAME,aAAa,GAAGR,cAAc,CAAC,CAAC,CAAC,CAAC;EACxC,MAAMS,cAAc,GAAGT,cAAc,CAAC,CAAC,CAAC;EAExC,MAAMU,KAAsC,GAAG;IAC7CH,gBAAgB;IAChBC,aAAa;IACbC;EACF,CAAC;EAED,oBACEP,IAAA,CAACC,0BAA0B,CAACQ,QAAQ;IAACD,KAAK,EAAEA,KAAM;IAAAL,QAAA,EAC/CA;EAAQ,CAC0B,CAAC;AAE1C,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMO,sBAAsB,GAAGA,CAAA,KAAuC;EAC3E,MAAMC,OAAO,GAAGf,UAAU,CAACK,0BAA0B,CAAC;EAEtD,IAAI,CAACU,OAAO,EAAE;IACZ,MAAM,IAAIC,KAAK,CACb,4EAA4E,GAC1E,2EACJ,CAAC;EACH;EAEA,OAAOD,OAAO;AAChB,CAAC","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"ReanimatedTrueSheetProvider.d.ts","sourceRoot":"","sources":["../../../../src/reanimated/ReanimatedTrueSheetProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE3E,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3E,MAAM,WAAW,+BAA+B;IAC9C;;OAEG;IACH,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACtC;;;OAGG;IACH,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC;;;OAGG;IACH,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACrC;AAID,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,2BAA2B,GAAI,cAAc,gCAAgC,4CAoBzF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,sBAAsB,QAAO,+BAWzC,CAAC"}
1
+ {"version":3,"file":"ReanimatedTrueSheetProvider.d.ts","sourceRoot":"","sources":["../../../../src/reanimated/ReanimatedTrueSheetProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAElE,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3E,MAAM,WAAW,+BAA+B;IAC9C;;OAEG;IACH,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACtC;;;OAGG;IACH,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC;;;OAGG;IACH,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACrC;AAID,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,2BAA2B,GAAI,cAAc,gCAAgC,4CAiBzF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,sBAAsB,QAAO,+BAWzC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lodev09/react-native-true-sheet",
3
- "version": "3.1.0-beta.6",
3
+ "version": "3.1.0-beta.7",
4
4
  "description": "The true native bottom sheet experience for your React Native Apps.",
5
5
  "source": "./src/index.ts",
6
6
  "main": "./lib/module/index.js",
@@ -1,4 +1,4 @@
1
- import { createContext, useContext, useMemo, type ReactNode } from 'react';
1
+ import { createContext, useContext, type ReactNode } from 'react';
2
2
  import { useWindowDimensions } from 'react-native';
3
3
  import { useSharedValue, type SharedValue } from 'react-native-reanimated';
4
4
 
@@ -48,14 +48,11 @@ export const ReanimatedTrueSheetProvider = ({ children }: ReanimatedTrueSheetPro
48
48
  const animatedIndex = useSharedValue(-1);
49
49
  const animatedDetent = useSharedValue(0);
50
50
 
51
- const value = useMemo(
52
- () => ({
53
- animatedPosition,
54
- animatedIndex,
55
- animatedDetent,
56
- }),
57
- [animatedPosition, animatedIndex, animatedDetent]
58
- );
51
+ const value: ReanimatedTrueSheetContextValue = {
52
+ animatedPosition,
53
+ animatedIndex,
54
+ animatedDetent,
55
+ };
59
56
 
60
57
  return (
61
58
  <ReanimatedTrueSheetContext.Provider value={value}>