@yandex/ui
Version:
Yandex UI components
99 lines (98 loc) • 5.68 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DrawerContent = void 0;
var tslib_1 = require("tslib");
var react_1 = tslib_1.__importStar(require("react"));
var Drawer_utils_1 = require("../Drawer.utils");
var Drawer_const_1 = require("../Drawer.const");
/**
* Компонент содержимого шторки.
*
* При использовании Popup мы не знаем в какой конкретно
* момент содержимое монтируется/размонтируется, если
* прокидывать его напрямую без обёрток.
*/
var DrawerContent = function (_a) {
var dragDisabled = _a.dragDisabled, visible = _a.visible, _b = _a.onClose, onClose = _b === void 0 ? Drawer_utils_1.noop : _b, springValue = _a.springValue, _c = _a.direction, direction = _c === void 0 ? 'bottom' : _c, maxSize = _a.maxSize, titleComponent = _a.titleComponent, children = _a.children, setSpringDisabled = _a.setSpringDisabled, setProgress = _a.setProgress;
var dragObserverRef = react_1.useRef(null);
var contentRef = react_1.useRef(null);
var axis = direction === 'bottom' ? 'y' : 'x';
var inverted = direction === 'left' ? -1 : 1;
var springOpacity = Math.max(springValue, 0);
var springTransform = axis === 'x'
? "translate3d(" + (1 - springValue) * 100 * inverted + "%,0,0)"
: "translate3d(0," + (1 - springValue) * 100 * inverted + "%,0)";
var curtainStyle = react_1.useMemo(function () {
var _a;
return (tslib_1.__assign({ transform: springTransform }, (maxSize && (_a = {}, _a[axis === 'x' ? 'maxWidth' : 'maxHeight'] = maxSize, _a))));
}, [springTransform, maxSize, axis]);
/**
* Обработчик drag событий с корневого DOM элемента шторки
*/
Drawer_utils_1.useDrag(dragObserverRef, function (dragState) {
if (!visible || !contentRef.current)
return;
var _a = dragState.velocity, vx = _a.x, vy = _a.y, _b = dragState.movement, mx = _b.x, my = _b.y, first = dragState.first, last = dragState.last, data = dragState.data, event = dragState.event;
var drawerSize = axis === 'x' ? contentRef.current.clientWidth : contentRef.current.clientHeight;
var movement = inverted * (axis === 'x' ? mx : my);
var velocity = inverted * (axis === 'x' ? vx : vy);
if (first) {
data.isTargetUnderContent = contentRef.current.contains(event.target);
data.initialScrollPosition = contentRef.current.scrollTop;
data.isScrolled = data.initialScrollPosition !== 0;
}
else {
data.isScrolled = data.isScrolled || data.initialScrollPosition - contentRef.current.scrollTop < 0;
}
// предотвращает инерционный проскролл родительских элементов, если это возможно
if (event.cancelable && event.type === 'touchmove') {
if (data.isTargetUnderContent) {
// элемент проскроллен до верхней границы
if (contentRef.current.scrollTop <= 0 && my > 0) {
event.preventDefault();
}
// элемент проскроллен до нижней границы
if (contentRef.current.scrollHeight - contentRef.current.scrollTop <= contentRef.current.clientHeight &&
my < 0) {
event.preventDefault();
}
}
else {
event.preventDefault();
}
}
// ничего не делаем когда жест происходит одновременно с проскроллом
// или если шторка в статичном состоянии
// @see SERP-107544
if (dragDisabled || (data.isTargetUnderContent && data.isScrolled)) {
return;
}
// жест завершен, возвращаем шторку в открытое положение, если
// скорость была недостаточной и, закрываем если наоборот
if (last) {
setSpringDisabled(false);
if (Math.abs(velocity) >= 0.1) {
return velocity > 0 ? onClose() : setProgress(1);
}
else if (movement / drawerSize >= 0.3) {
return onClose();
}
return setProgress(1);
}
if (movement > 0) {
setSpringDisabled(true);
var progress = Math.max(0, 1 - movement / drawerSize);
if (progress === 0) {
return onClose();
}
return setProgress(progress);
}
});
return (react_1.default.createElement("div", { className: Drawer_const_1.cnDrawerDragObserver, ref: dragObserverRef },
react_1.default.createElement("div", { className: Drawer_const_1.cnDrawerOverlay, style: { opacity: springOpacity }, onClick: onClose }),
react_1.default.createElement("div", { className: Drawer_const_1.cnDrawerCurtain, style: curtainStyle },
react_1.default.createElement("div", { className: Drawer_const_1.cnDrawerHandle, style: { opacity: springOpacity } }),
titleComponent && react_1.default.createElement("div", { className: Drawer_const_1.cnDrawerTitle }, titleComponent),
react_1.default.createElement("div", { className: Drawer_const_1.cnDrawerContent, ref: contentRef }, children))));
};
exports.DrawerContent = DrawerContent;