@swmansion/react-native-bottom-sheet 0.14.1 → 0.15.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.
- package/README.md +9 -2
- package/android/src/main/java/com/swmansion/reactnativebottomsheet/BottomSheetView.kt +21 -9
- package/android/src/main/java/com/swmansion/reactnativebottomsheet/BottomSheetViewManager.kt +6 -2
- package/ios/BottomSheetComponentView.mm +5 -2
- package/ios/BottomSheetContentView.h +3 -1
- package/ios/BottomSheetContentView.mm +4 -2
- package/ios/BottomSheetHostingView.swift +109 -71
- package/ios/CriticalSpring.swift +39 -0
- package/lib/module/BottomSheet.js.map +1 -1
- package/lib/module/BottomSheetNativeComponent.ts +1 -1
- package/lib/typescript/src/BottomSheet.d.ts +7 -0
- package/lib/typescript/src/BottomSheet.d.ts.map +1 -1
- package/lib/typescript/src/BottomSheetNativeComponent.d.ts +1 -0
- package/lib/typescript/src/BottomSheetNativeComponent.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/BottomSheet.tsx +7 -0
- package/src/BottomSheetNativeComponent.ts +1 -1
package/README.md
CHANGED
|
@@ -303,7 +303,12 @@ drag snapping but can still be targeted via `index` updates.
|
|
|
303
303
|
|
|
304
304
|
Use `onPositionChange` to observe the sheet’s current position. It is a standard
|
|
305
305
|
native event; read the distance in pixels from the bottom of the screen to the
|
|
306
|
-
top of the sheet from `event.nativeEvent.position`.
|
|
306
|
+
top of the sheet from `event.nativeEvent.position`. The same event also
|
|
307
|
+
carries `event.nativeEvent.index`—the fractional detent index in
|
|
308
|
+
`0..(detents.length - 1)` (`0` at the shortest detent, `1` at the next, and so
|
|
309
|
+
on, interpolated in between)—the continuous counterpart of `onIndexChange`,
|
|
310
|
+
handy for driving a backdrop or per-detent animation without knowing the
|
|
311
|
+
sheet’s height.
|
|
307
312
|
|
|
308
313
|
```tsx
|
|
309
314
|
<BottomSheet // Or `ModalBottomSheet`.
|
|
@@ -311,7 +316,7 @@ top of the sheet from `event.nativeEvent.position`.
|
|
|
311
316
|
onIndexChange={setIndex}
|
|
312
317
|
surface={/* ... */}
|
|
313
318
|
onPositionChange={(event) => {
|
|
314
|
-
console.log(event.nativeEvent.position);
|
|
319
|
+
console.log(event.nativeEvent.position, event.nativeEvent.index);
|
|
315
320
|
}}
|
|
316
321
|
>
|
|
317
322
|
{/* ... */}
|
|
@@ -356,6 +361,7 @@ import {
|
|
|
356
361
|
|
|
357
362
|
```tsx
|
|
358
363
|
const position = useSharedValue(0);
|
|
364
|
+
const detentIndex = useSharedValue(0);
|
|
359
365
|
|
|
360
366
|
const onPositionChange = useEvent<
|
|
361
367
|
NativeSyntheticEvent<PositionChangeEventData>
|
|
@@ -363,6 +369,7 @@ const onPositionChange = useEvent<
|
|
|
363
369
|
(event) => {
|
|
364
370
|
'worklet';
|
|
365
371
|
position.value = event.position;
|
|
372
|
+
detentIndex.value = event.index;
|
|
366
373
|
},
|
|
367
374
|
['onPositionChange']
|
|
368
375
|
);
|
|
@@ -35,7 +35,7 @@ interface BottomSheetViewListener {
|
|
|
35
35
|
|
|
36
36
|
fun onSettle(index: Int)
|
|
37
37
|
|
|
38
|
-
fun onPositionChange(position: Double)
|
|
38
|
+
fun onPositionChange(position: Double, index: Double)
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
@@ -484,10 +484,17 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
484
484
|
updateScrim(position)
|
|
485
485
|
updateSheetVisibility(position)
|
|
486
486
|
updateInteractionState()
|
|
487
|
-
listener?.onPositionChange((position / density).toDouble())
|
|
487
|
+
listener?.onPositionChange((position / density).toDouble(), detentIndexAt(position).toDouble())
|
|
488
488
|
updateShadowState(ty)
|
|
489
489
|
}
|
|
490
490
|
|
|
491
|
+
// Fractional detent index in 0..(detentSpecs.size - 1): 0 at the shortest
|
|
492
|
+
// detent, 1 at the next, and so on, interpolated by position in between. The
|
|
493
|
+
// continuous counterpart of `onIndexChange`, so consumers can drive a backdrop
|
|
494
|
+
// or animate per detent without knowing the sheet's height.
|
|
495
|
+
private fun detentIndexAt(position: Float): Float =
|
|
496
|
+
interpolateAtPosition(position, detentSpecs.indices.map { it.toFloat() })
|
|
497
|
+
|
|
491
498
|
private fun updateSheetVisibility(position: Float) {
|
|
492
499
|
sheetContainer.alpha = if (position <= 0.5f) 0f else 1f
|
|
493
500
|
}
|
|
@@ -911,15 +918,20 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
911
918
|
* Interpolates the scrim opacity for a sheet height by bracketing it between adjacent detent
|
|
912
919
|
* heights and lerping each detent index's configured value.
|
|
913
920
|
*/
|
|
914
|
-
private fun scrimOpacityAt(position: Float): Float
|
|
921
|
+
private fun scrimOpacityAt(position: Float): Float =
|
|
922
|
+
interpolateAtPosition(
|
|
923
|
+
position,
|
|
924
|
+
detentSpecs.indices.map {
|
|
925
|
+
scrimOpacities[it.coerceAtMost(scrimOpacities.size - 1)].coerceIn(0f, 1f)
|
|
926
|
+
},
|
|
927
|
+
)
|
|
928
|
+
|
|
929
|
+
// Interpolates a per-detent value (one per detent, by index) by the sheet
|
|
930
|
+
// position, using each detent's resolved height as the breakpoint.
|
|
931
|
+
private fun interpolateAtPosition(position: Float, values: List<Float>): Float {
|
|
915
932
|
if (detentSpecs.isEmpty()) return 0f
|
|
916
933
|
val pairs =
|
|
917
|
-
detentSpecs.indices
|
|
918
|
-
.map { index ->
|
|
919
|
-
detentSpecs[index].height to
|
|
920
|
-
scrimOpacities[index.coerceAtMost(scrimOpacities.size - 1)].coerceIn(0f, 1f)
|
|
921
|
-
}
|
|
922
|
-
.sortedBy { it.first }
|
|
934
|
+
detentSpecs.indices.map { detentSpecs[it].height to values[it] }.sortedBy { it.first }
|
|
923
935
|
|
|
924
936
|
val first = pairs.first()
|
|
925
937
|
val last = pairs.last()
|
package/android/src/main/java/com/swmansion/reactnativebottomsheet/BottomSheetViewManager.kt
CHANGED
|
@@ -44,8 +44,12 @@ class BottomSheetViewManager :
|
|
|
44
44
|
dispatchEvent(view, "topSettle", event)
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
override fun onPositionChange(position: Double) {
|
|
48
|
-
val event =
|
|
47
|
+
override fun onPositionChange(position: Double, index: Double) {
|
|
48
|
+
val event =
|
|
49
|
+
Arguments.createMap().apply {
|
|
50
|
+
putDouble("position", position)
|
|
51
|
+
putDouble("index", index)
|
|
52
|
+
}
|
|
49
53
|
dispatchEvent(view, "topPositionChange", event)
|
|
50
54
|
}
|
|
51
55
|
}
|
|
@@ -140,11 +140,14 @@ using namespace facebook::react;
|
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
- (void)bottomSheetView:(BottomSheetContentView *)view
|
|
143
|
+
- (void)bottomSheetView:(BottomSheetContentView *)view
|
|
144
|
+
didChangePosition:(CGFloat)position
|
|
145
|
+
index:(CGFloat)index
|
|
144
146
|
{
|
|
145
147
|
if (_eventEmitter) {
|
|
146
148
|
auto emitter = std::static_pointer_cast<const BottomSheetViewEventEmitter>(_eventEmitter);
|
|
147
|
-
emitter->onPositionChange(
|
|
149
|
+
emitter->onPositionChange(
|
|
150
|
+
{.position = static_cast<double>(position), .index = static_cast<double>(index)});
|
|
148
151
|
}
|
|
149
152
|
|
|
150
153
|
float contentOffsetY = static_cast<float>(view.currentContentOffsetY);
|
|
@@ -7,7 +7,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
7
7
|
@protocol BottomSheetContentViewDelegate <NSObject>
|
|
8
8
|
- (void)bottomSheetView:(BottomSheetContentView *)view didChangeIndex:(NSInteger)index;
|
|
9
9
|
- (void)bottomSheetView:(BottomSheetContentView *)view didSettle:(NSInteger)index;
|
|
10
|
-
- (void)bottomSheetView:(BottomSheetContentView *)view
|
|
10
|
+
- (void)bottomSheetView:(BottomSheetContentView *)view
|
|
11
|
+
didChangePosition:(CGFloat)position
|
|
12
|
+
index:(CGFloat)index;
|
|
11
13
|
- (void)bottomSheetView:(BottomSheetContentView *)view didReportError:(NSString *)message;
|
|
12
14
|
@end
|
|
13
15
|
|
|
@@ -125,9 +125,11 @@
|
|
|
125
125
|
[self.delegate bottomSheetView:self didSettle:index];
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
- (void)bottomSheetHostingView:(BottomSheetHostingView *)view
|
|
128
|
+
- (void)bottomSheetHostingView:(BottomSheetHostingView *)view
|
|
129
|
+
didChangePosition:(CGFloat)position
|
|
130
|
+
index:(CGFloat)index
|
|
129
131
|
{
|
|
130
|
-
[self.delegate bottomSheetView:self didChangePosition:position];
|
|
132
|
+
[self.delegate bottomSheetView:self didChangePosition:position index:index];
|
|
131
133
|
}
|
|
132
134
|
|
|
133
135
|
- (void)bottomSheetHostingView:(BottomSheetHostingView *)view didReportError:(NSString *)message
|
|
@@ -3,7 +3,8 @@ import UIKit
|
|
|
3
3
|
@objc public protocol BottomSheetHostingViewDelegate: AnyObject {
|
|
4
4
|
func bottomSheetHostingView(_ view: BottomSheetHostingView, didChangeIndex index: Int)
|
|
5
5
|
func bottomSheetHostingView(_ view: BottomSheetHostingView, didSettle index: Int)
|
|
6
|
-
func bottomSheetHostingView(
|
|
6
|
+
func bottomSheetHostingView(
|
|
7
|
+
_ view: BottomSheetHostingView, didChangePosition position: CGFloat, index: CGFloat)
|
|
7
8
|
func bottomSheetHostingView(_ view: BottomSheetHostingView, didReportError message: String)
|
|
8
9
|
}
|
|
9
10
|
|
|
@@ -67,8 +68,9 @@ public final class BottomSheetHostingView: UIView {
|
|
|
67
68
|
public let sheetContainer = UIView()
|
|
68
69
|
private let scrimView = UIControl()
|
|
69
70
|
private var panGesture: UIPanGestureRecognizer!
|
|
70
|
-
private var
|
|
71
|
-
private var
|
|
71
|
+
private var activeSpring: CriticalSpring?
|
|
72
|
+
private var activeSpringTargetIndex: Int = 0
|
|
73
|
+
private var activeSpringEmitsSettle = false
|
|
72
74
|
private var scrimPinnedFull = false
|
|
73
75
|
private var displayLink: CADisplayLink?
|
|
74
76
|
private var pendingIndex: Int?
|
|
@@ -180,20 +182,13 @@ public final class BottomSheetHostingView: UIView {
|
|
|
180
182
|
return
|
|
181
183
|
}
|
|
182
184
|
|
|
183
|
-
if
|
|
185
|
+
if activeSpring != nil || isPanning { return }
|
|
184
186
|
sheetContainer.transform = CGAffineTransform(translationX: 0, y: translationY(for: targetIndex))
|
|
185
187
|
updateScrim()
|
|
186
188
|
}
|
|
187
189
|
|
|
188
|
-
private var presentedSheetFrame: CGRect {
|
|
189
|
-
if activeAnimator != nil, let presentation = sheetContainer.layer.presentation() {
|
|
190
|
-
return presentation.frame
|
|
191
|
-
}
|
|
192
|
-
return sheetContainer.frame
|
|
193
|
-
}
|
|
194
|
-
|
|
195
190
|
override public func point(inside point: CGPoint, with _: UIEvent?) -> Bool {
|
|
196
|
-
if
|
|
191
|
+
if sheetContainer.frame.contains(point) {
|
|
197
192
|
return true
|
|
198
193
|
}
|
|
199
194
|
|
|
@@ -203,7 +198,7 @@ public final class BottomSheetHostingView: UIView {
|
|
|
203
198
|
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
|
204
199
|
guard self.point(inside: point, with: event) else { return nil }
|
|
205
200
|
|
|
206
|
-
if isScrimVisible, !
|
|
201
|
+
if isScrimVisible, !sheetContainer.frame.contains(point) {
|
|
207
202
|
let scrimPoint = convert(point, to: scrimView)
|
|
208
203
|
return scrimView.hitTest(scrimPoint, with: event)
|
|
209
204
|
}
|
|
@@ -268,8 +263,8 @@ public final class BottomSheetHostingView: UIView {
|
|
|
268
263
|
}
|
|
269
264
|
|
|
270
265
|
public func resetSheetState() {
|
|
271
|
-
|
|
272
|
-
|
|
266
|
+
activeSpring = nil
|
|
267
|
+
activeSpringEmitsSettle = false
|
|
273
268
|
stopDisplayLink()
|
|
274
269
|
rawDetentSpecs = []
|
|
275
270
|
detentSpecs = []
|
|
@@ -357,12 +352,13 @@ public final class BottomSheetHostingView: UIView {
|
|
|
357
352
|
updateScrim(forPosition: position)
|
|
358
353
|
updateSheetVisibility(forPosition: position)
|
|
359
354
|
updateInteractionState()
|
|
360
|
-
eventDelegate?.bottomSheetHostingView(
|
|
355
|
+
eventDelegate?.bottomSheetHostingView(
|
|
356
|
+
self, didChangePosition: position, index: detentIndex(forPosition: position))
|
|
361
357
|
}
|
|
362
358
|
|
|
363
359
|
private func startDisplayLink() {
|
|
364
360
|
guard displayLink == nil else { return }
|
|
365
|
-
let link = CADisplayLink(target: self, selector: #selector(displayLinkFired))
|
|
361
|
+
let link = CADisplayLink(target: self, selector: #selector(displayLinkFired(_:)))
|
|
366
362
|
link.add(to: .main, forMode: .common)
|
|
367
363
|
displayLink = link
|
|
368
364
|
}
|
|
@@ -383,8 +379,9 @@ public final class BottomSheetHostingView: UIView {
|
|
|
383
379
|
isContentInteractionDisabled = !isEnabled
|
|
384
380
|
}
|
|
385
381
|
|
|
386
|
-
@objc private func displayLinkFired() {
|
|
387
|
-
|
|
382
|
+
@objc private func displayLinkFired(_ link: CADisplayLink) {
|
|
383
|
+
// `targetTimestamp` is predicted when the NEXT frame will be shown
|
|
384
|
+
stepSpring(targetTime: link.targetTimestamp)
|
|
388
385
|
}
|
|
389
386
|
|
|
390
387
|
@objc private func handleScrimPress() {
|
|
@@ -392,7 +389,7 @@ public final class BottomSheetHostingView: UIView {
|
|
|
392
389
|
modal,
|
|
393
390
|
let closedIndex,
|
|
394
391
|
targetIndex != closedIndex,
|
|
395
|
-
|
|
392
|
+
activeSpring == nil || currentSheetHeight > 0.5
|
|
396
393
|
else {
|
|
397
394
|
return
|
|
398
395
|
}
|
|
@@ -416,43 +413,71 @@ public final class BottomSheetHostingView: UIView {
|
|
|
416
413
|
let currentTy = sheetContainer.transform.ty
|
|
417
414
|
let targetTy = translationY(for: index)
|
|
418
415
|
let distance = targetTy - currentTy
|
|
416
|
+
|
|
419
417
|
let velocityRatio = distance != 0 ? velocity / distance : 0
|
|
420
418
|
let clampedRatio = min(max(velocityRatio, -5), 5)
|
|
421
|
-
let
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
}
|
|
419
|
+
let v0 = clampedRatio * distance
|
|
420
|
+
|
|
421
|
+
let duration: CFTimeInterval = 0.45
|
|
422
|
+
// Pick the stiffness so the sheet looks settled (within ~0.5% of target)
|
|
423
|
+
// right at `duration`. For a critically-damped spring that point is
|
|
424
|
+
// ω·t ≈ 8, so ω = 8 / duration. Exact agreement with UIKit's spring doesn't
|
|
425
|
+
// matter here — we drive the modal from this curve.
|
|
426
|
+
//
|
|
427
|
+
// NOTE: This solution may affect the animation performance when the main thread is busy.
|
|
428
|
+
// If that becomes a problem, consider adopting this solution: https://github.com/kirillzyusko/react-native-keyboard-controller/pull/412
|
|
429
|
+
let omega = 8.0 / CGFloat(duration)
|
|
430
|
+
activeSpringEmitsSettle = emitSettle
|
|
431
|
+
activeSpringTargetIndex = index
|
|
432
|
+
|
|
433
|
+
activeSpring = CriticalSpring(
|
|
434
|
+
from: currentTy,
|
|
435
|
+
target: targetTy,
|
|
436
|
+
v0: v0,
|
|
437
|
+
omega: omega,
|
|
438
|
+
startTime: CACurrentMediaTime(),
|
|
439
|
+
duration: duration
|
|
440
|
+
)
|
|
441
|
+
|
|
445
442
|
// Report the index change as soon as the snap is committed, not when it
|
|
446
443
|
// finishes: `targetIndex` is already set, and a programmatic snap's start is
|
|
447
444
|
// known to the caller. `onSettle` remains the signal for movement end.
|
|
448
445
|
if emitIndexChange {
|
|
449
446
|
eventDelegate?.bottomSheetHostingView(self, didChangeIndex: index)
|
|
450
447
|
}
|
|
451
|
-
animator.startAnimation()
|
|
452
|
-
activeAnimator = animator
|
|
453
448
|
startDisplayLink()
|
|
454
449
|
}
|
|
455
450
|
|
|
451
|
+
private func stepSpring(targetTime: CFTimeInterval) {
|
|
452
|
+
guard let spring = activeSpring else { return }
|
|
453
|
+
if spring.isFinished(at: targetTime) {
|
|
454
|
+
finishSpring()
|
|
455
|
+
return
|
|
456
|
+
}
|
|
457
|
+
let ty = spring.value(at: targetTime)
|
|
458
|
+
sheetContainer.transform = CGAffineTransform(translationX: 0, y: ty)
|
|
459
|
+
emitPosition()
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
private func finishSpring() {
|
|
463
|
+
let index = activeSpringTargetIndex
|
|
464
|
+
let emitSettle = activeSpringEmitsSettle
|
|
465
|
+
let targetTy = translationY(for: index)
|
|
466
|
+
|
|
467
|
+
activeSpring = nil
|
|
468
|
+
activeSpringEmitsSettle = false
|
|
469
|
+
stopDisplayLink()
|
|
470
|
+
|
|
471
|
+
sheetContainer.transform = CGAffineTransform(translationX: 0, y: targetTy)
|
|
472
|
+
emitPosition()
|
|
473
|
+
scrimPinnedFull = false
|
|
474
|
+
setContentInteractionEnabled(true)
|
|
475
|
+
updateInteractionState()
|
|
476
|
+
if emitSettle {
|
|
477
|
+
eventDelegate?.bottomSheetHostingView(self, didSettle: index)
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
456
481
|
@objc private func handlePan(_ gesture: UIPanGestureRecognizer) {
|
|
457
482
|
let maxHeight = sheetContainerHeight
|
|
458
483
|
|
|
@@ -468,12 +493,10 @@ public final class BottomSheetHostingView: UIView {
|
|
|
468
493
|
handler.isEnabled = true
|
|
469
494
|
}
|
|
470
495
|
gesture.setTranslation(.zero, in: self)
|
|
471
|
-
if
|
|
496
|
+
if activeSpring != nil {
|
|
472
497
|
stopDisplayLink()
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
sheetContainer.transform = visual
|
|
476
|
-
activeAnimator = nil
|
|
498
|
+
activeSpring = nil
|
|
499
|
+
activeSpringEmitsSettle = false
|
|
477
500
|
}
|
|
478
501
|
|
|
479
502
|
case .changed:
|
|
@@ -691,13 +714,13 @@ public final class BottomSheetHostingView: UIView {
|
|
|
691
714
|
let newMaxHeight = sheetContainerHeight
|
|
692
715
|
let targetTy = translationY(for: targetIndex)
|
|
693
716
|
|
|
694
|
-
if
|
|
717
|
+
if activeSpring != nil {
|
|
695
718
|
stopDisplayLink()
|
|
696
|
-
|
|
697
|
-
let
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
719
|
+
// `transform.ty` is the live on-screen value (set each frame).
|
|
720
|
+
let visualTy = sheetContainer.transform.ty
|
|
721
|
+
let shouldEmitSettle = activeSpringEmitsSettle
|
|
722
|
+
activeSpring = nil
|
|
723
|
+
activeSpringEmitsSettle = false
|
|
701
724
|
// Re-anchor the in-flight position to the new container height so the
|
|
702
725
|
// sheet surface keeps the same on-screen height across the resize.
|
|
703
726
|
let visibleHeight = previousMaxHeight - visualTy
|
|
@@ -838,9 +861,10 @@ extension BottomSheetHostingView: UIGestureRecognizerDelegate {
|
|
|
838
861
|
|
|
839
862
|
private extension BottomSheetHostingView {
|
|
840
863
|
var currentTranslationY: CGFloat {
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
864
|
+
// Both the drag and the settle assign `transform` directly every frame, so
|
|
865
|
+
// it always holds the live on-screen value. (If the settle were run by a
|
|
866
|
+
// UIViewPropertyAnimator instead, the in-flight value would live on the
|
|
867
|
+
// render server and we'd have to read `layer.presentation()` here.)
|
|
844
868
|
return sheetContainer.transform.ty
|
|
845
869
|
}
|
|
846
870
|
|
|
@@ -866,7 +890,7 @@ private extension BottomSheetHostingView {
|
|
|
866
890
|
if
|
|
867
891
|
let closedIndex,
|
|
868
892
|
targetIndex == closedIndex,
|
|
869
|
-
|
|
893
|
+
activeSpring == nil,
|
|
870
894
|
!isPanning
|
|
871
895
|
{
|
|
872
896
|
scrimView.alpha = 0
|
|
@@ -899,26 +923,40 @@ private extension BottomSheetHostingView {
|
|
|
899
923
|
/// Interpolates the scrim opacity for a sheet height by bracketing it between
|
|
900
924
|
/// adjacent detent heights and lerping each detent index's configured value.
|
|
901
925
|
private func scrimOpacity(forPosition position: CGFloat) -> CGFloat {
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
.map {
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
926
|
+
interpolate(
|
|
927
|
+
forPosition: position,
|
|
928
|
+
values: detentSpecs.indices.map {
|
|
929
|
+
clampOpacity(scrimOpacities[min($0, scrimOpacities.count - 1)])
|
|
930
|
+
})
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
// Fractional detent index in 0...(detentSpecs.count - 1): 0 at the shortest
|
|
934
|
+
// detent, 1 at the next, and so on, interpolated by position in between. The
|
|
935
|
+
// continuous counterpart of `onIndexChange`, so consumers can drive a backdrop
|
|
936
|
+
// or animate per detent without knowing the sheet's height.
|
|
937
|
+
private func detentIndex(forPosition position: CGFloat) -> CGFloat {
|
|
938
|
+
interpolate(forPosition: position, values: detentSpecs.indices.map { CGFloat($0) })
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
// Interpolates a per-detent value (one per detent, by index) by the sheet
|
|
942
|
+
// position, using each detent's resolved height as the breakpoint.
|
|
943
|
+
private func interpolate(forPosition position: CGFloat, values: [CGFloat]) -> CGFloat {
|
|
944
|
+
let pairs = zip(detentSpecs.map(\.height), values)
|
|
945
|
+
.map { (height: $0, value: $1) }
|
|
908
946
|
.sorted { $0.height < $1.height }
|
|
909
947
|
|
|
910
948
|
guard let first = pairs.first, let last = pairs.last else { return 0 }
|
|
911
|
-
if position <= first.height { return first.
|
|
912
|
-
if position >= last.height { return last.
|
|
949
|
+
if position <= first.height { return first.value }
|
|
950
|
+
if position >= last.height { return last.value }
|
|
913
951
|
|
|
914
952
|
for i in 1 ..< pairs.count where position <= pairs[i].height {
|
|
915
953
|
let lower = pairs[i - 1]
|
|
916
954
|
let upper = pairs[i]
|
|
917
955
|
let span = upper.height - lower.height
|
|
918
956
|
let t = span <= 0 ? 1 : (position - lower.height) / span
|
|
919
|
-
return lower.
|
|
957
|
+
return lower.value + (upper.value - lower.value) * t
|
|
920
958
|
}
|
|
921
|
-
return last.
|
|
959
|
+
return last.value
|
|
922
960
|
}
|
|
923
961
|
|
|
924
962
|
private func clampOpacity(_ value: CGFloat) -> CGFloat {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import QuartzCore
|
|
2
|
+
|
|
3
|
+
/// A spring we evaluate ourselves each frame instead of letting
|
|
4
|
+
/// `UIViewPropertyAnimator` run the settle. The animator runs on the "render
|
|
5
|
+
/// server", so its value is only readable one frame late via `presentation()` —
|
|
6
|
+
/// the cause of the follower view (fed by `onPositionChange`) trailing the
|
|
7
|
+
/// modal. Computing it in-process lets us emit the exact value we set.
|
|
8
|
+
/// Critically damped (ζ = 1): reaches the target as fast as possible without
|
|
9
|
+
/// overshooting.
|
|
10
|
+
struct CriticalSpring {
|
|
11
|
+
let from: CGFloat
|
|
12
|
+
let target: CGFloat
|
|
13
|
+
/// Initial velocity (points/sec) — e.g. carried over from a finger flick.
|
|
14
|
+
let v0: CGFloat
|
|
15
|
+
/// Angular frequency (rad/sec) — the spring's stiffness/speed. Higher ω snaps faster;
|
|
16
|
+
let omega: CGFloat
|
|
17
|
+
let startTime: CFTimeInterval
|
|
18
|
+
let duration: CFTimeInterval
|
|
19
|
+
|
|
20
|
+
/// Position at an absolute `time`, from the closed-form solution of a
|
|
21
|
+
/// critically-damped spring (ζ = 1):
|
|
22
|
+
/// x(t) = target + e^(−ω·t)·[A + (v0 + ω·A)·t]
|
|
23
|
+
/// where A is the starting offset from the target. The `e^(−ω·t)` term decays
|
|
24
|
+
/// the offset toward 0 (so x → target), and the linear `…·t` factor is what
|
|
25
|
+
/// lets a critically-damped spring carry initial velocity without oscillating.
|
|
26
|
+
func value(at time: CFTimeInterval) -> CGFloat {
|
|
27
|
+
// Seconds since the spring started (clamped so a past `time` reads as t = 0).
|
|
28
|
+
let t = CGFloat(max(0, time - startTime))
|
|
29
|
+
// A: how far `from` is from `target` — the offset the spring must close.
|
|
30
|
+
let a = from - target
|
|
31
|
+
// Exponential envelope: 1 at t = 0, shrinking toward 0 as time passes.
|
|
32
|
+
let decay = exp(-omega * t)
|
|
33
|
+
return target + decay * (a + (v0 + omega * a) * t)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
func isFinished(at time: CFTimeInterval) -> Bool {
|
|
37
|
+
time - startTime >= duration
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useState","StyleSheet","View","useSafeAreaFrame","useSafeAreaInsets","BottomSheetNativeView","BottomSheetSurfaceNativeComponent","Portal","jsx","_jsx","jsxs","_jsxs","programmatic","BottomSheet","children","surface","style","detents","index","animateIn","onIndexChange","onSettle","onPositionChange","wrapNativeView","modal","disableScrollableNegotiation","scrimColor","scrimOpacities","height","windowHeight","insets","maxHeight","top","nativeDetents","map","detent","isDetentProgrammatic","value","resolveDetentValue","kind","Math","max","min","clampedIndex","length","selectedDetentValue","isCollapsed","resolvedScrimOpacity","handleIndexChange","event","nativeEvent","handleSettle","NativeView","sheet","absoluteFill","pointerEvents","position","left","right","bottom","maxDetentHeight","collapsable","flex"],"sourceRoot":"../../src","sources":["BottomSheet.tsx"],"mappings":";;AAAA,SAASA,QAAQ,QAA4C,OAAO;AAEpE,SAASC,UAAU,EAAEC,IAAI,QAAQ,cAAc;AAC/C,SACEC,gBAAgB,EAChBC,iBAAiB,QACZ,gCAAgC;AAEvC,OAAOC,qBAAqB,MAErB,8BAA8B;AACrC,OAAOC,iCAAiC,MAAM,qCAAqC;AACnF,SAASC,MAAM,QAAQ,0BAAuB;AAAC,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAG/C,SAASC,YAAY,QAAQ,uBAAoB;;AAEjD;AACA;AACA;AACA;;
|
|
1
|
+
{"version":3,"names":["useState","StyleSheet","View","useSafeAreaFrame","useSafeAreaInsets","BottomSheetNativeView","BottomSheetSurfaceNativeComponent","Portal","jsx","_jsx","jsxs","_jsxs","programmatic","BottomSheet","children","surface","style","detents","index","animateIn","onIndexChange","onSettle","onPositionChange","wrapNativeView","modal","disableScrollableNegotiation","scrimColor","scrimOpacities","height","windowHeight","insets","maxHeight","top","nativeDetents","map","detent","isDetentProgrammatic","value","resolveDetentValue","kind","Math","max","min","clampedIndex","length","selectedDetentValue","isCollapsed","resolvedScrimOpacity","handleIndexChange","event","nativeEvent","handleSettle","NativeView","sheet","absoluteFill","pointerEvents","position","left","right","bottom","maxDetentHeight","collapsable","flex"],"sourceRoot":"../../src","sources":["BottomSheet.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -27,7 +27,7 @@ export interface NativeProps extends ViewProps {
|
|
|
27
27
|
Readonly<{ index: CodegenTypes.Int32 }>
|
|
28
28
|
>;
|
|
29
29
|
onPositionChange?: CodegenTypes.DirectEventHandler<
|
|
30
|
-
Readonly<{ position: CodegenTypes.Double }>
|
|
30
|
+
Readonly<{ position: CodegenTypes.Double; index: CodegenTypes.Double }>
|
|
31
31
|
>;
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -11,6 +11,13 @@ export { programmatic } from './bottomSheetUtils';
|
|
|
11
11
|
export type PositionChangeEventData = Readonly<{
|
|
12
12
|
/** Sheet position, in points from the bottom. */
|
|
13
13
|
position: number;
|
|
14
|
+
/**
|
|
15
|
+
* Fractional detent index in `0..(detents.length - 1)`: `0` at the shortest
|
|
16
|
+
* detent, `1` at the next, and so on, interpolated as the sheet moves between
|
|
17
|
+
* them. The continuous counterpart of `onIndexChange`, so a backdrop or
|
|
18
|
+
* per-detent animation can be driven without knowing the sheet's height.
|
|
19
|
+
*/
|
|
20
|
+
index: number;
|
|
14
21
|
}>;
|
|
15
22
|
/**
|
|
16
23
|
* Props for the inline bottom-sheet component.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../../src/BottomSheet.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACrE,OAAO,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAO/E,OAA8B,EAC5B,KAAK,WAAW,EACjB,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC;IAC7C,iDAAiD;IACjD,QAAQ,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../../src/BottomSheet.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACrE,OAAO,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAO/E,OAA8B,EAC5B,KAAK,WAAW,EACjB,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC;IAC7C,iDAAiD;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,wDAAwD;IACxD,QAAQ,EAAE,SAAS,CAAC;IACpB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CACjB,KAAK,EAAE,oBAAoB,CAAC,uBAAuB,CAAC,KACjD,IAAI,CAAC;IACV;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,EAAE,CACf,SAAS,EAAE,aAAa,CAAC,WAAW,CAAC,KAClC,aAAa,CAAC,WAAW,CAAC,CAAC;IAChC,gDAAgD;IAChD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;;;;;OAYG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,gFAAgF;AAChF,eAAO,MAAM,WAAW,GAAI,sLAezB,gBAAgB,4CAgHlB,CAAC"}
|
|
@@ -21,6 +21,7 @@ export interface NativeProps extends ViewProps {
|
|
|
21
21
|
}>>;
|
|
22
22
|
onPositionChange?: CodegenTypes.DirectEventHandler<Readonly<{
|
|
23
23
|
position: CodegenTypes.Double;
|
|
24
|
+
index: CodegenTypes.Double;
|
|
24
25
|
}>>;
|
|
25
26
|
}
|
|
26
27
|
declare const _default: import("react-native/types_generated/Libraries/Utilities/codegenNativeComponent").NativeComponentType<NativeProps>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BottomSheetNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/BottomSheetNativeComponent.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAEtB,KAAK,YAAY,GAAG,QAAQ,CAAC;IAC3B,KAAK,EAAE,YAAY,CAAC,MAAM,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC,CAAC;AAEH,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,eAAe,EAAE,YAAY,CAAC,MAAM,CAAC;IACrC,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC;IAC1B,SAAS,CAAC,EAAE,YAAY,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACpD,KAAK,EAAE,OAAO,CAAC;IACf,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,cAAc,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IACpD,aAAa,CAAC,EAAE,YAAY,CAAC,kBAAkB,CAC7C,QAAQ,CAAC;QAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAA;KAAE,CAAC,CACxC,CAAC;IACF,QAAQ,CAAC,EAAE,YAAY,CAAC,kBAAkB,CACxC,QAAQ,CAAC;QAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAA;KAAE,CAAC,CACxC,CAAC;IACF,gBAAgB,CAAC,EAAE,YAAY,CAAC,kBAAkB,CAChD,QAAQ,CAAC;QAAE,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAA;KAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"BottomSheetNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/BottomSheetNativeComponent.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAEtB,KAAK,YAAY,GAAG,QAAQ,CAAC;IAC3B,KAAK,EAAE,YAAY,CAAC,MAAM,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC,CAAC;AAEH,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,eAAe,EAAE,YAAY,CAAC,MAAM,CAAC;IACrC,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC;IAC1B,SAAS,CAAC,EAAE,YAAY,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACpD,KAAK,EAAE,OAAO,CAAC;IACf,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,cAAc,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IACpD,aAAa,CAAC,EAAE,YAAY,CAAC,kBAAkB,CAC7C,QAAQ,CAAC;QAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAA;KAAE,CAAC,CACxC,CAAC;IACF,QAAQ,CAAC,EAAE,YAAY,CAAC,kBAAkB,CACxC,QAAQ,CAAC;QAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAA;KAAE,CAAC,CACxC,CAAC;IACF,gBAAgB,CAAC,EAAE,YAAY,CAAC,kBAAkB,CAChD,QAAQ,CAAC;QAAE,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAC;QAAC,KAAK,EAAE,YAAY,CAAC,MAAM,CAAA;KAAE,CAAC,CACxE,CAAC;CACH;;AAED,wBAAsE"}
|
package/package.json
CHANGED
package/src/BottomSheet.tsx
CHANGED
|
@@ -22,6 +22,13 @@ export { programmatic } from './bottomSheetUtils';
|
|
|
22
22
|
export type PositionChangeEventData = Readonly<{
|
|
23
23
|
/** Sheet position, in points from the bottom. */
|
|
24
24
|
position: number;
|
|
25
|
+
/**
|
|
26
|
+
* Fractional detent index in `0..(detents.length - 1)`: `0` at the shortest
|
|
27
|
+
* detent, `1` at the next, and so on, interpolated as the sheet moves between
|
|
28
|
+
* them. The continuous counterpart of `onIndexChange`, so a backdrop or
|
|
29
|
+
* per-detent animation can be driven without knowing the sheet's height.
|
|
30
|
+
*/
|
|
31
|
+
index: number;
|
|
25
32
|
}>;
|
|
26
33
|
|
|
27
34
|
/**
|
|
@@ -27,7 +27,7 @@ export interface NativeProps extends ViewProps {
|
|
|
27
27
|
Readonly<{ index: CodegenTypes.Int32 }>
|
|
28
28
|
>;
|
|
29
29
|
onPositionChange?: CodegenTypes.DirectEventHandler<
|
|
30
|
-
Readonly<{ position: CodegenTypes.Double }>
|
|
30
|
+
Readonly<{ position: CodegenTypes.Double; index: CodegenTypes.Double }>
|
|
31
31
|
>;
|
|
32
32
|
}
|
|
33
33
|
|