@lodev09/react-native-true-sheet 4.0.0-beta.2 → 4.0.0-beta.21

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 (205) hide show
  1. package/README.md +25 -4
  2. package/android/build.gradle +22 -1
  3. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerView.kt +50 -16
  4. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentView.kt +303 -184
  5. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentViewManager.kt +5 -1
  6. package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterView.kt +21 -110
  7. package/android/src/main/java/com/lodev09/truesheet/TrueSheetOverlayView.kt +116 -0
  8. package/android/src/main/java/com/lodev09/truesheet/TrueSheetOverlayViewManager.kt +45 -0
  9. package/android/src/main/java/com/lodev09/truesheet/TrueSheetPackage.kt +2 -1
  10. package/android/src/main/java/com/lodev09/truesheet/TrueSheetStateUpdater.kt +18 -0
  11. package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +124 -50
  12. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +369 -163
  13. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +59 -12
  14. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetBottomSheetBehavior.kt +126 -0
  15. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetBottomSheetView.kt +22 -9
  16. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetCoordinatorLayout.kt +84 -5
  17. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDetentCalculator.kt +104 -39
  18. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDimView.kt +3 -0
  19. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetOverlayRootView.kt +137 -0
  20. package/android/src/main/java/com/lodev09/truesheet/events/TrueSheetLifecycleEvents.kt +15 -0
  21. package/android/src/main/java/com/lodev09/truesheet/utils/KeyboardUtils.kt +15 -2
  22. package/android/src/main/java/com/lodev09/truesheet/utils/ScreenUtils.kt +0 -12
  23. package/android/src/main/java/com/lodev09/truesheet/utils/ViewUtils.kt +19 -7
  24. package/android/src/main/jni/TrueSheetSpec.h +1 -0
  25. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewComponentDescriptor.h +1 -9
  26. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.cpp +110 -30
  27. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.h +30 -7
  28. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewState.cpp +2 -2
  29. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewState.h +9 -8
  30. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewComponentDescriptor.h +3 -5
  31. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewShadowNode.cpp +9 -3
  32. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewShadowNode.h +3 -6
  33. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewState.cpp +1 -1
  34. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewState.h +4 -6
  35. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetInsets.cpp +1 -1
  36. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetInsets.h +1 -1
  37. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetLayoutUtils.h +43 -0
  38. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetOverlayViewComponentDescriptor.h +21 -0
  39. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetOverlayViewShadowNode.cpp +17 -0
  40. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetOverlayViewShadowNode.h +33 -0
  41. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewComponentDescriptor.h +3 -5
  42. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.cpp +7 -40
  43. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.h +3 -7
  44. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewState.cpp +3 -5
  45. package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewState.h +4 -5
  46. package/ios/TrueSheetContainerView.h +27 -7
  47. package/ios/TrueSheetContainerView.mm +31 -11
  48. package/ios/TrueSheetContentView.h +43 -15
  49. package/ios/TrueSheetContentView.mm +211 -189
  50. package/ios/TrueSheetFooterView.h +6 -0
  51. package/ios/TrueSheetFooterView.mm +93 -17
  52. package/ios/TrueSheetModule.h +2 -7
  53. package/ios/TrueSheetModule.mm +7 -16
  54. package/ios/TrueSheetOverlayView.h +32 -0
  55. package/ios/TrueSheetOverlayView.mm +161 -0
  56. package/ios/TrueSheetView.mm +275 -56
  57. package/ios/TrueSheetViewController.h +31 -3
  58. package/ios/TrueSheetViewController.mm +393 -94
  59. package/ios/core/TrueSheetBlurView.h +0 -2
  60. package/ios/core/TrueSheetBlurView.mm +3 -36
  61. package/ios/core/TrueSheetDetentCalculator.h +7 -1
  62. package/ios/core/TrueSheetDetentCalculator.mm +27 -4
  63. package/ios/core/TrueSheetGrabberView.mm +13 -3
  64. package/ios/core/TrueSheetKeyboardObserver.mm +2 -0
  65. package/ios/core/TrueSheetOverlayContainerView.h +31 -0
  66. package/ios/core/TrueSheetOverlayContainerView.mm +35 -0
  67. package/ios/events/TrueSheetLifecycleEvents.h +2 -0
  68. package/ios/events/TrueSheetLifecycleEvents.mm +8 -0
  69. package/ios/tvos/TrueSheetStubs.mm +12 -0
  70. package/ios/utils/UIView+ScrollEdgeInteraction.h +1 -0
  71. package/ios/utils/UIView+ScrollEdgeInteraction.mm +24 -2
  72. package/lib/module/TrueSheet.js +175 -39
  73. package/lib/module/TrueSheet.js.map +1 -1
  74. package/lib/module/TrueSheet.web.js +220 -243
  75. package/lib/module/TrueSheet.web.js.map +1 -1
  76. package/lib/module/TrueSheetBackground.js +15 -0
  77. package/lib/module/TrueSheetBackground.js.map +1 -0
  78. package/lib/module/TrueSheetOverlay.js +30 -0
  79. package/lib/module/TrueSheetOverlay.js.map +1 -0
  80. package/lib/module/TrueSheetOverlay.web.js +35 -0
  81. package/lib/module/TrueSheetOverlay.web.js.map +1 -0
  82. package/lib/module/TrueSheetPeek.web.js +20 -15
  83. package/lib/module/TrueSheetPeek.web.js.map +1 -1
  84. package/lib/module/detentBackgrounds.js +21 -0
  85. package/lib/module/detentBackgrounds.js.map +1 -0
  86. package/lib/module/fabric/TrueSheetContentViewNativeComponent.ts +1 -1
  87. package/lib/module/fabric/TrueSheetOverlayViewNativeComponent.ts +12 -0
  88. package/lib/module/fabric/TrueSheetViewNativeComponent.ts +15 -10
  89. package/lib/module/index.js +1 -0
  90. package/lib/module/index.js.map +1 -1
  91. package/lib/module/mocks/index.js +18 -2
  92. package/lib/module/mocks/index.js.map +1 -1
  93. package/lib/module/mocks/navigationExpoRouter.js.map +1 -1
  94. package/lib/module/navigation/base-types.js +2 -0
  95. package/lib/module/navigation/base-types.js.map +1 -0
  96. package/lib/module/navigation/createTrueSheetRouter.js +0 -9
  97. package/lib/module/navigation/createTrueSheetRouter.js.map +1 -1
  98. package/lib/module/navigation/expo-router/base-types.js +2 -0
  99. package/lib/module/navigation/expo-router/base-types.js.map +1 -0
  100. package/lib/module/navigation/expo-router/index.js +10 -7
  101. package/lib/module/navigation/expo-router/index.js.map +1 -1
  102. package/lib/module/navigation/expo-router/types.js +4 -0
  103. package/lib/module/navigation/expo-router/types.js.map +1 -0
  104. package/lib/module/navigation/index.js.map +1 -1
  105. package/lib/module/navigation/screen/useSheetScreenState.js +1 -0
  106. package/lib/module/navigation/screen/useSheetScreenState.js.map +1 -1
  107. package/lib/module/web/constants.js +1 -1
  108. package/lib/module/web/constants.js.map +1 -1
  109. package/lib/module/web/layout.js +168 -0
  110. package/lib/module/web/layout.js.map +1 -0
  111. package/lib/module/web/vaul/constants.js +9 -0
  112. package/lib/module/web/vaul/constants.js.map +1 -1
  113. package/lib/module/web/vaul/context.js.map +1 -1
  114. package/lib/module/web/vaul/helpers.js +1 -0
  115. package/lib/module/web/vaul/helpers.js.map +1 -1
  116. package/lib/module/web/vaul/index.js +47 -7
  117. package/lib/module/web/vaul/index.js.map +1 -1
  118. package/lib/module/web/vaul/use-snap-points.js +21 -10
  119. package/lib/module/web/vaul/use-snap-points.js.map +1 -1
  120. package/lib/typescript/src/TrueSheet.d.ts +6 -0
  121. package/lib/typescript/src/TrueSheet.d.ts.map +1 -1
  122. package/lib/typescript/src/TrueSheet.types.d.ts +157 -34
  123. package/lib/typescript/src/TrueSheet.types.d.ts.map +1 -1
  124. package/lib/typescript/src/TrueSheet.web.d.ts.map +1 -1
  125. package/lib/typescript/src/TrueSheetBackground.d.ts +3 -0
  126. package/lib/typescript/src/TrueSheetBackground.d.ts.map +1 -0
  127. package/lib/typescript/src/TrueSheetOverlay.d.ts +8 -0
  128. package/lib/typescript/src/TrueSheetOverlay.d.ts.map +1 -0
  129. package/lib/typescript/src/TrueSheetOverlay.web.d.ts +8 -0
  130. package/lib/typescript/src/TrueSheetOverlay.web.d.ts.map +1 -0
  131. package/lib/typescript/src/TrueSheetPeek.web.d.ts +8 -4
  132. package/lib/typescript/src/TrueSheetPeek.web.d.ts.map +1 -1
  133. package/lib/typescript/src/detentBackgrounds.d.ts +10 -0
  134. package/lib/typescript/src/detentBackgrounds.d.ts.map +1 -0
  135. package/lib/typescript/src/fabric/TrueSheetOverlayViewNativeComponent.d.ts +6 -0
  136. package/lib/typescript/src/fabric/TrueSheetOverlayViewNativeComponent.d.ts.map +1 -0
  137. package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts +12 -7
  138. package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts.map +1 -1
  139. package/lib/typescript/src/index.d.ts +1 -0
  140. package/lib/typescript/src/index.d.ts.map +1 -1
  141. package/lib/typescript/src/mocks/index.d.ts +4 -0
  142. package/lib/typescript/src/mocks/index.d.ts.map +1 -1
  143. package/lib/typescript/src/mocks/navigationExpoRouter.d.ts +3 -3
  144. package/lib/typescript/src/mocks/navigationExpoRouter.d.ts.map +1 -1
  145. package/lib/typescript/src/navigation/base-types.d.ts +9 -0
  146. package/lib/typescript/src/navigation/base-types.d.ts.map +1 -0
  147. package/lib/typescript/src/navigation/createTrueSheetRouter.d.ts +2 -13
  148. package/lib/typescript/src/navigation/createTrueSheetRouter.d.ts.map +1 -1
  149. package/lib/typescript/src/navigation/expo-router/base-types.d.ts +8 -0
  150. package/lib/typescript/src/navigation/expo-router/base-types.d.ts.map +1 -0
  151. package/lib/typescript/src/navigation/expo-router/index.d.ts +8 -6
  152. package/lib/typescript/src/navigation/expo-router/index.d.ts.map +1 -1
  153. package/lib/typescript/src/navigation/expo-router/types.d.ts +44 -0
  154. package/lib/typescript/src/navigation/expo-router/types.d.ts.map +1 -0
  155. package/lib/typescript/src/navigation/index.d.ts +3 -4
  156. package/lib/typescript/src/navigation/index.d.ts.map +1 -1
  157. package/lib/typescript/src/navigation/screen/useSheetScreenState.d.ts +2 -1
  158. package/lib/typescript/src/navigation/screen/useSheetScreenState.d.ts.map +1 -1
  159. package/lib/typescript/src/navigation/types.d.ts +41 -5
  160. package/lib/typescript/src/navigation/types.d.ts.map +1 -1
  161. package/lib/typescript/src/web/constants.d.ts +1 -1
  162. package/lib/typescript/src/web/constants.d.ts.map +1 -1
  163. package/lib/typescript/src/web/layout.d.ts +19 -0
  164. package/lib/typescript/src/web/layout.d.ts.map +1 -0
  165. package/lib/typescript/src/web/vaul/constants.d.ts +3 -0
  166. package/lib/typescript/src/web/vaul/constants.d.ts.map +1 -1
  167. package/lib/typescript/src/web/vaul/context.d.ts +1 -0
  168. package/lib/typescript/src/web/vaul/context.d.ts.map +1 -1
  169. package/lib/typescript/src/web/vaul/helpers.d.ts +1 -0
  170. package/lib/typescript/src/web/vaul/helpers.d.ts.map +1 -1
  171. package/lib/typescript/src/web/vaul/index.d.ts +13 -1
  172. package/lib/typescript/src/web/vaul/index.d.ts.map +1 -1
  173. package/lib/typescript/src/web/vaul/use-snap-points.d.ts +2 -1
  174. package/lib/typescript/src/web/vaul/use-snap-points.d.ts.map +1 -1
  175. package/package.json +17 -8
  176. package/react-native.config.js +1 -0
  177. package/src/TrueSheet.tsx +208 -48
  178. package/src/TrueSheet.types.ts +166 -35
  179. package/src/TrueSheet.web.tsx +272 -290
  180. package/src/TrueSheetBackground.tsx +17 -0
  181. package/src/TrueSheetOverlay.tsx +24 -0
  182. package/src/TrueSheetOverlay.web.tsx +33 -0
  183. package/src/TrueSheetPeek.web.tsx +25 -23
  184. package/src/detentBackgrounds.ts +24 -0
  185. package/src/fabric/TrueSheetContentViewNativeComponent.ts +1 -1
  186. package/src/fabric/TrueSheetOverlayViewNativeComponent.ts +12 -0
  187. package/src/fabric/TrueSheetViewNativeComponent.ts +15 -10
  188. package/src/index.ts +1 -0
  189. package/src/mocks/index.ts +17 -2
  190. package/src/mocks/navigationExpoRouter.ts +6 -5
  191. package/src/navigation/base-types.ts +20 -0
  192. package/src/navigation/createTrueSheetRouter.ts +5 -33
  193. package/src/navigation/expo-router/base-types.ts +18 -0
  194. package/src/navigation/expo-router/index.ts +28 -30
  195. package/src/navigation/expo-router/types.ts +116 -0
  196. package/src/navigation/index.ts +6 -7
  197. package/src/navigation/screen/useSheetScreenState.ts +2 -0
  198. package/src/navigation/types.ts +75 -22
  199. package/src/web/constants.ts +1 -1
  200. package/src/web/layout.ts +196 -0
  201. package/src/web/vaul/constants.ts +9 -0
  202. package/src/web/vaul/context.ts +1 -0
  203. package/src/web/vaul/helpers.ts +5 -0
  204. package/src/web/vaul/index.tsx +75 -5
  205. package/src/web/vaul/use-snap-points.ts +32 -15
package/README.md CHANGED
@@ -6,8 +6,8 @@
6
6
 
7
7
  The true native bottom sheet experience for your React Native Apps. 💩
8
8
 
9
- <img alt="React Native True Sheet - iPad" src="docs/static/img/preview-ipad.gif" width="744" /><br>
10
- <img alt="React Native True Sheet - IOS" src="docs/static/img/preview-ios.gif" width="248" height="500" /><img alt="React Native True Sheet - Android" src="docs/static/img/preview-android.gif" width="248" height="500" /><img alt="React Native True Sheet - Web" src="docs/static/img/preview-web.gif" width="248" height="500" />
9
+ <img alt="React Native True Sheet - iPad" src="docs/public/img/preview-ipad.gif" width="744" /><br>
10
+ <img alt="React Native True Sheet - IOS" src="docs/public/img/preview-ios.gif" width="248" height="500" /><img alt="React Native True Sheet - Android" src="docs/public/img/preview-android.gif" width="248" height="500" /><img alt="React Native True Sheet - Web" src="docs/public/img/preview-web.gif" width="248" height="500" />
11
11
 
12
12
  ## Features
13
13
 
@@ -22,6 +22,25 @@ The true native bottom sheet experience for your React Native Apps. 💩
22
22
  * 🧭 **React Navigation** - Built-in [sheet navigator](https://sheet.lodev09.com/guides/navigation) for seamless navigation integration
23
23
  * 🌐 **Web Support** - Full [web support](https://sheet.lodev09.com/guides/web) out of the box
24
24
 
25
+ ## 🎉 What's New in v4
26
+
27
+ > [!TIP]
28
+ > ✨ **v4 is in beta!** It rewrites the layout engine — the sheet now lays out synchronously per detent, so the container is sized to the sheet's visible height and tracks it in realtime while dragging.
29
+
30
+ * 📏 **Synchronous layout** - Content resizes in the same frame as the sheet, no more lag
31
+ * 📐 **`auto` detent with scrollables** - The sheet now sizes itself to a `ScrollView`/`FlatList`'s content height
32
+ * 📜 **`scrollableRef`** - Pass a `ScrollView`/`FlatList` ref to wire nested scrolling, keyboard insets, and `auto` detent sizing
33
+ * 🦶 **Relative footers** - Footers take up space below the content by default
34
+ * 🧭 **Expo Router** - First-class support via the `Sheet` layout from `/navigation/expo-router`
35
+ * 🍞 **`TrueSheetOverlay`** - Render toasts, dialogs, and other [overlays above your sheets](https://sheet.lodev09.com/guides/overlays) — no more `FullWindowOverlay`/`Modal` workarounds
36
+ * 🔍 **Element inspector** - React Native's dev menu inspector now works inside a presented sheet
37
+
38
+ ```sh
39
+ npx expo install @lodev09/react-native-true-sheet@beta
40
+ ```
41
+
42
+ See the [Migration Guide](docs/docs/migration.mdx) to upgrade. **v3 is still supported** for React Native 0.81+ and remains the `latest` release on npm.
43
+
25
44
  ## Installation
26
45
 
27
46
  > [!IMPORTANT]
@@ -30,7 +49,7 @@ The true native bottom sheet experience for your React Native Apps. 💩
30
49
 
31
50
  ### Prerequisites
32
51
 
33
- - React Native 0.82+
52
+ - React Native 0.82+ (0.81+ on v3)
34
53
  - New Architecture enabled
35
54
  - Xcode 26.1+
36
55
 
@@ -55,6 +74,8 @@ yarn add @lodev09/react-native-true-sheet
55
74
  cd ios && pod install
56
75
  ```
57
76
 
77
+ These install v3. For v4, append `@beta` — see [🎉 What's New in v4](#-whats-new-in-v4).
78
+
58
79
  ## Documentation
59
80
 
60
81
  - [Example](example)
@@ -63,7 +84,7 @@ cd ios && pod install
63
84
  - [React Navigation](https://sheet.lodev09.com/guides/navigation)
64
85
  - [Troubleshooting](https://sheet.lodev09.com/troubleshooting)
65
86
  - [Testing with Jest](https://sheet.lodev09.com/guides/jest)
66
- - [Migrating to v3](https://sheet.lodev09.com/migration)
87
+ - [Migrating to v3](https://sheet.lodev09.com/migration-v3)
67
88
 
68
89
  ## Usage
69
90
 
@@ -17,7 +17,28 @@ buildscript {
17
17
 
18
18
 
19
19
  apply plugin: "com.android.library"
20
- apply plugin: "kotlin-android"
20
+ // Android Gradle Plugin 9 ships built-in Kotlin support and applies the Kotlin
21
+ // plugin itself. Applying it a second time fails the configuration phase with
22
+ // "Cannot add extension with name 'kotlin'". Apply it only when AGP is not
23
+ // providing Kotlin: AGP 8 and older, or AGP 9 with android.builtInKotlin=false.
24
+ def shouldApplyKotlinPlugin() {
25
+ def agpMajor = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')[0].toInteger()
26
+ if (agpMajor <= 8) {
27
+ return true
28
+ }
29
+ // AGP 10 removes the opt-out: built-in Kotlin is always active there.
30
+ if (agpMajor >= 10) {
31
+ return false
32
+ }
33
+ def propertyVal = providers.gradleProperty("android.builtInKotlin").orNull
34
+ def builtInKotlinEnabled = propertyVal != null ? propertyVal.toBoolean() : true
35
+ return !builtInKotlinEnabled
36
+ }
37
+
38
+ if (shouldApplyKotlinPlugin()) {
39
+ apply plugin: "kotlin-android"
40
+ }
41
+
21
42
  apply plugin: "com.facebook.react"
22
43
 
23
44
  def getExtOrIntegerDefault(name) {
@@ -4,17 +4,15 @@ import android.annotation.SuppressLint
4
4
  import android.view.View
5
5
  import android.view.ViewGroup
6
6
  import com.facebook.react.uimanager.ThemedReactContext
7
- import com.facebook.react.uimanager.events.EventDispatcher
8
- import com.facebook.react.util.RNLog
9
7
  import com.facebook.react.views.view.ReactViewGroup
10
8
 
11
9
  interface TrueSheetContainerViewDelegate {
12
- val eventDispatcher: EventDispatcher?
13
10
  fun containerViewContentDidChangeSize(width: Int, height: Int)
14
11
  fun containerViewContentDidScroll()
15
12
  fun containerViewScrollViewDidChange()
16
13
  fun containerViewHeaderDidChangeSize(width: Int, height: Int)
17
14
  fun containerViewFooterDidChangeSize(width: Int, height: Int)
15
+ fun containerViewFooterDidLayout()
18
16
  fun containerViewPeekDidChangeSize(width: Int, height: Int)
19
17
  }
20
18
 
@@ -61,9 +59,19 @@ class TrueSheetContainerView(reactContext: ThemedReactContext) :
61
59
  return bottom
62
60
  }
63
61
 
64
- var insetAdjustment: TrueSheetInsetAdjustment = TrueSheetInsetAdjustment.AUTOMATIC
65
- var scrollViewBottomInset: Int = 0
66
62
  var absoluteFooter: Boolean = false
63
+ set(value) {
64
+ if (field == value) return
65
+ field = value
66
+ contentView?.updateContentInset()
67
+ }
68
+
69
+ override var footerAvoidsKeyboard: Boolean = true
70
+ set(value) {
71
+ if (field == value) return
72
+ field = value
73
+ contentView?.updateContentInset()
74
+ }
67
75
 
68
76
  /**
69
77
  * Bottom safe-area inset the footer absorbs as padding — the footer
@@ -80,14 +88,22 @@ class TrueSheetContainerView(reactContext: ThemedReactContext) :
80
88
  contentView?.scrollableOptions = value
81
89
  }
82
90
 
83
- var hasAutoDetent = false
91
+ // React tag of the user-provided scrollable within the content (see the scrollableRef prop)
92
+ var scrollableHandle: Int = -1
84
93
  set(value) {
85
94
  field = value
86
- contentView?.hasAutoDetent = value
95
+ contentView?.scrollableHandle = value
87
96
  }
88
97
 
89
- override val eventDispatcher: EventDispatcher?
90
- get() = delegate?.eventDispatcher
98
+ /**
99
+ * Bottom safe-area inset the plugged scrollable applies as content padding
100
+ * while it can scroll (see ScrollableOptions.contentInsetAdjustment)
101
+ */
102
+ var scrollableBottomInset: Int = 0
103
+ set(value) {
104
+ field = value
105
+ contentView?.bottomInset = value
106
+ }
91
107
 
92
108
  init {
93
109
  // Allow footer to position outside container bounds
@@ -96,8 +112,7 @@ class TrueSheetContainerView(reactContext: ThemedReactContext) :
96
112
  }
97
113
 
98
114
  fun setupScrollable() {
99
- val bottomInset = if (insetAdjustment == TrueSheetInsetAdjustment.AUTOMATIC) scrollViewBottomInset else 0
100
- contentView?.setupScrollable(bottomInset)
115
+ contentView?.setupScrollable()
101
116
  }
102
117
 
103
118
  fun setupKeyboardHandler() {
@@ -115,9 +130,13 @@ class TrueSheetContainerView(reactContext: ThemedReactContext) :
115
130
  is TrueSheetContentView -> {
116
131
  child.delegate = this
117
132
  child.scrollableOptions = scrollableOptions
118
- child.hasAutoDetent = hasAutoDetent
133
+ child.scrollableHandle = scrollableHandle
134
+ child.bottomInset = scrollableBottomInset
119
135
  contentView = child
120
136
 
137
+ // State lands before the view is attached, so pull the current value
138
+ contentHeight = child.naturalHeight
139
+
121
140
  // Children mount bottom-up, so the content subtree is complete here.
122
141
  // Late-mounted peek views attach themselves instead (see TrueSheetPeekView).
123
142
  findPeekView(child)?.let { attachPeekView(it) }
@@ -177,10 +196,9 @@ class TrueSheetContainerView(reactContext: ThemedReactContext) :
177
196
  fun attachPeekView(view: TrueSheetPeekView) {
178
197
  if (peekView === view) return
179
198
 
180
- if (peekView != null) {
181
- RNLog.w(context as ThemedReactContext, "TrueSheet: Sheet can only have one peek component.")
182
- return
183
- }
199
+ // Last-attached wins. During a screen transition the incoming peek mounts
200
+ // before the outgoing one detaches, and the outgoing detach is a no-op.
201
+ peekView?.delegate = null
184
202
 
185
203
  peekView = view
186
204
  view.delegate = this
@@ -205,6 +223,15 @@ class TrueSheetContainerView(reactContext: ThemedReactContext) :
205
223
  override val footerKeyboardOcclusion: Int
206
224
  get() = if (absoluteFooter) footerView?.keyboardOcclusionHeight ?: 0 else -(footerView?.height ?: 0)
207
225
 
226
+ override val absoluteFooterHeight: Int
227
+ get() = if (absoluteFooter) footerView?.height ?: 0 else 0
228
+
229
+ override val absoluteFooterTop: Int
230
+ get() = footerView?.y?.toInt() ?: height
231
+
232
+ override val hasRelativeFooter: Boolean
233
+ get() = footerView != null && !absoluteFooter
234
+
208
235
  override fun contentViewDidScroll() {
209
236
  delegate?.containerViewContentDidScroll()
210
237
  }
@@ -221,6 +248,13 @@ class TrueSheetContainerView(reactContext: ThemedReactContext) :
221
248
  override fun footerViewDidChangeSize(width: Int, height: Int) {
222
249
  footerHeight = height
223
250
  delegate?.containerViewFooterDidChangeSize(width, height)
251
+ // A relative footer takes over the bottom inset — drop the scrollable's;
252
+ // an absolute one may pad the scrollable by its height
253
+ contentView?.updateContentInset()
254
+ }
255
+
256
+ override fun footerViewDidLayout() {
257
+ delegate?.containerViewFooterDidLayout()
224
258
  }
225
259
 
226
260
  override fun peekViewDidChangeSize(width: Int, height: Int) {