@lodev09/react-native-true-sheet 3.11.10 → 4.0.0-beta.1
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 +6 -5
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerView.kt +23 -2
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentView.kt +116 -26
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentViewManager.kt +7 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterView.kt +48 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterViewManager.kt +7 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetStateUpdater.kt +45 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +28 -12
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +99 -34
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +9 -5
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetCoordinatorLayout.kt +12 -3
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDetentCalculator.kt +33 -4
- package/android/src/main/jni/TrueSheetSpec.h +2 -0
- package/android/src/main/jni/TrueSheetStateUpdater.cpp +96 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewComponentDescriptor.h +24 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.cpp +43 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.h +28 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewState.cpp +11 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewState.h +37 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewComponentDescriptor.h +24 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewShadowNode.cpp +56 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewShadowNode.h +28 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewState.cpp +11 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewState.h +41 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetInsets.cpp +18 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetInsets.h +16 -0
- package/ios/TrueSheetContainerView.h +12 -10
- package/ios/TrueSheetContainerView.mm +11 -29
- package/ios/TrueSheetContentView.h +22 -7
- package/ios/TrueSheetContentView.mm +143 -41
- package/ios/TrueSheetFooterView.h +12 -2
- package/ios/TrueSheetFooterView.mm +74 -71
- package/ios/TrueSheetHeaderView.mm +0 -1
- package/ios/TrueSheetView.mm +60 -27
- package/ios/TrueSheetViewController.h +9 -0
- package/ios/TrueSheetViewController.mm +288 -122
- package/ios/core/TrueSheetDetentCalculator.h +9 -0
- package/ios/core/TrueSheetDetentCalculator.mm +13 -4
- package/ios/tvos/TrueSheetStubs.mm +2 -0
- package/lib/module/TrueSheet.js +32 -13
- package/lib/module/TrueSheet.js.map +1 -1
- package/lib/module/TrueSheet.web.js +262 -38
- package/lib/module/TrueSheet.web.js.map +1 -1
- package/lib/module/fabric/TrueSheetContentViewNativeComponent.ts +5 -1
- package/lib/module/fabric/TrueSheetFooterViewNativeComponent.ts +10 -2
- package/lib/module/fabric/TrueSheetViewNativeComponent.ts +8 -1
- package/lib/module/web/vaul/index.js +17 -6
- package/lib/module/web/vaul/index.js.map +1 -1
- package/lib/typescript/src/TrueSheet.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheet.types.d.ts +35 -11
- 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/fabric/TrueSheetContentViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/fabric/TrueSheetFooterViewNativeComponent.d.ts +2 -0
- package/lib/typescript/src/fabric/TrueSheetFooterViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts +5 -1
- package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/navigation/types.d.ts +1 -1
- package/lib/typescript/src/navigation/types.d.ts.map +1 -1
- package/lib/typescript/src/web/vaul/index.d.ts +8 -1
- package/lib/typescript/src/web/vaul/index.d.ts.map +1 -1
- package/package.json +10 -10
- package/react-native.config.js +5 -1
- package/src/TrueSheet.tsx +45 -14
- package/src/TrueSheet.types.ts +38 -12
- package/src/TrueSheet.web.tsx +314 -44
- package/src/fabric/TrueSheetContentViewNativeComponent.ts +5 -1
- package/src/fabric/TrueSheetFooterViewNativeComponent.ts +10 -2
- package/src/fabric/TrueSheetViewNativeComponent.ts +8 -1
- package/src/navigation/types.ts +3 -1
- package/src/web/vaul/index.tsx +23 -5
- package/ios/utils/LayoutUtil.h +0 -77
- package/ios/utils/LayoutUtil.mm +0 -106
package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewComponentDescriptor.h
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <react/renderer/components/TrueSheetSpec/TrueSheetFooterViewShadowNode.h>
|
|
4
|
+
#include <react/renderer/core/ConcreteComponentDescriptor.h>
|
|
5
|
+
|
|
6
|
+
namespace facebook::react {
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* Descriptor for <TrueSheetFooterView> component.
|
|
10
|
+
*/
|
|
11
|
+
class TrueSheetFooterViewComponentDescriptor final
|
|
12
|
+
: public ConcreteComponentDescriptor<TrueSheetFooterViewShadowNode> {
|
|
13
|
+
using ConcreteComponentDescriptor::ConcreteComponentDescriptor;
|
|
14
|
+
|
|
15
|
+
void adopt(ShadowNode &shadowNode) const override {
|
|
16
|
+
auto &concreteShadowNode =
|
|
17
|
+
static_cast<TrueSheetFooterViewShadowNode &>(shadowNode);
|
|
18
|
+
concreteShadowNode.adjustLayoutWithState();
|
|
19
|
+
|
|
20
|
+
ConcreteComponentDescriptor::adopt(shadowNode);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#include "TrueSheetFooterViewShadowNode.h"
|
|
2
|
+
|
|
3
|
+
#include <react/renderer/components/view/conversions.h>
|
|
4
|
+
|
|
5
|
+
#include "TrueSheetInsets.h"
|
|
6
|
+
|
|
7
|
+
namespace facebook::react {
|
|
8
|
+
|
|
9
|
+
using namespace yoga;
|
|
10
|
+
|
|
11
|
+
extern const char TrueSheetFooterViewComponentName[] = "TrueSheetFooterView";
|
|
12
|
+
|
|
13
|
+
void TrueSheetFooterViewShadowNode::adjustLayoutWithState() {
|
|
14
|
+
ensureUnsealed();
|
|
15
|
+
|
|
16
|
+
auto state = std::static_pointer_cast<
|
|
17
|
+
const TrueSheetFooterViewShadowNode::ConcreteState>(getState());
|
|
18
|
+
auto stateData = state->getData();
|
|
19
|
+
|
|
20
|
+
auto &props = getConcreteProps();
|
|
21
|
+
|
|
22
|
+
// Until native pushes the real inset (which requires this node to already
|
|
23
|
+
// exist), seed a late-mounted footer's first layout with the precalculated
|
|
24
|
+
// inset — otherwise it lays out unpadded and forces a second sheet resize.
|
|
25
|
+
float bottomInset = stateData.bottomInset;
|
|
26
|
+
if (!stateData.initialized && props.autoBottomInset) {
|
|
27
|
+
bottomInset = TrueSheetInsets::bottomSafeArea();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// A footer pinned to the sheet's bottom edge owns the bottom safe-area
|
|
31
|
+
// inset — pad it on top of any style padding so its content clears the
|
|
32
|
+
// home indicator while the background fills the inset.
|
|
33
|
+
auto padding = props.yogaStyle.padding(Edge::Bottom);
|
|
34
|
+
if (bottomInset > 0) {
|
|
35
|
+
// Base bottom padding from the style — Edge::Bottom wins over
|
|
36
|
+
// Vertical/All, mirroring Yoga's own resolution. Points only.
|
|
37
|
+
float base = 0;
|
|
38
|
+
for (auto edge : {Edge::Bottom, Edge::Vertical, Edge::All}) {
|
|
39
|
+
auto length = props.yogaStyle.padding(edge);
|
|
40
|
+
if (length.isDefined()) {
|
|
41
|
+
base = length.isPoints() ? length.value().unwrap() : 0;
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
padding = StyleLength::points(base + bottomInset);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (yogaNode_.style().padding(Edge::Bottom) != padding) {
|
|
49
|
+
yoga::Style adjustedStyle = props.yogaStyle;
|
|
50
|
+
adjustedStyle.setPadding(Edge::Bottom, padding);
|
|
51
|
+
yogaNode_.setStyle(adjustedStyle);
|
|
52
|
+
yogaNode_.setDirty(true);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <jsi/jsi.h>
|
|
4
|
+
#include <react/renderer/components/TrueSheetSpec/EventEmitters.h>
|
|
5
|
+
#include <react/renderer/components/TrueSheetSpec/Props.h>
|
|
6
|
+
#include <react/renderer/components/TrueSheetSpec/TrueSheetFooterViewState.h>
|
|
7
|
+
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
|
8
|
+
|
|
9
|
+
namespace facebook::react {
|
|
10
|
+
|
|
11
|
+
JSI_EXPORT extern const char TrueSheetFooterViewComponentName[];
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
* `ShadowNode` for <TrueSheetFooterView> component.
|
|
15
|
+
*/
|
|
16
|
+
class JSI_EXPORT TrueSheetFooterViewShadowNode final
|
|
17
|
+
: public ConcreteViewShadowNode<
|
|
18
|
+
TrueSheetFooterViewComponentName,
|
|
19
|
+
TrueSheetFooterViewProps,
|
|
20
|
+
TrueSheetFooterViewEventEmitter,
|
|
21
|
+
TrueSheetFooterViewState> {
|
|
22
|
+
using ConcreteViewShadowNode::ConcreteViewShadowNode;
|
|
23
|
+
|
|
24
|
+
public:
|
|
25
|
+
void adjustLayoutWithState();
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#include "TrueSheetFooterViewState.h"
|
|
2
|
+
|
|
3
|
+
namespace facebook::react {
|
|
4
|
+
|
|
5
|
+
#ifdef ANDROID
|
|
6
|
+
folly::dynamic TrueSheetFooterViewState::getDynamic() const {
|
|
7
|
+
return folly::dynamic::object("bottomInset", bottomInset);
|
|
8
|
+
}
|
|
9
|
+
#endif
|
|
10
|
+
|
|
11
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#ifdef ANDROID
|
|
4
|
+
#include <folly/dynamic.h>
|
|
5
|
+
#include <react/renderer/mapbuffer/MapBuffer.h>
|
|
6
|
+
#include <react/renderer/mapbuffer/MapBufferBuilder.h>
|
|
7
|
+
#endif
|
|
8
|
+
|
|
9
|
+
namespace facebook::react {
|
|
10
|
+
|
|
11
|
+
/*
|
|
12
|
+
* State for <TrueSheetFooterView> component.
|
|
13
|
+
* Set from native with the sheet's bottom safe-area inset so the shadow node
|
|
14
|
+
* pads the footer's bottom edge (see TrueSheetFooterViewShadowNode).
|
|
15
|
+
*/
|
|
16
|
+
class TrueSheetFooterViewState final {
|
|
17
|
+
public:
|
|
18
|
+
TrueSheetFooterViewState() = default;
|
|
19
|
+
|
|
20
|
+
#ifdef ANDROID
|
|
21
|
+
TrueSheetFooterViewState(
|
|
22
|
+
TrueSheetFooterViewState const &previousState,
|
|
23
|
+
folly::dynamic data)
|
|
24
|
+
: bottomInset(static_cast<float>(data["bottomInset"].getDouble())),
|
|
25
|
+
initialized(true) {}
|
|
26
|
+
#endif
|
|
27
|
+
|
|
28
|
+
float bottomInset{0};
|
|
29
|
+
// True once native has pushed a real inset — until then the shadow node
|
|
30
|
+
// seeds the layout from TrueSheetInsets (see TrueSheetFooterViewShadowNode)
|
|
31
|
+
bool initialized{false};
|
|
32
|
+
|
|
33
|
+
#ifdef ANDROID
|
|
34
|
+
folly::dynamic getDynamic() const;
|
|
35
|
+
MapBuffer getMapBuffer() const {
|
|
36
|
+
return MapBufferBuilder::EMPTY();
|
|
37
|
+
}
|
|
38
|
+
#endif
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#include "TrueSheetInsets.h"
|
|
2
|
+
|
|
3
|
+
#include <atomic>
|
|
4
|
+
|
|
5
|
+
namespace facebook::react {
|
|
6
|
+
|
|
7
|
+
// Written from the UI thread, read from the layout thread
|
|
8
|
+
static std::atomic<float> gBottomSafeArea{0};
|
|
9
|
+
|
|
10
|
+
void TrueSheetInsets::setBottomSafeArea(float inset) {
|
|
11
|
+
gBottomSafeArea.store(inset, std::memory_order_relaxed);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
float TrueSheetInsets::bottomSafeArea() {
|
|
15
|
+
return gBottomSafeArea.load(std::memory_order_relaxed);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
namespace facebook::react {
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* Bottom safe-area inset published by the host platform (points/dp) so a
|
|
7
|
+
* late-mounted footer's first layout can be padded before any Fabric state
|
|
8
|
+
* lands (see TrueSheetFooterViewShadowNode).
|
|
9
|
+
*/
|
|
10
|
+
class TrueSheetInsets {
|
|
11
|
+
public:
|
|
12
|
+
static void setBottomSafeArea(float inset);
|
|
13
|
+
static float bottomSafeArea();
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
} // namespace facebook::react
|
|
@@ -45,11 +45,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
45
45
|
*/
|
|
46
46
|
@property (nonatomic, weak, nullable) id<TrueSheetContainerViewDelegate> delegate;
|
|
47
47
|
|
|
48
|
-
/**
|
|
49
|
-
* Enable scrollable content
|
|
50
|
-
*/
|
|
51
|
-
@property (nonatomic, assign) BOOL scrollableEnabled;
|
|
52
|
-
|
|
53
48
|
/**
|
|
54
49
|
* Inset adjustment mode for scrollable content
|
|
55
50
|
*/
|
|
@@ -60,6 +55,18 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
60
55
|
*/
|
|
61
56
|
@property (nonatomic, strong, nullable) ScrollableOptions *scrollableOptions;
|
|
62
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Whether the sheet has an `auto` detent — bounds the pinned scrollable's
|
|
60
|
+
* viewport to the container so the sheet height can derive from its content size
|
|
61
|
+
*/
|
|
62
|
+
@property (nonatomic, assign) BOOL hasAutoDetent;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Bottom safe-area inset the footer absorbs as padding — the footer
|
|
66
|
+
* owns the sheet's bottom edge, so its background fills the inset
|
|
67
|
+
*/
|
|
68
|
+
@property (nonatomic, assign) CGFloat footerBottomInset;
|
|
69
|
+
|
|
63
70
|
/**
|
|
64
71
|
* Returns the current content height
|
|
65
72
|
*/
|
|
@@ -85,11 +92,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
85
92
|
*/
|
|
86
93
|
- (void)attachPeekView:(TrueSheetPeekView *)peekView;
|
|
87
94
|
|
|
88
|
-
/**
|
|
89
|
-
* Updates footer layout constraints if needed
|
|
90
|
-
*/
|
|
91
|
-
- (void)layoutFooter;
|
|
92
|
-
|
|
93
95
|
/**
|
|
94
96
|
* Re-applies the footer's keyboard slide to reflect a live `keyboardOffset` change.
|
|
95
97
|
*/
|
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
|
|
27
27
|
#import <React/RCTConversions.h>
|
|
28
28
|
#import <React/RCTLog.h>
|
|
29
|
-
#import <react/renderer/core/LayoutMetrics.h>
|
|
30
29
|
|
|
31
30
|
using namespace facebook::react;
|
|
32
31
|
|
|
@@ -56,7 +55,6 @@ using namespace facebook::react;
|
|
|
56
55
|
TrueSheetFooterView *_footerView;
|
|
57
56
|
TrueSheetPeekView *__weak _peekView;
|
|
58
57
|
TrueSheetKeyboardObserver *_keyboardObserver;
|
|
59
|
-
BOOL _scrollableSet;
|
|
60
58
|
}
|
|
61
59
|
|
|
62
60
|
#pragma mark - Initialization
|
|
@@ -74,7 +72,6 @@ using namespace facebook::react;
|
|
|
74
72
|
_contentView = nil;
|
|
75
73
|
_headerView = nil;
|
|
76
74
|
_footerView = nil;
|
|
77
|
-
_scrollableSet = NO;
|
|
78
75
|
self.isAccessibilityElement = NO;
|
|
79
76
|
}
|
|
80
77
|
return self;
|
|
@@ -109,13 +106,8 @@ using namespace facebook::react;
|
|
|
109
106
|
|
|
110
107
|
#pragma mark - Layout
|
|
111
108
|
|
|
112
|
-
- (void)layoutSubviews {
|
|
113
|
-
[super layoutSubviews];
|
|
114
|
-
[_contentView updateScrollViewHeight];
|
|
115
|
-
}
|
|
116
|
-
|
|
117
109
|
- (CGFloat)contentHeight {
|
|
118
|
-
return _contentView ? _contentView.
|
|
110
|
+
return _contentView ? _contentView.naturalHeight : 0;
|
|
119
111
|
}
|
|
120
112
|
|
|
121
113
|
- (CGFloat)headerHeight {
|
|
@@ -141,22 +133,13 @@ using namespace facebook::react;
|
|
|
141
133
|
return CGRectGetMaxY([_peekView convertRect:_peekView.bounds toView:_contentView]);
|
|
142
134
|
}
|
|
143
135
|
|
|
144
|
-
- (void)layoutFooter {
|
|
145
|
-
if (_footerView) {
|
|
146
|
-
CGFloat height = _footerView.frame.size.height;
|
|
147
|
-
if (height > 0) {
|
|
148
|
-
[_footerView setupConstraintsWithHeight:height];
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
136
|
- (void)updateFooterKeyboardOffset {
|
|
154
137
|
[_footerView applyKeyboardOffset];
|
|
155
138
|
}
|
|
156
139
|
|
|
157
|
-
- (void)
|
|
158
|
-
|
|
159
|
-
|
|
140
|
+
- (void)setFooterBottomInset:(CGFloat)footerBottomInset {
|
|
141
|
+
_footerBottomInset = footerBottomInset;
|
|
142
|
+
[_footerView setBottomInset:footerBottomInset];
|
|
160
143
|
}
|
|
161
144
|
|
|
162
145
|
- (void)setScrollableOptions:(ScrollableOptions *)scrollableOptions {
|
|
@@ -165,12 +148,13 @@ using namespace facebook::react;
|
|
|
165
148
|
}
|
|
166
149
|
|
|
167
150
|
- (void)setupScrollable {
|
|
168
|
-
if (
|
|
151
|
+
if (_contentView) {
|
|
169
152
|
CGFloat bottomInset = 0;
|
|
170
153
|
if (_insetAdjustment == TrueSheetViewInsetAdjustment::Automatic) {
|
|
171
154
|
bottomInset = [WindowUtil keyWindow].safeAreaInsets.bottom;
|
|
172
155
|
}
|
|
173
|
-
|
|
156
|
+
_contentView.hasAutoDetent = _hasAutoDetent;
|
|
157
|
+
[_contentView setupScrollableWithBottomInset:bottomInset];
|
|
174
158
|
[_contentView applyScrollEdgeEffects:_scrollableOptions];
|
|
175
159
|
if (@available(iOS 26.0, *)) {
|
|
176
160
|
[self setupEdgeInteractions];
|
|
@@ -214,6 +198,7 @@ using namespace facebook::react;
|
|
|
214
198
|
}
|
|
215
199
|
_contentView = (TrueSheetContentView *)childComponentView;
|
|
216
200
|
_contentView.delegate = self;
|
|
201
|
+
_contentView.footerView = _footerView;
|
|
217
202
|
|
|
218
203
|
// Children mount bottom-up, so the content subtree is complete here.
|
|
219
204
|
// Late-mounted peek views attach themselves instead (see TrueSheetPeekView).
|
|
@@ -240,6 +225,8 @@ using namespace facebook::react;
|
|
|
240
225
|
}
|
|
241
226
|
_footerView = (TrueSheetFooterView *)childComponentView;
|
|
242
227
|
_footerView.delegate = self;
|
|
228
|
+
_contentView.footerView = _footerView;
|
|
229
|
+
[_footerView setBottomInset:_footerBottomInset];
|
|
243
230
|
[self footerViewDidChangeSize:_footerView.frame.size];
|
|
244
231
|
}
|
|
245
232
|
}
|
|
@@ -259,6 +246,7 @@ using namespace facebook::react;
|
|
|
259
246
|
if ([childComponentView isKindOfClass:[TrueSheetFooterView class]]) {
|
|
260
247
|
_footerView.delegate = nil;
|
|
261
248
|
_footerView = nil;
|
|
249
|
+
_contentView.footerView = nil;
|
|
262
250
|
[self footerViewDidChangeSize:CGSizeZero];
|
|
263
251
|
}
|
|
264
252
|
|
|
@@ -269,12 +257,6 @@ using namespace facebook::react;
|
|
|
269
257
|
[super updateProps:props oldProps:oldProps];
|
|
270
258
|
}
|
|
271
259
|
|
|
272
|
-
#pragma clang diagnostic ignored "-Wobjc-missing-super-calls"
|
|
273
|
-
- (void)updateLayoutMetrics:(const LayoutMetrics &)layoutMetrics
|
|
274
|
-
oldLayoutMetrics:(const LayoutMetrics &)oldLayoutMetrics {
|
|
275
|
-
// Intentionally skip super - AutoLayout handles container's frame, not Yoga
|
|
276
|
-
}
|
|
277
|
-
|
|
278
260
|
#pragma mark - TrueSheetContentViewDelegate
|
|
279
261
|
|
|
280
262
|
- (void)contentViewDidChangeSize:(CGSize)newSize {
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
#import "core/TrueSheetKeyboardObserver.h"
|
|
16
16
|
|
|
17
17
|
@class TrueSheetViewController;
|
|
18
|
+
@class TrueSheetFooterView;
|
|
18
19
|
@class RCTScrollViewComponentView;
|
|
19
20
|
@class ScrollableOptions;
|
|
20
21
|
|
|
@@ -33,19 +34,33 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
33
34
|
@property (nonatomic, assign) CGFloat keyboardScrollOffset;
|
|
34
35
|
@property (nonatomic, weak, nullable) TrueSheetKeyboardObserver *keyboardObserver;
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Sibling footer view — an absolute footer rises above the keyboard and
|
|
39
|
+
* occludes the content's bottom edge, so it counts toward the keyboard inset.
|
|
40
|
+
*/
|
|
41
|
+
@property (nonatomic, weak, nullable) TrueSheetFooterView *footerView;
|
|
37
42
|
|
|
38
43
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
44
|
+
* Whether the sheet has an `auto` detent. Deriving the sheet height from the
|
|
45
|
+
* scroll content is circular with natural layout, so the pinned ScrollView's
|
|
46
|
+
* viewport is force-bounded to the container only in this case.
|
|
47
|
+
*/
|
|
48
|
+
@property (nonatomic, assign) BOOL hasAutoDetent;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Content height with the pinned ScrollView's viewport replaced by its content
|
|
52
|
+
* size — the height the content wants regardless of container bounds.
|
|
53
|
+
* Falls back to the frame height when no ScrollView is pinned.
|
|
42
54
|
*/
|
|
43
|
-
|
|
55
|
+
@property (nonatomic, readonly) CGFloat naturalHeight;
|
|
56
|
+
|
|
57
|
+
- (RCTScrollViewComponentView *_Nullable)findScrollView;
|
|
44
58
|
|
|
45
59
|
/**
|
|
46
|
-
*
|
|
60
|
+
* Pin the first ScrollView found in the content, wiring insets and keyboard handling
|
|
61
|
+
* @param bottomInset Bottom content inset for the scroll view
|
|
47
62
|
*/
|
|
48
|
-
- (void)
|
|
63
|
+
- (void)setupScrollableWithBottomInset:(CGFloat)bottomInset;
|
|
49
64
|
|
|
50
65
|
/**
|
|
51
66
|
* Apply scroll edge effects to the pinned scroll view (iOS 26+)
|