import clsx from "clsx" import React, { forwardRef, useCallback, useEffect, useRef } from "react" import { ButtonProps } from "../Button" import { useModal } from "../../providers/modal" import ModalHeader from "./Header" import ModalFooter from "./Footer" import useKeyboardShortcut from "../../hooks/use-keyboard-shortcut" export type ModalProps = { className?: string title?: string actions?: ButtonProps[] modalContainerClassName?: string contentClassName?: string onClose?: React.ReactEventHandler open?: boolean footerContent?: React.ReactNode } & Omit, "ref"> const Modal = forwardRef(function Modal( { className, title, actions, children, contentClassName, modalContainerClassName, onClose, open = true, footerContent, ...props }, passedRef ) { const { closeModal } = useModal() const ref = useRef(null) const setRefs = useCallback( (node: HTMLDialogElement) => { // Ref's from useRef needs to have the node assigned to `current` ref.current = node if (typeof passedRef === "function") { passedRef(node) } else if (passedRef && "current" in passedRef) { passedRef.current = node } }, [passedRef] ) useKeyboardShortcut({ metakey: false, checkEditing: false, shortcutKeys: ["escape"], action: () => { if (open) { ref.current?.close() } }, }) const handleClick = (e: React.MouseEvent) => { // close modal when the user clicks outside the content if (e.target === ref.current) { closeModal() onClose?.(e) } } const handleClose = (e: React.SyntheticEvent) => { onClose?.(e) closeModal() } useEffect(() => { if (open) { document.body.setAttribute("data-modal", "opened") } else { document.body.removeAttribute("data-modal") } }, [open]) return (
{title && }
{children}
{actions && actions?.length > 0 && } {footerContent && {footerContent}}
) }) export default Modal