UNPKG

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

Version:
111 lines (106 loc) 4.89 kB
"use strict"; // 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