UNPKG

@veracity/vui

Version:

Veracity UI is a React component library crafted for use within Veracity applications and pages. Based on Styled Components and @xstyled.

103 lines (101 loc) 3.78 kB
import { callAll } from "../utils/function.js"; import { mergeRefs } from "../utils/react.js"; import { cs } from "../utils/styles.js"; import zIndices_default from "../theme/foundations/zIndices.js"; import vui from "../core/vui.js"; import { Portal } from "../portal/portal.js"; import { Box } from "../box/box.js"; import { ModalProvider } from "./context.js"; import { FocusLock } from "../focusLock/focusLock.js"; import { ModalBackdrop } from "./modalBackdrop.js"; import { ModalContent } from "./modalContent.js"; import { manager, useModalManager } from "./modalManager.js"; import { cloneElement, useRef } from "react"; import { jsx, jsxs } from "react/jsx-runtime"; //#region src/modal/modal.tsx /** * Displays provided content on top of a dark backdrop element with fixed position. * By default uses Portal for content and closes when clicking backdrop or pressing 'Escape'. * Uses focus and scroll lock to achieve proper accessibility. * More about accessibility: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/dialog_role */ const Modal = vui((props, ref) => { const { allowPinchZoom, animation = "fadeDown", children, className, contentProps, disableAutoFocus, disableBackdropClose, disableEscClose, disablePortal, disableReturnFocus, disableScrollLock, disableTrapFocus, finalFocusRef, hideBackdrop, initialFocusRef, isOpen, onBackdropClick: onBackdropClickProp, onClose, onEsc, preserveScrollBar, size, type = "modal", variant, zIndex: zIndexProp, ...rest } = props; const modalRef = useRef(null); const mouseDownTargetRef = useRef(null); useModalManager(modalRef, isOpen, disableScrollLock); if (!isOpen) return null; const onBackdropClick = (e) => { e.stopPropagation(); if (mouseDownTargetRef.current !== e.target) return; if (!manager.isTopModal(modalRef)) return; if (!disableBackdropClose) { onClose?.(); onBackdropClickProp?.(e); } }; const onKeyDown = (e) => { if (e.key === "Escape") { e.stopPropagation(); !disableEscClose && onClose?.(); onEsc?.(); } }; const onMouseDown = (e) => mouseDownTargetRef.current = e.target; const childProps = { onClick: (e) => { e.stopPropagation(); (children?.props)?.onClick?.(e); }, tabIndex: (children?.props)?.tabIndex ?? -1 }; const typeZIndices = { modal: zIndices_default.modal, dialog: zIndices_default.modal, drawer: zIndices_default.drawer }; let calculatedZIndex = zIndexProp ?? typeZIndices[type]; if (!zIndexProp && manager.modals.length > 0) calculatedZIndex = Math.max(zIndices_default.modal, zIndices_default.drawer) + manager.modals.length * 10; const backdropZIndex = calculatedZIndex - 1; return /* @__PURE__ */ jsx(ModalProvider, { value: { type, isOpen, onBackdropClick, onClose, size, variant, zIndex: calculatedZIndex, backdropZIndex }, children: /* @__PURE__ */ jsx(Portal, { disablePortal, children: /* @__PURE__ */ jsxs(Box, { className: cs("vui-modal", className), ref: mergeRefs(ref, modalRef), ...rest, onKeyDown: callAll(props.onKeyDown, onKeyDown), onMouseDown: callAll(props.onMouseDown, onMouseDown), children: [!hideBackdrop && /* @__PURE__ */ jsx(ModalBackdrop, {}), /* @__PURE__ */ jsx(FocusLock, { autoFocus: !disableAutoFocus, finalFocusRef, initialFocusRef, isDisabled: disableTrapFocus, returnFocus: !disableReturnFocus, children: /* @__PURE__ */ jsx(ModalContent, { animation, ...contentProps, children: cloneElement(children, childProps) }) })] }) }) }); }); Modal.Backdrop = ModalBackdrop; Modal.Content = ModalContent; Modal.displayName = "Modal"; //#endregion export { Modal, Modal as default }; globalThis.__vuiVersion__ = "5.3.1" //# sourceMappingURL=modal.js.map