import cn from "classnames"; import React, { forwardRef, useEffect, useRef } from "react"; import PropTypes from "prop-types"; import { IModalProps } from "./modal.d"; const FOCUSABLE_ELEMENTS = [ 'a[href]:not([tabindex^="-"]):not([inert])', 'area[href]:not([tabindex^="-"]):not([inert])', "input:not([disabled]):not([inert])", "select:not([disabled]):not([inert])", "textarea:not([disabled]):not([inert])", "button:not([disabled]):not([inert])", 'iframe:not([tabindex^="-"]):not([inert])', 'audio:not([tabindex^="-"]):not([inert])', 'video:not([tabindex^="-"]):not([inert])', '[contenteditable]:not([tabindex^="-"]):not([inert])', '[tabindex]:not([tabindex^="-"]):not([inert])' ]; const Modal: React.FC = forwardRef((props, ref: React.Ref) => { const { children, className, isCentered, isCloseOnEscapeKey, isFocusOnFirstFocusableEl, isRelative, isScrollable, onClose, size, isRightPanel, rightPanelWidth, backdrop } = props; const dataTestId = props["data-testid"] || "honey-ui-modal"; const refRoot = useRef(null); useEffect(() => { const onKeyPressed = (event: KeyboardEvent) => isCloseOnEscapeKey && event.key === "Escape" && onClose(); if (isFocusOnFirstFocusableEl && refRoot && refRoot.current) { const modalBody = refRoot.current.querySelector(".modal-body"); const modalFooter = refRoot.current.querySelector(".modal-footer"); const modalHeader = refRoot.current.querySelector(".modal-footer"); const el = (modalBody && (modalBody.querySelectorAll(FOCUSABLE_ELEMENTS.join(","))[0] as HTMLElement)) || (modalFooter && (modalFooter.querySelectorAll(FOCUSABLE_ELEMENTS.join(","))[0] as HTMLElement)) || (modalHeader && (modalHeader.querySelectorAll(FOCUSABLE_ELEMENTS.join(","))[0] as HTMLElement)); if (el) { el.focus(); } } if (!isRelative) { document.body.classList.add("modal-open"); } document.addEventListener("keyup", onKeyPressed, false); return () => { if (!isRelative) { document.body.classList.remove("modal-open"); } document.removeEventListener("keyup", onKeyPressed, false); }; }, []); return ( <>
{children}
); }); Modal.displayName = "Modal"; Modal.propTypes = { backdrop: PropTypes.bool, className: PropTypes.string, isCentered: PropTypes.bool, isCloseOnEscapeKey: PropTypes.bool, isFocusOnFirstFocusableEl: PropTypes.bool, isRelative: PropTypes.bool, isScrollable: PropTypes.bool, onClose: PropTypes.func.isRequired, size: PropTypes.oneOf(["xl", "lg", "sm", "initial"]) }; Modal.defaultProps = { backdrop: true, isCloseOnEscapeKey: true, isFocusOnFirstFocusableEl: true }; export default Modal;