@attio/react-native-bottom-sheet-toolbox
Version:
84 lines (80 loc) • 3.52 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useBottomSheetSnapWhenIdle = useBottomSheetSnapWhenIdle;
var _reactNativeReanimated = require("react-native-reanimated");
var _context = require("../context");
var _utils = require("../utils");
var _useBottomSheetPositionLock = require("./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.
*/
function useBottomSheetSnapWhenIdle() {
const {
currentPositionSharedValue,
currentPositionLastVelocitySharedValue,
currentPositionDestinationSharedValue,
normalizedSnapPointsSharedValue,
isReadySharedValue,
currentPositionLockSharedValue
} = (0, _context.useBottomSheetToolboxInternalContext)();
const {
canLockSharedValue,
hasLockSharedValue,
lock,
release,
setPositionAnimate,
setVelocity
} = (0, _useBottomSheetPositionLock.useBottomSheetPositionLock)(LOCK_ID, _utils.BottomSheetPositionBuiltInLockPriority.SNAP_WHEN_IDLE);
const lastSnapPointIndexSharedValue = (0, _reactNativeReanimated.useSharedValue)(-1);
(0, _reactNativeReanimated.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 ? (0, _utils.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