UNPKG

@yamada-ui/modal

Version:

Yamada UI modal component

631 lines (615 loc) • 21.4 kB
"use client" "use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/modal.tsx var modal_exports = {}; __export(modal_exports, { Modal: () => Modal }); module.exports = __toCommonJS(modal_exports); var import_core6 = require("@yamada-ui/core"); var import_focus_lock = require("@yamada-ui/focus-lock"); var import_motion6 = require("@yamada-ui/motion"); var import_portal = require("@yamada-ui/portal"); var import_use_value2 = require("@yamada-ui/use-value"); var import_utils11 = require("@yamada-ui/utils"); var import_react2 = require("react"); var import_react_remove_scroll = require("react-remove-scroll"); // src/dialog-overlay.tsx var import_motion2 = require("@yamada-ui/motion"); var import_utils3 = require("@yamada-ui/utils"); // src/modal-context.ts var import_utils = require("@yamada-ui/utils"); var [ModalProvider, useModal] = (0, import_utils.createContext)({ name: `ModalContext`, errorMessage: `useModal returned is 'undefined'. Seems you forgot to wrap the components in "<Modal />" ` }); var [DialogProvider, useDialog] = (0, import_utils.createContext)({ name: `DialogContext`, errorMessage: `useDialog returned is 'undefined'. Seems you forgot to wrap the components in "<Dialog />" ` }); var [DrawerProvider, useDrawer] = (0, import_utils.createContext)({ name: `DrawerContext`, errorMessage: `useDrawer returned is 'undefined'. Seems you forgot to wrap the components in "<Drawer />" ` }); // src/modal-overlay.tsx var import_motion = require("@yamada-ui/motion"); var import_transitions = require("@yamada-ui/transitions"); var import_utils2 = require("@yamada-ui/utils"); var import_jsx_runtime = require("react/jsx-runtime"); var ModalOverlay = (0, import_motion.motionForwardRef)( ({ className, onClick, __css, ...rest }, ref) => { const { animation, closeOnOverlay, duration, styles, onClose, onOverlayClick } = useModal(); const css = { h: "100dvh", left: 0, position: "fixed", top: 0, w: "100vw", ...__css ? __css : styles.overlay }; const props = animation !== "none" ? import_transitions.fadeProps : {}; return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_motion.motion.div, { ref, className: (0, import_utils2.cx)("ui-modal__overlay", className), "aria-hidden": true, custom: { duration }, onClick: (0, import_utils2.handlerAll)(onClick, onOverlayClick, (ev) => { ev.stopPropagation(); if (closeOnOverlay) onClose == null ? void 0 : onClose(); }), __css: css, ...props, ...rest } ); } ); ModalOverlay.displayName = "ModalOverlay"; ModalOverlay.__ui__ = "ModalOverlay"; // src/dialog-overlay.tsx var import_jsx_runtime2 = require("react/jsx-runtime"); var DialogOverlay = (0, import_motion2.motionForwardRef)( ({ className, ...rest }, ref) => { const styles = useDialog(); const css = { ...styles.overlay }; return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( ModalOverlay, { ref, className: (0, import_utils3.cx)("ui-dialog__overlay", className), __css: css, ...rest } ); } ); DialogOverlay.displayName = "DialogOverlay"; DialogOverlay.__ui__ = "DialogOverlay"; // src/drawer-content.tsx var import_core4 = require("@yamada-ui/core"); var import_motion3 = require("@yamada-ui/motion"); var import_transitions2 = require("@yamada-ui/transitions"); var import_use_value = require("@yamada-ui/use-value"); var import_utils7 = require("@yamada-ui/utils"); var import_react = require("react"); // src/drawer-close-button.tsx var import_core2 = require("@yamada-ui/core"); var import_utils5 = require("@yamada-ui/utils"); // src/modal-close-button.tsx var import_close_button = require("@yamada-ui/close-button"); var import_core = require("@yamada-ui/core"); var import_utils4 = require("@yamada-ui/utils"); var import_jsx_runtime3 = require("react/jsx-runtime"); var ModalCloseButton = (0, import_core.forwardRef)( ({ onClick, __css, ...rest }, ref) => { const { styles, onClose } = useModal(); const css = { position: "absolute", ...__css ? __css : styles.closeButton }; return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)( import_close_button.CloseButton, { ref, className: (0, import_utils4.cx)("ui-modal__close-button"), "aria-label": "Close modal", onClick: (0, import_utils4.handlerAll)(onClick, (ev) => { ev.stopPropagation(); onClose == null ? void 0 : onClose(); }), __css: css, ...rest } ); } ); ModalCloseButton.displayName = "ModalCloseButton"; ModalCloseButton.__ui__ = "ModalCloseButton"; // src/drawer-close-button.tsx var import_jsx_runtime4 = require("react/jsx-runtime"); var DrawerCloseButton = (0, import_core2.forwardRef)( ({ className, ...rest }, ref) => { const styles = useDrawer(); const css = { ...styles.closeButton }; return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)( ModalCloseButton, { ref, className: (0, import_utils5.cx)("ui-drawer__close-button", className), __css: css, ...rest } ); } ); DrawerCloseButton.displayName = "DrawerCloseButton"; DrawerCloseButton.__ui__ = "DrawerCloseButton"; // src/drawer-drag-bar.tsx var import_core3 = require("@yamada-ui/core"); var import_utils6 = require("@yamada-ui/utils"); var import_jsx_runtime5 = require("react/jsx-runtime"); var DrawerDragBar = (0, import_core3.forwardRef)( ({ className, __css, ...rest }, ref) => { const styles = useDrawer(); const css = { ...styles.dragBar }; return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)( import_core3.ui.div, { ref, className: (0, import_utils6.cx)("ui-drawer__drag-bar", className), __css: css, ...rest } ); } ); DrawerDragBar.displayName = "DrawerDragBar"; DrawerDragBar.__ui__ = "DrawerDragBar"; // src/drawer-content.tsx var import_jsx_runtime6 = require("react/jsx-runtime"); var DrawerContent = (0, import_motion3.motionForwardRef)( ({ className, children, closeOnDrag, dragConstraints, dragElastic, dragOffset, dragVelocity, placement: _placement, withCloseButton, withDragBar, blankForDragProps, ...rest }, ref) => { var _a, _b; const { bodyRef, duration, headerRef, open, onClose } = useModal(); const styles = useDrawer(); const placement = (0, import_use_value.useValue)(_placement); const validChildren = (0, import_utils7.getValidChildren)(children); const [customDrawerCloseButton, ...cloneChildren] = (0, import_utils7.findChildren)( validChildren, DrawerCloseButton ); const blankForDragBg = (0, import_react.useMemo)(() => { var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j; const propBg = (_c = (_b2 = (_a2 = rest.backgroundColor) != null ? _a2 : rest.bgColor) != null ? _b2 : rest.background) != null ? _c : rest.bg; const styleBg = (_j = (_h = (_f = (_d = styles.container) == null ? void 0 : _d.backgroundColor) != null ? _f : (_e = styles.container) == null ? void 0 : _e.bgColor) != null ? _h : (_g = styles.container) == null ? void 0 : _g.background) != null ? _j : (_i = styles.container) == null ? void 0 : _i.bg; const computedBg = propBg != null ? propBg : styleBg; return (0, import_utils7.isArray)(computedBg) ? computedBg : [computedBg]; }, [rest, styles]); const blankForDrag = (0, import_react.useMemo)(() => { let position = {}; switch (placement) { case "top": position = { left: 0, right: 0, top: "calc(-100dvh + 1px)" }; break; case "bottom": position = { bottom: "calc(-100dvh + 1px)", left: 0, right: 0 }; break; case "left": position = { bottom: 0, left: "calc(-100% + 1px)", top: 0 }; break; case "right": position = { bottom: 0, right: "calc(-100% + 1px)", top: 0 }; break; } const [lightBg, darkBg] = blankForDragBg; return { _after: { bg: lightBg, content: '""', display: "block", h: "100dvh", position: "absolute", w: "100%", ...position, ...blankForDragProps }, _dark: { _after: { bg: darkBg } } }; }, [placement, blankForDragBg, blankForDragProps]); const css = (0, import_react.useMemo)( () => ({ display: "flex", flexDirection: placement === "top" || placement === "bottom" ? "column" : "row", outline: 0, ...closeOnDrag ? blankForDrag : {}, ...styles.container }), [blankForDrag, closeOnDrag, placement, styles] ); const getDragDirectionRestriction = (0, import_react.useCallback)( (value) => { switch (placement) { case "top": return { bottom: value }; case "bottom": return { top: value }; case "left": return { right: value }; case "right": return { left: value }; } }, [placement] ); const getDragDirection = (0, import_react.useCallback)(() => { switch (placement) { case "top": case "bottom": return "y"; case "left": case "right": return "x"; } }, [placement]); const isCloseByDragInfo = (0, import_react.useCallback)( (info) => { switch (placement) { case "top": return info.velocity.y <= dragVelocity * -1 || info.offset.y <= dragOffset * -1; case "bottom": return info.velocity.y >= dragVelocity || info.offset.y >= dragOffset; case "left": return info.velocity.x <= dragVelocity * -1 || info.offset.x <= dragOffset * -1; case "right": return info.velocity.x >= dragVelocity || info.offset.x >= dragOffset; } }, [placement, dragVelocity, dragOffset] ); return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)( import_transitions2.Slide, { ref, className: (0, import_utils7.cx)("ui-drawer", className), "aria-describedby": (_a = bodyRef.current) == null ? void 0 : _a.id, "aria-labelledby": (_b = headerRef.current) == null ? void 0 : _b.id, "aria-modal": "true", drag: closeOnDrag ? getDragDirection() : false, dragConstraints: getDragDirectionRestriction(dragConstraints), dragElastic: getDragDirectionRestriction(dragElastic), dragMomentum: false, dragSnapToOrigin: true, duration, isOpen: open, placement, role: "dialog", tabIndex: -1, onDragEnd: (_, info) => { if (isCloseByDragInfo(info)) onClose == null ? void 0 : onClose(); }, __css: css, ...rest, children: [ customDrawerCloseButton != null ? customDrawerCloseButton : withCloseButton && onClose ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DrawerCloseButton, {}) : null, withDragBar && closeOnDrag && (placement === "bottom" || placement === "right") ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DrawerDragBar, {}) : null, /* @__PURE__ */ (0, import_jsx_runtime6.jsx)( import_core4.ui.div, { className: "ui-drawer__inner", __css: { display: "flex", flexDirection: "column", w: "100%", ...styles.inner }, children: cloneChildren } ), withDragBar && closeOnDrag && (placement === "top" || placement === "left") ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DrawerDragBar, {}) : null ] } ); } ); DrawerContent.displayName = "DrawerContent"; DrawerContent.__ui__ = "DrawerContent"; // src/drawer-overlay.tsx var import_motion4 = require("@yamada-ui/motion"); var import_utils8 = require("@yamada-ui/utils"); var import_jsx_runtime7 = require("react/jsx-runtime"); var DrawerOverlay = (0, import_motion4.motionForwardRef)( ({ className, ...rest }, ref) => { const styles = useDrawer(); const css = { ...styles.overlay }; return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)( ModalOverlay, { ref, className: (0, import_utils8.cx)("ui-drawer__overlay", className), __css: css, ...rest } ); } ); DrawerOverlay.displayName = "DrawerOverlay"; DrawerOverlay.__ui__ = "DrawerOverlay"; // src/modal-content.tsx var import_motion5 = require("@yamada-ui/motion"); var import_transitions3 = require("@yamada-ui/transitions"); var import_utils10 = require("@yamada-ui/utils"); // src/dialog-close-button.tsx var import_core5 = require("@yamada-ui/core"); var import_utils9 = require("@yamada-ui/utils"); var import_jsx_runtime8 = require("react/jsx-runtime"); var DialogCloseButton = (0, import_core5.forwardRef)( ({ className, ...rest }, ref) => { const styles = useDialog(); const css = { ...styles.closeButton }; return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)( ModalCloseButton, { ref, className: (0, import_utils9.cx)("ui-dialog__close-button", className), "aria-label": "Close dialog", __css: css, ...rest } ); } ); DialogCloseButton.displayName = "DialogCloseButton"; DialogCloseButton.__ui__ = "DialogCloseButton"; // src/modal-content.tsx var import_jsx_runtime9 = require("react/jsx-runtime"); var getModalContentProps = (animation = "scale", duration) => { switch (animation) { case "scale": return { ...import_transitions3.scaleFadeProps, custom: { duration, reverse: true, scale: 0.95 } }; case "top": return { ...import_transitions3.slideFadeProps, custom: { duration, offsetY: -16, reverse: true } }; case "right": return { ...import_transitions3.slideFadeProps, custom: { duration, offsetX: 16, reverse: true } }; case "left": return { ...import_transitions3.slideFadeProps, custom: { duration, offsetX: -16, reverse: true } }; case "bottom": return { ...import_transitions3.slideFadeProps, custom: { duration, offsetY: 16, reverse: true } }; } }; var ModalContent = (0, import_motion5.motionForwardRef)( ({ className, children, __css, ...rest }, ref) => { var _a, _b; const { animation, bodyRef, duration, headerRef, scrollBehavior, styles, withCloseButton, onClose } = useModal(); const validChildren = (0, import_utils10.getValidChildren)(children); const [customModalCloseButton, ...cloneChildren] = (0, import_utils10.findChildren)( validChildren, ModalCloseButton, DialogCloseButton ); const props = animation !== "none" ? getModalContentProps(animation, duration) : {}; const css = { display: "flex", flexDirection: "column", maxH: "100%", outline: 0, overflow: scrollBehavior === "inside" ? "hidden" : "auto", position: "relative", ...__css ? __css : styles.container }; return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)( import_motion5.motion.section, { ref, className: (0, import_utils10.cx)("ui-modal", className), "aria-describedby": (_a = bodyRef.current) == null ? void 0 : _a.id, "aria-labelledby": (_b = headerRef.current) == null ? void 0 : _b.id, "aria-modal": "true", role: "dialog", tabIndex: -1, __css: css, ...props, ...rest, children: [ customModalCloseButton != null ? customModalCloseButton : withCloseButton && onClose ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ModalCloseButton, {}) : null, cloneChildren ] } ); } ); ModalContent.displayName = "ModalContent"; ModalContent.__ui__ = "ModalContent"; // src/modal.tsx var import_jsx_runtime10 = require("react/jsx-runtime"); var Modal = (0, import_motion6.motionForwardRef)( ({ size, ...props }, ref) => { const [styles, mergedProps] = (0, import_core6.useComponentMultiStyle)("Modal", { size, ...props }); const { className, allowPinchZoom = false, animation = "scale", autoFocus, blockScrollOnMount = true, children, closeOnEsc = true, closeOnOverlay = true, duration, finalFocusRef, initialFocusRef, isOpen, lockFocusAcrossFrames = true, open = isOpen, outside = "fallback(4, 1rem)", placement: _placement = "center", restoreFocus, scrollBehavior = "inside", withCloseButton = true, withOverlay = true, containerProps, portalProps, onClose, onCloseComplete, onEsc, onOverlayClick, ...rest } = (0, import_core6.omitThemeProps)(mergedProps); const headerRef = (0, import_react2.useRef)(null); const bodyRef = (0, import_react2.useRef)(null); const placement = (0, import_use_value2.useValue)(_placement); const validChildren = (0, import_utils11.getValidChildren)(children); const [customModalOverlay, ...cloneChildren] = (0, import_utils11.findChildren)( validChildren, ModalOverlay, DialogOverlay, DrawerOverlay ); const css = { alignItems: placement.includes("top") ? "flex-start" : placement.includes("bottom") ? "flex-end" : "center", display: "flex", h: "100dvh", justifyContent: placement.includes("left") ? "flex-start" : placement.includes("right") ? "flex-end" : "center", left: 0, p: size !== "full" ? outside : void 0, position: "fixed", top: 0, w: "100vw", zIndex: "fallback(jeice, 110)" }; const onKeyDown = (0, import_react2.useCallback)( (ev) => { if (ev.key !== "Escape") return; ev.stopPropagation(); if (closeOnEsc) onClose == null ? void 0 : onClose(); onEsc == null ? void 0 : onEsc(); }, [closeOnEsc, onClose, onEsc] ); let drawerContent = (0, import_utils11.findChild)(validChildren, DrawerContent); if (drawerContent) drawerContent = (0, import_react2.cloneElement)(drawerContent, { onKeyDown }); return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)( ModalProvider, { value: { animation, bodyRef, closeOnOverlay, duration, headerRef, open, scrollBehavior, styles, withCloseButton, onClose, onOverlayClick }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_motion6.AnimatePresence, { onExitComplete: onCloseComplete, children: open ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_portal.Portal, { ...portalProps, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)( import_focus_lock.FocusLock, { autoFocus, finalFocusRef, initialFocusRef, lockFocusAcrossFrames, restoreFocus, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)( import_react_remove_scroll.RemoveScroll, { allowPinchZoom, enabled: blockScrollOnMount, forwardProps: true, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_core6.ui.div, { __css: css, ...containerProps, children: [ customModalOverlay != null ? customModalOverlay : withOverlay && size !== "full" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ModalOverlay, {}) : null, drawerContent != null ? drawerContent : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)( ModalContent, { ref, className, onKeyDown, ...rest, children: cloneChildren } ) ] }) } ) } ) }) : null }) } ); } ); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Modal }); //# sourceMappingURL=modal.js.map