@ozen-ui/kit
Version:
React component library
90 lines (89 loc) • 3.89 kB
JavaScript
import { __read } from "tslib";
import { rubberbandIfOutOfBounds, useDrag } from '@use-gesture/react';
import { clamp } from '../../../utils/math';
import { isNaN } from '../../../utils/number';
import { BOTTOM_SHEET_BASE_CSS_VARIABLE } from '../constants';
import { useBottomSheetBaseContext } from '../context';
import { useBottomSheetBaseCSSValue } from './useBottomSheetBaseCSSValue';
var rubberbandIfOutOfBoundsConstant = 0.55;
export var useBottomSheetBaseDrag = function (target, options) {
var _a = options !== null && options !== void 0 ? options : {}, _b = _a.isCloseOnTap, isCloseOnTap = _b === void 0 ? false : _b, _c = _a.isDraggable, isDraggable = _c === void 0 ? true : _c;
var _d = useBottomSheetBaseContext(), minSnap = _d.minSnap, onCloseContext = _d.onClose, canDrag = _d.canDrag, maxSnap = _d.maxSnap, isClosable = _d.isClosable, snapsControl = _d.snapsControl, findClosestSnap = _d.findClosestSnap, rootRef = _d.rootRef;
var userSelect = useBottomSheetBaseCSSValue({
rootRef: rootRef,
defaultValue: 'auto',
variableName: BOTTOM_SHEET_BASE_CSS_VARIABLE.USER_SELECT,
});
var onClose = function () {
snapsControl.toClosed(true);
onCloseContext === null || onCloseContext === void 0 ? void 0 : onCloseContext();
};
var calculateAnimationTime = function (pxChange, velocity) {
var rawTime = Math.abs(pxChange / velocity);
if (isNaN(rawTime)) {
return 0;
}
return clamp(rawTime, 200, 500);
};
var onDragStart = function () {
userSelect.setValue('none');
};
var onDragFinish = function () {
userSelect.setValue('auto');
};
useDrag(function (params) {
var cancel = params.cancel, down = params.down, first = params.first, last = params.last, _a = params.memo, memo = _a === void 0 ? snapsControl.point.current : _a, _b = __read(params.movement, 2), _my = _b[1], tap = params.tap, _c = __read(params.velocity, 2), velocity = _c[1];
var my = _my * -1;
if (!canDrag.current) {
cancel();
return memo;
}
if (isClosable && isCloseOnTap && tap) {
cancel();
setTimeout(function () { return onClose(); }, 0);
return memo;
}
if (tap) {
return memo;
}
if (first) {
onDragStart();
}
var rawOffset = memo + my;
var predictedDistance = my * velocity;
var predictedPoint = Math.max(minSnap, Math.min(maxSnap, rawOffset + predictedDistance * 2));
if (last && isClosable && rawOffset + predictedDistance < minSnap / 2) {
onDragFinish();
onClose();
return memo;
}
var newOffset = (function () {
if (!down) {
return predictedPoint;
}
if (!isClosable && minSnap === maxSnap) {
if (rawOffset < minSnap) {
return rubberbandIfOutOfBounds(rawOffset, minSnap, maxSnap * 1.5, rubberbandIfOutOfBoundsConstant);
}
return rubberbandIfOutOfBounds(rawOffset, minSnap / 1.5, maxSnap, rubberbandIfOutOfBoundsConstant);
}
return rubberbandIfOutOfBounds(rawOffset, isClosable ? 0 : minSnap, maxSnap, rubberbandIfOutOfBoundsConstant);
})();
if (last) {
var closestSnap = findClosestSnap.current(newOffset);
snapsControl.toAnimated(closestSnap, {
duration: calculateAnimationTime(Math.abs(closestSnap - snapsControl.point.current), velocity),
});
onDragFinish();
return memo;
}
snapsControl.to(newOffset);
return memo;
}, {
target: isDraggable
? target
: {
current: null,
},
});
};