@attio/react-native-bottom-sheet-toolbox
Version:
111 lines (106 loc) • 4.89 kB
JavaScript
;
// import { nanoid } from "nanoid/non-secure";
import * as React from "react";
import { useAnimatedReaction, useSharedValue } from "react-native-reanimated";
import { useBottomSheetToolboxInternalContext } from "../context";
import { DEFAULT_CLOSE_SHEET_SNAP_POINT_SPRING_CONFIG } from "../utils";
import { BottomSheetPositionBuiltInLockPriority, CLOSED_SNAP_POINT } from "../utils/constants";
import { useBottomSheetOnSnapDetection } from "./use-bottom-sheet-on-snap-detection";
import { useBottomSheetPositionLock } from "./use-bottom-sheet-position-lock";
import { useWorkletUiCallback } from "./use-worklet-ui-callback";
/**
* Creates a set of actions that can be used to imperatively control the bottom sheet.
*/
export function useBottomSheetActions(id) {
const {
currentPositionSharedValue,
normalizedSnapPointsSharedValue
} = useBottomSheetToolboxInternalContext();
const {
lock: snapLock,
release: setSnapRelease,
setPositionAnimate: setSnapPositionAnimate,
setVelocity: setSnapVelocity,
hasLockSharedValue: hasSnapLockSharedValue
} = useBottomSheetPositionLock(`useBottomSheetActions:${id}:snap`, BottomSheetPositionBuiltInLockPriority.ACTIONS_SNAP);
// We apply imperative snaps reactively, like this, so we can adjust for changes in the snap points etc.
const snapDestinationIndexSharedValue = useSharedValue(null);
const lastSnapPointsSharedValue = useSharedValue(null);
useAnimatedReaction(() => ({
currentPosition: currentPositionSharedValue.get(),
snapDestinationIndex: snapDestinationIndexSharedValue.get(),
snapPoints: normalizedSnapPointsSharedValue.get(),
hasSnapLock: hasSnapLockSharedValue.get()
}), ({
currentPosition,
snapPoints,
snapDestinationIndex,
hasSnapLock
}, lastResult) => {
if (!hasSnapLock && lastResult?.hasSnapLock === true) {
snapDestinationIndexSharedValue.set(null);
return;
}
if (snapPoints === null || snapDestinationIndex === null) return;
const lastSnapPoints = lastSnapPointsSharedValue.get();
const didSnapChange = lastSnapPoints === null || lastSnapPoints[snapDestinationIndex] !== snapPoints[snapDestinationIndex] || lastResult?.snapDestinationIndex !== snapDestinationIndex;
const snapPoint = snapPoints[snapDestinationIndex] ?? null;
if (snapPoint === null || currentPosition === snapPoint) {
snapDestinationIndexSharedValue.set(null);
setSnapRelease();
return;
}
if (!didSnapChange) return;
lastSnapPointsSharedValue.set(snapPoints);
setSnapVelocity(0);
setSnapPositionAnimate(snapPoint);
}, [hasSnapLockSharedValue, currentPositionSharedValue, normalizedSnapPointsSharedValue]);
const snapToIndex = useWorkletUiCallback(snapPointIndex => {
"worklet";
const normalizedSnapPoints = normalizedSnapPointsSharedValue.get();
if (!normalizedSnapPoints || normalizedSnapPoints.length === 0) {
throw new Error("No snap-points to snap to.");
}
if (!(snapPointIndex in normalizedSnapPoints)) {
throw new Error(`Invalid snap point index: ${snapPointIndex}`);
}
snapLock();
snapDestinationIndexSharedValue.set(snapPointIndex);
}, [snapLock, normalizedSnapPointsSharedValue]);
const {
lock: closeLock,
release: closeRelease,
setPositionAnimate: setClosePositionAnimate,
setVelocity: setCloseVelocity,
hasLockSharedValue: hasCloseLockSharedValue
} = useBottomSheetPositionLock(`useBottomSheetActions:${id}:close`, BottomSheetPositionBuiltInLockPriority.ACTIONS_CLOSE);
const expand = useWorkletUiCallback(() => {
"worklet";
const normalizedSnapPoints = normalizedSnapPointsSharedValue.get();
if (!normalizedSnapPoints || normalizedSnapPoints.length === 0) {
throw new Error("No snap-points to snap to.");
} else if (normalizedSnapPoints.length === 1 && normalizedSnapPoints[0] === 0) {
throw new Error("Sheet cannot expand as only available snap-point is '0'.");
}
snapToIndex(normalizedSnapPoints.length - 1);
}, [normalizedSnapPointsSharedValue, snapToIndex]);
const close = useWorkletUiCallback(() => {
"worklet";
if (hasCloseLockSharedValue.get()) return;
closeLock();
setCloseVelocity(0);
setClosePositionAnimate(CLOSED_SNAP_POINT, DEFAULT_CLOSE_SHEET_SNAP_POINT_SPRING_CONFIG, closeRelease);
}, [hasCloseLockSharedValue, closeLock, setCloseVelocity, setClosePositionAnimate, closeRelease]);
const currentSnapRef = React.useRef(null);
useBottomSheetOnSnapDetection(React.useCallback(snap => {
currentSnapRef.current = snap;
}, []));
const getCurrentSnapIndex = React.useCallback(() => currentSnapRef.current, []);
return React.useMemo(() => ({
snapToIndex,
expand,
close,
getCurrentSnapIndex
}), [snapToIndex, expand, close, getCurrentSnapIndex]);
}
//# sourceMappingURL=use-bottom-sheet-actions.js.map