@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
JavaScript
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