@ozen-ui/kit
Version:
React component library
95 lines (94 loc) • 6.58 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Modal = exports.cnModal = void 0;
var tslib_1 = require("tslib");
require("./Modal.css");
var react_1 = tslib_1.__importStar(require("react"));
var react_transition_group_1 = require("react-transition-group");
var environment_1 = require("../../constants/environment");
var useClickOutside_1 = require("../../hooks/useClickOutside");
var useEventListener_1 = require("../../hooks/useEventListener");
var useFocusTrap_1 = require("../../hooks/useFocusTrap");
var useLockBodyScroll_1 = require("../../hooks/useLockBodyScroll");
var useMultiRef_1 = require("../../hooks/useMultiRef");
var usePortalContainer_1 = require("../../hooks/usePortalContainer");
var classname_1 = require("../../utils/classname");
var isKey_1 = require("../../utils/isKey");
var Backdrop_1 = require("../Backdrop");
var PortalBase_1 = require("../PortalBase");
var components_1 = require("./components");
var constants_1 = require("./constants");
var index_1 = require("./index");
exports.cnModal = (0, classname_1.cn)('Modal');
exports.Modal = (0, react_1.forwardRef)(function (_a, ref) {
var _b = _a.open, open = _b === void 0 ? constants_1.MODAL_DEFAULT_OPEN : _b, _c = _a.keepMounted, keepMounted = _c === void 0 ? constants_1.MODAL_DEFAULT_KEEP_MOUNTED : _c, _d = _a.hideBackdrop, hideBackdrop = _d === void 0 ? constants_1.MODAL_DEFAULT_HIDE_BACKDROP : _d, _e = _a.disableScrollLock, disableScrollLock = _e === void 0 ? constants_1.MODAL_DEFAULT_DISABLE_SCROLL_LOCK : _e, _f = _a.disableClickOutside, disableClickOutside = _f === void 0 ? constants_1.MODAL_DEFAULT_DISABLE_CLICK_OUTSIDE : _f, _g = _a.disableEscapeKeyDown, disableEscapeKeyDown = _g === void 0 ? constants_1.MODAL_DEFAULT_ESCAPE_KEY_DOWN : _g, children = _a.children, onEnter = _a.onEnter, onEntered = _a.onEntered, onExit = _a.onExit, onExitedProp = _a.onExited, onClose = _a.onClose, backdropProps = _a.backdropProps, windowProps = _a.windowProps, transitionProps = _a.transitionProps, className = _a.className, ignoreClickOutsideRefs = _a.ignoreClickOutsideRefs, _h = _a.container, containerProp = _h === void 0 ? constants_1.MODAL_DEFAULT_PORTAL_CONTAINER : _h, other = tslib_1.__rest(_a, ["open", "keepMounted", "hideBackdrop", "disableScrollLock", "disableClickOutside", "disableEscapeKeyDown", "children", "onEnter", "onEntered", "onExit", "onExited", "onClose", "backdropProps", "windowProps", "transitionProps", "className", "ignoreClickOutsideRefs", "container"]);
var hasBackdrop = !hideBackdrop;
var rootRef = (0, react_1.useRef)(null);
var windowInnerRef = (0, react_1.useRef)(null);
var focusedElement = (0, react_1.useRef)(null);
var _j = tslib_1.__read((0, react_1.useState)(false), 2), openState = _j[0], setOpenState = _j[1];
var _k = tslib_1.__read((0, react_1.useState)(false), 2), opened = _k[0], setOpened = _k[1];
var container = (0, usePortalContainer_1.usePortalContainer)(containerProp);
var _l = (0, index_1.useModalManager)(windowInnerRef, 1000, openState), isTop = _l.isTop, refsClickOutside = _l.refsClickOutside;
var portalMultiRef = (0, useMultiRef_1.useMultiRef)([rootRef, ref]);
var trapRef = (0, useFocusTrap_1.useFocusTrap)({
active: isTop,
focusinTrap: false,
});
var modalConsumerMultiRef = (0, useMultiRef_1.useMultiRef)([
windowInnerRef,
trapRef,
windowProps === null || windowProps === void 0 ? void 0 : windowProps.ref,
]);
(0, useClickOutside_1.useClickOutside)({
refs: tslib_1.__spreadArray(tslib_1.__spreadArray([
windowInnerRef
], tslib_1.__read(refsClickOutside), false), tslib_1.__read((ignoreClickOutsideRefs || [])), false),
handler: onClose,
active: open && !disableClickOutside,
});
// Блокирует прокрутку основного окна приложения
(0, useLockBodyScroll_1.useLockBodyScroll)(opened && !disableScrollLock);
(0, react_1.useEffect)(function () {
var _a;
// Сохраняем фокус активного элемента до момента открытия всплывающего окна
if (open) {
setOpened(true);
focusedElement.current =
document.activeElement;
(_a = focusedElement.current) === null || _a === void 0 ? void 0 : _a.blur();
}
setOpenState(open);
}, [open]);
var onExited = (0, react_1.useCallback)(function () {
var _a, _b;
if (environment_1.isServer) {
return;
}
// Возвращаем фокус активного элемента
if (((_a = windowInnerRef.current) === null || _a === void 0 ? void 0 : _a.contains(document.activeElement)) ||
document.activeElement === document.body) {
(_b = focusedElement.current) === null || _b === void 0 ? void 0 : _b.focus({ preventScroll: true });
}
setOpened(false);
onExitedProp === null || onExitedProp === void 0 ? void 0 : onExitedProp();
}, [onExitedProp]);
// Нажатие клавиши {ESC}
(0, useEventListener_1.useEventListener)({
eventName: 'keydown',
handler: function (event) {
if (!(0, isKey_1.isKey)(event, 'Escape'))
return;
onClose === null || onClose === void 0 ? void 0 : onClose();
},
active: isTop && !disableEscapeKeyDown,
});
if (!container) {
return null;
}
return (react_1.default.createElement(react_transition_group_1.CSSTransition, tslib_1.__assign({ classNames: (0, exports.cnModal)({ animation: true }), nodeRef: rootRef, timeout: 300 }, transitionProps, { in: openState, onEnter: onEnter, onEntered: onEntered, onExit: onExit, onExited: onExited, unmountOnExit: !keepMounted, appear: true }),
react_1.default.createElement(PortalBase_1.PortalBase, tslib_1.__assign({}, other, { container: container, className: (0, exports.cnModal)({ hidden: keepMounted && !openState, hasBackdrop: hasBackdrop }, [className]), ref: portalMultiRef }),
!hideBackdrop && (react_1.default.createElement(Backdrop_1.Backdrop, tslib_1.__assign({ zIndex: -1, open: openState }, backdropProps, { className: backdropProps === null || backdropProps === void 0 ? void 0 : backdropProps.className }))),
react_1.default.createElement(components_1.ModalConsumer, tslib_1.__assign({}, windowProps, { ref: modalConsumerMultiRef }), children))));
});
exports.Modal.displayName = 'Modal';