UNPKG

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

Version:
113 lines (110 loc) 5.36 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useBottomSheetDragGesture = useBottomSheetDragGesture; var React = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _reactNativeGestureHandler = require("react-native-gesture-handler"); var _reactNativeReanimated = require("react-native-reanimated"); var _context = require("../context"); var _utils = require("../utils"); var _useBottomSheetPositionLock = require("./use-bottom-sheet-position-lock"); function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } const LOCK_ID_NAMESPACE = "useBottomSheetDragGesture"; // Gesture velocity is calculated between gesture updates. // If the user does not move their finger, the gesture doesn't see update // and so the velocity is miss-leading (i.e. not 0) // We detect this by checking the time between the last gesture update. const SUPPRESS_VELOCITY_TIME_MS = 150; function useBottomSheetDragGesture({ id, disabled = false, clamped = false, frozenSharedValue }) { const { currentPositionSharedValue, currentPositionLastVelocitySharedValue, wrapperHeightSharedValue, normalizedSnapPointsSharedValue } = (0, _context.useBottomSheetToolboxInternalContext)(); const { lock, release, setPosition, setVelocity, canLockSharedValue, hasLockSharedValue } = (0, _useBottomSheetPositionLock.useBottomSheetPositionLock)(`${LOCK_ID_NAMESPACE}:${id}`, _utils.BottomSheetPositionBuiltInLockPriority.GESTURE); const lastLockRef = React.useRef(id); React.useEffect(() => { if (id !== lastLockRef.current) throw new Error("Lock id can't be changed."); }, [id]); const startPositionSharedValue = (0, _reactNativeReanimated.useSharedValue)(0); const lastUpdateTime = (0, _reactNativeReanimated.useSharedValue)(0); const [enabled, setEnabled] = React.useState(false); (0, _reactNativeReanimated.useAnimatedReaction)(() => canLockSharedValue.get() || hasLockSharedValue.get(), (lockable, lastLockable) => { if (lockable === lastLockable) return; (0, _reactNativeReanimated.runOnJS)(setEnabled)(lockable); }, [canLockSharedValue, hasLockSharedValue.get]); const [windowHeight, setWindowHeight] = React.useState(_reactNative.Dimensions.get("window").height); React.useEffect(() => { const handle = _reactNative.Dimensions.addEventListener("change", ({ window }) => { setWindowHeight(window.height); }); return () => handle.remove(); }, []); const frozenOriginOffsetYSharedValue = (0, _reactNativeReanimated.useSharedValue)(0); return _reactNativeGestureHandler.Gesture.Pan().onBegin(() => { if (!canLockSharedValue.get()) return; startPositionSharedValue.set(currentPositionSharedValue.get()); frozenOriginOffsetYSharedValue.set(0); }).onUpdate(evt => { const normalizedSnapPoints = normalizedSnapPointsSharedValue.get(); const wrapperHeight = wrapperHeightSharedValue.get(); const lockable = canLockSharedValue.get() || hasLockSharedValue.get(); if (!lockable || !normalizedSnapPoints || !wrapperHeight) return; // We want to lock onUpdate, rather than onBegin, so nested // touches do no unnecessarily lock the position. if (!hasLockSharedValue.get()) { lock(); } if (frozenSharedValue?.get()) { frozenOriginOffsetYSharedValue.set(evt.translationY); return; } setVelocity(evt.velocityY); const rawPosition = startPositionSharedValue.get() - evt.translationY + frozenOriginOffsetYSharedValue.get(); const maxSnapPoint = Math.max(...normalizedSnapPoints); const overshoot = Math.max(0, rawPosition - maxSnapPoint); if (clamped) { const clampedPosition = Math.max(Math.min(rawPosition, maxSnapPoint), 0); setPosition(clampedPosition); } else if (overshoot > 0) { const topInset = Math.max(1, windowHeight - wrapperHeight); const frictionRatio = (0, _utils.friction)(overshoot / topInset); const frictionPosition = maxSnapPoint + topInset * frictionRatio; const finalPosition = Math.min(frictionPosition, wrapperHeight + topInset); setPosition(finalPosition); } else { setPosition(rawPosition); } lastUpdateTime.set(Date.now()); }).onFinalize(evt => { if (!hasLockSharedValue.get()) return; if (frozenSharedValue?.get()) { setVelocity(0); } else { const currentTime = Date.now(); const velocity = -evt.velocityY; const timeSinceLastUpdate = currentTime - lastUpdateTime.get(); currentPositionLastVelocitySharedValue.set(timeSinceLastUpdate > SUPPRESS_VELOCITY_TIME_MS ? 0 : velocity); setVelocity(velocity); } release(); }).enabled(enabled && !disabled); } //# sourceMappingURL=use-bottom-sheet-drag-gesture.js.map