@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.
- package/README.md +25 -4
- package/android/build.gradle +22 -1
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerView.kt +50 -16
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentView.kt +303 -184
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentViewManager.kt +5 -1
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterView.kt +21 -110
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetOverlayView.kt +116 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetOverlayViewManager.kt +45 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetPackage.kt +2 -1
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetStateUpdater.kt +18 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +124 -50
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +369 -163
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +59 -12
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetBottomSheetBehavior.kt +126 -0
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetBottomSheetView.kt +22 -9
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetCoordinatorLayout.kt +84 -5
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDetentCalculator.kt +104 -39
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDimView.kt +3 -0
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetOverlayRootView.kt +137 -0
- package/android/src/main/java/com/lodev09/truesheet/events/TrueSheetLifecycleEvents.kt +15 -0
- package/android/src/main/java/com/lodev09/truesheet/utils/KeyboardUtils.kt +15 -2
- package/android/src/main/java/com/lodev09/truesheet/utils/ScreenUtils.kt +0 -12
- package/android/src/main/java/com/lodev09/truesheet/utils/ViewUtils.kt +19 -7
- package/android/src/main/jni/TrueSheetSpec.h +1 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewComponentDescriptor.h +1 -9
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.cpp +110 -30
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.h +30 -7
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewState.cpp +2 -2
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewState.h +9 -8
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewComponentDescriptor.h +3 -5
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewShadowNode.cpp +9 -3
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewShadowNode.h +3 -6
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewState.cpp +1 -1
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewState.h +4 -6
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetInsets.cpp +1 -1
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetInsets.h +1 -1
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetLayoutUtils.h +43 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetOverlayViewComponentDescriptor.h +21 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetOverlayViewShadowNode.cpp +17 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetOverlayViewShadowNode.h +33 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewComponentDescriptor.h +3 -5
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.cpp +7 -40
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.h +3 -7
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewState.cpp +3 -5
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewState.h +4 -5
- package/ios/TrueSheetContainerView.h +27 -7
- package/ios/TrueSheetContainerView.mm +31 -11
- package/ios/TrueSheetContentView.h +43 -15
- package/ios/TrueSheetContentView.mm +211 -189
- package/ios/TrueSheetFooterView.h +6 -0
- package/ios/TrueSheetFooterView.mm +93 -17
- package/ios/TrueSheetModule.h +2 -7
- package/ios/TrueSheetModule.mm +7 -16
- package/ios/TrueSheetOverlayView.h +32 -0
- package/ios/TrueSheetOverlayView.mm +161 -0
- package/ios/TrueSheetView.mm +275 -56
- package/ios/TrueSheetViewController.h +31 -3
- package/ios/TrueSheetViewController.mm +393 -94
- package/ios/core/TrueSheetBlurView.h +0 -2
- package/ios/core/TrueSheetBlurView.mm +3 -36
- package/ios/core/TrueSheetDetentCalculator.h +7 -1
- package/ios/core/TrueSheetDetentCalculator.mm +27 -4
- package/ios/core/TrueSheetGrabberView.mm +13 -3
- package/ios/core/TrueSheetKeyboardObserver.mm +2 -0
- package/ios/core/TrueSheetOverlayContainerView.h +31 -0
- package/ios/core/TrueSheetOverlayContainerView.mm +35 -0
- package/ios/events/TrueSheetLifecycleEvents.h +2 -0
- package/ios/events/TrueSheetLifecycleEvents.mm +8 -0
- package/ios/tvos/TrueSheetStubs.mm +12 -0
- package/ios/utils/UIView+ScrollEdgeInteraction.h +1 -0
- package/ios/utils/UIView+ScrollEdgeInteraction.mm +24 -2
- package/lib/module/TrueSheet.js +175 -39
- package/lib/module/TrueSheet.js.map +1 -1
- package/lib/module/TrueSheet.web.js +220 -243
- package/lib/module/TrueSheet.web.js.map +1 -1
- package/lib/module/TrueSheetBackground.js +15 -0
- package/lib/module/TrueSheetBackground.js.map +1 -0
- package/lib/module/TrueSheetOverlay.js +30 -0
- package/lib/module/TrueSheetOverlay.js.map +1 -0
- package/lib/module/TrueSheetOverlay.web.js +35 -0
- package/lib/module/TrueSheetOverlay.web.js.map +1 -0
- package/lib/module/TrueSheetPeek.web.js +20 -15
- package/lib/module/TrueSheetPeek.web.js.map +1 -1
- package/lib/module/detentBackgrounds.js +21 -0
- package/lib/module/detentBackgrounds.js.map +1 -0
- package/lib/module/fabric/TrueSheetContentViewNativeComponent.ts +1 -1
- package/lib/module/fabric/TrueSheetOverlayViewNativeComponent.ts +12 -0
- package/lib/module/fabric/TrueSheetViewNativeComponent.ts +15 -10
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/mocks/index.js +18 -2
- package/lib/module/mocks/index.js.map +1 -1
- package/lib/module/mocks/navigationExpoRouter.js.map +1 -1
- package/lib/module/navigation/base-types.js +2 -0
- package/lib/module/navigation/base-types.js.map +1 -0
- package/lib/module/navigation/createTrueSheetRouter.js +0 -9
- package/lib/module/navigation/createTrueSheetRouter.js.map +1 -1
- package/lib/module/navigation/expo-router/base-types.js +2 -0
- package/lib/module/navigation/expo-router/base-types.js.map +1 -0
- package/lib/module/navigation/expo-router/index.js +10 -7
- package/lib/module/navigation/expo-router/index.js.map +1 -1
- package/lib/module/navigation/expo-router/types.js +4 -0
- package/lib/module/navigation/expo-router/types.js.map +1 -0
- package/lib/module/navigation/index.js.map +1 -1
- package/lib/module/navigation/screen/useSheetScreenState.js +1 -0
- package/lib/module/navigation/screen/useSheetScreenState.js.map +1 -1
- package/lib/module/web/constants.js +1 -1
- package/lib/module/web/constants.js.map +1 -1
- package/lib/module/web/layout.js +168 -0
- package/lib/module/web/layout.js.map +1 -0
- package/lib/module/web/vaul/constants.js +9 -0
- package/lib/module/web/vaul/constants.js.map +1 -1
- package/lib/module/web/vaul/context.js.map +1 -1
- package/lib/module/web/vaul/helpers.js +1 -0
- package/lib/module/web/vaul/helpers.js.map +1 -1
- package/lib/module/web/vaul/index.js +47 -7
- package/lib/module/web/vaul/index.js.map +1 -1
- package/lib/module/web/vaul/use-snap-points.js +21 -10
- package/lib/module/web/vaul/use-snap-points.js.map +1 -1
- package/lib/typescript/src/TrueSheet.d.ts +6 -0
- package/lib/typescript/src/TrueSheet.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheet.types.d.ts +157 -34
- package/lib/typescript/src/TrueSheet.types.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheet.web.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheetBackground.d.ts +3 -0
- package/lib/typescript/src/TrueSheetBackground.d.ts.map +1 -0
- package/lib/typescript/src/TrueSheetOverlay.d.ts +8 -0
- package/lib/typescript/src/TrueSheetOverlay.d.ts.map +1 -0
- package/lib/typescript/src/TrueSheetOverlay.web.d.ts +8 -0
- package/lib/typescript/src/TrueSheetOverlay.web.d.ts.map +1 -0
- package/lib/typescript/src/TrueSheetPeek.web.d.ts +8 -4
- package/lib/typescript/src/TrueSheetPeek.web.d.ts.map +1 -1
- package/lib/typescript/src/detentBackgrounds.d.ts +10 -0
- package/lib/typescript/src/detentBackgrounds.d.ts.map +1 -0
- package/lib/typescript/src/fabric/TrueSheetOverlayViewNativeComponent.d.ts +6 -0
- package/lib/typescript/src/fabric/TrueSheetOverlayViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts +12 -7
- package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/mocks/index.d.ts +4 -0
- package/lib/typescript/src/mocks/index.d.ts.map +1 -1
- package/lib/typescript/src/mocks/navigationExpoRouter.d.ts +3 -3
- package/lib/typescript/src/mocks/navigationExpoRouter.d.ts.map +1 -1
- package/lib/typescript/src/navigation/base-types.d.ts +9 -0
- package/lib/typescript/src/navigation/base-types.d.ts.map +1 -0
- package/lib/typescript/src/navigation/createTrueSheetRouter.d.ts +2 -13
- package/lib/typescript/src/navigation/createTrueSheetRouter.d.ts.map +1 -1
- package/lib/typescript/src/navigation/expo-router/base-types.d.ts +8 -0
- package/lib/typescript/src/navigation/expo-router/base-types.d.ts.map +1 -0
- package/lib/typescript/src/navigation/expo-router/index.d.ts +8 -6
- package/lib/typescript/src/navigation/expo-router/index.d.ts.map +1 -1
- package/lib/typescript/src/navigation/expo-router/types.d.ts +44 -0
- package/lib/typescript/src/navigation/expo-router/types.d.ts.map +1 -0
- package/lib/typescript/src/navigation/index.d.ts +3 -4
- package/lib/typescript/src/navigation/index.d.ts.map +1 -1
- package/lib/typescript/src/navigation/screen/useSheetScreenState.d.ts +2 -1
- package/lib/typescript/src/navigation/screen/useSheetScreenState.d.ts.map +1 -1
- package/lib/typescript/src/navigation/types.d.ts +41 -5
- package/lib/typescript/src/navigation/types.d.ts.map +1 -1
- package/lib/typescript/src/web/constants.d.ts +1 -1
- package/lib/typescript/src/web/constants.d.ts.map +1 -1
- package/lib/typescript/src/web/layout.d.ts +19 -0
- package/lib/typescript/src/web/layout.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/constants.d.ts +3 -0
- package/lib/typescript/src/web/vaul/constants.d.ts.map +1 -1
- package/lib/typescript/src/web/vaul/context.d.ts +1 -0
- package/lib/typescript/src/web/vaul/context.d.ts.map +1 -1
- package/lib/typescript/src/web/vaul/helpers.d.ts +1 -0
- package/lib/typescript/src/web/vaul/helpers.d.ts.map +1 -1
- package/lib/typescript/src/web/vaul/index.d.ts +13 -1
- package/lib/typescript/src/web/vaul/index.d.ts.map +1 -1
- package/lib/typescript/src/web/vaul/use-snap-points.d.ts +2 -1
- package/lib/typescript/src/web/vaul/use-snap-points.d.ts.map +1 -1
- package/package.json +17 -8
- package/react-native.config.js +1 -0
- package/src/TrueSheet.tsx +208 -48
- package/src/TrueSheet.types.ts +166 -35
- package/src/TrueSheet.web.tsx +272 -290
- package/src/TrueSheetBackground.tsx +17 -0
- package/src/TrueSheetOverlay.tsx +24 -0
- package/src/TrueSheetOverlay.web.tsx +33 -0
- package/src/TrueSheetPeek.web.tsx +25 -23
- package/src/detentBackgrounds.ts +24 -0
- package/src/fabric/TrueSheetContentViewNativeComponent.ts +1 -1
- package/src/fabric/TrueSheetOverlayViewNativeComponent.ts +12 -0
- package/src/fabric/TrueSheetViewNativeComponent.ts +15 -10
- package/src/index.ts +1 -0
- package/src/mocks/index.ts +17 -2
- package/src/mocks/navigationExpoRouter.ts +6 -5
- package/src/navigation/base-types.ts +20 -0
- package/src/navigation/createTrueSheetRouter.ts +5 -33
- package/src/navigation/expo-router/base-types.ts +18 -0
- package/src/navigation/expo-router/index.ts +28 -30
- package/src/navigation/expo-router/types.ts +116 -0
- package/src/navigation/index.ts +6 -7
- package/src/navigation/screen/useSheetScreenState.ts +2 -0
- package/src/navigation/types.ts +75 -22
- package/src/web/constants.ts +1 -1
- package/src/web/layout.ts +196 -0
- package/src/web/vaul/constants.ts +9 -0
- package/src/web/vaul/context.ts +1 -0
- package/src/web/vaul/helpers.ts +5 -0
- package/src/web/vaul/index.tsx +75 -5
- package/src/web/vaul/use-snap-points.ts +32 -15
package/ios/TrueSheetView.mm
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
#import "TrueSheetContentView.h"
|
|
14
14
|
#import "TrueSheetFooterView.h"
|
|
15
15
|
#import "TrueSheetModule.h"
|
|
16
|
+
#import "TrueSheetOverlayView.h"
|
|
16
17
|
#import "TrueSheetViewController.h"
|
|
17
18
|
#import "core/RNScreensEventObserver.h"
|
|
18
19
|
#import "events/TrueSheetDragEvents.h"
|
|
@@ -53,7 +54,7 @@ using namespace facebook::react;
|
|
|
53
54
|
NSInteger _initialDetentIndex;
|
|
54
55
|
TrueSheetViewInsetAdjustment _insetAdjustment;
|
|
55
56
|
ScrollableOptions *_scrollableOptions;
|
|
56
|
-
|
|
57
|
+
NSInteger _scrollableHandle;
|
|
57
58
|
BOOL _initialDetentAnimated;
|
|
58
59
|
BOOL _isSheetUpdatePending;
|
|
59
60
|
BOOL _pendingLayoutUpdate;
|
|
@@ -63,6 +64,9 @@ using namespace facebook::react;
|
|
|
63
64
|
BOOL _pendingMountEvent;
|
|
64
65
|
BOOL _pendingSizeChange;
|
|
65
66
|
BOOL _pendingPropsUpdate;
|
|
67
|
+
BOOL _isPresentPending;
|
|
68
|
+
NSUInteger _pendingPresentGeneration;
|
|
69
|
+
TrueSheetCompletionBlock _pendingPresentCompletion;
|
|
66
70
|
NSArray *_pendingDetents;
|
|
67
71
|
RNScreensEventObserver *_screensEventObserver;
|
|
68
72
|
}
|
|
@@ -110,24 +114,80 @@ using namespace facebook::react;
|
|
|
110
114
|
return;
|
|
111
115
|
}
|
|
112
116
|
|
|
113
|
-
|
|
114
|
-
|
|
117
|
+
[self presentInitialIfNeeded];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// JS holds initialDetentIndex back one commit so effect-driven content (e.g. a
|
|
121
|
+
// navigation footer set via setOptions) commits together with it — by the time
|
|
122
|
+
// the prop lands the tree is final and the sheet presents at its final height.
|
|
123
|
+
// Called from didMoveToWindow (re-attach) and finalizeUpdates (the prop
|
|
124
|
+
// arriving after attach, which didMoveToWindow won't re-fire for).
|
|
125
|
+
- (void)presentInitialIfNeeded {
|
|
126
|
+
if (_initialDetentIndex < 0 || _didInitiallyPresent)
|
|
127
|
+
return;
|
|
115
128
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
129
|
+
UIViewController *vc = [self findPresentingViewController];
|
|
130
|
+
|
|
131
|
+
// Only present if the view controller is in the same window
|
|
132
|
+
if (!vc || vc.view.window != self.window) {
|
|
133
|
+
// Animate next time when sheet finally moves to the correct window
|
|
134
|
+
_initialDetentAnimated = YES;
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// A sheet still animating out of the presenter (e.g. our own controller,
|
|
139
|
+
// recycled mid-dismissal) blocks presentation — retry once its transition ends.
|
|
140
|
+
UIViewController *dismissing = vc.presentedViewController;
|
|
141
|
+
if (dismissing && dismissing.isBeingDismissed) {
|
|
142
|
+
_initialDetentAnimated = YES;
|
|
143
|
+
|
|
144
|
+
__weak __typeof(self) weakSelf = self;
|
|
145
|
+
void (^retry)(void) = ^{
|
|
146
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
147
|
+
[weakSelf presentInitialIfNeeded];
|
|
148
|
+
});
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
id<UIViewControllerTransitionCoordinator> coordinator = dismissing.transitionCoordinator;
|
|
152
|
+
if (coordinator) {
|
|
153
|
+
[coordinator animateAlongsideTransition:nil
|
|
154
|
+
completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
|
|
155
|
+
retry();
|
|
156
|
+
}];
|
|
120
157
|
} else {
|
|
121
|
-
|
|
122
|
-
_initialDetentAnimated = YES;
|
|
158
|
+
retry();
|
|
123
159
|
}
|
|
160
|
+
return;
|
|
124
161
|
}
|
|
162
|
+
|
|
163
|
+
_didInitiallyPresent = YES;
|
|
164
|
+
|
|
165
|
+
// Deferred a runloop turn so sibling mounts from the current transaction
|
|
166
|
+
// (e.g. a footer committed alongside the prop) land before measuring.
|
|
167
|
+
__weak __typeof(self) weakSelf = self;
|
|
168
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
169
|
+
__typeof(self) strongSelf = weakSelf;
|
|
170
|
+
if (!strongSelf || strongSelf->_controller.isPresented || strongSelf->_controller.isBeingPresented)
|
|
171
|
+
return;
|
|
172
|
+
|
|
173
|
+
[strongSelf presentAtIndex:strongSelf->_initialDetentIndex
|
|
174
|
+
animated:strongSelf->_initialDetentAnimated
|
|
175
|
+
completion:^(BOOL success, NSError *_Nullable error) {
|
|
176
|
+
// Present can fail if the view detached during this turn —
|
|
177
|
+
// reset so the next attach/prop update retries.
|
|
178
|
+
if (!success) {
|
|
179
|
+
strongSelf->_didInitiallyPresent = NO;
|
|
180
|
+
}
|
|
181
|
+
}];
|
|
182
|
+
});
|
|
125
183
|
}
|
|
126
184
|
|
|
127
185
|
- (void)dealloc {
|
|
128
186
|
[_screensEventObserver stopObserving];
|
|
129
187
|
_screensEventObserver = nil;
|
|
130
188
|
|
|
189
|
+
[self cancelPendingPresent];
|
|
190
|
+
|
|
131
191
|
if (_controller && _controller.presentingViewController) {
|
|
132
192
|
// Find the root presenting controller to dismiss the entire stack
|
|
133
193
|
UIViewController *root = _controller.presentingViewController;
|
|
@@ -146,8 +206,6 @@ using namespace facebook::react;
|
|
|
146
206
|
|
|
147
207
|
[_snapshotView removeFromSuperview];
|
|
148
208
|
_snapshotView = nil;
|
|
149
|
-
|
|
150
|
-
[TrueSheetModule unregisterViewWithTag:@(self.tag)];
|
|
151
209
|
}
|
|
152
210
|
|
|
153
211
|
#pragma mark - RCTComponentViewProtocol
|
|
@@ -163,12 +221,8 @@ using namespace facebook::react;
|
|
|
163
221
|
|
|
164
222
|
// Detents (-1 represents "auto")
|
|
165
223
|
NSMutableArray *detents = [NSMutableArray new];
|
|
166
|
-
_hasAutoDetent = NO;
|
|
167
224
|
for (const auto &detent : newProps.detents) {
|
|
168
225
|
[detents addObject:@(detent)];
|
|
169
|
-
if (detent == -1) {
|
|
170
|
-
_hasAutoDetent = YES;
|
|
171
|
-
}
|
|
172
226
|
}
|
|
173
227
|
|
|
174
228
|
if (oldProps) {
|
|
@@ -187,14 +241,29 @@ using namespace facebook::react;
|
|
|
187
241
|
// Background color
|
|
188
242
|
_controller.backgroundColor = RCTUIColorFromSharedColor(newProps.backgroundColor);
|
|
189
243
|
|
|
244
|
+
NSMutableArray<NSDictionary *> *detentBackgrounds = [NSMutableArray new];
|
|
245
|
+
ContextContainer contextContainer;
|
|
246
|
+
PropsParserContext parserContext{-1, contextContainer};
|
|
247
|
+
for (const auto &entry : newProps.detentBackgrounds) {
|
|
248
|
+
NSMutableDictionary *background = [NSMutableDictionary new];
|
|
249
|
+
UIColor *color = RCTUIColorFromSharedColor(entry.color);
|
|
250
|
+
if (color) {
|
|
251
|
+
background[@"color"] = color;
|
|
252
|
+
}
|
|
253
|
+
if (!entry.blur.empty()) {
|
|
254
|
+
auto blur = TrueSheetViewBackgroundBlur::None;
|
|
255
|
+
fromRawValue(parserContext, RawValue(entry.blur), blur);
|
|
256
|
+
background[@"blur"] = @(static_cast<int>(blur));
|
|
257
|
+
}
|
|
258
|
+
[detentBackgrounds addObject:background];
|
|
259
|
+
}
|
|
260
|
+
if (![_controller.detentBackgrounds isEqualToArray:detentBackgrounds]) {
|
|
261
|
+
_controller.detentBackgrounds = detentBackgrounds;
|
|
262
|
+
}
|
|
263
|
+
|
|
190
264
|
// Blur tint
|
|
191
265
|
_controller.backgroundBlur = newProps.backgroundBlur;
|
|
192
266
|
|
|
193
|
-
// Blur options
|
|
194
|
-
const auto &blurOpts = newProps.blurOptions;
|
|
195
|
-
_controller.blurIntensity = blurOpts.intensity >= 0 ? @(blurOpts.intensity) : nil;
|
|
196
|
-
_controller.blurInteraction = blurOpts.interaction;
|
|
197
|
-
|
|
198
267
|
// Corner radius
|
|
199
268
|
_controller.cornerRadius = newProps.cornerRadius < 0 ? nil : @(newProps.cornerRadius);
|
|
200
269
|
|
|
@@ -204,8 +273,7 @@ using namespace facebook::react;
|
|
|
204
273
|
// Content width
|
|
205
274
|
_controller.maxContentWidth = newProps.maxContentWidth != 0.0 ? @(newProps.maxContentWidth) : nil;
|
|
206
275
|
|
|
207
|
-
|
|
208
|
-
_controller.anchor = newProps.anchor;
|
|
276
|
+
_controller.placement = newProps.placement;
|
|
209
277
|
|
|
210
278
|
_controller.grabber = newProps.grabber;
|
|
211
279
|
|
|
@@ -248,33 +316,38 @@ using namespace facebook::react;
|
|
|
248
316
|
_initialDetentIndex = newProps.initialDetentIndex;
|
|
249
317
|
_initialDetentAnimated = newProps.initialDetentAnimated;
|
|
250
318
|
|
|
251
|
-
|
|
252
|
-
BOOL scrollingExpandsSheet = scrollableOpts.scrollingExpandsSheet;
|
|
253
|
-
auto topEdgeEffect = scrollableOpts.topScrollEdgeEffect;
|
|
254
|
-
auto bottomEdgeEffect = scrollableOpts.bottomScrollEdgeEffect;
|
|
255
|
-
BOOL hasScrollableOptions = scrollableOpts.keyboardScrollOffset > 0 || !scrollingExpandsSheet ||
|
|
256
|
-
topEdgeEffect != TrueSheetViewTopScrollEdgeEffect::Hidden ||
|
|
257
|
-
bottomEdgeEffect != TrueSheetViewBottomScrollEdgeEffect::Hidden;
|
|
258
|
-
|
|
259
|
-
if (hasScrollableOptions) {
|
|
260
|
-
ScrollableOptions *options = [[ScrollableOptions alloc] init];
|
|
261
|
-
options.keyboardScrollOffset = scrollableOpts.keyboardScrollOffset;
|
|
262
|
-
options.scrollingExpandsSheet = scrollingExpandsSheet;
|
|
263
|
-
options.topScrollEdgeEffect = topEdgeEffect;
|
|
264
|
-
options.bottomScrollEdgeEffect = bottomEdgeEffect;
|
|
265
|
-
_scrollableOptions = options;
|
|
266
|
-
} else {
|
|
267
|
-
_scrollableOptions = nil;
|
|
268
|
-
}
|
|
319
|
+
_scrollableHandle = newProps.scrollableHandle;
|
|
269
320
|
|
|
270
|
-
|
|
321
|
+
const auto &scrollableOpts = newProps.scrollableOptions;
|
|
322
|
+
ScrollableOptions *options = [[ScrollableOptions alloc] init];
|
|
323
|
+
options.contentInsetAdjustment = scrollableOpts.contentInsetAdjustment;
|
|
324
|
+
options.keyboardScrollOffset = scrollableOpts.keyboardScrollOffset;
|
|
325
|
+
options.keyboardOffset = scrollableOpts.keyboardOffset;
|
|
326
|
+
options.scrollingExpandsSheet = scrollableOpts.scrollingExpandsSheet;
|
|
327
|
+
options.topScrollEdgeEffect = scrollableOpts.topScrollEdgeEffect;
|
|
328
|
+
options.bottomScrollEdgeEffect = scrollableOpts.bottomScrollEdgeEffect;
|
|
329
|
+
|
|
330
|
+
// nil while every option is at its default
|
|
331
|
+
BOOL hasScrollableOptions = options.keyboardScrollOffset > 0 || options.keyboardOffset != 0 ||
|
|
332
|
+
!options.scrollingExpandsSheet ||
|
|
333
|
+
options.contentInsetAdjustment != TrueSheetViewContentInsetAdjustment::Automatic ||
|
|
334
|
+
options.topScrollEdgeEffect != TrueSheetViewTopScrollEdgeEffect::Hidden ||
|
|
335
|
+
options.bottomScrollEdgeEffect != TrueSheetViewBottomScrollEdgeEffect::Hidden;
|
|
336
|
+
_scrollableOptions = hasScrollableOptions ? options : nil;
|
|
337
|
+
|
|
338
|
+
_controller.scrollingExpandsSheet = options.scrollingExpandsSheet;
|
|
271
339
|
|
|
272
340
|
_controller.absoluteHeader = newProps.headerOptions.position == TrueSheetViewPosition::Absolute;
|
|
273
341
|
_controller.absoluteFooter = newProps.footerOptions.footerPosition == TrueSheetViewFooterPosition::Absolute;
|
|
342
|
+
_controller.footerInsetAdjustment =
|
|
343
|
+
options.footerInsetAdjustment && _controller.absoluteFooter && _scrollableHandle > 0;
|
|
274
344
|
|
|
275
345
|
CGFloat footerKeyboardOffset = newProps.footerOptions.keyboardOffset;
|
|
276
|
-
|
|
346
|
+
BOOL footerAvoidsKeyboard = newProps.footerOptions.avoidKeyboard;
|
|
347
|
+
if (_controller.footerKeyboardOffset != footerKeyboardOffset ||
|
|
348
|
+
_controller.footerAvoidsKeyboard != footerAvoidsKeyboard) {
|
|
277
349
|
_controller.footerKeyboardOffset = footerKeyboardOffset;
|
|
350
|
+
_controller.footerAvoidsKeyboard = footerAvoidsKeyboard;
|
|
278
351
|
[_containerView updateFooterKeyboardOffset];
|
|
279
352
|
}
|
|
280
353
|
|
|
@@ -342,13 +415,49 @@ using namespace facebook::react;
|
|
|
342
415
|
_pendingPropsUpdate = YES;
|
|
343
416
|
} else if (_initialDetentIndex >= 0) {
|
|
344
417
|
_pendingLayoutUpdate = NO;
|
|
418
|
+
if (self.window) {
|
|
419
|
+
[self presentInitialIfNeeded];
|
|
420
|
+
}
|
|
345
421
|
}
|
|
346
422
|
}
|
|
347
423
|
|
|
348
424
|
- (void)prepareForRecycle {
|
|
349
425
|
[super prepareForRecycle];
|
|
350
426
|
|
|
351
|
-
|
|
427
|
+
// Pooled mid-dismissal: the next mount can reuse this host — and its
|
|
428
|
+
// controller — while the previous sheet is still animating out. Detach until
|
|
429
|
+
// that transition ends so its tail (didBlur, didDismiss, position) can't reach
|
|
430
|
+
// the new mount, then hand the controller back and let auto-present retry.
|
|
431
|
+
if (_controller.isBeingDismissed) {
|
|
432
|
+
_controller.delegate = nil;
|
|
433
|
+
|
|
434
|
+
__weak __typeof(self) weakSelf = self;
|
|
435
|
+
void (^reattach)(void) = ^{
|
|
436
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
437
|
+
__typeof(self) strongSelf = weakSelf;
|
|
438
|
+
if (!strongSelf)
|
|
439
|
+
return;
|
|
440
|
+
|
|
441
|
+
strongSelf->_controller.delegate = strongSelf;
|
|
442
|
+
strongSelf->_controller.activeDetentIndex = -1;
|
|
443
|
+
if (strongSelf.window) {
|
|
444
|
+
[strongSelf presentInitialIfNeeded];
|
|
445
|
+
}
|
|
446
|
+
});
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
id<UIViewControllerTransitionCoordinator> coordinator = _controller.transitionCoordinator;
|
|
450
|
+
if (coordinator) {
|
|
451
|
+
[coordinator animateAlongsideTransition:nil
|
|
452
|
+
completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
|
|
453
|
+
reattach();
|
|
454
|
+
}];
|
|
455
|
+
} else {
|
|
456
|
+
reattach();
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
[self cancelPendingPresent];
|
|
352
461
|
|
|
353
462
|
_lastStateSize = CGSizeZero;
|
|
354
463
|
_didInitiallyPresent = NO;
|
|
@@ -389,7 +498,6 @@ using namespace facebook::react;
|
|
|
389
498
|
[_touchHandler attachToView:_containerView];
|
|
390
499
|
[_controller.view addSubview:_containerView];
|
|
391
500
|
[_controller.view bringSubviewToFront:_containerView];
|
|
392
|
-
_containerView.accessibilityViewIsModal = YES;
|
|
393
501
|
_controller.accessibilityContentView = _containerView;
|
|
394
502
|
[_controller setupAccessibilityContainer];
|
|
395
503
|
|
|
@@ -403,9 +511,8 @@ using namespace facebook::react;
|
|
|
403
511
|
_controller.headerHeight = @(headerHeight);
|
|
404
512
|
}
|
|
405
513
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
_controller.footerHeight = @(footerHeight);
|
|
514
|
+
if ([_containerView footerHeight] > 0) {
|
|
515
|
+
[self syncFooterMetrics];
|
|
409
516
|
}
|
|
410
517
|
|
|
411
518
|
CGFloat peekContentHeight = [_containerView peekContentHeight];
|
|
@@ -445,7 +552,7 @@ using namespace facebook::react;
|
|
|
445
552
|
- (void)presentAtIndex:(NSInteger)index
|
|
446
553
|
animated:(BOOL)animated
|
|
447
554
|
completion:(nullable TrueSheetCompletionBlock)completion {
|
|
448
|
-
if (_controller.isBeingPresented || _controller.isPresented) {
|
|
555
|
+
if (_controller.isBeingPresented || _controller.isPresented || _isPresentPending) {
|
|
449
556
|
RCTLogWarn(@"TrueSheet: sheet is already presented. Use resize() to change detent.");
|
|
450
557
|
if (completion) {
|
|
451
558
|
completion(YES, nil);
|
|
@@ -467,11 +574,41 @@ using namespace facebook::react;
|
|
|
467
574
|
return;
|
|
468
575
|
}
|
|
469
576
|
|
|
577
|
+
// A controller still animating out of the presenter (e.g. a navigation modal
|
|
578
|
+
// closing) makes UIKit queue this presentation, so everything measured below
|
|
579
|
+
// goes stale before it starts. Present once that transition ends.
|
|
580
|
+
UIViewController *dismissing = presentingViewController.presentedViewController;
|
|
581
|
+
id<UIViewControllerTransitionCoordinator> dismissCoordinator =
|
|
582
|
+
dismissing.isBeingDismissed ? dismissing.transitionCoordinator : nil;
|
|
583
|
+
if (dismissCoordinator) {
|
|
584
|
+
_isPresentPending = YES;
|
|
585
|
+
_pendingPresentCompletion = completion;
|
|
586
|
+
NSUInteger generation = ++_pendingPresentGeneration;
|
|
587
|
+
|
|
588
|
+
__weak __typeof(self) weakSelf = self;
|
|
589
|
+
[dismissCoordinator
|
|
590
|
+
animateAlongsideTransition:nil
|
|
591
|
+
completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
|
|
592
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
593
|
+
__typeof(self) strongSelf = weakSelf;
|
|
594
|
+
if (!strongSelf || !strongSelf->_isPresentPending ||
|
|
595
|
+
strongSelf->_pendingPresentGeneration != generation)
|
|
596
|
+
return;
|
|
597
|
+
|
|
598
|
+
TrueSheetCompletionBlock pendingCompletion = strongSelf->_pendingPresentCompletion;
|
|
599
|
+
strongSelf->_isPresentPending = NO;
|
|
600
|
+
strongSelf->_pendingPresentCompletion = nil;
|
|
601
|
+
[strongSelf presentAtIndex:index animated:animated completion:pendingCompletion];
|
|
602
|
+
});
|
|
603
|
+
}];
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
|
|
470
607
|
[_controller setupAnchorViewInView:presentingViewController.view];
|
|
471
608
|
[_controller setupSheetSizing];
|
|
472
609
|
[_controller setupSheetProps];
|
|
473
610
|
|
|
474
|
-
//
|
|
611
|
+
// Detect before measuring so a first-time detection doesn't shift sizes mid-animation.
|
|
475
612
|
[self setupScrollable];
|
|
476
613
|
|
|
477
614
|
// Measure synchronously so the presentation starts at the right height —
|
|
@@ -480,24 +617,41 @@ using namespace facebook::react;
|
|
|
480
617
|
if (_containerView) {
|
|
481
618
|
_controller.contentHeight = @([_containerView contentHeight]);
|
|
482
619
|
_controller.headerHeight = @([_containerView headerHeight]);
|
|
483
|
-
|
|
620
|
+
[self syncFooterMetrics];
|
|
484
621
|
_controller.peekContentHeight = @([_containerView peekContentHeight]);
|
|
485
622
|
}
|
|
486
623
|
_pendingSizeChange = NO;
|
|
487
624
|
|
|
625
|
+
[self refreshFooterBottomInset];
|
|
488
626
|
[_controller setupSheetDetents];
|
|
489
627
|
[_controller setupActiveDetentWithIndex:index];
|
|
490
628
|
|
|
491
629
|
[_screensEventObserver capturePresenterScreenFromView:self];
|
|
492
630
|
[_screensEventObserver startObservingWithState:_state.get()->getData()];
|
|
493
631
|
|
|
632
|
+
UIWindow *window = presentingViewController.view.window;
|
|
494
633
|
[presentingViewController presentViewController:_controller
|
|
495
634
|
animated:animated
|
|
496
635
|
completion:^{
|
|
636
|
+
[TrueSheetOverlayView bringOverlaysToFrontInWindow:window];
|
|
497
637
|
if (completion) {
|
|
498
638
|
completion(YES, nil);
|
|
499
639
|
}
|
|
500
640
|
}];
|
|
641
|
+
|
|
642
|
+
// Presenting adds the sheet's transition view on top of the window once the
|
|
643
|
+
// transition starts — re-front overlays alongside it so the first frame is
|
|
644
|
+
// already ordered (and again on completion in case the transition was queued)
|
|
645
|
+
id<UIViewControllerTransitionCoordinator> coordinator = _controller.transitionCoordinator;
|
|
646
|
+
if (coordinator) {
|
|
647
|
+
[coordinator
|
|
648
|
+
animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
|
|
649
|
+
[TrueSheetOverlayView bringOverlaysToFrontInWindow:window];
|
|
650
|
+
}
|
|
651
|
+
completion:nil];
|
|
652
|
+
} else {
|
|
653
|
+
[TrueSheetOverlayView bringOverlaysToFrontInWindow:window];
|
|
654
|
+
}
|
|
501
655
|
}
|
|
502
656
|
|
|
503
657
|
- (void)resizeToIndex:(NSInteger)index completion:(nullable TrueSheetCompletionBlock)completion {
|
|
@@ -530,7 +684,32 @@ using namespace facebook::react;
|
|
|
530
684
|
realtime:NO];
|
|
531
685
|
}
|
|
532
686
|
|
|
687
|
+
/**
|
|
688
|
+
* Drops a deferred present and resolves its caller. Returns whether one was pending.
|
|
689
|
+
*/
|
|
690
|
+
- (BOOL)cancelPendingPresent {
|
|
691
|
+
if (!_isPresentPending) {
|
|
692
|
+
return NO;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
TrueSheetCompletionBlock pendingCompletion = _pendingPresentCompletion;
|
|
696
|
+
_isPresentPending = NO;
|
|
697
|
+
_pendingPresentCompletion = nil;
|
|
698
|
+
if (pendingCompletion) {
|
|
699
|
+
pendingCompletion(YES, nil);
|
|
700
|
+
}
|
|
701
|
+
return YES;
|
|
702
|
+
}
|
|
703
|
+
|
|
533
704
|
- (void)dismissAnimated:(BOOL)animated completion:(nullable TrueSheetCompletionBlock)completion {
|
|
705
|
+
// Dismissing before a deferred present starts cancels it — nothing was presented.
|
|
706
|
+
if ([self cancelPendingPresent]) {
|
|
707
|
+
if (completion) {
|
|
708
|
+
completion(YES, nil);
|
|
709
|
+
}
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
|
|
534
713
|
if (_controller.isBeingDismissed || !_controller.isPresented) {
|
|
535
714
|
RCTLogWarn(@"TrueSheet: sheet is already dismissed. No need to dismiss it again.");
|
|
536
715
|
|
|
@@ -583,6 +762,10 @@ using namespace facebook::react;
|
|
|
583
762
|
* Debounced sheet update to handle rapid content/header size changes.
|
|
584
763
|
*/
|
|
585
764
|
- (void)setupSheetDetentsForSizeChange {
|
|
765
|
+
// Keep the footer's absorbed inset in sync with the latest measured heights
|
|
766
|
+
// even before presenting, so the sheet presents at its final size.
|
|
767
|
+
[self refreshFooterBottomInset];
|
|
768
|
+
|
|
586
769
|
// Retargeting the in-flight presentation makes UIKit snap the whole stack
|
|
587
770
|
// (including the sheet behind) instead of animating. Defer to didPresent —
|
|
588
771
|
// presentAtIndex measured synchronously, so this is usually a no-op.
|
|
@@ -610,6 +793,7 @@ using namespace facebook::react;
|
|
|
610
793
|
// Refresh here (not just on peek size events) since the peek's offset
|
|
611
794
|
// within the content can change without its own size changing.
|
|
612
795
|
self->_controller.peekContentHeight = @([self->_containerView peekContentHeight]);
|
|
796
|
+
[self refreshFooterBottomInset];
|
|
613
797
|
[self->_controller setupSheetDetentsForSizeChange];
|
|
614
798
|
});
|
|
615
799
|
}
|
|
@@ -625,7 +809,7 @@ using namespace facebook::react;
|
|
|
625
809
|
}
|
|
626
810
|
|
|
627
811
|
- (void)containerViewFooterDidChangeSize:(CGSize)newSize {
|
|
628
|
-
|
|
812
|
+
[self syncFooterMetrics];
|
|
629
813
|
[self setupSheetDetentsForSizeChange];
|
|
630
814
|
[_controller setupAccessibilityContainer];
|
|
631
815
|
}
|
|
@@ -634,7 +818,7 @@ using namespace facebook::react;
|
|
|
634
818
|
[self setupSheetDetentsForSizeChange];
|
|
635
819
|
}
|
|
636
820
|
|
|
637
|
-
// When the ScrollView changes (e.g. conditional remount), re-
|
|
821
|
+
// When the ScrollView changes (e.g. conditional remount), re-detect the new ScrollView.
|
|
638
822
|
- (void)containerViewScrollViewDidChange {
|
|
639
823
|
[self setupScrollable];
|
|
640
824
|
}
|
|
@@ -687,6 +871,10 @@ using namespace facebook::react;
|
|
|
687
871
|
}
|
|
688
872
|
}
|
|
689
873
|
|
|
874
|
+
- (void)viewControllerDidAttemptDismiss {
|
|
875
|
+
[TrueSheetLifecycleEvents emitDismissAttempt:_eventEmitter];
|
|
876
|
+
}
|
|
877
|
+
|
|
690
878
|
- (void)viewControllerDidDismiss {
|
|
691
879
|
[_containerView cleanupKeyboardObserver];
|
|
692
880
|
if (!_dismissedByNavigation) {
|
|
@@ -716,6 +904,11 @@ using namespace facebook::react;
|
|
|
716
904
|
[self updateStateWithSize:size];
|
|
717
905
|
}
|
|
718
906
|
|
|
907
|
+
- (void)viewControllerSafeAreaInsetsDidChange {
|
|
908
|
+
[self refreshFooterBottomInset];
|
|
909
|
+
[_containerView updateFooterKeyboardOffset];
|
|
910
|
+
}
|
|
911
|
+
|
|
719
912
|
- (void)viewControllerWillFocus {
|
|
720
913
|
[TrueSheetFocusEvents emitWillFocus:_eventEmitter];
|
|
721
914
|
}
|
|
@@ -781,16 +974,41 @@ using namespace facebook::react;
|
|
|
781
974
|
if (!_containerView)
|
|
782
975
|
return;
|
|
783
976
|
|
|
784
|
-
_containerView.insetAdjustment = _insetAdjustment;
|
|
785
977
|
_containerView.scrollableOptions = _scrollableOptions;
|
|
786
|
-
_containerView.
|
|
787
|
-
_containerView.
|
|
978
|
+
_containerView.scrollableHandle = _scrollableHandle;
|
|
979
|
+
_containerView.safeAreaInsetAdjustment = (_scrollableOptions ? _scrollableOptions.safeAreaInsetAdjustment : YES) &&
|
|
980
|
+
_insetAdjustment == TrueSheetViewInsetAdjustment::Automatic;
|
|
981
|
+
_containerView.footerInsetAdjustment = _controller.footerInsetAdjustment;
|
|
982
|
+
[self refreshFooterBottomInset];
|
|
788
983
|
[_containerView setupScrollable];
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
// footerHeight and appliedFooterBottomInset must stay paired — detent math
|
|
987
|
+
// subtracts exactly the inset baked into the measured footer height (see
|
|
988
|
+
// autoDetentBottomInset/peekDetentBottomInset).
|
|
989
|
+
- (void)syncFooterMetrics {
|
|
990
|
+
_controller.footerHeight = @([_containerView footerHeight]);
|
|
991
|
+
_controller.appliedFooterBottomInset = [_containerView footerAppliedBottomInset];
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
// Recomputes the inset the footer absorbs and pushes it down. The inset
|
|
995
|
+
// depends on measured heights and detents (see maxNaturalDetentHeight), so
|
|
996
|
+
// this runs on size and detent changes — not just prop updates.
|
|
997
|
+
- (void)refreshFooterBottomInset {
|
|
998
|
+
if (!_containerView)
|
|
999
|
+
return;
|
|
1000
|
+
|
|
1001
|
+
// appliedFooterBottomInset is NOT set here — it tracks what's actually
|
|
1002
|
+
// baked into the footer's measured height (reported with its layout), not
|
|
1003
|
+
// what was just pushed. Setting it at push time desyncs the pair and lets
|
|
1004
|
+
// a seeded inset read as natural content height (see maxNaturalDetentHeight).
|
|
1005
|
+
CGFloat inset = _controller.footerBottomInset;
|
|
1006
|
+
_containerView.footerBottomInset = inset;
|
|
789
1007
|
|
|
790
1008
|
// Publish the inset so a footer set later (e.g. navigation setOptions) is
|
|
791
1009
|
// padded on its very first layout instead of resizing the sheet twice.
|
|
792
1010
|
if (_insetAdjustment == TrueSheetViewInsetAdjustment::Automatic) {
|
|
793
|
-
TrueSheetInsets::setBottomSafeArea(
|
|
1011
|
+
TrueSheetInsets::setBottomSafeArea(inset);
|
|
794
1012
|
}
|
|
795
1013
|
}
|
|
796
1014
|
|
|
@@ -801,6 +1019,7 @@ using namespace facebook::react;
|
|
|
801
1019
|
if (_pendingDetents) {
|
|
802
1020
|
_controller.detents = _pendingDetents;
|
|
803
1021
|
_pendingDetents = nil;
|
|
1022
|
+
[self refreshFooterBottomInset];
|
|
804
1023
|
}
|
|
805
1024
|
|
|
806
1025
|
UIView *presenterView = _controller.presentingViewController.view;
|
|
@@ -26,6 +26,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
26
26
|
- (void)viewControllerDidPresentAtIndex:(NSInteger)index position:(CGFloat)position detent:(CGFloat)detent;
|
|
27
27
|
- (void)viewControllerWillDismiss;
|
|
28
28
|
- (void)viewControllerDidDismiss;
|
|
29
|
+
- (void)viewControllerDidAttemptDismiss;
|
|
29
30
|
- (void)viewControllerDidChangeDetent:(NSInteger)index position:(CGFloat)position detent:(CGFloat)detent;
|
|
30
31
|
- (void)viewControllerDidDrag:(UIGestureRecognizerState)state
|
|
31
32
|
index:(NSInteger)index
|
|
@@ -36,6 +37,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
36
37
|
detent:(CGFloat)detent
|
|
37
38
|
realtime:(BOOL)realtime;
|
|
38
39
|
- (void)viewControllerDidChangeSize:(CGSize)size;
|
|
40
|
+
- (void)viewControllerSafeAreaInsetsDidChange;
|
|
39
41
|
- (void)viewControllerWillFocus;
|
|
40
42
|
- (void)viewControllerDidFocus;
|
|
41
43
|
- (void)viewControllerWillBlur;
|
|
@@ -53,6 +55,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
53
55
|
|
|
54
56
|
@property (nonatomic, weak, nullable) id<TrueSheetViewControllerDelegate> delegate;
|
|
55
57
|
@property (nonatomic, strong) NSArray<NSNumber *> *detents;
|
|
58
|
+
@property (nonatomic, copy) NSArray<NSDictionary *> *detentBackgrounds;
|
|
56
59
|
@property (nonatomic, strong, nullable) NSNumber *maxContentHeight;
|
|
57
60
|
@property (nonatomic, strong, nullable) NSNumber *maxContentWidth;
|
|
58
61
|
@property (nonatomic, strong, nullable) NSNumber *contentHeight;
|
|
@@ -60,6 +63,13 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
60
63
|
@property (nonatomic, assign) BOOL absoluteHeader;
|
|
61
64
|
@property (nonatomic, strong, nullable) NSNumber *footerHeight;
|
|
62
65
|
@property (nonatomic, assign) BOOL absoluteFooter;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* YES while the plugged scrollable is padded by the absolute footer's height
|
|
69
|
+
* (see ScrollableOptions.contentInsetAdjustment) — the footer then counts
|
|
70
|
+
* toward the auto detent like a relative one, so the content ends above it.
|
|
71
|
+
*/
|
|
72
|
+
@property (nonatomic, assign) BOOL footerInsetAdjustment;
|
|
63
73
|
@property (nonatomic, strong, nullable) NSNumber *peekContentHeight;
|
|
64
74
|
@property (nonatomic, strong, nullable) UIColor *backgroundColor;
|
|
65
75
|
@property (nonatomic, strong, nullable) NSNumber *cornerRadius;
|
|
@@ -70,13 +80,17 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
70
80
|
@property (nonatomic, assign) BOOL dimmed;
|
|
71
81
|
@property (nonatomic, strong, nullable) NSNumber *dimmedDetentIndex;
|
|
72
82
|
@property (nonatomic, assign) facebook::react::TrueSheetViewBackgroundBlur backgroundBlur;
|
|
73
|
-
@property (nonatomic, strong, nullable) NSNumber *blurIntensity;
|
|
74
|
-
@property (nonatomic, assign) BOOL blurInteraction;
|
|
75
83
|
@property (nonatomic, assign) facebook::react::TrueSheetViewPresentation presentation;
|
|
76
|
-
@property (nonatomic, assign) facebook::react::
|
|
84
|
+
@property (nonatomic, assign) facebook::react::TrueSheetViewPlacement placement;
|
|
77
85
|
@property (nonatomic, assign) facebook::react::TrueSheetViewInsetAdjustment insetAdjustment;
|
|
78
86
|
@property (nonatomic, assign) BOOL scrollingExpandsSheet;
|
|
79
87
|
@property (nonatomic, assign) CGFloat footerKeyboardOffset;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* NO keeps an absolute footer pinned to the sheet's bottom edge behind the
|
|
91
|
+
* keyboard instead of rising above it.
|
|
92
|
+
*/
|
|
93
|
+
@property (nonatomic, assign) BOOL footerAvoidsKeyboard;
|
|
80
94
|
@property (nonatomic, assign) BOOL dismissible;
|
|
81
95
|
@property (nonatomic, assign) BOOL isPresented;
|
|
82
96
|
@property (nonatomic, assign) NSInteger activeDetentIndex;
|
|
@@ -87,6 +101,12 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
87
101
|
* ~keyboardHeight into the learned offset.
|
|
88
102
|
*/
|
|
89
103
|
@property (nonatomic, assign) BOOL keyboardSheetGrown;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Target keyboard height, set as soon as the keyboard frame change is
|
|
107
|
+
* announced — ahead of the grow/shrink animation, unlike keyboardSheetGrown.
|
|
108
|
+
*/
|
|
109
|
+
@property (nonatomic, assign) CGFloat keyboardHeight;
|
|
90
110
|
@property (nonatomic, readonly) BOOL isTopmostPresentedController;
|
|
91
111
|
@property (nonatomic, readonly) BOOL isStackedBehindChild;
|
|
92
112
|
@property (nonatomic, weak, nullable) UIView *accessibilityContentView;
|
|
@@ -99,6 +119,14 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
99
119
|
*/
|
|
100
120
|
@property (nonatomic, readonly) CGFloat footerBottomInset;
|
|
101
121
|
|
|
122
|
+
/**
|
|
123
|
+
* The inset currently baked into the footer's measured height, reported
|
|
124
|
+
* alongside its layout (see TrueSheetFooterView.appliedBottomInset). Detent
|
|
125
|
+
* resolution subtracts this exact value so the baked inset is never
|
|
126
|
+
* double-counted.
|
|
127
|
+
*/
|
|
128
|
+
@property (nonatomic, assign) CGFloat appliedFooterBottomInset;
|
|
129
|
+
|
|
102
130
|
- (void)setupAccessibilityContainer;
|
|
103
131
|
- (void)applyActiveDetent;
|
|
104
132
|
- (void)setupActiveDetentWithIndex:(NSInteger)index;
|