UNPKG

@attio/react-native-bottom-sheet-toolbox

Version:
80 lines (76 loc) 3.37 kB
"use strict"; import { useAnimatedReaction, useSharedValue } from "react-native-reanimated"; import { useBottomSheetToolboxInternalContext } from "../context"; import { BottomSheetPositionBuiltInLockPriority, snapPoint } from "../utils"; import { useBottomSheetPositionLock } from "./use-bottom-sheet-position-lock"; const LOCK_ID = "useBottomSheetSnapWhenIdle"; /** * This hook snaps the bottom sheet to the nearest snap point when * nothing else is interacting with it. It takes into account the * last known velocity. * * A snap is triggered after either of the following two conditions: * - The position off any snap-point, and has been released. * - The underlying snap-points have changed. */ export function useBottomSheetSnapWhenIdle() { const { currentPositionSharedValue, currentPositionLastVelocitySharedValue, currentPositionDestinationSharedValue, normalizedSnapPointsSharedValue, isReadySharedValue, currentPositionLockSharedValue } = useBottomSheetToolboxInternalContext(); const { canLockSharedValue, hasLockSharedValue, lock, release, setPositionAnimate, setVelocity } = useBottomSheetPositionLock(LOCK_ID, BottomSheetPositionBuiltInLockPriority.SNAP_WHEN_IDLE); const lastSnapPointIndexSharedValue = useSharedValue(-1); useAnimatedReaction(() => ({ canLock: isReadySharedValue.get() && canLockSharedValue.get(), hasLock: hasLockSharedValue.get(), snapPoints: normalizedSnapPointsSharedValue.get() }), ({ canLock, hasLock, snapPoints }, lastResults) => { const canLockOrHasLock = canLock || hasLock; if (!snapPoints || !canLockOrHasLock) { lastSnapPointIndexSharedValue.set(-1); return; } const lastCanLockOrHasLock = lastResults?.canLock || lastResults?.hasLock; const didLockStatusChange = lastCanLockOrHasLock !== canLockOrHasLock; const lastSnapPoints = lastResults?.snapPoints || []; const didSnapPointsChange = snapPoints === null ? lastSnapPoints === null : lastSnapPoints.length !== snapPoints.length || lastSnapPoints.some((v, index) => v !== snapPoints[index]); // Nothing to do if (!didLockStatusChange && !didSnapPointsChange) return; /** * If our snap-points change, then try to follow the snap-point we * were last at. This also supports the case where the snap-points * are updated to be equal, but then separate again. That case can * happen when the keyboard opens. */ lastSnapPointIndexSharedValue.set(lastSnapPoints.indexOf(currentPositionDestinationSharedValue.get())); const currentPosition = currentPositionSharedValue.get(); const point = lastSnapPointIndexSharedValue.get() === -1 ? snapPoint(currentPosition, currentPositionLastVelocitySharedValue.get(), snapPoints) : snapPoints[lastSnapPointIndexSharedValue.get()] ?? null; if (point === null || point === currentPosition) return; if (!hasLock) { lock(); } setPositionAnimate(point, undefined, finished => { const currentPositionLock = currentPositionLockSharedValue.get(); if (finished || currentPositionLock?.id !== LOCK_ID) { release(); } }); setVelocity(0); }, [canLockSharedValue, hasLockSharedValue, normalizedSnapPointsSharedValue, isReadySharedValue.get]); } //# sourceMappingURL=use-bottom-sheet-snap-when-idle.js.map