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