UNPKG

irisrad-ui

Version:

UI elements developered for IRIS R&D Group Inc

181 lines (168 loc) 5.56 kB
import React, { useState, useEffect, useRef, useCallback } from "react"; import "../../style/styles.css"; import PropTypes from "prop-types"; import { IrisButton } from "../irisButton/IrisButton"; // element ids const MODAL_WRAPPER_ID = "iris-modal-wrapper"; const MODAL_CONTENT_ID = "iris-modal-content"; const MODAL_CONTENT_TITLE = "iris-modal-content-title"; const MODAL_CONTENT_BODY = "iris-modal-content-body"; const MODAL_CONTENT_ACTION_BTNS = "iris-modal-content-action-btns-container"; // wrapper css classes const WRAPPER_BASE_CLASS = MODAL_WRAPPER_ID; const WRAPPER_FADE_IN_CLASS = WRAPPER_BASE_CLASS + "__fade-in"; const WRAPPER_FADE_OUT_CLASS = WRAPPER_BASE_CLASS + "__fade-out"; const WRAPPER_DISMISS_CLASS = WRAPPER_FADE_OUT_CLASS + "__dismiss"; const WRAPPER_DISPLAY_CLASS = WRAPPER_FADE_IN_CLASS + "__display"; // content css classes const CONTENT_BASE_CLASS = "iris-modal-content-wrapper"; const CONTENT_SLIDDOWN_CLASS = `${CONTENT_BASE_CLASS}--slide-down`; const CONTENT_SLIDUP_CLASS = `${CONTENT_BASE_CLASS}--slide-up`; const ANIMATION_TIME_IN_MILI = 200; const fadeIn = (wrapper, content, timeoutFunctionRef, isFadeIn) => { const modalWrapper = wrapper; const modalContent = content; let timeoutFunction = timeoutFunctionRef?.current; if (timeoutFunction) { clearTimeout(timeoutFunction); timeoutFunction = null; } if (modalWrapper) { const { classList: modalClassList } = modalWrapper; const { classList: contentClassList } = modalContent; if (modalClassList) { modalClassList.remove(WRAPPER_DISPLAY_CLASS); modalClassList.remove(WRAPPER_DISMISS_CLASS); modalClassList.remove(WRAPPER_FADE_IN_CLASS); modalClassList.remove(WRAPPER_FADE_OUT_CLASS); contentClassList.remove(CONTENT_SLIDUP_CLASS); contentClassList.remove(CONTENT_SLIDDOWN_CLASS); if (isFadeIn) { modalClassList.add(WRAPPER_DISPLAY_CLASS); timeoutFunction = setTimeout(() => { modalClassList.add(WRAPPER_FADE_IN_CLASS); contentClassList.add(CONTENT_SLIDDOWN_CLASS); }, 50); } else { modalClassList.add(WRAPPER_FADE_OUT_CLASS); timeoutFunction = setTimeout(() => { modalClassList.add(WRAPPER_DISMISS_CLASS); contentClassList.add(CONTENT_SLIDUP_CLASS); }, ANIMATION_TIME_IN_MILI); } } } }; export const IrisModal = ({ open, onClose, children, className = "", closeOnBackdrlpClicked, ...props }) => { const [show, setShow] = useState(false); const modalWrapperRef = useRef(); const modalContentRef = useRef(); const timeoutFunctionRef = useRef(null); const delayTimeoutFunctionRef = useRef(null); const clearTimeoutFunctions = useCallback(() => { if (timeoutFunctionRef?.current) { clearTimeout(timeoutFunctionRef.current); } if (delayTimeoutFunctionRef?.current) { clearTimeout(delayTimeoutFunctionRef.current); } }, [timeoutFunctionRef, delayTimeoutFunctionRef]); useEffect(() => { console.log(`showing`, show); clearTimeoutFunctions(); if (show) { fadeIn( modalWrapperRef?.current, modalContentRef?.current, timeoutFunctionRef?.current, show ); } }, [ clearTimeoutFunctions, timeoutFunctionRef, modalWrapperRef, modalContentRef, show, ]); useEffect(() => { console.log(`toggleing`, open); clearTimeoutFunctions(); if (show) { fadeIn( modalWrapperRef?.current, modalContentRef?.current, timeoutFunctionRef?.current, false ); delayTimeoutFunctionRef.current = setTimeout(() => { setShow(open); }, ANIMATION_TIME_IN_MILI); } else { setShow(open); } }, [clearTimeoutFunctions, timeoutFunctionRef, open]); let wrapperClass = WRAPPER_BASE_CLASS; if (typeof className === "string" && className !== "") { wrapperClass += " " + className; } let contentBaseClass = CONTENT_BASE_CLASS; if (!children) { contentBaseClass += " default-width"; } if (!show) return null; return ( <div ref={modalWrapperRef} className={wrapperClass} onClick={(e) => { if (closeOnBackdrlpClicked && onClose) { onClose(); } }} {...props} > <div ref={modalContentRef} className={contentBaseClass} onClick={(e) => { e.stopPropagation(); }} > {children ? ( children ) : ( <div className={`${CONTENT_BASE_CLASS}__container`}> <h2 className={`${CONTENT_BASE_CLASS}__container__title`}> default layout for title </h2> <h2 className={`${CONTENT_BASE_CLASS}__container__content`}> default layout for content </h2> <div className={`${CONTENT_BASE_CLASS}__container__action-btns`}> <IrisButton color="secondary" onClick={onClose}> Cancel </IrisButton> <IrisButton color="primary" onClick={onClose}> okay </IrisButton> </div> </div> )} </div> </div> ); }; IrisModal.propTypes = { className: PropTypes.string, open: PropTypes.bool.isRequired, onClose: PropTypes.func, closeOnBackdrlpClicked: PropTypes.bool, };