@lodev09/react-native-true-sheet 2.0.6 → 4.0.0-beta.0

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 (194) hide show
  1. package/README.md +36 -8
  2. package/RNTrueSheet.podspec +20 -0
  3. package/android/build.gradle +26 -14
  4. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerView.kt +108 -0
  5. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerViewManager.kt +21 -0
  6. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentView.kt +46 -0
  7. package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentViewManager.kt +21 -0
  8. package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterView.kt +47 -0
  9. package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterViewManager.kt +21 -0
  10. package/android/src/main/java/com/lodev09/truesheet/TrueSheetModule.kt +165 -0
  11. package/android/src/main/java/com/lodev09/truesheet/TrueSheetPackage.kt +36 -4
  12. package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +257 -303
  13. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +855 -0
  14. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +104 -82
  15. package/android/src/main/java/com/lodev09/truesheet/events/DetentChangeEvent.kt +26 -0
  16. package/android/src/main/java/com/lodev09/truesheet/events/DidDismissEvent.kt +20 -0
  17. package/android/src/main/java/com/lodev09/truesheet/events/DidPresentEvent.kt +26 -0
  18. package/android/src/main/java/com/lodev09/truesheet/events/DragBeginEvent.kt +26 -0
  19. package/android/src/main/java/com/lodev09/truesheet/events/DragChangeEvent.kt +26 -0
  20. package/android/src/main/java/com/lodev09/truesheet/events/DragEndEvent.kt +26 -0
  21. package/android/src/main/java/com/lodev09/truesheet/events/MountEvent.kt +20 -0
  22. package/android/src/main/java/com/lodev09/truesheet/events/PositionChangeEvent.kt +32 -0
  23. package/android/src/main/java/com/lodev09/truesheet/events/SizeChangeEvent.kt +27 -0
  24. package/android/src/main/java/com/lodev09/truesheet/events/WillDismissEvent.kt +20 -0
  25. package/android/src/main/java/com/lodev09/truesheet/events/WillPresentEvent.kt +26 -0
  26. package/android/src/main/java/com/lodev09/truesheet/{core/Utils.kt → utils/ScreenUtils.kt} +47 -17
  27. package/android/src/main/res/values/styles.xml +8 -0
  28. package/ios/TrueSheetComponentDescriptor.h +24 -0
  29. package/ios/TrueSheetContainerView.h +47 -0
  30. package/ios/TrueSheetContainerView.mm +117 -0
  31. package/ios/TrueSheetContentView.h +37 -0
  32. package/ios/TrueSheetContentView.mm +114 -0
  33. package/ios/TrueSheetFooterView.h +27 -0
  34. package/ios/TrueSheetFooterView.mm +101 -0
  35. package/ios/TrueSheetModule.h +44 -0
  36. package/ios/TrueSheetModule.mm +133 -0
  37. package/ios/TrueSheetView.h +53 -0
  38. package/ios/TrueSheetView.mm +433 -0
  39. package/ios/TrueSheetViewController.h +53 -0
  40. package/ios/TrueSheetViewController.mm +649 -0
  41. package/ios/events/OnDetentChangeEvent.h +28 -0
  42. package/ios/events/OnDetentChangeEvent.mm +30 -0
  43. package/ios/events/OnDidDismissEvent.h +26 -0
  44. package/ios/events/OnDidDismissEvent.mm +25 -0
  45. package/ios/events/OnDidPresentEvent.h +28 -0
  46. package/ios/events/OnDidPresentEvent.mm +30 -0
  47. package/ios/events/OnDragBeginEvent.h +28 -0
  48. package/ios/events/OnDragBeginEvent.mm +30 -0
  49. package/ios/events/OnDragChangeEvent.h +28 -0
  50. package/ios/events/OnDragChangeEvent.mm +30 -0
  51. package/ios/events/OnDragEndEvent.h +28 -0
  52. package/ios/events/OnDragEndEvent.mm +30 -0
  53. package/ios/events/OnMountEvent.h +26 -0
  54. package/ios/events/OnMountEvent.mm +25 -0
  55. package/ios/events/OnPositionChangeEvent.h +29 -0
  56. package/ios/events/OnPositionChangeEvent.mm +32 -0
  57. package/ios/events/OnSizeChangeEvent.h +28 -0
  58. package/ios/events/OnSizeChangeEvent.mm +30 -0
  59. package/ios/events/OnWillDismissEvent.h +26 -0
  60. package/ios/events/OnWillDismissEvent.mm +25 -0
  61. package/ios/events/OnWillPresentEvent.h +28 -0
  62. package/ios/events/OnWillPresentEvent.mm +30 -0
  63. package/ios/utils/GestureUtil.h +25 -0
  64. package/ios/utils/GestureUtil.mm +26 -0
  65. package/ios/utils/LayoutUtil.h +44 -0
  66. package/ios/utils/LayoutUtil.mm +50 -0
  67. package/ios/utils/WindowUtil.h +27 -0
  68. package/ios/utils/WindowUtil.mm +42 -0
  69. package/lib/module/TrueSheet.js +231 -135
  70. package/lib/module/TrueSheet.js.map +1 -1
  71. package/lib/module/TrueSheetGrabber.js +16 -14
  72. package/lib/module/TrueSheetGrabber.js.map +1 -1
  73. package/lib/module/fabric/TrueSheetContainerViewNativeComponent.ts +8 -0
  74. package/lib/module/fabric/TrueSheetContentViewNativeComponent.ts +8 -0
  75. package/lib/module/fabric/TrueSheetFooterViewNativeComponent.ts +8 -0
  76. package/lib/module/fabric/TrueSheetViewNativeComponent.ts +63 -0
  77. package/lib/module/index.js +1 -0
  78. package/lib/module/index.js.map +1 -1
  79. package/lib/module/reanimated/ReanimatedTrueSheet.js +87 -0
  80. package/lib/module/reanimated/ReanimatedTrueSheet.js.map +1 -0
  81. package/lib/module/reanimated/ReanimatedTrueSheetProvider.js +72 -0
  82. package/lib/module/reanimated/ReanimatedTrueSheetProvider.js.map +1 -0
  83. package/lib/module/reanimated/index.js +6 -0
  84. package/lib/module/reanimated/index.js.map +1 -0
  85. package/lib/module/reanimated/useReanimatedPositionChangeHandler.js +19 -0
  86. package/lib/module/reanimated/useReanimatedPositionChangeHandler.js.map +1 -0
  87. package/lib/module/specs/NativeTrueSheetModule.js +12 -0
  88. package/lib/module/specs/NativeTrueSheetModule.js.map +1 -0
  89. package/lib/typescript/package.json +1 -0
  90. package/lib/typescript/src/TrueSheet.d.ts +79 -0
  91. package/lib/typescript/src/TrueSheet.d.ts.map +1 -0
  92. package/lib/typescript/src/TrueSheet.types.d.ts +260 -0
  93. package/lib/typescript/src/TrueSheet.types.d.ts.map +1 -0
  94. package/lib/typescript/{commonjs/src → src}/TrueSheetGrabber.d.ts +1 -1
  95. package/lib/typescript/src/TrueSheetGrabber.d.ts.map +1 -0
  96. package/lib/typescript/src/fabric/TrueSheetContainerViewNativeComponent.d.ts +6 -0
  97. package/lib/typescript/src/fabric/TrueSheetContainerViewNativeComponent.d.ts.map +1 -0
  98. package/lib/typescript/src/fabric/TrueSheetContentViewNativeComponent.d.ts +6 -0
  99. package/lib/typescript/src/fabric/TrueSheetContentViewNativeComponent.d.ts.map +1 -0
  100. package/lib/typescript/src/fabric/TrueSheetFooterViewNativeComponent.d.ts +6 -0
  101. package/lib/typescript/src/fabric/TrueSheetFooterViewNativeComponent.d.ts.map +1 -0
  102. package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts +44 -0
  103. package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts.map +1 -0
  104. package/lib/typescript/{commonjs/src → src}/index.d.ts +1 -0
  105. package/lib/typescript/src/index.d.ts.map +1 -0
  106. package/lib/typescript/src/reanimated/ReanimatedTrueSheet.d.ts +43 -0
  107. package/lib/typescript/src/reanimated/ReanimatedTrueSheet.d.ts.map +1 -0
  108. package/lib/typescript/src/reanimated/ReanimatedTrueSheetProvider.d.ts +57 -0
  109. package/lib/typescript/src/reanimated/ReanimatedTrueSheetProvider.d.ts.map +1 -0
  110. package/lib/typescript/src/reanimated/index.d.ts +4 -0
  111. package/lib/typescript/src/reanimated/index.d.ts.map +1 -0
  112. package/lib/typescript/src/reanimated/useReanimatedPositionChangeHandler.d.ts +6 -0
  113. package/lib/typescript/src/reanimated/useReanimatedPositionChangeHandler.d.ts.map +1 -0
  114. package/lib/typescript/src/specs/NativeTrueSheetModule.d.ts +34 -0
  115. package/lib/typescript/src/specs/NativeTrueSheetModule.d.ts.map +1 -0
  116. package/package.json +104 -75
  117. package/react-native.config.js +17 -0
  118. package/src/TrueSheet.tsx +285 -188
  119. package/src/TrueSheet.types.ts +119 -106
  120. package/src/TrueSheetGrabber.tsx +29 -28
  121. package/src/__mocks__/index.js +60 -12
  122. package/src/fabric/TrueSheetContainerViewNativeComponent.ts +8 -0
  123. package/src/fabric/TrueSheetContentViewNativeComponent.ts +8 -0
  124. package/src/fabric/TrueSheetFooterViewNativeComponent.ts +8 -0
  125. package/src/fabric/TrueSheetViewNativeComponent.ts +63 -0
  126. package/src/index.ts +4 -3
  127. package/src/reanimated/ReanimatedTrueSheet.tsx +95 -0
  128. package/src/reanimated/ReanimatedTrueSheetProvider.tsx +92 -0
  129. package/src/reanimated/index.ts +3 -0
  130. package/src/reanimated/useReanimatedPositionChangeHandler.ts +26 -0
  131. package/src/specs/NativeTrueSheetModule.ts +38 -0
  132. package/TrueSheet.podspec +0 -49
  133. package/android/src/main/java/com/lodev09/truesheet/TrueSheetDialog.kt +0 -413
  134. package/android/src/main/java/com/lodev09/truesheet/TrueSheetEvent.kt +0 -22
  135. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewModule.kt +0 -63
  136. package/android/src/main/java/com/lodev09/truesheet/core/KeyboardManager.kt +0 -58
  137. package/android/src/main/java/com/lodev09/truesheet/core/RootSheetView.kt +0 -102
  138. package/ios/Extensions/UIBlurEffect+withTint.swift +0 -62
  139. package/ios/Extensions/UIView+pinTo.swift +0 -74
  140. package/ios/Extensions/UIViewController+detentForSize.swift +0 -134
  141. package/ios/TrueSheet-Bridging-Header.h +0 -14
  142. package/ios/TrueSheetEvent.swift +0 -48
  143. package/ios/TrueSheetView.swift +0 -467
  144. package/ios/TrueSheetViewController.swift +0 -275
  145. package/ios/TrueSheetViewManager.m +0 -53
  146. package/ios/TrueSheetViewManager.swift +0 -48
  147. package/ios/Utils/Logger.swift +0 -39
  148. package/ios/Utils/Promise.swift +0 -25
  149. package/lib/commonjs/TrueSheet.js +0 -258
  150. package/lib/commonjs/TrueSheet.js.map +0 -1
  151. package/lib/commonjs/TrueSheet.types.js +0 -6
  152. package/lib/commonjs/TrueSheet.types.js.map +0 -1
  153. package/lib/commonjs/TrueSheetFooter.js +0 -19
  154. package/lib/commonjs/TrueSheetFooter.js.map +0 -1
  155. package/lib/commonjs/TrueSheetGrabber.js +0 -54
  156. package/lib/commonjs/TrueSheetGrabber.js.map +0 -1
  157. package/lib/commonjs/TrueSheetModule.js +0 -19
  158. package/lib/commonjs/TrueSheetModule.js.map +0 -1
  159. package/lib/commonjs/__mocks__/index.js +0 -52
  160. package/lib/commonjs/__mocks__/index.js.map +0 -1
  161. package/lib/commonjs/index.js +0 -39
  162. package/lib/commonjs/index.js.map +0 -1
  163. package/lib/module/TrueSheetFooter.js +0 -14
  164. package/lib/module/TrueSheetFooter.js.map +0 -1
  165. package/lib/module/TrueSheetModule.js +0 -15
  166. package/lib/module/TrueSheetModule.js.map +0 -1
  167. package/lib/module/__mocks__/index.js +0 -21
  168. package/lib/module/__mocks__/index.js.map +0 -1
  169. package/lib/typescript/commonjs/package.json +0 -1
  170. package/lib/typescript/commonjs/src/TrueSheet.d.ts +0 -70
  171. package/lib/typescript/commonjs/src/TrueSheet.d.ts.map +0 -1
  172. package/lib/typescript/commonjs/src/TrueSheet.types.d.ts +0 -241
  173. package/lib/typescript/commonjs/src/TrueSheet.types.d.ts.map +0 -1
  174. package/lib/typescript/commonjs/src/TrueSheetFooter.d.ts +0 -7
  175. package/lib/typescript/commonjs/src/TrueSheetFooter.d.ts.map +0 -1
  176. package/lib/typescript/commonjs/src/TrueSheetGrabber.d.ts.map +0 -1
  177. package/lib/typescript/commonjs/src/TrueSheetModule.d.ts +0 -2
  178. package/lib/typescript/commonjs/src/TrueSheetModule.d.ts.map +0 -1
  179. package/lib/typescript/commonjs/src/index.d.ts.map +0 -1
  180. package/lib/typescript/module/src/TrueSheet.d.ts +0 -70
  181. package/lib/typescript/module/src/TrueSheet.d.ts.map +0 -1
  182. package/lib/typescript/module/src/TrueSheet.types.d.ts +0 -241
  183. package/lib/typescript/module/src/TrueSheet.types.d.ts.map +0 -1
  184. package/lib/typescript/module/src/TrueSheetFooter.d.ts +0 -7
  185. package/lib/typescript/module/src/TrueSheetFooter.d.ts.map +0 -1
  186. package/lib/typescript/module/src/TrueSheetGrabber.d.ts +0 -39
  187. package/lib/typescript/module/src/TrueSheetGrabber.d.ts.map +0 -1
  188. package/lib/typescript/module/src/TrueSheetModule.d.ts +0 -2
  189. package/lib/typescript/module/src/TrueSheetModule.d.ts.map +0 -1
  190. package/lib/typescript/module/src/index.d.ts +0 -4
  191. package/lib/typescript/module/src/index.d.ts.map +0 -1
  192. package/src/TrueSheetFooter.tsx +0 -17
  193. package/src/TrueSheetModule.ts +0 -19
  194. /package/lib/{typescript/module → module}/package.json +0 -0
package/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # React Native True Sheet
2
2
 
3
3
  [![CI](https://github.com/lodev09/react-native-true-sheet/actions/workflows/ci.yml/badge.svg)](https://github.com/lodev09/react-native-true-sheet/actions/workflows/ci.yml)
4
- [![Maintainability](https://api.codeclimate.com/v1/badges/0bd49973c6c61d85e2be/maintainability)](https://codeclimate.com/github/lodev09/react-native-true-sheet/maintainability)
5
4
  [![NPM Downloads](https://img.shields.io/npm/d18m/%40lodev09%2Freact-native-true-sheet)](https://www.npmjs.com/package/@lodev09/react-native-true-sheet)
6
5
 
7
6
  The true native bottom sheet experience for your React Native Apps. 💩
@@ -10,14 +9,24 @@ The true native bottom sheet experience for your React Native Apps. 💩
10
9
 
11
10
  ## Features
12
11
 
13
- * Implemented in the native realm.
14
- * Clean, fast, and lightweight.
15
- * Asynchronus `ref` [methods](https://sheet.lodev09.com/reference/methods#ref-methods).
16
- * Bonus! [Blur](https://sheet.lodev09.com/reference/types#blurtint) support on IOS 😎
12
+ * **Powered by Fabric** - Built on React Native's new architecture for maximum performance
13
+ * 🎯 **Type-safe** - Full TypeScript support with Codegen-generated native interfaces
14
+ * 🚀 **Blazing fast** - Direct C++ communication, no bridge overhead
15
+ * 🎨 **Native** - Implemented in the native realm
16
+ * 🔄 **Imperative API** - Asynchronus `ref` [methods](https://sheet.lodev09.com/reference/methods#ref-methods)
17
17
 
18
18
  ## Installation
19
19
 
20
- You can install the package by using either `yarn` or `npm`.
20
+ > [!IMPORTANT]
21
+ > **Version 3.0+ requires React Native's New Architecture (Fabric)**
22
+ > For the old architecture, use version 2.x. See the [Migration Guide (v2 → v3)](https://sheet.lodev09.com/migration) for upgrading.
23
+
24
+ ### Prerequisites
25
+
26
+ - React Native >= 0.81
27
+ - New Architecture enabled (`RCT_NEW_ARCH_ENABLED=1` for iOS, `newArchEnabled=true` for Android)
28
+
29
+ ### Install
21
30
 
22
31
  ```sh
23
32
  yarn add @lodev09/react-native-true-sheet
@@ -26,18 +35,25 @@ yarn add @lodev09/react-native-true-sheet
26
35
  npm i @lodev09/react-native-true-sheet
27
36
  ```
28
37
 
29
- Next, run the following to install it on IOS.
38
+ ### iOS Setup
30
39
 
31
40
  ```sh
32
41
  cd ios && pod install
33
42
  ```
34
43
 
44
+ > **Note:** If you need old architecture support, use version 2.x:
45
+ > ```sh
46
+ > yarn add @lodev09/react-native-true-sheet@^2.0.0
47
+ > ```
48
+
35
49
  ## Documentation
36
50
 
37
51
  - [Example](example)
38
52
  - [Guides](https://sheet.lodev09.com/category/guides)
39
53
  - [Reference](https://sheet.lodev09.com/category/reference)
54
+ - [Migration Guide (v2 → v3)](https://sheet.lodev09.com/migration)
40
55
  - [Troubleshooting](https://sheet.lodev09.com/troubleshooting)
56
+ - [Testing with Jest](https://sheet.lodev09.com/guides/jest)
41
57
 
42
58
  ## Usage
43
59
 
@@ -64,7 +80,7 @@ export const App = () => {
64
80
  <Button onPress={present} title="Present" />
65
81
  <TrueSheet
66
82
  ref={sheet}
67
- sizes={['auto', 'large']}
83
+ detents={['auto', 1]}
68
84
  cornerRadius={24}
69
85
  >
70
86
  <Button onPress={dismiss} title="Dismiss" />
@@ -74,6 +90,18 @@ export const App = () => {
74
90
  }
75
91
  ```
76
92
 
93
+ ## Testing
94
+
95
+ TrueSheet includes built-in Jest mocks for easy testing. Simply mock the package in your tests:
96
+
97
+ ```tsx
98
+ jest.mock('@lodev09/react-native-true-sheet');
99
+ ```
100
+
101
+ All methods (`present`, `dismiss`, `resize`) are mocked as Jest functions, allowing you to test your components without native dependencies.
102
+
103
+ **[Full Testing Guide](https://sheet.lodev09.com/guides/jest)**
104
+
77
105
  ## Contributing
78
106
 
79
107
  See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
@@ -0,0 +1,20 @@
1
+ require "json"
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = "RNTrueSheet"
7
+ s.version = package["version"]
8
+ s.summary = package["description"]
9
+ s.homepage = package["homepage"]
10
+ s.license = package["license"]
11
+ s.authors = package["author"]
12
+
13
+ s.platforms = { :ios => min_ios_version_supported }
14
+ s.source = { :git => "https://github.com/lodev09/react-native-true-sheet.git", :tag => "#{s.version}" }
15
+
16
+ s.source_files = "ios/**/*.{h,m,mm,swift,cpp}"
17
+ s.private_header_files = "ios/**/*.h"
18
+
19
+ install_modules_dependencies(s)
20
+ end
@@ -16,24 +16,19 @@ buildscript {
16
16
  }
17
17
 
18
18
 
19
- def isNewArchitectureEnabled() {
20
- return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
21
- }
22
-
23
19
  apply plugin: "com.android.library"
24
20
  apply plugin: "kotlin-android"
25
-
26
- // TODO:
27
- // When running example, comment this block!
28
- // Not sure what's going on but we are getting multiple definition error when this is enabled.
29
- if (isNewArchitectureEnabled()) {
30
- apply plugin: "com.facebook.react"
31
- }
21
+ apply plugin: "com.facebook.react"
32
22
 
33
23
  def getExtOrIntegerDefault(name) {
34
24
  return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["TrueSheet_" + name]).toInteger()
35
25
  }
36
26
 
27
+ def getEdgeToEdgeEnabled() {
28
+ def edgeToEdge = project.findProperty("edgeToEdgeEnabled")
29
+ return edgeToEdge != null ? edgeToEdge.toBoolean() : false
30
+ }
31
+
37
32
  def supportsNamespace() {
38
33
  def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
39
34
  def major = parsed[0].toInteger()
@@ -59,7 +54,7 @@ android {
59
54
  defaultConfig {
60
55
  minSdkVersion getExtOrIntegerDefault("minSdkVersion")
61
56
  targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
62
-
57
+ buildConfigField "boolean", "EDGE_TO_EDGE_ENABLED", "${getEdgeToEdgeEnabled()}"
63
58
  }
64
59
 
65
60
  buildTypes {
@@ -73,8 +68,25 @@ android {
73
68
  }
74
69
 
75
70
  compileOptions {
76
- sourceCompatibility JavaVersion.VERSION_1_8
77
- targetCompatibility JavaVersion.VERSION_1_8
71
+ sourceCompatibility JavaVersion.VERSION_17
72
+ targetCompatibility JavaVersion.VERSION_17
73
+ }
74
+
75
+ kotlinOptions {
76
+ jvmTarget = "17"
77
+ }
78
+
79
+ buildFeatures {
80
+ buildConfig = true
81
+ }
82
+
83
+ sourceSets {
84
+ main {
85
+ java.srcDirs += [
86
+ "generated/java",
87
+ "generated/jni"
88
+ ]
89
+ }
78
90
  }
79
91
  }
80
92
 
@@ -0,0 +1,108 @@
1
+ package com.lodev09.truesheet
2
+
3
+ import android.annotation.SuppressLint
4
+ import android.view.View
5
+ import androidx.core.view.isNotEmpty
6
+ import com.facebook.react.uimanager.ThemedReactContext
7
+ import com.facebook.react.views.view.ReactViewGroup
8
+
9
+ /**
10
+ * Delegate interface for container view changes
11
+ */
12
+ interface TrueSheetContainerViewDelegate {
13
+ fun containerViewContentDidChangeSize(width: Int, height: Int)
14
+ fun containerViewFooterDidChangeSize(width: Int, height: Int)
15
+ }
16
+
17
+ /**
18
+ * Container view that manages the bottom sheet content and holds content and footer views.
19
+ * Simplified to be a lightweight content manager - events are now handled via dialog delegate.
20
+ */
21
+ @SuppressLint("ViewConstructor")
22
+ class TrueSheetContainerView(private val reactContext: ThemedReactContext) :
23
+ ReactViewGroup(reactContext),
24
+ TrueSheetContentViewDelegate,
25
+ TrueSheetFooterViewDelegate {
26
+
27
+ var delegate: TrueSheetContainerViewDelegate? = null
28
+
29
+ /**
30
+ * Reference to content view (first child)
31
+ */
32
+ val contentView: TrueSheetContentView?
33
+ get() = if (isNotEmpty() && getChildAt(0) is TrueSheetContentView) {
34
+ getChildAt(0) as TrueSheetContentView
35
+ } else {
36
+ null
37
+ }
38
+
39
+ /**
40
+ * Reference to footer view (second child)
41
+ */
42
+ val footerView: TrueSheetFooterView?
43
+ get() = if (childCount > 1 && getChildAt(1) is TrueSheetFooterView) {
44
+ getChildAt(1) as TrueSheetFooterView
45
+ } else {
46
+ null
47
+ }
48
+
49
+ /**
50
+ * The content view height
51
+ */
52
+ val contentHeight: Int
53
+ get() = contentView?.height ?: 0
54
+
55
+ /**
56
+ * The footer view height
57
+ */
58
+ val footerHeight: Int
59
+ get() = footerView?.height ?: 0
60
+
61
+ init {
62
+ // Container should not clip children to allow footer to position absolutely
63
+ clipChildren = false
64
+ clipToPadding = false
65
+ }
66
+
67
+ override fun addView(child: View?, index: Int) {
68
+ super.addView(child, index)
69
+
70
+ // Set up delegate when content view is added
71
+ if (child is TrueSheetContentView) {
72
+ child.delegate = this
73
+ }
74
+
75
+ // Set up delegate when footer view is added
76
+ if (child is TrueSheetFooterView) {
77
+ child.delegate = this
78
+ }
79
+ }
80
+
81
+ override fun removeView(view: View?) {
82
+ // Clean up delegate when content view is removed
83
+ if (view is TrueSheetContentView) {
84
+ view.delegate = null
85
+ }
86
+
87
+ // Clean up delegate when footer view is removed
88
+ if (view is TrueSheetFooterView) {
89
+ view.delegate = null
90
+ }
91
+
92
+ super.removeView(view)
93
+ }
94
+
95
+ // ==================== TrueSheetContentViewDelegate Implementation ====================
96
+
97
+ override fun contentViewDidChangeSize(width: Int, height: Int) {
98
+ // Forward content size changes to controller for sheet resizing
99
+ delegate?.containerViewContentDidChangeSize(width, height)
100
+ }
101
+
102
+ // ==================== TrueSheetFooterViewDelegate Implementation ====================
103
+
104
+ override fun footerViewDidChangeSize(width: Int, height: Int) {
105
+ // Forward footer size changes to host view for repositioning
106
+ delegate?.containerViewFooterDidChangeSize(width, height)
107
+ }
108
+ }
@@ -0,0 +1,21 @@
1
+ package com.lodev09.truesheet
2
+
3
+ import com.facebook.react.module.annotations.ReactModule
4
+ import com.facebook.react.uimanager.ThemedReactContext
5
+ import com.facebook.react.uimanager.ViewGroupManager
6
+
7
+ /**
8
+ * ViewManager for TrueSheetContainerView
9
+ * Container that holds content and footer views
10
+ */
11
+ @ReactModule(name = TrueSheetContainerViewManager.REACT_CLASS)
12
+ class TrueSheetContainerViewManager : ViewGroupManager<TrueSheetContainerView>() {
13
+
14
+ override fun getName(): String = REACT_CLASS
15
+
16
+ override fun createViewInstance(reactContext: ThemedReactContext): TrueSheetContainerView = TrueSheetContainerView(reactContext)
17
+
18
+ companion object {
19
+ const val REACT_CLASS = "TrueSheetContainerView"
20
+ }
21
+ }
@@ -0,0 +1,46 @@
1
+ package com.lodev09.truesheet
2
+
3
+ import android.annotation.SuppressLint
4
+ import com.facebook.react.uimanager.ThemedReactContext
5
+ import com.facebook.react.views.view.ReactViewGroup
6
+
7
+ /**
8
+ * Delegate interface for content view size changes
9
+ */
10
+ interface TrueSheetContentViewDelegate {
11
+ fun contentViewDidChangeSize(width: Int, height: Int)
12
+ }
13
+
14
+ /**
15
+ * Content view that holds the main sheet content
16
+ * This is the first child of TrueSheetContainerView
17
+ */
18
+ @SuppressLint("ViewConstructor")
19
+ class TrueSheetContentView(context: ThemedReactContext) : ReactViewGroup(context) {
20
+ var delegate: TrueSheetContentViewDelegate? = null
21
+
22
+ private var lastWidth = 0
23
+ private var lastHeight = 0
24
+
25
+ override fun onLayout(
26
+ changed: Boolean,
27
+ left: Int,
28
+ top: Int,
29
+ right: Int,
30
+ bottom: Int
31
+ ) {
32
+ super.onLayout(changed, left, top, right, bottom)
33
+
34
+ // Notify delegate when content size changes
35
+ val newWidth = right - left
36
+ val newHeight = bottom - top
37
+
38
+ if (newWidth != lastWidth || newHeight != lastHeight) {
39
+ lastWidth = newWidth
40
+ lastHeight = newHeight
41
+
42
+ // Notify delegate of size change
43
+ delegate?.contentViewDidChangeSize(newWidth, newHeight)
44
+ }
45
+ }
46
+ }
@@ -0,0 +1,21 @@
1
+ package com.lodev09.truesheet
2
+
3
+ import com.facebook.react.module.annotations.ReactModule
4
+ import com.facebook.react.uimanager.ThemedReactContext
5
+ import com.facebook.react.uimanager.ViewGroupManager
6
+
7
+ /**
8
+ * ViewManager for TrueSheetContentView
9
+ * Manages the main content area of the sheet
10
+ */
11
+ @ReactModule(name = TrueSheetContentViewManager.REACT_CLASS)
12
+ class TrueSheetContentViewManager : ViewGroupManager<TrueSheetContentView>() {
13
+
14
+ override fun getName(): String = REACT_CLASS
15
+
16
+ override fun createViewInstance(reactContext: ThemedReactContext): TrueSheetContentView = TrueSheetContentView(reactContext)
17
+
18
+ companion object {
19
+ const val REACT_CLASS = "TrueSheetContentView"
20
+ }
21
+ }
@@ -0,0 +1,47 @@
1
+ package com.lodev09.truesheet
2
+
3
+ import android.annotation.SuppressLint
4
+ import com.facebook.react.uimanager.ThemedReactContext
5
+ import com.facebook.react.views.view.ReactViewGroup
6
+
7
+ /**
8
+ * Delegate interface for footer view size changes
9
+ */
10
+ interface TrueSheetFooterViewDelegate {
11
+ fun footerViewDidChangeSize(width: Int, height: Int)
12
+ }
13
+
14
+ /**
15
+ * Footer view that holds the footer content
16
+ * This is the second child of TrueSheetContainerView
17
+ * Positioned absolutely at the bottom of the sheet
18
+ */
19
+ @SuppressLint("ViewConstructor")
20
+ class TrueSheetFooterView(context: ThemedReactContext) : ReactViewGroup(context) {
21
+ var delegate: TrueSheetFooterViewDelegate? = null
22
+
23
+ private var lastWidth = 0
24
+ private var lastHeight = 0
25
+
26
+ override fun onLayout(
27
+ changed: Boolean,
28
+ left: Int,
29
+ top: Int,
30
+ right: Int,
31
+ bottom: Int
32
+ ) {
33
+ super.onLayout(changed, left, top, right, bottom)
34
+
35
+ // Notify delegate when footer size changes
36
+ val newWidth = right - left
37
+ val newHeight = bottom - top
38
+
39
+ if (newWidth != lastWidth || newHeight != lastHeight) {
40
+ lastWidth = newWidth
41
+ lastHeight = newHeight
42
+
43
+ // Notify delegate of size change
44
+ delegate?.footerViewDidChangeSize(newWidth, newHeight)
45
+ }
46
+ }
47
+ }
@@ -0,0 +1,21 @@
1
+ package com.lodev09.truesheet
2
+
3
+ import com.facebook.react.module.annotations.ReactModule
4
+ import com.facebook.react.uimanager.ThemedReactContext
5
+ import com.facebook.react.uimanager.ViewGroupManager
6
+
7
+ /**
8
+ * ViewManager for TrueSheetFooterView
9
+ * Manages the footer area of the sheet
10
+ */
11
+ @ReactModule(name = TrueSheetFooterViewManager.REACT_CLASS)
12
+ class TrueSheetFooterViewManager : ViewGroupManager<TrueSheetFooterView>() {
13
+
14
+ override fun getName(): String = REACT_CLASS
15
+
16
+ override fun createViewInstance(reactContext: ThemedReactContext): TrueSheetFooterView = TrueSheetFooterView(reactContext)
17
+
18
+ companion object {
19
+ const val REACT_CLASS = "TrueSheetFooterView"
20
+ }
21
+ }
@@ -0,0 +1,165 @@
1
+ package com.lodev09.truesheet
2
+
3
+ import android.os.Handler
4
+ import android.os.Looper
5
+ import com.facebook.react.bridge.Promise
6
+ import com.facebook.react.bridge.ReactApplicationContext
7
+ import com.facebook.react.bridge.ReactMethod
8
+ import com.facebook.react.module.annotations.ReactModule
9
+ import com.facebook.react.turbomodule.core.interfaces.TurboModule
10
+ import com.facebook.react.uimanager.UIManagerHelper
11
+ import java.util.concurrent.ConcurrentHashMap
12
+
13
+ /**
14
+ * TurboModule for TrueSheet imperative API
15
+ * Provides promise-based async operations using view references
16
+ */
17
+ @ReactModule(name = TrueSheetModule.NAME)
18
+ class TrueSheetModule(reactContext: ReactApplicationContext) :
19
+ com.facebook.react.bridge.ReactContextBaseJavaModule(reactContext),
20
+ TurboModule {
21
+
22
+ override fun getName(): String = NAME
23
+
24
+ override fun initialize() {
25
+ super.initialize()
26
+ }
27
+
28
+ override fun invalidate() {
29
+ super.invalidate()
30
+ // Clear all registered views on module invalidation
31
+ synchronized(viewRegistry) {
32
+ viewRegistry.clear()
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Present a sheet by reference
38
+ *
39
+ * @param viewTag Native view tag of the sheet component
40
+ * @param index Detent index to present at
41
+ * @param promise Promise that resolves when sheet is fully presented
42
+ * @throws VIEW_NOT_FOUND if the view with the given tag is not found
43
+ * @throws INVALID_VIEW_TYPE if the view is not a TrueSheetView
44
+ * @throws OPERATION_FAILED if the operation fails for any other reason
45
+ */
46
+ @ReactMethod
47
+ fun presentByRef(viewTag: Double, index: Double, promise: Promise) {
48
+ val tag = viewTag.toInt()
49
+ val detentIndex = index.toInt()
50
+
51
+ withTrueSheetView(tag, promise) { view ->
52
+ view.present(detentIndex) {
53
+ promise.resolve(null)
54
+ }
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Dismiss a sheet by reference
60
+ *
61
+ * @param viewTag Native view tag of the sheet component
62
+ * @param promise Promise that resolves when sheet is fully dismissed
63
+ * @throws VIEW_NOT_FOUND if the view with the given tag is not found
64
+ * @throws INVALID_VIEW_TYPE if the view is not a TrueSheetView
65
+ * @throws OPERATION_FAILED if the operation fails for any other reason
66
+ */
67
+ @ReactMethod
68
+ fun dismissByRef(viewTag: Double, promise: Promise) {
69
+ val tag = viewTag.toInt()
70
+
71
+ withTrueSheetView(tag, promise) { view ->
72
+ view.dismiss {
73
+ promise.resolve(null)
74
+ }
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Resize a sheet to a different index by reference
80
+ *
81
+ * @param viewTag Native view tag of the sheet component
82
+ * @param index New detent index
83
+ * @param promise Promise that resolves when resize is complete
84
+ * @throws VIEW_NOT_FOUND if the view with the given tag is not found
85
+ * @throws INVALID_VIEW_TYPE if the view is not a TrueSheetView
86
+ * @throws OPERATION_FAILED if the operation fails for any other reason
87
+ */
88
+ @ReactMethod
89
+ fun resizeByRef(viewTag: Double, index: Double, promise: Promise) {
90
+ // Resize is just an alias for present
91
+ presentByRef(viewTag, index, promise)
92
+ }
93
+
94
+ /**
95
+ * Helper method to get TrueSheetView by tag and execute closure
96
+ */
97
+ private fun withTrueSheetView(tag: Int, promise: Promise, closure: (view: TrueSheetView) -> Unit) {
98
+ Handler(Looper.getMainLooper()).post {
99
+ try {
100
+ // First try to get from registry (faster)
101
+ val view = getSheetByTag(tag)
102
+
103
+ if (view != null) {
104
+ closure(view)
105
+ } else {
106
+ // Fallback to UIManager resolution
107
+ val manager = UIManagerHelper.getUIManagerForReactTag(reactApplicationContext, tag)
108
+ val resolvedView = manager?.resolveView(tag)
109
+
110
+ if (resolvedView == null) {
111
+ promise.reject("VIEW_NOT_FOUND", "TrueSheetView with tag $tag not found")
112
+ return@post
113
+ }
114
+
115
+ if (resolvedView is TrueSheetView) {
116
+ closure(resolvedView)
117
+ } else {
118
+ promise.reject(
119
+ "INVALID_VIEW_TYPE",
120
+ "View with tag $tag is not a TrueSheetView (got ${resolvedView::class.simpleName})"
121
+ )
122
+ }
123
+ }
124
+ } catch (e: Exception) {
125
+ promise.reject("OPERATION_FAILED", "Failed to execute operation: ${e.message}", e)
126
+ }
127
+ }
128
+ }
129
+
130
+ companion object {
131
+ const val NAME = "TrueSheetModule"
132
+
133
+ /**
134
+ * Registry to keep track of TrueSheetView instances by their view tag
135
+ * This provides fast lookup for ref-based operations
136
+ */
137
+ private val viewRegistry = ConcurrentHashMap<Int, TrueSheetView>()
138
+
139
+ /**
140
+ * Register a TrueSheetView instance
141
+ * Called automatically by TrueSheetView during initialization
142
+ */
143
+ @JvmStatic
144
+ fun registerView(view: TrueSheetView, tag: Int) {
145
+ viewRegistry[tag] = view
146
+ }
147
+
148
+ /**
149
+ * Unregister a TrueSheetView instance
150
+ * Called automatically by TrueSheetView during cleanup
151
+ */
152
+ @JvmStatic
153
+ fun unregisterView(tag: Int) {
154
+ viewRegistry.remove(tag)
155
+ }
156
+
157
+ /**
158
+ * Get a TrueSheetView by its tag
159
+ * @param tag - The React native tag of the view
160
+ * @return The TrueSheetView instance, or null if not found
161
+ */
162
+ @JvmStatic
163
+ fun getSheetByTag(tag: Int): TrueSheetView? = viewRegistry[tag]
164
+ }
165
+ }
@@ -1,12 +1,44 @@
1
1
  package com.lodev09.truesheet
2
2
 
3
- import com.facebook.react.ReactPackage
3
+ import com.facebook.react.TurboReactPackage
4
4
  import com.facebook.react.bridge.NativeModule
5
5
  import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.module.model.ReactModuleInfo
7
+ import com.facebook.react.module.model.ReactModuleInfoProvider
6
8
  import com.facebook.react.uimanager.ViewManager
7
9
 
8
- class TrueSheetPackage : ReactPackage {
9
- override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> = listOf(TrueSheetViewModule(reactContext))
10
+ /**
11
+ * TrueSheet package for Fabric architecture
12
+ * Registers all view managers and the TurboModule
13
+ */
14
+ class TrueSheetPackage : TurboReactPackage() {
10
15
 
11
- override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> = listOf(TrueSheetViewManager())
16
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? =
17
+ when (name) {
18
+ TrueSheetModule.NAME -> TrueSheetModule(reactContext)
19
+ else -> null
20
+ }
21
+
22
+ override fun getReactModuleInfoProvider(): ReactModuleInfoProvider =
23
+ ReactModuleInfoProvider {
24
+ mapOf(
25
+ TrueSheetModule.NAME to ReactModuleInfo(
26
+ TrueSheetModule.NAME,
27
+ TrueSheetModule::class.java.name,
28
+ false, // canOverrideExistingModule
29
+ false, // needsEagerInit
30
+ true, // hasConstants
31
+ false, // isCxxModule
32
+ true // isTurboModule
33
+ )
34
+ )
35
+ }
36
+
37
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> =
38
+ listOf(
39
+ TrueSheetViewManager(),
40
+ TrueSheetContainerViewManager(),
41
+ TrueSheetContentViewManager(),
42
+ TrueSheetFooterViewManager()
43
+ )
12
44
  }