@geezee/react-ui
Version:
Modern and minimalist React UI library.
113 lines (98 loc) • 3.37 kB
JavaScript
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import React, { useState, useEffect, useMemo, forwardRef, useImperativeHandle } from 'react';
import { createPortal } from 'react-dom';
import usePortal from '../utils/use-portal';
import ModalWrapper from './modal-wrapper';
import ModalAction from './modal-action';
import ModalActions from './modal-actions';
import Backdrop from '../shared/backdrop';
import { ModalContext } from './modal-context';
import { pickChild } from '../utils/collections';
import useBodyScroll from '../utils/use-body-scroll';
import ModalIcon from './modal-icon';
import useTheme from '../styles/use-theme';
var defaultProps = {
width: '30rem',
wrapClassName: '',
disableBackdropClick: false,
closable: false
};
var Modal = forwardRef(function (_ref, ref) {
var children = _ref.children,
disableBackdropClick = _ref.disableBackdropClick,
onClose = _ref.onClose,
onOpen = _ref.onOpen,
open = _ref.open,
wrapperWidth = _ref.width,
wrapClassName = _ref.wrapClassName,
closable = _ref.closable;
var portal = usePortal('modal');
var _useState = useState(false),
_useState2 = _slicedToArray(_useState, 2),
visible = _useState2[0],
_setVisible = _useState2[1];
var _useBodyScroll = useBodyScroll(),
_useBodyScroll2 = _slicedToArray(_useBodyScroll, 2),
setBodyHidden = _useBodyScroll2[1];
var _pickChild = pickChild(children, ModalAction),
_pickChild2 = _slicedToArray(_pickChild, 2),
withoutActionsChildren = _pickChild2[0],
ActionsChildren = _pickChild2[1];
var hasActions = ActionsChildren && React.Children.count(ActionsChildren) > 0;
var theme = useTheme();
var closeModal = function closeModal() {
onClose && onClose();
if (open === undefined) {
_setVisible(false);
setBodyHidden(false);
}
};
useImperativeHandle(ref, function () {
return {
setVisible: function setVisible() {
var visible = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
_setVisible(visible);
},
getVisible: function getVisible() {
return visible;
}
};
});
useEffect(function () {
if (open === undefined) return;
if (open) {
onOpen && onOpen();
}
if (!open) {
onClose && onClose();
}
_setVisible(open);
setBodyHidden(open);
}, [open]);
var closeFromBackdrop = function closeFromBackdrop() {
if (disableBackdropClick && hasActions) return;
closeModal();
};
var modalConfig = useMemo(function () {
return {
close: closeModal
};
}, []);
if (!portal) return null;
return createPortal( /*#__PURE__*/React.createElement(ModalContext.Provider, {
value: modalConfig
}, /*#__PURE__*/React.createElement(Backdrop, {
onClick: closeFromBackdrop,
visible: visible
}, /*#__PURE__*/React.createElement(ModalWrapper, {
visible: visible,
className: "modal ".concat(wrapClassName),
width: wrapperWidth
}, closable && /*#__PURE__*/React.createElement(ModalIcon, {
size: 16,
color: theme.palette.cNeutral5,
onClick: closeModal
}), withoutActionsChildren, hasActions && /*#__PURE__*/React.createElement(ModalActions, null, ActionsChildren)))), portal);
});
Modal.defaultProps = defaultProps;
export default Modal;