@lodev09/react-native-true-sheet 4.0.0-beta.2 → 4.0.0-beta.20
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 +302 -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 +119 -50
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +360 -163
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +54 -12
- 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 +212 -55
- 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 +173 -39
- package/lib/module/TrueSheet.js.map +1 -1
- package/lib/module/TrueSheet.web.js +218 -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 +14 -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 +4 -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 +44 -6
- package/lib/module/web/vaul/index.js.map +1 -1
- package/lib/module/web/vaul/use-snap-points.js +6 -8
- 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 +135 -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 +11 -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 +1 -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 +7 -1
- package/lib/typescript/src/web/vaul/index.d.ts.map +1 -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 +206 -48
- package/src/TrueSheet.types.ts +142 -35
- package/src/TrueSheet.web.tsx +270 -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 +14 -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 +4 -0
- package/src/web/vaul/context.ts +1 -0
- package/src/web/vaul/helpers.ts +5 -0
- package/src/web/vaul/index.tsx +67 -5
- package/src/web/vaul/use-snap-points.ts +6 -14
|
@@ -14,8 +14,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
14
14
|
@interface TrueSheetBlurView : UIVisualEffectView
|
|
15
15
|
|
|
16
16
|
@property (nonatomic, assign) facebook::react::TrueSheetViewBackgroundBlur backgroundBlur;
|
|
17
|
-
@property (nonatomic, strong, nullable) NSNumber *blurIntensity;
|
|
18
|
-
@property (nonatomic, assign) BOOL blurInteraction;
|
|
19
17
|
|
|
20
18
|
/// Adds the blur view to a parent view with proper constraints
|
|
21
19
|
- (void)addToView:(UIView *)parentView;
|
|
@@ -13,15 +13,13 @@
|
|
|
13
13
|
|
|
14
14
|
using namespace facebook::react;
|
|
15
15
|
|
|
16
|
-
@implementation TrueSheetBlurView
|
|
17
|
-
UIViewPropertyAnimator *_blurAnimator;
|
|
18
|
-
}
|
|
16
|
+
@implementation TrueSheetBlurView
|
|
19
17
|
|
|
20
18
|
#pragma mark - Initialization
|
|
21
19
|
|
|
22
20
|
- (instancetype)init {
|
|
23
21
|
if (self = [super init]) {
|
|
24
|
-
|
|
22
|
+
self.userInteractionEnabled = NO;
|
|
25
23
|
}
|
|
26
24
|
return self;
|
|
27
25
|
}
|
|
@@ -38,45 +36,14 @@ using namespace facebook::react;
|
|
|
38
36
|
[parentView insertSubview:self atIndex:0];
|
|
39
37
|
}
|
|
40
38
|
|
|
41
|
-
- (void)clearAnimator {
|
|
42
|
-
if (_blurAnimator) {
|
|
43
|
-
[_blurAnimator stopAnimation:YES];
|
|
44
|
-
_blurAnimator = nil;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
39
|
- (void)applyBlurEffect {
|
|
49
|
-
self.userInteractionEnabled = self.blurInteraction;
|
|
50
|
-
|
|
51
40
|
if (self.backgroundBlur == TrueSheetViewBackgroundBlur::None) {
|
|
52
|
-
[self clearAnimator];
|
|
53
41
|
self.effect = nil;
|
|
54
42
|
return;
|
|
55
43
|
}
|
|
56
44
|
|
|
57
45
|
UIBlurEffectStyle style = [BlurUtil blurEffectStyleFromEnum:self.backgroundBlur];
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
CGFloat intensity =
|
|
61
|
-
(self.blurIntensity && [self.blurIntensity floatValue] >= 0) ? [self.blurIntensity floatValue] / 100.0 : 1.0;
|
|
62
|
-
|
|
63
|
-
if (intensity >= 1.0) {
|
|
64
|
-
[self clearAnimator];
|
|
65
|
-
self.effect = blurEffect;
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (!_blurAnimator) {
|
|
70
|
-
__weak __typeof(self) weakSelf = self;
|
|
71
|
-
_blurAnimator = [[UIViewPropertyAnimator alloc] initWithDuration:1.0
|
|
72
|
-
curve:UIViewAnimationCurveLinear
|
|
73
|
-
animations:^{
|
|
74
|
-
weakSelf.effect = blurEffect;
|
|
75
|
-
}];
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
_blurAnimator.pausesOnCompletion = YES;
|
|
79
|
-
_blurAnimator.fractionComplete = intensity;
|
|
46
|
+
self.effect = [UIBlurEffect effectWithStyle:style];
|
|
80
47
|
}
|
|
81
48
|
|
|
82
49
|
@end
|
|
@@ -24,6 +24,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
24
24
|
@property (nonatomic, readonly) BOOL absoluteHeader;
|
|
25
25
|
@property (nonatomic, strong, readonly, nullable) NSNumber *footerHeight;
|
|
26
26
|
@property (nonatomic, readonly) BOOL absoluteFooter;
|
|
27
|
+
@property (nonatomic, readonly) BOOL footerInsetAdjustment;
|
|
28
|
+
@property (nonatomic, readonly) BOOL footerAvoidsKeyboard;
|
|
29
|
+
@property (nonatomic, readonly) CGFloat appliedFooterBottomInset;
|
|
27
30
|
@property (nonatomic, strong, readonly, nullable) NSNumber *peekContentHeight;
|
|
28
31
|
|
|
29
32
|
@end
|
|
@@ -43,12 +46,15 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
43
46
|
For peek (-2) detents, calculates based on header + footer height.
|
|
44
47
|
*/
|
|
45
48
|
- (CGFloat)detentValueForIndex:(NSInteger)index;
|
|
49
|
+
- (NSInteger)backgroundIndexForPosition:(CGFloat)position displayedIndex:(NSInteger)displayedIndex;
|
|
46
50
|
|
|
47
51
|
/**
|
|
48
52
|
Returns the height for auto (-1) detents: content + header + footer height.
|
|
49
53
|
An absolute (floating) header or footer contributes no height.
|
|
54
|
+
A pinned footer contributes only its overlap above the keyboard. UIKit adds
|
|
55
|
+
the keyboard expansion separately. Pass 0 for the keyboard-free height.
|
|
50
56
|
*/
|
|
51
|
-
- (CGFloat)
|
|
57
|
+
- (CGFloat)autoHeightForKeyboardHeight:(CGFloat)keyboardHeight;
|
|
52
58
|
|
|
53
59
|
/**
|
|
54
60
|
Returns the height for peek (-2) detents: header + footer + peek content height.
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
if (index >= 0 && index < (NSInteger)detents.count) {
|
|
20
20
|
CGFloat value = [detents[index] doubleValue];
|
|
21
21
|
if (value == -1) {
|
|
22
|
-
return [self
|
|
22
|
+
return [self autoHeightForKeyboardHeight:0] / self.delegate.screenHeight;
|
|
23
23
|
}
|
|
24
24
|
if (value == -2) {
|
|
25
25
|
return [self peekHeight] / self.delegate.screenHeight;
|
|
@@ -29,10 +29,15 @@
|
|
|
29
29
|
return 0;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
- (CGFloat)
|
|
33
|
-
// An absolute (floating) header or footer overlaps the content, so it contributes no height
|
|
32
|
+
- (CGFloat)autoHeightForKeyboardHeight:(CGFloat)keyboardHeight {
|
|
33
|
+
// An absolute (floating) header or footer overlaps the content, so it contributes no height —
|
|
34
|
+
// unless the footer pads the scrollable, then the content ends above it like a relative footer
|
|
34
35
|
CGFloat headerHeight = self.delegate.absoluteHeader ? 0 : [self.delegate.headerHeight floatValue];
|
|
35
|
-
|
|
36
|
+
BOOL floatingFooter = self.delegate.absoluteFooter && !self.delegate.footerInsetAdjustment;
|
|
37
|
+
CGFloat footerHeight = floatingFooter ? 0 : [self.delegate.footerHeight floatValue];
|
|
38
|
+
if (self.delegate.absoluteFooter && !floatingFooter && !self.delegate.footerAvoidsKeyboard) {
|
|
39
|
+
footerHeight -= MIN(keyboardHeight, MAX(0, footerHeight - self.delegate.appliedFooterBottomInset));
|
|
40
|
+
}
|
|
36
41
|
return [self.delegate.contentHeight floatValue] + headerHeight + footerHeight;
|
|
37
42
|
}
|
|
38
43
|
|
|
@@ -93,6 +98,24 @@
|
|
|
93
98
|
return 0;
|
|
94
99
|
}
|
|
95
100
|
|
|
101
|
+
- (NSInteger)backgroundIndexForPosition:(CGFloat)position displayedIndex:(NSInteger)displayedIndex {
|
|
102
|
+
NSInteger count = self.delegate.detents.count;
|
|
103
|
+
if (count == 0)
|
|
104
|
+
return -1;
|
|
105
|
+
|
|
106
|
+
CGFloat height = self.delegate.screenHeight - position;
|
|
107
|
+
NSInteger nextIndex = MAX(0, MIN(displayedIndex, count - 1));
|
|
108
|
+
CGFloat distance = fabs(height - [self resolvedHeightForIndex:nextIndex]);
|
|
109
|
+
for (NSInteger index = 0; index < count; index++) {
|
|
110
|
+
CGFloat nextDistance = fabs(height - [self resolvedHeightForIndex:index]);
|
|
111
|
+
if (nextDistance < distance) {
|
|
112
|
+
nextIndex = index;
|
|
113
|
+
distance = nextDistance;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return nextIndex;
|
|
117
|
+
}
|
|
118
|
+
|
|
96
119
|
- (BOOL)findSegmentForPosition:(CGFloat)position outIndex:(NSInteger *)outIndex outProgress:(CGFloat *)outProgress {
|
|
97
120
|
NSArray<NSNumber *> *detents = self.delegate.detents;
|
|
98
121
|
NSInteger count = detents.count;
|
|
@@ -91,6 +91,13 @@ static const CGFloat kHitPaddingVertical = 10.0;
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
// Pad the pill evenly like the system grabber. The view frame itself stays inside
|
|
95
|
+
// the sheet, since the reveal check reads the frame rather than this rect.
|
|
96
|
+
- (CGRect)accessibilityFrame {
|
|
97
|
+
CGRect rect = CGRectInset(_vibrancyView.frame, -kHitPaddingHorizontal, -kHitPaddingVertical);
|
|
98
|
+
return UIAccessibilityConvertFrameToScreenCoordinates(rect, self);
|
|
99
|
+
}
|
|
100
|
+
|
|
94
101
|
- (void)accessibilityIncrement {
|
|
95
102
|
if (_onIncrement) {
|
|
96
103
|
_onIncrement();
|
|
@@ -144,14 +151,17 @@ static const CGFloat kHitPaddingVertical = 10.0;
|
|
|
144
151
|
CGFloat topMargin = [self effectiveTopMargin];
|
|
145
152
|
CGFloat parentWidth = self.superview ? self.superview.bounds.size.width : UIScreen.mainScreen.bounds.size.width;
|
|
146
153
|
|
|
154
|
+
// Keep the frame inside the sheet. A frame above the top edge reads as a clipped element
|
|
155
|
+
// to VoiceOver, and the sheet reveals it on focus by moving to the next detent.
|
|
147
156
|
CGFloat frameWidth = pillWidth + kHitPaddingHorizontal * 2;
|
|
148
|
-
CGFloat
|
|
149
|
-
CGFloat
|
|
157
|
+
CGFloat frameY = MAX(0, topMargin - kHitPaddingVertical);
|
|
158
|
+
CGFloat pillY = topMargin - frameY;
|
|
159
|
+
CGFloat frameHeight = pillY + pillHeight + kHitPaddingVertical;
|
|
150
160
|
|
|
151
161
|
self.frame = CGRectMake((parentWidth - frameWidth) / 2.0, frameY, frameWidth, frameHeight);
|
|
152
162
|
self.backgroundColor = UIColor.clearColor;
|
|
153
163
|
|
|
154
|
-
CGRect pillRect = CGRectMake(kHitPaddingHorizontal,
|
|
164
|
+
CGRect pillRect = CGRectMake(kHitPaddingHorizontal, pillY, pillWidth, pillHeight);
|
|
155
165
|
_vibrancyView.frame = pillRect;
|
|
156
166
|
_vibrancyView.layer.cornerRadius = [self effectiveCornerRadius];
|
|
157
167
|
_vibrancyView.clipsToBounds = YES;
|
|
@@ -0,0 +1,31 @@
|
|
|
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 <UIKit/UIKit.h>
|
|
12
|
+
|
|
13
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
14
|
+
|
|
15
|
+
@protocol TrueSheetOverlayContainerViewDelegate <NSObject>
|
|
16
|
+
- (void)overlayContainerViewDidLayout:(CGSize)size;
|
|
17
|
+
@end
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Window-level view hosting an overlay's children.
|
|
21
|
+
* Touches that miss every child fall through to the views beneath.
|
|
22
|
+
*/
|
|
23
|
+
@interface TrueSheetOverlayContainerView : UIView
|
|
24
|
+
|
|
25
|
+
@property (nonatomic, weak, nullable) id<TrueSheetOverlayContainerViewDelegate> delegate;
|
|
26
|
+
|
|
27
|
+
@end
|
|
28
|
+
|
|
29
|
+
NS_ASSUME_NONNULL_END
|
|
30
|
+
|
|
31
|
+
#endif
|
|
@@ -0,0 +1,35 @@
|
|
|
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 "TrueSheetOverlayContainerView.h"
|
|
12
|
+
|
|
13
|
+
@implementation TrueSheetOverlayContainerView
|
|
14
|
+
|
|
15
|
+
- (instancetype)initWithFrame:(CGRect)frame {
|
|
16
|
+
if (self = [super initWithFrame:frame]) {
|
|
17
|
+
self.backgroundColor = UIColor.clearColor;
|
|
18
|
+
self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
|
19
|
+
}
|
|
20
|
+
return self;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event {
|
|
24
|
+
UIView *hit = [super hitTest:point withEvent:event];
|
|
25
|
+
return hit == self ? nil : hit;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
- (void)layoutSubviews {
|
|
29
|
+
[super layoutSubviews];
|
|
30
|
+
[self.delegate overlayContainerViewDidLayout:self.bounds.size];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@end
|
|
34
|
+
|
|
35
|
+
#endif
|
|
@@ -33,6 +33,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
33
33
|
|
|
34
34
|
+ (void)emitDidDismiss:(std::shared_ptr<const facebook::react::EventEmitter>)eventEmitter;
|
|
35
35
|
|
|
36
|
+
+ (void)emitDismissAttempt:(std::shared_ptr<const facebook::react::EventEmitter>)eventEmitter;
|
|
37
|
+
|
|
36
38
|
@end
|
|
37
39
|
|
|
38
40
|
NS_ASSUME_NONNULL_END
|
|
@@ -66,6 +66,14 @@
|
|
|
66
66
|
emitter->onDidDismiss({});
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
+ (void)emitDismissAttempt:(std::shared_ptr<const facebook::react::EventEmitter>)eventEmitter {
|
|
70
|
+
if (!eventEmitter)
|
|
71
|
+
return;
|
|
72
|
+
|
|
73
|
+
auto emitter = std::static_pointer_cast<TrueSheetViewEventEmitter const>(eventEmitter);
|
|
74
|
+
emitter->onDismissAttempt({});
|
|
75
|
+
}
|
|
76
|
+
|
|
69
77
|
@end
|
|
70
78
|
|
|
71
79
|
#endif // RCT_NEW_ARCH_ENABLED
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
#import <react/renderer/components/TrueSheetSpec/ComponentDescriptors.h>
|
|
21
21
|
#import <react/renderer/components/TrueSheetSpec/TrueSheetContentViewComponentDescriptor.h>
|
|
22
22
|
#import <react/renderer/components/TrueSheetSpec/TrueSheetFooterViewComponentDescriptor.h>
|
|
23
|
+
#import <react/renderer/components/TrueSheetSpec/TrueSheetOverlayViewComponentDescriptor.h>
|
|
23
24
|
#import <react/renderer/components/TrueSheetSpec/TrueSheetViewComponentDescriptor.h>
|
|
24
25
|
|
|
25
26
|
#import <TrueSheetSpec/TrueSheetSpec.h>
|
|
@@ -94,6 +95,17 @@ using namespace facebook::react;
|
|
|
94
95
|
|
|
95
96
|
@end
|
|
96
97
|
|
|
98
|
+
@interface TrueSheetOverlayView : RCTViewComponentView
|
|
99
|
+
@end
|
|
100
|
+
|
|
101
|
+
@implementation TrueSheetOverlayView
|
|
102
|
+
|
|
103
|
+
+ (ComponentDescriptorProvider)componentDescriptorProvider {
|
|
104
|
+
return concreteComponentDescriptorProvider<TrueSheetOverlayViewComponentDescriptor>();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@end
|
|
108
|
+
|
|
97
109
|
#pragma mark - Module
|
|
98
110
|
|
|
99
111
|
@interface TrueSheetModule : NSObject <RCTBridgeModule, NativeTrueSheetModuleSpec>
|
|
@@ -17,6 +17,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
17
17
|
- (void)setupEdgeInteractionWithScrollView:(nullable UIScrollView *)scrollView
|
|
18
18
|
edge:(UIRectEdge)edge API_AVAILABLE(ios(26.0));
|
|
19
19
|
- (void)cleanupEdgeInteraction API_AVAILABLE(ios(26.0));
|
|
20
|
+
- (nullable UIScrollView *)edgeInteractionScrollView API_AVAILABLE(ios(26.0));
|
|
20
21
|
|
|
21
22
|
@end
|
|
22
23
|
|
|
@@ -31,15 +31,37 @@ static const void *kEdgeEffectHintKey = &kEdgeEffectHintKey;
|
|
|
31
31
|
objc_setAssociatedObject(self, kEdgeEffectHintKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
- (nullable UIScrollView *)edgeInteractionScrollView API_AVAILABLE(ios(26.0)) {
|
|
35
|
+
#if RNTS_IPHONE_OS_VERSION_AVAILABLE(26_0)
|
|
36
|
+
for (id<UIInteraction> interaction in self.interactions) {
|
|
37
|
+
if ([interaction isKindOfClass:[UIScrollEdgeElementContainerInteraction class]]) {
|
|
38
|
+
return ((UIScrollEdgeElementContainerInteraction *)interaction).scrollView;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
#endif
|
|
42
|
+
return nil;
|
|
43
|
+
}
|
|
44
|
+
|
|
34
45
|
- (void)setupEdgeInteractionWithScrollView:(nullable UIScrollView *)scrollView
|
|
35
46
|
edge:(UIRectEdge)edge API_AVAILABLE(ios(26.0)) {
|
|
36
|
-
[self cleanupEdgeInteraction];
|
|
37
|
-
|
|
38
47
|
if (!scrollView) {
|
|
48
|
+
[self cleanupEdgeInteraction];
|
|
39
49
|
return;
|
|
40
50
|
}
|
|
41
51
|
|
|
42
52
|
#if RNTS_IPHONE_OS_VERSION_AVAILABLE(26_0)
|
|
53
|
+
// Update in place — this re-runs on every footer/header size change, and
|
|
54
|
+
// tearing the interaction down mid keyboard animation flashes the edge
|
|
55
|
+
// effect at the footer's final position.
|
|
56
|
+
for (id<UIInteraction> interaction in self.interactions) {
|
|
57
|
+
if ([interaction isKindOfClass:[UIScrollEdgeElementContainerInteraction class]]) {
|
|
58
|
+
UIScrollEdgeElementContainerInteraction *existing = (UIScrollEdgeElementContainerInteraction *)interaction;
|
|
59
|
+
existing.scrollView = scrollView;
|
|
60
|
+
existing.edge = edge;
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
43
65
|
// UIScrollEdgeElementContainerInteraction requires standard UIKit element
|
|
44
66
|
// descendants (UILabel, UIControl, etc.) to trigger the edge effect.
|
|
45
67
|
// RCTViewComponentView subviews are not recognized, so we add a
|