UNPKG

@hhgtech/hhg-components

Version:
250 lines (239 loc) • 7.19 kB
import React__default, { useState, useRef, useEffect } from 'react'; import { u as useScrollbarSize } from './useScrollbarSize-fb07c817.js'; import { createPortal } from 'react-dom'; import styled from '@emotion/styled'; import { M as MediaQueries } from './utils-cb7242c7.js'; import { setDefaultClass } from './miscDefaultClassWrapper.js'; import { theme } from './miscTheme.js'; const StyledModal = setDefaultClass(styled.div ` position: relative; z-index: 200; background-color: ${theme.colors.white}; border-radius: ${theme.borderRadius}; box-shadow: 0px 8px 40px 0px #0000001a; &[data-site-type='marryBaby'] { border-radius: 16px; .hhg-modal__content { position: relative; z-index: 111; height: 100%; padding: 24px; } } .hhg-modal__content { position: relative; z-index: 111; height: 100%; padding: 16px; } .hhg-modal__video { position: relative; z-index: 111; height: 100%; background-color: none; box-shadow: none; } `, 'hhgcomp-modal-modal'); const StyledModalWrapper = styled.div ` position: fixed; top: 0; left: 0; z-index: 201; display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; overflow-x: hidden; overflow-y: auto; outline: 0; visibility: hidden; opacity: 0; background-color: rgba(0, 0, 0, 0.6); transition: opacity 0.3s ease-in-out; .hhg-modal__close { position: absolute; top: 16px; right: 16px; cursor: pointer; img { width: 100%; height: 100%; border-radius: 50%; } } &[data-type='video'] { z-index: 1001; } &[data-open='true'] { opacity: 1; visibility: visible; } ${StyledModal.classSelector} { transition: transform 0.3s ease-in-out; } &.slideTop { ${StyledModal.classSelector} { transform: translate(0, -100vh); } &[data-open='true'] { ${StyledModal.classSelector} { transform: translate(0); } } } &.scaleUp { ${StyledModal.classSelector} { transform: scale(0.9); } &[data-open='true'] { ${StyledModal.classSelector} { transform: scale(1); } } } &[data-type='tail'] { justify-content: flex-end; ${StyledModal.classSelector} { width: 420px; height: 100%; border-radius: 0; overflow: hidden auto; } } &[data-type='form'] { ${StyledModal.classSelector} { width: 496px; height: 548px; max-height: 100%; overflow-y: auto; ${MediaQueries.mbDown} { width: 340px; } } } &[data-type='video'] { ${StyledModal.classSelector} { height: 100%; max-height: 539px; ${MediaQueries.mbDown} { height: 192px; width: 100%; height: 100%; border-radius: ${theme.borderRadius}; max-height: 192px; } } } &[data-type='confirm'] { ${StyledModal.classSelector} { width: 100%; max-width: 407px; ${MediaQueries.mbDown} { width: calc(100% - 32px); max-width: calc(100% - 32px); } } } `; const StyledModalMask = styled.div ` position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; align-items: center; &[data-open='false'] { display: none; } &[data-type='video'] { background-color: ${theme.colors.secondaryDark}; } `; const MODAL_ROOT_ID = 'hhg-modals'; const getModalsRoot = () => { let el = document.getElementById(MODAL_ROOT_ID); if (!el) { el = document.createElement('div'); el.setAttribute('id', MODAL_ROOT_ID); document.body.append(el); } return el; }; const cleanUpModalShow = () => { const selector = '.hhg-modal[data-open="true"]'; const remainingPopupOpened = document.querySelectorAll(selector); // Remove the opening class if there are only 1 popup is shown if (remainingPopupOpened.length < 1) { document.body.classList.remove('hhc-modal-show'); } }; const cleanUpDisabledScroll = () => { // Clear the overflow if there are only 1 popup is shown. useEffect runs after so the count number becomes zero const selector = '.hhg-modal[data-open="true"]'; const remainingPopupOpened = document.querySelectorAll(selector); if (remainingPopupOpened.length < 1) { document.body.style.overflow = ''; document.body.style.paddingRight = ''; document.body.classList.remove('hhc-disabled-scroll'); } }; /** * @deprecated Consider to use at '@hhgtech/hhg-components/mantine' */ const Modal = ({ type = 'lead', closeIcon, isOpen = true, onClose, children, className = '', animationType = 'scaleUp', isStaticBackdrop = false, siteType, }) => { const [mounted, setMounted] = useState(false); const elRef = useRef(null); const { width: scrollBarWidth } = useScrollbarSize(); if (!elRef.current && mounted) { elRef.current = document.createElement('div'); } useEffect(() => { setMounted(true); return () => { setMounted(false); cleanUpModalShow(); cleanUpDisabledScroll(); }; }, []); useEffect(() => { if (mounted) { const modalsRoot = getModalsRoot(); modalsRoot.appendChild(elRef.current); return () => { modalsRoot.removeChild(elRef.current); }; } }, [mounted]); useEffect(() => { if (isOpen) { document.body.classList.add('hhc-modal-show'); } else { cleanUpModalShow(); } }, [isOpen]); useEffect(() => { if (isOpen) { document.body.style.overflow = 'hidden'; document.body.style.paddingRight = scrollBarWidth + 'px'; document.body.classList.add('hhc-disabled-scroll'); } else { cleanUpDisabledScroll(); } }, [isOpen, scrollBarWidth]); if (!mounted) return null; const classes = ['hhg-modal__wrapper', className, animationType] .filter((s) => s) .join(' '); return createPortal(React__default.createElement(StyledModalWrapper, { className: classes, "data-open": isOpen, "data-type": type }, !isStaticBackdrop && (React__default.createElement(StyledModalMask, { "data-open": isOpen, onClick: onClose, "data-type": type })), !isStaticBackdrop && type === 'video' && !!closeIcon && (React__default.createElement("div", { className: "hhg-modal__close", onClick: onClose }, closeIcon)), React__default.createElement(StyledModal, { className: "hhg-modal", "data-open": isOpen, "data-site-type": siteType }, React__default.createElement("div", { className: type === 'video' ? 'hhg-modal__video' : 'hhg-modal__content' }, !!closeIcon && type !== 'video' && (React__default.createElement("div", { className: "hhg-modal__close", onClick: onClose }, closeIcon)), children))), elRef.current); }; export { Modal as M };