@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
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
- import type { DrawerDirection } from './types';
3
- export declare function useSnapPoints({ activeSnapPointProp, setActiveSnapPointProp, snapPoints, drawerRef, overlayRef, fadeFromIndex, onSnapPointChange, direction, container, snapToSequentialPoint, isOpen, contentHeight, detachedOffset, maxContentHeight, peekHeight, initialAnimated, }: {
2
+ import type { DrawerDirection, KeyboardViewport } from './types';
3
+ export declare function useSnapPoints({ activeSnapPointProp, setActiveSnapPointProp, snapPoints, drawerRef, overlayRef, fadeFromIndex, onSnapPointChange, direction, container, snapToSequentialPoint, isOpen, contentHeight, detachedOffset, maxContentHeight, peekHeight, initialAnimated, keyboardViewport, }: {
4
4
  activeSnapPointProp?: number | string | null;
5
5
  setActiveSnapPointProp?(snapPoint: number | null | string): void;
6
6
  snapPoints?: (number | string)[];
@@ -17,6 +17,7 @@ export declare function useSnapPoints({ activeSnapPointProp, setActiveSnapPointP
17
17
  maxContentHeight?: number;
18
18
  peekHeight?: number;
19
19
  initialAnimated?: boolean;
20
+ keyboardViewport?: KeyboardViewport;
20
21
  }): {
21
22
  isLastSnapPoint: true | null;
22
23
  activeSnapPoint: string | number | null | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"use-snap-points.d.ts","sourceRoot":"","sources":["../../../../../src/web/vaul/use-snap-points.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAU1B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,wBAAgB,aAAa,CAAC,EAC5B,mBAAmB,EACnB,sBAAsB,EACtB,UAAU,EACV,SAAS,EACT,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,SAAoB,EACpB,SAAS,EACT,qBAAqB,EACrB,MAAM,EACN,aAAa,EACb,cAAkB,EAClB,gBAAgB,EAChB,UAAU,EACV,eAAsB,GACvB,EAAE;IACD,mBAAmB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC7C,sBAAsB,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;IACjE,UAAU,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAClD,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACnD,iBAAiB,CAAC,oBAAoB,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IACzE,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,SAAS,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC;IAC3C,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;;;;+CA+XmD,MAAM,kBAAkB,OAAO;;;4FA9I9E;QACD,eAAe,EAAE,MAAM,CAAC;QACxB,WAAW,EAAE,MAAM,IAAI,CAAC;QACxB,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,OAAO,CAAC;QACrB,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC;KACpC;kCA6FoC;QAAE,eAAe,EAAE,MAAM,CAAA;KAAE;;EA8GjE"}
1
+ {"version":3,"file":"use-snap-points.d.ts","sourceRoot":"","sources":["../../../../../src/web/vaul/use-snap-points.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAU1B,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEjE,wBAAgB,aAAa,CAAC,EAC5B,mBAAmB,EACnB,sBAAsB,EACtB,UAAU,EACV,SAAS,EACT,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,SAAoB,EACpB,SAAS,EACT,qBAAqB,EACrB,MAAM,EACN,aAAa,EACb,cAAkB,EAClB,gBAAgB,EAChB,UAAU,EACV,eAAsB,EACtB,gBAAgB,GACjB,EAAE;IACD,mBAAmB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC7C,sBAAsB,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;IACjE,UAAU,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAClD,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACnD,iBAAiB,CAAC,oBAAoB,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IACzE,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,SAAS,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC;IAC3C,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;;;;+CAuYmD,MAAM,kBAAkB,OAAO;;;4FA9I9E;QACD,eAAe,EAAE,MAAM,CAAC;QACxB,WAAW,EAAE,MAAM,IAAI,CAAC;QACxB,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,OAAO,CAAC;QACrB,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC;KACpC;kCA6FoC;QAAE,eAAe,EAAE,MAAM,CAAA;KAAE;;EA8GjE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lodev09/react-native-true-sheet",
3
- "version": "4.0.0-beta.24",
3
+ "version": "4.0.0-beta.26",
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",
package/src/TrueSheet.tsx CHANGED
@@ -39,6 +39,7 @@ import TrueSheetFooterViewNativeComponent from './fabric/TrueSheetFooterViewNati
39
39
  import TrueSheetModule from './specs/NativeTrueSheetModule';
40
40
  import { TrueSheetBackground } from './TrueSheetBackground';
41
41
  import { normalizeDetentBackground } from './detentBackgrounds';
42
+ import { resolveScrollable } from './scrollable';
42
43
 
43
44
  import {
44
45
  Platform,
@@ -139,9 +140,19 @@ export class TrueSheet
139
140
  private static readonly instances: { [name: string]: TrueSheet } = {};
140
141
 
141
142
  /**
142
- * Resolver to be called when mount event is received
143
+ * All mounted sheets, named or not.
143
144
  */
144
- private presentationResolver: (() => void) | null = null;
145
+ private static readonly mountedInstances = new Set<TrueSheet>();
146
+
147
+ /**
148
+ * Resolver to be called when mount event is received, or with `false` when the present is cancelled
149
+ */
150
+ private presentationResolver: ((mounted: boolean) => void) | null = null;
151
+
152
+ /**
153
+ * Settles once a scheduled lazy unmount has committed
154
+ */
155
+ private nativeViewUnmount: Promise<void> | null = null;
145
156
 
146
157
  /**
147
158
  * Tracks if a present operation is in progress
@@ -198,13 +209,17 @@ export class TrueSheet
198
209
  if (scrollableRef?.current) {
199
210
  try {
200
211
  scrollableHandle = findNodeHandle(
201
- scrollableRef.current as Parameters<typeof findNodeHandle>[0]
212
+ resolveScrollable(scrollableRef.current) as Parameters<typeof findNodeHandle>[0]
202
213
  );
203
214
  } catch (error) {
204
- // A stale ref (e.g. a wrapper that never clears it on unmount) makes
205
- // findNodeHandle throw. Treat it as no scrollable instead of crashing.
215
+ // findNodeHandle throws on a stale ref (e.g. a wrapper that never clears
216
+ // it on unmount) or a handle with no usable scroll accessor. Treat it as
217
+ // no scrollable instead of crashing.
206
218
  if (__DEV__) {
207
- console.warn('TrueSheet: scrollableRef points to an unmounted component.', error);
219
+ console.warn(
220
+ 'TrueSheet: scrollableRef could not be resolved to a native view. It may be stale or expose no scroll node.',
221
+ error
222
+ );
208
223
  }
209
224
  }
210
225
  }
@@ -343,6 +358,7 @@ export class TrueSheet
343
358
  * @returns Promise that resolves when all sheets are dismissed
344
359
  */
345
360
  public static async dismissAll(animated: boolean = true): Promise<void> {
361
+ TrueSheet.mountedInstances.forEach((sheet) => sheet.cancelPendingPresent());
346
362
  return TrueSheetModule?.dismissAll(animated);
347
363
  }
348
364
 
@@ -396,16 +412,17 @@ export class TrueSheet
396
412
 
397
413
  // Non-lazy content stays mounted; otherwise clean it up unless another presentation is active.
398
414
  if (!this.isPresenting && this.props.lazy !== false) {
399
- this.setState({ shouldRenderNativeView: false });
415
+ this.unmountNativeView();
400
416
  }
401
417
 
402
418
  this.props.onDidDismiss?.(event);
403
419
  }
404
420
 
405
421
  private onMount(event: MountEvent): void {
406
- // Resolve the mount promise if waiting
407
- if (this.presentationResolver) {
408
- this.presentationResolver();
422
+ // Resolve the mount promise if waiting. While an unmount is pending, the event is from
423
+ // the outgoing view — present() waits for the remount instead.
424
+ if (this.presentationResolver && !this.nativeViewUnmount) {
425
+ this.presentationResolver(true);
409
426
  this.presentationResolver = null;
410
427
  }
411
428
 
@@ -465,7 +482,9 @@ export class TrueSheet
465
482
  return onBackPress?.() ?? onDismissAttempt != null;
466
483
  }
467
484
 
468
- TrueSheetModule?.handleBackPress(nodeHandle);
485
+ // Rejects when the native view is gone but JS hasn't unmounted yet (e.g. the surface
486
+ // stopped while this back press was queued). Nothing is left to dismiss.
487
+ TrueSheetModule?.handleBackPress(nodeHandle).catch(() => {});
469
488
  return this.props.onBackPress?.() ?? true;
470
489
  }
471
490
 
@@ -482,20 +501,67 @@ export class TrueSheet
482
501
  );
483
502
  }
484
503
 
504
+ // Still waiting on the lazy mount — like native, a second present is a no-op
505
+ if (this.presentationResolver) {
506
+ console.warn('TrueSheet: sheet is already presented. Use resize() to change detent.');
507
+ return;
508
+ }
509
+
485
510
  this.isPresenting = true;
486
511
 
487
512
  // Lazy load: render native view if not already rendered
488
- if (!this.state.shouldRenderNativeView) {
489
- await new Promise<void>((resolve) => {
513
+ const unmount = this.nativeViewUnmount;
514
+ if (unmount || !this.state.shouldRenderNativeView) {
515
+ const mounted = await new Promise<boolean>((resolve) => {
490
516
  this.presentationResolver = resolve;
491
- this.setState({ shouldRenderNativeView: true });
517
+
518
+ const mount = () => {
519
+ if (this.presentationResolver === resolve) {
520
+ this.setState({ shouldRenderNativeView: true });
521
+ }
522
+ };
523
+
524
+ // An unmount from the last dismiss may not have committed yet — state still reads
525
+ // mounted, and presenting now would lose the sheet when it lands. Remount after it.
526
+ if (unmount) {
527
+ unmount.then(mount);
528
+ } else {
529
+ mount();
530
+ }
492
531
  });
532
+
533
+ // Dismissed before the native view mounted
534
+ if (!mounted) {
535
+ this.isPresenting = false;
536
+ return;
537
+ }
493
538
  }
494
539
 
495
540
  await TrueSheetModule?.presentByRef(this.handle, index, animated);
496
541
  this.isPresenting = false;
497
542
  }
498
543
 
544
+ /**
545
+ * Cancels a present still waiting on the lazy mount. Returns whether one was pending.
546
+ */
547
+ private cancelPendingPresent(): boolean {
548
+ if (!this.presentationResolver) return false;
549
+
550
+ this.presentationResolver(false);
551
+ this.presentationResolver = null;
552
+ this.unmountNativeView();
553
+ return true;
554
+ }
555
+
556
+ private unmountNativeView(): void {
557
+ this.nativeViewUnmount = new Promise((resolve) => {
558
+ this.setState({ shouldRenderNativeView: false }, () => {
559
+ this.nativeViewUnmount = null;
560
+ resolve();
561
+ });
562
+ });
563
+ }
564
+
499
565
  /**
500
566
  * Resize the sheet to a given detent index.
501
567
  * @param index - The detent index to resize to
@@ -509,6 +575,9 @@ export class TrueSheet
509
575
  * @param animated - Whether to animate the dismissal (default: true)
510
576
  */
511
577
  public async dismiss(animated: boolean = true): Promise<void> {
578
+ // Dismissing before the lazy mount finishes cancels the present — nothing was presented
579
+ if (this.cancelPendingPresent()) return;
580
+
512
581
  return TrueSheetModule?.dismissByRef(this.handle, animated);
513
582
  }
514
583
 
@@ -522,6 +591,7 @@ export class TrueSheet
522
591
  }
523
592
 
524
593
  componentDidMount(): void {
594
+ TrueSheet.mountedInstances.add(this);
525
595
  this.registerInstance();
526
596
  this.updateScrollableHandle();
527
597
  }
@@ -558,9 +628,12 @@ export class TrueSheet
558
628
  }
559
629
 
560
630
  componentWillUnmount(): void {
631
+ TrueSheet.mountedInstances.delete(this);
561
632
  this.unregisterInstance();
562
633
  this.backHandlerSubscription?.remove();
563
634
  this.backHandlerSubscription = null;
635
+ // Don't leave a present waiting on the lazy mount hanging
636
+ this.presentationResolver?.(false);
564
637
  this.presentationResolver = null;
565
638
  }
566
639
 
@@ -578,6 +651,8 @@ export class TrueSheet
578
651
  grabberOptions,
579
652
  accessibilityOptions,
580
653
  dimmed = true,
654
+ dimColor,
655
+ dimOpacity,
581
656
  initialDetentIndex = -1,
582
657
  initialDetentAnimated = true,
583
658
  dimmedDetentIndex,
@@ -686,6 +761,8 @@ export class TrueSheet
686
761
  grabberOptions={this.resolvedGrabberOptions}
687
762
  accessibilityOptions={accessibilityOptions}
688
763
  dimmed={dimmed}
764
+ dimColor={dimColor}
765
+ dimOpacity={dimOpacity}
689
766
  dimmedDetentIndex={dimmedDetentIndex}
690
767
  initialDetentIndex={gatedInitialDetentIndex}
691
768
  initialDetentAnimated={initialDetentAnimated}
@@ -262,6 +262,33 @@ export interface HeaderOptions {
262
262
  position?: 'relative' | 'absolute';
263
263
  }
264
264
 
265
+ /**
266
+ * Options for foldables. Applies while the device is half-open with a horizontal
267
+ * fold (tabletop). In book posture (vertical fold), iOS already keeps sheets on
268
+ * one panel — use `placement` to pick the side.
269
+ */
270
+ export interface FoldOptions {
271
+ /**
272
+ * The detent that rests on the hinge in tabletop, so the sheet fills the panel
273
+ * below it. In any other posture the detent keeps its own value. Lower detents
274
+ * stay below it and higher ones above it, so the detents keep their order.
275
+ */
276
+ hingeDetentIndex?: number;
277
+
278
+ /**
279
+ * How the sheet treats the hinge in tabletop.
280
+ *
281
+ * - `'none'`: Detents are free to cross the hinge.
282
+ * - `'avoid'`: Caps every detent at the hinge, so the sheet never crosses it.
283
+ * - `'snap'`: Like `'avoid'`, and also moves the sheet to `hingeDetentIndex` when
284
+ * the device enters tabletop, then back to its previous detent when it leaves,
285
+ * unless the sheet was moved off the hinge in between.
286
+ *
287
+ * @default 'none'
288
+ */
289
+ hingeBehavior?: 'none' | 'avoid' | 'snap';
290
+ }
291
+
265
292
  /**
266
293
  * Options for footer behavior
267
294
  */
@@ -439,6 +466,22 @@ export interface TrueSheetProps extends ViewProps {
439
466
  */
440
467
  dimmed?: boolean;
441
468
 
469
+ /**
470
+ * The color of the dim overlay behind the sheet.
471
+ * This is ignored if `dimmed` is set to `false`.
472
+ *
473
+ * @default '#000000'
474
+ */
475
+ dimColor?: ColorValue;
476
+
477
+ /**
478
+ * The maximum opacity of the dim overlay behind the sheet (0 to 1).
479
+ * This is ignored if `dimmed` is set to `false`.
480
+ *
481
+ * @default 0.5
482
+ */
483
+ dimOpacity?: number;
484
+
442
485
  /**
443
486
  * Initially present the sheet, after mounting, at a given detent index.
444
487
  *
@@ -629,6 +672,13 @@ export interface TrueSheetProps extends ViewProps {
629
672
  */
630
673
  placementOffset?: number;
631
674
 
675
+ /**
676
+ * How the sheet behaves on a foldable.
677
+ *
678
+ * @platform ios 27.1+
679
+ */
680
+ foldOptions?: FoldOptions;
681
+
632
682
  /**
633
683
  * Controls how the sheet adjusts its height for system insets (safe area).
634
684
  *
@@ -677,7 +727,9 @@ export interface TrueSheetProps extends ViewProps {
677
727
 
678
728
  /**
679
729
  * A ref to the scrollable component (e.g. `ScrollView`, `FlatList`)
680
- * rendered within the sheet content.
730
+ * rendered within the sheet content. Lists that expose an imperative handle
731
+ * (e.g. `LegendList`, `FlashList`) work too, through their
732
+ * `getScrollableNode()` or `getNativeScrollRef()`.
681
733
  * Required for scrollable handling — nested scrolling, keyboard insets,
682
734
  * and `auto` detent sizing are wired to this scrollable.
683
735
  *
@@ -690,7 +742,13 @@ export interface TrueSheetProps extends ViewProps {
690
742
  * </TrueSheet>
691
743
  * ```
692
744
  */
693
- scrollableRef?: RefObject<Component<unknown> | HostInstance | null>;
745
+ scrollableRef?: RefObject<
746
+ | Component<unknown>
747
+ | HostInstance
748
+ | { getScrollableNode(): unknown }
749
+ | { getNativeScrollRef(): unknown }
750
+ | null
751
+ >;
694
752
 
695
753
  /**
696
754
  * Options for scrollable behavior.