react-simple-hook-modal
Version:
A simple React modal with hook based API
213 lines (196 loc) • 6.11 kB
JavaScript
import React, { useContext, useEffect, useState, useCallback } from 'react';
import ReactDOM from 'react-dom';
import { useTransition, animated } from 'react-spring';
var ModalContext = /*#__PURE__*/React.createContext({});
var useModalContext = function useModalContext() {
return useContext(ModalContext);
};
var ModalTransition;
(function (ModalTransition) {
ModalTransition["NONE"] = "NONE";
ModalTransition["SCALE"] = "SCALE";
ModalTransition["TOP_DOWN"] = "TOP_DOWN";
ModalTransition["BOTTOM_UP"] = "BOTTOM_UP";
})(ModalTransition || (ModalTransition = {}));
var ModalTransitionConfig = {
NONE: {
from: {
transform: 'scale(1)'
},
enter: {
transform: 'scale(1)'
},
leave: {
transform: 'scale(1)'
}
},
SCALE: {
from: {
transform: 'scale(0)',
opacity: 0
},
enter: {
transform: 'scale(1)',
opacity: 1
},
leave: {
transform: 'scale(0)',
opacity: 0
},
config: {
tension: 800,
friction: 25
}
},
TOP_DOWN: {
from: {
transform: 'translateY(-150%)'
},
enter: {
transform: 'translateY(0)'
},
leave: {
transform: 'translateY(-150%)'
},
config: {
tension: 500,
friction: 25
}
},
BOTTOM_UP: {
from: {
transform: 'translateY(150%)'
},
enter: {
transform: 'translateY(0)'
},
leave: {
transform: 'translateY(150%)'
},
config: {
tension: 500,
friction: 25
}
}
};
var useModalTransition = function useModalTransition(transition, isOpen) {
if (transition === void 0) {
transition = ModalTransition.SCALE;
}
return useTransition(isOpen, null, ModalTransitionConfig[transition]);
};
var ModalContainer = function ModalContainer(_ref) {
var children = _ref.children,
isOpen = _ref.isOpen,
footer = _ref.footer,
transition = _ref.transition,
onBackdropClick = _ref.onBackdropClick,
transformDistance = _ref.transformDistance,
modalClassName = _ref.modalClassName;
var modalTransitions = useModalTransition(transition, isOpen);
return React.createElement(React.Fragment, null, modalTransitions.map(function (_ref2) {
var item = _ref2.item,
key = _ref2.key,
props = _ref2.props;
return item && React.createElement(animated.div, {
key: key,
style: props,
className: "rsm-fixed rsm-inset-0 rsm-m-4 sm:rsm-m-8 rsm-flex rsm-justify-center rsm-items-center rsm-z-40",
onClick: onBackdropClick
}, React.createElement("div", {
className: "rsm-bg-white rsm-rounded-md rsm-overflow-auto rsm-max-h-full rsm-w-full md:rsm-w-10/12 xl:rsm-w-1/2 rsm-opactiy-100 rsm-shadow-lg rsm-z-50 rsm-border rsm-border-gray-200 rsm-flex rsm-flex-col " + (modalClassName !== null && modalClassName !== void 0 ? modalClassName : ''),
style: {
minHeight: '70%',
transition: transition === ModalTransition.NONE ? '' : 'transform ease-in-out .2s',
transform: "translate(" + transformDistance + "px, " + transformDistance + "px)",
transformOrigin: 'center'
},
onClick: function onClick(e) {
return e.stopPropagation();
}
}, React.createElement("div", {
className: "rsm-flex-1 rsm-p-8"
}, children), !footer ? null : React.createElement("div", {
className: "rsm-bg-gray-200 rsm-p-4"
}, footer)));
}));
};
function hasDOM() {
return !!(typeof window !== 'undefined' && window.document && window.document.createElement);
}
var Modal = function Modal(modal) {
var _useModalContext = useModalContext(),
addOrUpdate = _useModalContext.addOrUpdate,
remove = _useModalContext.remove,
getStaggerPixels = _useModalContext.getStaggerPixels;
var id = modal.id,
isOpen = modal.isOpen;
var container = hasDOM() ? document.getElementById('react-simple-modal-container') : null;
useEffect(function () {
isOpen ? addOrUpdate(id) : remove(id);
return function () {
return remove(id);
};
}, [id, isOpen]);
return container ? ReactDOM.createPortal(React.createElement(ModalContainer, Object.assign({
transformDistance: getStaggerPixels(id)
}, modal)), container) : null;
};
var ModalProvider = function ModalProvider(_ref) {
var children = _ref.children,
backdropClassName = _ref.backdropClassName;
var _useState = useState([]),
openModals = _useState[0],
setOpenModals = _useState[1];
var addOrUpdate = useCallback(function (_id) {
setOpenModals(function (prev) {
var exists = prev.some(function (id) {
return id === _id;
});
return exists ? prev : [].concat(prev, [_id]);
});
}, []);
var remove = useCallback(function (_id) {
setOpenModals(function (prev) {
return prev.filter(function (id) {
return id !== _id;
});
});
}, []);
var modalOpen = openModals.length > 0;
var getStaggerPixels = useCallback(function (_id) {
var index = openModals.findIndex(function (id) {
return id === _id;
});
return openModals.length * 8 - (index + 1) * 8;
}, [openModals]);
return React.createElement(ModalContext.Provider, {
value: {
addOrUpdate: addOrUpdate,
remove: remove,
getStaggerPixels: getStaggerPixels
}
}, children, !modalOpen ? null : React.createElement("div", {
className: 'rsm-fixed rsm-inset-0 rsm-opacity-50 rsm-z-40 rsm-bg-gray-700 ' + backdropClassName || ''
}), React.createElement("div", {
id: "react-simple-modal-container"
}));
};
var useModal = function useModal() {
var _useState = useState(false),
isModalOpen = _useState[0],
setIsModalOpen = _useState[1];
var openModal = useCallback(function () {
return setIsModalOpen(true);
}, []);
var closeModal = useCallback(function () {
return setIsModalOpen(false);
}, []);
return {
isModalOpen: isModalOpen,
openModal: openModal,
closeModal: closeModal
};
};
export { Modal, ModalProvider, ModalTransition, useModal };
//# sourceMappingURL=react-simple-hook-modal.esm.js.map