@swmansion/react-native-bottom-sheet 0.6.3 → 0.7.0-next.2

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.
@@ -0,0 +1,100 @@
1
+ #import "BottomSheetComponentView.h"
2
+ #import "BottomSheetContentView.h"
3
+
4
+ #import <React/RCTConversions.h>
5
+ #import <React/RCTFabricComponentsPlugins.h>
6
+ #import <react/renderer/components/ReactNativeBottomSheetSpec/ComponentDescriptors.h>
7
+ #import <react/renderer/components/ReactNativeBottomSheetSpec/EventEmitters.h>
8
+ #import <react/renderer/components/ReactNativeBottomSheetSpec/Props.h>
9
+ #import <react/renderer/components/ReactNativeBottomSheetSpec/RCTComponentViewHelpers.h>
10
+
11
+ using namespace facebook::react;
12
+
13
+ @interface BottomSheetComponentView () <BottomSheetContentViewDelegate>
14
+ @end
15
+
16
+ @implementation BottomSheetComponentView {
17
+ BottomSheetContentView *_sheetView;
18
+ }
19
+
20
+ + (ComponentDescriptorProvider)componentDescriptorProvider
21
+ {
22
+ return concreteComponentDescriptorProvider<BottomSheetViewComponentDescriptor>();
23
+ }
24
+
25
+ - (instancetype)initWithFrame:(CGRect)frame
26
+ {
27
+ if (self = [super initWithFrame:frame]) {
28
+ static const auto defaultProps = std::make_shared<const BottomSheetViewProps>();
29
+ _props = defaultProps;
30
+
31
+ _sheetView = [[BottomSheetContentView alloc] initWithFrame:CGRectZero];
32
+ _sheetView.delegate = self;
33
+ _sheetView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
34
+ self.contentView = _sheetView;
35
+ }
36
+ return self;
37
+ }
38
+
39
+ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps
40
+ {
41
+ const auto &newViewProps = static_cast<const BottomSheetViewProps &>(*props);
42
+ const auto &oldViewProps = static_cast<const BottomSheetViewProps &>(*_props);
43
+
44
+ // Always update detents — the codegen struct lacks operator==.
45
+ {
46
+ NSMutableArray<NSDictionary *> *detentsArray = [NSMutableArray new];
47
+ for (const auto &detent : newViewProps.detents) {
48
+ [detentsArray addObject:@{
49
+ @"height": @(detent.height),
50
+ @"programmatic": @(detent.programmatic),
51
+ }];
52
+ }
53
+ [_sheetView setDetents:detentsArray];
54
+ }
55
+
56
+ if (newViewProps.index != oldViewProps.index) {
57
+ [_sheetView setDetentIndex:newViewProps.index];
58
+ }
59
+
60
+ if (newViewProps.animateIn != oldViewProps.animateIn) {
61
+ _sheetView.animateIn = newViewProps.animateIn;
62
+ }
63
+
64
+ [super updateProps:props oldProps:oldProps];
65
+ }
66
+
67
+ - (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
68
+ {
69
+ [_sheetView mountChildComponentView:childComponentView atIndex:index];
70
+ }
71
+
72
+ - (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
73
+ {
74
+ [_sheetView unmountChildComponentView:childComponentView];
75
+ }
76
+
77
+ #pragma mark - BottomSheetContentViewDelegate
78
+
79
+ - (void)bottomSheetView:(BottomSheetContentView *)view didChangeIndex:(NSInteger)index
80
+ {
81
+ if (_eventEmitter) {
82
+ auto emitter = std::static_pointer_cast<const BottomSheetViewEventEmitter>(_eventEmitter);
83
+ emitter->onIndexChange({.index = static_cast<int>(index)});
84
+ }
85
+ }
86
+
87
+ - (void)bottomSheetView:(BottomSheetContentView *)view didChangePosition:(CGFloat)position
88
+ {
89
+ if (_eventEmitter) {
90
+ auto emitter = std::static_pointer_cast<const BottomSheetViewEventEmitter>(_eventEmitter);
91
+ emitter->onPositionChange({.position = static_cast<double>(position)});
92
+ }
93
+ }
94
+
95
+ @end
96
+
97
+ Class<RCTComponentViewProtocol> BottomSheetViewCls(void)
98
+ {
99
+ return BottomSheetComponentView.class;
100
+ }
@@ -0,0 +1,25 @@
1
+ #import <UIKit/UIKit.h>
2
+
3
+ NS_ASSUME_NONNULL_BEGIN
4
+
5
+ @class BottomSheetContentView;
6
+
7
+ @protocol BottomSheetContentViewDelegate <NSObject>
8
+ - (void)bottomSheetView:(BottomSheetContentView *)view didChangeIndex:(NSInteger)index;
9
+ - (void)bottomSheetView:(BottomSheetContentView *)view didChangePosition:(CGFloat)position;
10
+ @end
11
+
12
+ @interface BottomSheetContentView : UIView
13
+
14
+ @property (nonatomic, weak, nullable) id<BottomSheetContentViewDelegate> delegate;
15
+ @property (nonatomic) BOOL animateIn;
16
+ @property (nonatomic, readonly) UIView *sheetContainer;
17
+
18
+ - (void)setDetents:(NSArray<NSDictionary *> *)raw;
19
+ - (void)setDetentIndex:(NSInteger)newIndex;
20
+ - (void)mountChildComponentView:(UIView *)childView atIndex:(NSInteger)index;
21
+ - (void)unmountChildComponentView:(UIView *)childView;
22
+
23
+ @end
24
+
25
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,73 @@
1
+ #import "BottomSheetContentView.h"
2
+
3
+ #if __has_include("ReactNativeBottomSheet-Swift.h")
4
+ #import "ReactNativeBottomSheet-Swift.h"
5
+ #else
6
+ #import <ReactNativeBottomSheet/ReactNativeBottomSheet-Swift.h>
7
+ #endif
8
+
9
+ @interface BottomSheetContentView () <RNSBottomSheetHostingViewDelegate>
10
+ @end
11
+
12
+ @implementation BottomSheetContentView {
13
+ RNSBottomSheetHostingView *_impl;
14
+ }
15
+
16
+ - (instancetype)initWithFrame:(CGRect)frame
17
+ {
18
+ if (self = [super initWithFrame:frame]) {
19
+ _impl = [[RNSBottomSheetHostingView alloc] initWithFrame:self.bounds];
20
+ _impl.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
21
+ _impl.eventDelegate = self;
22
+ [self addSubview:_impl];
23
+ }
24
+
25
+ return self;
26
+ }
27
+
28
+ - (BOOL)animateIn
29
+ {
30
+ return _impl.animateIn;
31
+ }
32
+
33
+ - (void)setAnimateIn:(BOOL)animateIn
34
+ {
35
+ _impl.animateIn = animateIn;
36
+ }
37
+
38
+ - (UIView *)sheetContainer
39
+ {
40
+ return _impl.sheetContainer;
41
+ }
42
+
43
+ - (void)setDetents:(NSArray<NSDictionary *> *)raw
44
+ {
45
+ [_impl setDetents:raw];
46
+ }
47
+
48
+ - (void)setDetentIndex:(NSInteger)newIndex
49
+ {
50
+ [_impl setDetentIndex:newIndex];
51
+ }
52
+
53
+ - (void)mountChildComponentView:(UIView *)childView atIndex:(NSInteger)index
54
+ {
55
+ [_impl mountChildComponentView:childView atIndex:index];
56
+ }
57
+
58
+ - (void)unmountChildComponentView:(UIView *)childView
59
+ {
60
+ [_impl unmountChildComponentView:childView];
61
+ }
62
+
63
+ - (void)bottomSheetHostingView:(RNSBottomSheetHostingView *)view didChangeIndex:(NSInteger)index
64
+ {
65
+ [self.delegate bottomSheetView:self didChangeIndex:index];
66
+ }
67
+
68
+ - (void)bottomSheetHostingView:(RNSBottomSheetHostingView *)view didChangePosition:(CGFloat)position
69
+ {
70
+ [self.delegate bottomSheetView:self didChangePosition:position];
71
+ }
72
+
73
+ @end
@@ -0,0 +1,294 @@
1
+ import UIKit
2
+
3
+ @objc public protocol RNSBottomSheetHostingViewDelegate: AnyObject {
4
+ func bottomSheetHostingView(_ view: RNSBottomSheetHostingView, didChangeIndex index: Int)
5
+ func bottomSheetHostingView(_ view: RNSBottomSheetHostingView, didChangePosition position: CGFloat)
6
+ }
7
+
8
+ private struct DetentSpec {
9
+ let height: CGFloat
10
+ let programmatic: Bool
11
+ }
12
+
13
+ @objcMembers
14
+ public final class RNSBottomSheetHostingView: UIView {
15
+ public weak var eventDelegate: RNSBottomSheetHostingViewDelegate?
16
+
17
+ private var detentSpecs: [DetentSpec] = [] {
18
+ didSet { setNeedsLayout() }
19
+ }
20
+
21
+ private var targetIndex: Int = 0
22
+ public var animateIn: Bool = true
23
+
24
+ public let sheetContainer = UIView()
25
+ private var panGesture: UIPanGestureRecognizer!
26
+ private var activeAnimator: UIViewPropertyAnimator?
27
+ private var displayLink: CADisplayLink?
28
+ private var pendingIndex: Int?
29
+ private var hasLaidOut = false
30
+ private var isPanning = false
31
+
32
+ public override init(frame: CGRect) {
33
+ super.init(frame: frame)
34
+ backgroundColor = .clear
35
+ clipsToBounds = false
36
+
37
+ sheetContainer.backgroundColor = .clear
38
+ sheetContainer.clipsToBounds = false
39
+ addSubview(sheetContainer)
40
+
41
+ panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
42
+ panGesture.delegate = self
43
+ sheetContainer.addGestureRecognizer(panGesture)
44
+ }
45
+
46
+ public required init?(coder: NSCoder) {
47
+ fatalError("init(coder:) has not been implemented")
48
+ }
49
+
50
+ public override func layoutSubviews() {
51
+ super.layoutSubviews()
52
+ guard bounds.width > 0, bounds.height > 0 else { return }
53
+
54
+ let maxHeight = detentSpecs.last?.height ?? bounds.height
55
+ sheetContainer.bounds = CGRect(x: 0, y: 0, width: bounds.width, height: maxHeight)
56
+ sheetContainer.center = CGPoint(x: bounds.width / 2, y: bounds.height - maxHeight / 2)
57
+
58
+ if !hasLaidOut && !detentSpecs.isEmpty {
59
+ hasLaidOut = true
60
+ let indexToApply = pendingIndex ?? targetIndex
61
+ pendingIndex = nil
62
+ targetIndex = max(0, min(detentSpecs.count - 1, indexToApply))
63
+
64
+ if animateIn {
65
+ let closedTy = detentSpecs.last?.height ?? bounds.height
66
+ sheetContainer.transform = CGAffineTransform(translationX: 0, y: closedTy)
67
+ emitPosition()
68
+ snapToIndex(targetIndex, velocity: 0)
69
+ } else {
70
+ sheetContainer.transform = CGAffineTransform(translationX: 0, y: translationY(for: targetIndex))
71
+ emitPosition()
72
+ eventDelegate?.bottomSheetHostingView(self, didChangeIndex: targetIndex)
73
+ }
74
+ return
75
+ }
76
+
77
+ if activeAnimator != nil || isPanning { return }
78
+ sheetContainer.transform = CGAffineTransform(translationX: 0, y: translationY(for: targetIndex))
79
+ }
80
+
81
+ public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
82
+ let containerPoint = convert(point, to: sheetContainer)
83
+ guard sheetContainer.bounds.contains(containerPoint) else { return nil }
84
+ return sheetContainer.hitTest(containerPoint, with: event)
85
+ }
86
+
87
+ public func setDetents(_ raw: [NSDictionary]) {
88
+ detentSpecs = raw.compactMap { dict in
89
+ guard let height = dict["height"] as? Double ?? (dict["height"] as? NSNumber)?.doubleValue else {
90
+ return nil
91
+ }
92
+ let programmatic = (dict["programmatic"] as? Bool) ?? (dict["programmatic"] as? NSNumber)?.boolValue ?? false
93
+ return DetentSpec(height: CGFloat(height), programmatic: programmatic)
94
+ }
95
+ }
96
+
97
+ public func setDetentIndex(_ newIndex: Int) {
98
+ guard newIndex >= 0 else { return }
99
+
100
+ if !hasLaidOut {
101
+ pendingIndex = newIndex
102
+ targetIndex = newIndex
103
+ return
104
+ }
105
+
106
+ guard newIndex < detentSpecs.count, newIndex != targetIndex else { return }
107
+ snapToIndex(newIndex, velocity: 0)
108
+ }
109
+
110
+ public func mountChildComponentView(_ childView: UIView, atIndex index: Int) {
111
+ sheetContainer.insertSubview(childView, at: index)
112
+ }
113
+
114
+ public func unmountChildComponentView(_ childView: UIView) {
115
+ childView.removeFromSuperview()
116
+ }
117
+
118
+ private func detent(at index: Int) -> DetentSpec {
119
+ guard detentSpecs.indices.contains(index) else {
120
+ return DetentSpec(height: 0, programmatic: false)
121
+ }
122
+ return detentSpecs[index]
123
+ }
124
+
125
+ private func translationY(for index: Int) -> CGFloat {
126
+ let maxHeight = detentSpecs.last?.height ?? bounds.height
127
+ let snapHeight = detent(at: index).height
128
+ return maxHeight - snapHeight
129
+ }
130
+
131
+ private var draggableRange: (minTy: CGFloat, maxTy: CGFloat) {
132
+ let draggable = detentSpecs.enumerated().filter { !$0.element.programmatic }
133
+ let highestIndex = draggable.last?.offset ?? 0
134
+ let lowestIndex = draggable.first?.offset ?? 0
135
+ return (minTy: translationY(for: highestIndex), maxTy: translationY(for: lowestIndex))
136
+ }
137
+
138
+ private func emitPosition() {
139
+ let maxHeight = detentSpecs.last?.height ?? bounds.height
140
+ let ty = sheetContainer.layer.presentation()?.affineTransform().ty ?? sheetContainer.transform.ty
141
+ eventDelegate?.bottomSheetHostingView(self, didChangePosition: maxHeight - ty)
142
+ }
143
+
144
+ private func startDisplayLink() {
145
+ guard displayLink == nil else { return }
146
+ let link = CADisplayLink(target: self, selector: #selector(displayLinkFired))
147
+ link.add(to: .main, forMode: .common)
148
+ displayLink = link
149
+ }
150
+
151
+ private func stopDisplayLink() {
152
+ displayLink?.invalidate()
153
+ displayLink = nil
154
+ }
155
+
156
+ @objc private func displayLinkFired() {
157
+ emitPosition()
158
+ }
159
+
160
+ private func snapToIndex(_ index: Int, velocity: CGFloat) {
161
+ guard index >= 0, index < detentSpecs.count else { return }
162
+ targetIndex = index
163
+
164
+ let currentTy = sheetContainer.transform.ty
165
+ let targetTy = translationY(for: index)
166
+ let distance = targetTy - currentTy
167
+ let velocityRatio = distance != 0 ? velocity / distance : 0
168
+ let clampedRatio = min(max(velocityRatio, -5), 5)
169
+ let initialVelocity = CGVector(dx: 0, dy: clampedRatio)
170
+
171
+ activeAnimator?.stopAnimation(true)
172
+
173
+ let spring = UISpringTimingParameters(dampingRatio: 1.0, initialVelocity: initialVelocity)
174
+ let animator = UIViewPropertyAnimator(duration: 0.45, timingParameters: spring)
175
+
176
+ animator.addAnimations {
177
+ self.sheetContainer.transform = CGAffineTransform(translationX: 0, y: targetTy)
178
+ }
179
+ animator.addCompletion { [weak self] position in
180
+ guard let self, position == .end else { return }
181
+ self.stopDisplayLink()
182
+ self.emitPosition()
183
+ self.activeAnimator = nil
184
+ self.eventDelegate?.bottomSheetHostingView(self, didChangeIndex: index)
185
+ }
186
+ animator.startAnimation()
187
+ activeAnimator = animator
188
+ startDisplayLink()
189
+ }
190
+
191
+ @objc private func handlePan(_ gesture: UIPanGestureRecognizer) {
192
+ let maxHeight = detentSpecs.last?.height ?? bounds.height
193
+
194
+ switch gesture.state {
195
+ case .began:
196
+ isPanning = true
197
+ gesture.setTranslation(.zero, in: self)
198
+ if let animator = activeAnimator {
199
+ stopDisplayLink()
200
+ let visual = sheetContainer.layer.presentation()?.affineTransform() ?? sheetContainer.transform
201
+ animator.stopAnimation(true)
202
+ sheetContainer.transform = visual
203
+ activeAnimator = nil
204
+ }
205
+
206
+ case .changed:
207
+ let delta = gesture.translation(in: self).y
208
+ gesture.setTranslation(.zero, in: self)
209
+ let minTy = draggableRange.minTy
210
+ let maxTy = draggableRange.maxTy
211
+ let newTy = max(minTy, min(maxTy, sheetContainer.transform.ty + delta))
212
+ sheetContainer.transform = CGAffineTransform(translationX: 0, y: newTy)
213
+ emitPosition()
214
+
215
+ case .ended, .cancelled:
216
+ isPanning = false
217
+ let velocity = gesture.velocity(in: self).y
218
+ let currentHeight = maxHeight - sheetContainer.transform.ty
219
+ let index = bestSnapIndex(for: currentHeight, velocity: velocity)
220
+ snapToIndex(index, velocity: velocity)
221
+
222
+ case .failed:
223
+ isPanning = false
224
+
225
+ default:
226
+ break
227
+ }
228
+ }
229
+
230
+ private func bestSnapIndex(for height: CGFloat, velocity: CGFloat) -> Int {
231
+ let draggable = detentSpecs.enumerated().filter { !$0.element.programmatic }
232
+ guard !draggable.isEmpty else { return targetIndex }
233
+
234
+ let flickThreshold: CGFloat = 600
235
+
236
+ if velocity < -flickThreshold {
237
+ return draggable.first(where: { $0.element.height > height })?.offset
238
+ ?? draggable.last?.offset ?? targetIndex
239
+ }
240
+ if velocity > flickThreshold {
241
+ return draggable.last(where: { $0.element.height < height })?.offset
242
+ ?? draggable.first?.offset ?? targetIndex
243
+ }
244
+
245
+ return draggable.min(by: {
246
+ abs($0.element.height - height) < abs($1.element.height - height)
247
+ })?.offset ?? targetIndex
248
+ }
249
+
250
+ private func firstScrollView(in view: UIView) -> UIScrollView? {
251
+ for subview in view.subviews {
252
+ if let scrollView = subview as? UIScrollView {
253
+ return scrollView
254
+ }
255
+ if let found = firstScrollView(in: subview) {
256
+ return found
257
+ }
258
+ }
259
+ return nil
260
+ }
261
+
262
+ public override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
263
+ guard gestureRecognizer === panGesture else { return true }
264
+
265
+ let velocity = panGesture.velocity(in: self)
266
+ guard abs(velocity.y) > abs(velocity.x) else { return false }
267
+
268
+ let maxDraggableIndex = detentSpecs.indices.last(where: { !detentSpecs[$0].programmatic }) ?? 0
269
+ guard targetIndex >= maxDraggableIndex else { return true }
270
+
271
+ if velocity.y < 0 {
272
+ return false
273
+ }
274
+
275
+ let scrollAtTop = (firstScrollView(in: sheetContainer)?.contentOffset.y ?? 0) <= 0
276
+ return scrollAtTop
277
+ }
278
+ }
279
+
280
+ extension RNSBottomSheetHostingView: UIGestureRecognizerDelegate {
281
+ public func gestureRecognizer(
282
+ _ gestureRecognizer: UIGestureRecognizer,
283
+ shouldBeRequiredToFailBy other: UIGestureRecognizer
284
+ ) -> Bool {
285
+ return gestureRecognizer === panGesture && other is UIPanGestureRecognizer
286
+ }
287
+
288
+ public func gestureRecognizer(
289
+ _ gestureRecognizer: UIGestureRecognizer,
290
+ shouldRecognizeSimultaneouslyWith other: UIGestureRecognizer
291
+ ) -> Bool {
292
+ return false
293
+ }
294
+ }
@@ -1,8 +1,89 @@
1
1
  "use strict";
2
2
 
3
- import { BottomSheetBase } from "./BottomSheetBase.js";
4
- import { jsx as _jsx } from "react/jsx-runtime";
5
- export const BottomSheet = props => /*#__PURE__*/_jsx(BottomSheetBase, {
6
- ...props
7
- });
3
+ import { useState } from 'react';
4
+ import { StyleSheet, View, useWindowDimensions } from 'react-native';
5
+ import { runOnUI } from 'react-native-reanimated';
6
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
7
+ import BottomSheetNativeComponent from './BottomSheetNativeComponent';
8
+ import { resolveDetent } from "./bottomSheetUtils.js";
9
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
+ export { programmatic } from "./bottomSheetUtils.js";
11
+ export const BottomSheet = ({
12
+ children,
13
+ style,
14
+ detents = [0, 'max'],
15
+ index,
16
+ animateIn = true,
17
+ onIndexChange,
18
+ position
19
+ }) => {
20
+ const {
21
+ height: screenHeight
22
+ } = useWindowDimensions();
23
+ const insets = useSafeAreaInsets();
24
+ const maxHeight = screenHeight - insets.top;
25
+ const [contentHeight, setContentHeight] = useState(0);
26
+ const resolvedDetents = detents.map(detent => {
27
+ const value = resolveDetent(detent, contentHeight, maxHeight);
28
+ return {
29
+ height: Math.max(0, Math.min(value, maxHeight)),
30
+ programmatic: isDetentProgrammatic(detent)
31
+ };
32
+ });
33
+ const handleSentinelLayout = event => {
34
+ setContentHeight(event.nativeEvent.layout.y);
35
+ };
36
+ const clampedIndex = Math.max(0, Math.min(index, resolvedDetents.length - 1));
37
+ const isCollapsed = (resolvedDetents[clampedIndex]?.height ?? 0) === 0;
38
+ const sheetPointerEvents = isCollapsed ? 'none' : 'box-none';
39
+ const handleIndexChange = event => {
40
+ onIndexChange?.(event.nativeEvent.index);
41
+ };
42
+ const handlePositionChange = event => {
43
+ if (position !== undefined) {
44
+ const height = event.nativeEvent.position;
45
+ runOnUI(() => {
46
+ 'worklet';
47
+
48
+ position.set(height);
49
+ })();
50
+ }
51
+ };
52
+ return /*#__PURE__*/_jsx(View, {
53
+ pointerEvents: "box-none",
54
+ style: StyleSheet.absoluteFill,
55
+ children: /*#__PURE__*/_jsx(BottomSheetNativeComponent, {
56
+ pointerEvents: sheetPointerEvents,
57
+ style: [{
58
+ position: 'absolute',
59
+ left: 0,
60
+ right: 0,
61
+ bottom: 0,
62
+ height: maxHeight
63
+ }, style],
64
+ detents: resolvedDetents,
65
+ index: index,
66
+ animateIn: animateIn,
67
+ onIndexChange: handleIndexChange,
68
+ onPositionChange: handlePositionChange,
69
+ children: /*#__PURE__*/_jsxs(View, {
70
+ collapsable: false,
71
+ style: {
72
+ flex: 1
73
+ },
74
+ pointerEvents: "box-none",
75
+ children: [children, /*#__PURE__*/_jsx(View, {
76
+ onLayout: handleSentinelLayout,
77
+ pointerEvents: "none"
78
+ })]
79
+ })
80
+ })
81
+ });
82
+ };
83
+ function isDetentProgrammatic(detent) {
84
+ if (typeof detent === 'object' && detent !== null) {
85
+ return detent.programmatic === true;
86
+ }
87
+ return false;
88
+ }
8
89
  //# sourceMappingURL=BottomSheet.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["BottomSheetBase","jsx","_jsx","BottomSheet","props"],"sourceRoot":"../../src","sources":["BottomSheet.tsx"],"mappings":";;AACA,SAASA,eAAe,QAAQ,sBAAmB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAIpD,OAAO,MAAMC,WAAW,GAAIC,KAAuB,iBACjDF,IAAA,CAACF,eAAe;EAAA,GAAKI;AAAK,CAAG,CAC9B","ignoreList":[]}
1
+ {"version":3,"names":["useState","StyleSheet","View","useWindowDimensions","runOnUI","useSafeAreaInsets","BottomSheetNativeComponent","resolveDetent","jsx","_jsx","jsxs","_jsxs","programmatic","BottomSheet","children","style","detents","index","animateIn","onIndexChange","position","height","screenHeight","insets","maxHeight","top","contentHeight","setContentHeight","resolvedDetents","map","detent","value","Math","max","min","isDetentProgrammatic","handleSentinelLayout","event","nativeEvent","layout","y","clampedIndex","length","isCollapsed","sheetPointerEvents","handleIndexChange","handlePositionChange","undefined","set","pointerEvents","absoluteFill","left","right","bottom","onPositionChange","collapsable","flex","onLayout"],"sourceRoot":"../../src","sources":["BottomSheet.tsx"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,24 @@
1
+ import {
2
+ codegenNativeComponent,
3
+ type CodegenTypes,
4
+ type ViewProps,
5
+ } from 'react-native';
6
+
7
+ type NativeDetent = Readonly<{
8
+ height: CodegenTypes.Double;
9
+ programmatic: boolean;
10
+ }>;
11
+
12
+ export interface NativeProps extends ViewProps {
13
+ detents: ReadonlyArray<NativeDetent>;
14
+ index: CodegenTypes.Int32;
15
+ animateIn: boolean;
16
+ onIndexChange?: CodegenTypes.DirectEventHandler<
17
+ Readonly<{ index: CodegenTypes.Int32 }>
18
+ >;
19
+ onPositionChange?: CodegenTypes.DirectEventHandler<
20
+ Readonly<{ position: CodegenTypes.Double }>
21
+ >;
22
+ }
23
+
24
+ export default codegenNativeComponent<NativeProps>('BottomSheetView');
@@ -5,6 +5,6 @@ export { ModalBottomSheet } from "./ModalBottomSheet.js";
5
5
  export { BottomSheetProvider } from "./BottomSheetProvider.js";
6
6
  export { BottomSheetFlatList } from "./BottomSheetFlatList.js";
7
7
  export { BottomSheetScrollView } from "./BottomSheetScrollView.js";
8
- export { programmatic } from "./BottomSheetBase.js";
8
+ export { programmatic } from "./bottomSheetUtils.js";
9
9
  export { bottomSheetScrollable } from "./bottomSheetScrollable.js";
10
10
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["BottomSheet","ModalBottomSheet","BottomSheetProvider","BottomSheetFlatList","BottomSheetScrollView","programmatic","bottomSheetScrollable"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,WAAW,QAAQ,kBAAe;AAE3C,SAASC,gBAAgB,QAAQ,uBAAoB;AAErD,SAASC,mBAAmB,QAAQ,0BAAuB;AAC3D,SAASC,mBAAmB,QAAQ,0BAAuB;AAE3D,SAASC,qBAAqB,QAAQ,4BAAyB;AAG/D,SAASC,YAAY,QAAQ,sBAAmB;AAChD,SAASC,qBAAqB,QAAQ,4BAAyB","ignoreList":[]}
1
+ {"version":3,"names":["BottomSheet","ModalBottomSheet","BottomSheetProvider","BottomSheetFlatList","BottomSheetScrollView","programmatic","bottomSheetScrollable"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,WAAW,QAAQ,kBAAe;AAE3C,SAASC,gBAAgB,QAAQ,uBAAoB;AAErD,SAASC,mBAAmB,QAAQ,0BAAuB;AAC3D,SAASC,mBAAmB,QAAQ,0BAAuB;AAE3D,SAASC,qBAAqB,QAAQ,4BAAyB;AAG/D,SAASC,YAAY,QAAQ,uBAAoB;AACjD,SAASC,qBAAqB,QAAQ,4BAAyB","ignoreList":[]}
@@ -1,4 +1,17 @@
1
- import type { BottomSheetCommonProps } from './BottomSheetBase';
2
- export type BottomSheetProps = BottomSheetCommonProps;
3
- export declare const BottomSheet: (props: BottomSheetProps) => import("react/jsx-runtime").JSX.Element;
1
+ import { type ReactNode } from 'react';
2
+ import type { StyleProp, ViewStyle } from 'react-native';
3
+ import { type SharedValue } from 'react-native-reanimated';
4
+ import { type Detent } from './bottomSheetUtils';
5
+ export type { Detent, DetentValue } from './bottomSheetUtils';
6
+ export { programmatic } from './bottomSheetUtils';
7
+ export interface BottomSheetProps {
8
+ children: ReactNode;
9
+ style?: StyleProp<ViewStyle>;
10
+ detents?: Detent[];
11
+ index: number;
12
+ animateIn?: boolean;
13
+ onIndexChange?: (index: number) => void;
14
+ position?: SharedValue<number>;
15
+ }
16
+ export declare const BottomSheet: ({ children, style, detents, index, animateIn, onIndexChange, position, }: BottomSheetProps) => import("react/jsx-runtime").JSX.Element;
4
17
  //# sourceMappingURL=BottomSheet.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../../src/BottomSheet.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAGhE,MAAM,MAAM,gBAAgB,GAAG,sBAAsB,CAAC;AAEtD,eAAO,MAAM,WAAW,GAAI,OAAO,gBAAgB,4CAElD,CAAC"}
1
+ {"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../../src/BottomSheet.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,KAAK,EAAqB,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE5E,OAAO,EAAW,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAIpE,OAAO,EAAE,KAAK,MAAM,EAAiB,MAAM,oBAAoB,CAAC;AAChE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAChC;AAED,eAAO,MAAM,WAAW,GAAI,0EAQzB,gBAAgB,4CAiElB,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { type CodegenTypes, type ViewProps } from 'react-native';
2
+ type NativeDetent = Readonly<{
3
+ height: CodegenTypes.Double;
4
+ programmatic: boolean;
5
+ }>;
6
+ export interface NativeProps extends ViewProps {
7
+ detents: ReadonlyArray<NativeDetent>;
8
+ index: CodegenTypes.Int32;
9
+ animateIn: boolean;
10
+ onIndexChange?: CodegenTypes.DirectEventHandler<Readonly<{
11
+ index: CodegenTypes.Int32;
12
+ }>>;
13
+ onPositionChange?: CodegenTypes.DirectEventHandler<Readonly<{
14
+ position: CodegenTypes.Double;
15
+ }>>;
16
+ }
17
+ declare const _default: import("react-native/types_generated/Libraries/Utilities/codegenNativeComponent").NativeComponentType<NativeProps>;
18
+ export default _default;
19
+ //# sourceMappingURL=BottomSheetNativeComponent.d.ts.map