@gdjiami/hooks
Version:
react hooks for mygzb.com
163 lines (162 loc) • 5.87 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var react_1 = require("react");
var useGesture_1 = tslib_1.__importDefault(require("./useGesture"));
var useRefProps_1 = tslib_1.__importDefault(require("./useRefProps"));
var useRefState_1 = tslib_1.__importDefault(require("./useRefState"));
/**
* 获取
* @param el
*/
function getElementBounds(el) {
var bounds = el.getBoundingClientRect();
return {
x: bounds.left,
y: bounds.top,
width: bounds.width,
height: bounds.height,
};
}
/**
* 限定在指定区域内
*
* @param offset
* @param el
* @param bounds
*/
function restrictInBounds(offset, el, bounds) {
if (bounds == null) {
return offset;
}
var elRect = getElementBounds(el);
var boundRect;
if (typeof bounds === 'string') {
var boundEl = bounds === 'parent' ? el.parentElement : document.querySelector(bounds);
if (boundEl == null || !(boundEl instanceof HTMLElement)) {
throw Error('Bounds selector "' + bounds + '" could not find an element.');
}
boundRect = getElementBounds(boundEl);
}
else {
boundRect = bounds;
}
var coordAfterDrag = { x: elRect.x + offset.x, y: elRect.y + offset.y };
var right = coordAfterDrag.x + elRect.width;
var bottom = coordAfterDrag.y + elRect.height;
var boundsRight = boundRect.x + boundRect.width;
var boundsBottom = boundRect.y + boundRect.height;
var x = coordAfterDrag.x;
var y = coordAfterDrag.y;
if (right > boundsRight) {
x -= right - boundsRight;
}
if (bottom > boundsBottom) {
y -= bottom - boundsBottom;
}
x = Math.max(x, boundRect.x);
y = Math.max(y, boundRect.y);
return {
x: x - elRect.x,
y: y - elRect.y,
};
}
/**
* 停靠边缘
*/
function berthEdge(offset, el, bounds, padding) {
if (bounds === void 0) { bounds = 'body'; }
if (padding === void 0) { padding = 0; }
var elRect = getElementBounds(el);
var boundRect;
if (typeof bounds === 'string') {
var boundEl = bounds === 'parent' ? el.parentElement : document.querySelector(bounds);
if (boundEl == null || !(boundEl instanceof HTMLElement)) {
throw Error('Bounds selector "' + bounds + '" could not find an element.');
}
boundRect = getElementBounds(boundEl);
}
else {
boundRect = bounds;
}
var x = elRect.x - boundRect.x > boundRect.width / 2
? boundRect.width - (elRect.width + padding) // right berth
: padding;
return {
x: x,
y: offset.y,
};
}
var DEFAULT_TRANSLATE = { x: 0, y: 0 };
/**
* 给指定element注入可拖拽行为
*/
function useDraggable(options) {
if (options === void 0) { options = {}; }
var _a = tslib_1.__read(react_1.useState(false), 2), dragging = _a[0], setDragging = _a[1];
var _b = tslib_1.__read(useRefState_1.default(options.defaultTranslate || DEFAULT_TRANSLATE), 3), offset = _b[0], setOffset = _b[1], offsetRef = _b[2];
var optionsRef = useRefProps_1.default(options);
var x = offset.x, y = offset.y;
var el = useGesture_1.default({
onDown: function (info) {
if (optionsRef.current.onDown &&
optionsRef.current.onDown(info) === false) {
return false;
}
setDragging(true);
return;
},
onMove: function (info) {
var axis = optionsRef.current.axis;
var _a = restrictInBounds({ x: info.deltaX, y: info.deltaY }, info.target, optionsRef.current.bounds ||
(optionsRef.current.edge ? 'body' : undefined)), deltaX = _a.x, deltaY = _a.y;
var offset = offsetRef.current;
var newOffset = {
x: axis === 'y' ? offset.x : deltaX + offset.x,
y: axis === 'x' ? offset.y : deltaY + offset.y,
};
if (optionsRef.current.onMove) {
optionsRef.current.onMove(info, offset);
}
setOffset(newOffset);
return;
},
onUp: function (info) {
setDragging(false);
var offset = offsetRef.current;
if (optionsRef.current.edge) {
offset = berthEdge(offset, info.target, optionsRef.current.bounds, optionsRef.current.edgePadding);
requestAnimationFrame(function () {
setOffset(offset);
});
}
if (optionsRef.current.onUp) {
optionsRef.current.onUp(info, offset);
}
},
ref: options.ref,
}).ref;
var resetOffset = react_1.useCallback(function () {
var _a = restrictInBounds(optionsRef.current.defaultTranslate || DEFAULT_TRANSLATE, el.current, optionsRef.current.bounds ||
(optionsRef.current.edge ? 'body' : undefined)), x = _a.x, y = _a.y;
var offset = offsetRef.current;
offset = {
x: x + offset.x,
y: y + offset.y,
};
if (optionsRef.current.edge) {
offset = berthEdge(offset, el.current, optionsRef.current.bounds, optionsRef.current.edgePadding);
}
setOffset(offset);
}, []);
react_1.useEffect(function () {
resetOffset();
}, []);
react_1.useEffect(function () {
if (!optionsRef.current.disableTransform) {
el.current.style.transform = "translate3d(" + x + "px, " + y + "px, 0)";
}
}, [x, y]);
return { ref: el, dragging: dragging, translate: offset, resetOffset: resetOffset };
}
exports.default = useDraggable;