import React, { useContext, useState, useEffect } from 'react'; export function isMobile() { if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) { return true; } else { return false; } } export interface IModalContextProps { bodyHasScrollbar?: boolean; isMobile?: boolean; visible?: boolean; show?: boolean; disableEscapeKeyDown?: boolean; onHide?(): void; setVisible?(bool: boolean): void; showModal?(bodyHasScrollbar: boolean, isMobile: boolean): void; hideModal?(): void; } const bodyHasScrollbar = () => { const hasScrollbar = document.body.scrollHeight > window.innerHeight; return hasScrollbar; }; export const ModalContext = React.createContext>({}); export const ModalProvider: React.FC = (props) => { const initialState = { visible: props.show, onHide: props.onHide, setVisible(bool: boolean) { setState((prevState) => ({ ...prevState, visible: bool })); }, showModal() { if (bodyHasScrollbar() && !isMobile()) { setTimeout(() => { document.body.style.paddingRight = '17px'; document.body.style.overflow = 'hidden'; }, 0); } }, hideModal() { document.body.style.removeProperty('padding-right'); document.body.style.removeProperty('overflow'); props.onHide && props.onHide(); }, }; const [state, setState] = useState(initialState); const handleKeyDown = (e: KeyboardEvent) => { if (props.disableEscapeKeyDown) return; if (e.key === 'Escape') { props.onHide && props.onHide(); } }; useEffect(() => { if (props.show) { state.setVisible(true); } else { state.setVisible(false); } }, [props.show]); useEffect(() => { if (state.visible) { document.addEventListener('keydown', handleKeyDown); state.showModal(); } else { state.hideModal(); } }, [state.visible]); useEffect(() => { return () => document.removeEventListener('keydown', handleKeyDown); }); return {props.children}; }; export function useModalContext() { const context = useContext(ModalContext); return context; }