@chakra-ui/core
Version:
Responsive and accessible React UI components built with React and Emotion
446 lines (381 loc) • 14.9 kB
JavaScript
"use strict";
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.ModalCloseButton = exports.ModalBody = exports.ModalFooter = exports.ModalHeader = exports.ModalContent = exports.ModalOverlay = exports.Modal = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _react = _interopRequireWildcard(require("react"));
var _bodyScrollLock = require("body-scroll-lock");
var _cjs = _interopRequireDefault(require("react-focus-lock/dist/cjs"));
var _utils = require("../utils");
var _Box = _interopRequireDefault(require("../Box"));
var _Portal = _interopRequireDefault(require("../Portal"));
var _CloseButton = _interopRequireDefault(require("../CloseButton"));
var _ariaHidden = require("aria-hidden");
var _autoId = require("@reach/auto-id");
var _ColorModeProvider = require("../ColorModeProvider");
var _exenv = _interopRequireDefault(require("exenv"));
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
////////////////////////////////////////////////////////////////////////
var canUseDOM = _exenv["default"].canUseDOM;
var ModalContext = (0, _react.createContext)({});
var useModalContext = function useModalContext() {
return (0, _react.useContext)(ModalContext);
}; ////////////////////////////////////////////////////////////////////////
function useAriaHider(_ref) {
var isOpen = _ref.isOpen,
id = _ref.id,
enableInert = _ref.enableInert,
_ref$container = _ref.container,
container = _ref$container === void 0 ? canUseDOM ? document.body : null : _ref$container;
var mountRef = (0, _react.useRef)(canUseDOM ? document.getElementById(id) || document.createElement("div") : null);
(0, _react.useEffect)(function () {
var undoAriaHidden = null;
var mountNode = mountRef.current;
if (isOpen && canUseDOM) {
mountRef.current.id = id;
container.appendChild(mountRef.current);
if (enableInert) {
undoAriaHidden = (0, _ariaHidden.hideOthers)(mountNode);
}
}
return function () {
if (enableInert && undoAriaHidden != null) {
undoAriaHidden();
}
if (mountNode.parentElement) {
mountNode.parentElement.removeChild(mountNode);
}
};
}, [isOpen, id, enableInert, container]);
return mountRef;
} ////////////////////////////////////////////////////////////////////////
var Modal = function Modal(_ref2) {
var isOpen = _ref2.isOpen,
initialFocusRef = _ref2.initialFocusRef,
finalFocusRef = _ref2.finalFocusRef,
onClose = _ref2.onClose,
_ref2$blockScrollOnMo = _ref2.blockScrollOnMount,
blockScrollOnMount = _ref2$blockScrollOnMo === void 0 ? true : _ref2$blockScrollOnMo,
_ref2$closeOnEsc = _ref2.closeOnEsc,
closeOnEsc = _ref2$closeOnEsc === void 0 ? true : _ref2$closeOnEsc,
_ref2$closeOnOverlayC = _ref2.closeOnOverlayClick,
closeOnOverlayClick = _ref2$closeOnOverlayC === void 0 ? true : _ref2$closeOnOverlayC,
_ref2$useInert = _ref2.useInert,
useInert = _ref2$useInert === void 0 ? true : _ref2$useInert,
_ref2$scrollBehavior = _ref2.scrollBehavior,
scrollBehavior = _ref2$scrollBehavior === void 0 ? "outside" : _ref2$scrollBehavior,
isCentered = _ref2.isCentered,
_ref2$addAriaLabels = _ref2.addAriaLabels,
addAriaLabels = _ref2$addAriaLabels === void 0 ? true : _ref2$addAriaLabels,
preserveScrollBarGap = _ref2.preserveScrollBarGap,
_ref2$formatIds = _ref2.formatIds,
formatIds = _ref2$formatIds === void 0 ? function (id) {
return {
content: "modal-" + id,
header: "modal-" + id + "-header",
body: "modal-" + id + "-body"
};
} : _ref2$formatIds,
container = _ref2.container,
_ref2$returnFocusOnCl = _ref2.returnFocusOnClose,
returnFocusOnClose = _ref2$returnFocusOnCl === void 0 ? true : _ref2$returnFocusOnCl,
children = _ref2.children,
id = _ref2.id,
_ref2$size = _ref2.size,
size = _ref2$size === void 0 ? "md" : _ref2$size;
var contentRef = (0, _react.useRef)(null);
var uuid = (0, _autoId.useId)();
var _id = id || uuid;
var contentId = formatIds(_id)["content"];
var headerId = formatIds(_id)["header"];
var bodyId = formatIds(_id)["body"];
var portalId = "chakra-portal-" + _id;
var addAriaLabelledby = false;
var addAriaDescribedby = false;
if (typeof addAriaLabels === "object") {
addAriaLabelledby = addAriaLabels["header"];
addAriaDescribedby = addAriaLabels["body"];
}
if (typeof addAriaLabels === "boolean") {
addAriaLabelledby = addAriaLabels;
addAriaDescribedby = addAriaLabels;
}
(0, _react.useEffect)(function () {
var dialogNode = contentRef.current;
if (isOpen && blockScrollOnMount) {
(0, _bodyScrollLock.disableBodyScroll)(dialogNode, {
reserveScrollBarGap: preserveScrollBarGap
});
}
return function () {
return (0, _bodyScrollLock.enableBodyScroll)(dialogNode);
};
}, [isOpen, blockScrollOnMount, preserveScrollBarGap]);
(0, _react.useEffect)(function () {
var func = function func(event) {
if (event.key === "Escape" && closeOnEsc) {
onClose(event, "pressedEscape");
}
};
if (isOpen && !closeOnOverlayClick) {
canUseDOM && document.addEventListener("keydown", func);
}
return function () {
canUseDOM && document.removeEventListener("keydown", func);
};
}, [isOpen, onClose, closeOnOverlayClick, closeOnEsc]);
var mountRef = useAriaHider({
isOpen: isOpen,
id: portalId,
enableInert: useInert,
container: container
});
var context = {
isOpen: isOpen,
initialFocusRef: initialFocusRef,
onClose: onClose,
blockScrollOnMount: blockScrollOnMount,
closeOnEsc: closeOnEsc,
closeOnOverlayClick: closeOnOverlayClick,
returnFocusOnClose: returnFocusOnClose,
contentRef: contentRef,
scrollBehavior: scrollBehavior,
isCentered: isCentered,
headerId: headerId,
bodyId: bodyId,
contentId: contentId,
size: size,
addAriaLabelledby: addAriaLabelledby,
addAriaDescribedby: addAriaDescribedby
};
var activateFocusLock = (0, _react.useCallback)(function () {
if (initialFocusRef && initialFocusRef.current) {
initialFocusRef.current.focus();
} else {
if (contentRef.current) {
var focusables = (0, _utils.getFocusables)(contentRef.current);
if (focusables.length === 0) {
contentRef.current.focus();
}
}
}
}, [initialFocusRef]);
var deactivateFocusLock = (0, _react.useCallback)(function () {
if (finalFocusRef && finalFocusRef.current) {
finalFocusRef.current.focus();
}
}, [finalFocusRef]);
if (!isOpen) return null;
return _react["default"].createElement(ModalContext.Provider, {
value: context
}, _react["default"].createElement(_Portal["default"], {
container: mountRef.current
}, _react["default"].createElement(_cjs["default"], {
returnFocus: returnFocusOnClose && !finalFocusRef,
onActivation: activateFocusLock,
onDeactivation: deactivateFocusLock
}, children)));
}; ////////////////////////////////////////////////////////////////////////
exports.Modal = Modal;
var ModalOverlay = _react["default"].forwardRef(function (props, ref) {
return _react["default"].createElement(_Box["default"], (0, _extends2["default"])({
pos: "fixed",
bg: "rgba(0,0,0,0.4)",
left: "0",
top: "0",
w: "100vw",
h: "100vh",
ref: ref,
zIndex: "overlay",
onClick: (0, _utils.wrapEvent)(props.onClick, function (event) {
event.stopPropagation();
})
}, props));
});
exports.ModalOverlay = ModalOverlay;
ModalOverlay.displayName = "ModalOverlay"; ////////////////////////////////////////////////////////////////////////
var ModalContent = _react["default"].forwardRef(function (_ref3, ref) {
var onClick = _ref3.onClick,
children = _ref3.children,
_ref3$zIndex = _ref3.zIndex,
zIndex = _ref3$zIndex === void 0 ? "modal" : _ref3$zIndex,
noStyles = _ref3.noStyles,
props = (0, _objectWithoutPropertiesLoose2["default"])(_ref3, ["onClick", "children", "zIndex", "noStyles"]);
var _useModalContext = useModalContext(),
contentRef = _useModalContext.contentRef,
onClose = _useModalContext.onClose,
isCentered = _useModalContext.isCentered,
bodyId = _useModalContext.bodyId,
headerId = _useModalContext.headerId,
contentId = _useModalContext.contentId,
size = _useModalContext.size,
closeOnEsc = _useModalContext.closeOnEsc,
addAriaLabelledby = _useModalContext.addAriaLabelledby,
addAriaDescribedby = _useModalContext.addAriaDescribedby,
scrollBehavior = _useModalContext.scrollBehavior,
closeOnOverlayClick = _useModalContext.closeOnOverlayClick;
var _contentRef = (0, _utils.useForkRef)(ref, contentRef);
var _useColorMode = (0, _ColorModeProvider.useColorMode)(),
colorMode = _useColorMode.colorMode;
var colorModeStyles = {
light: {
bg: "white",
shadow: "0 7px 14px 0 rgba(0,0,0, 0.1), 0 3px 6px 0 rgba(0, 0, 0, .07)"
},
dark: {
bg: "gray.700",
shadow: "rgba(0, 0, 0, 0.1) 0px 0px 0px 1px, rgba(0, 0, 0, 0.2) 0px 5px 10px, rgba(0, 0, 0, 0.4) 0px 15px 40px"
}
};
var boxStyleProps = colorModeStyles[colorMode];
var wrapperStyle = {};
var contentStyle = {};
if (isCentered) {
wrapperStyle = {
display: "flex",
alignItems: "center",
justifyContent: "center"
};
} else {
contentStyle = {
top: "3.75rem",
mx: "auto"
};
}
if (scrollBehavior === "inside") {
wrapperStyle = _objectSpread({}, wrapperStyle, {
maxHeight: "calc(100vh - 7.5rem)",
overflow: "hidden",
top: "3.75rem"
});
contentStyle = _objectSpread({}, contentStyle, {
height: "100%",
top: 0
});
}
if (scrollBehavior === "outside") {
wrapperStyle = _objectSpread({}, wrapperStyle, {
overflowY: "auto",
overflowX: "hidden"
});
contentStyle = _objectSpread({}, contentStyle, {
my: "3.75rem",
top: 0
});
}
if (noStyles) {
wrapperStyle = {};
contentStyle = {};
}
return _react["default"].createElement(_Box["default"], (0, _extends2["default"])({
pos: "fixed",
left: "0",
top: "0",
w: "100%",
h: "100%",
zIndex: zIndex,
onClick: function onClick(event) {
event.stopPropagation();
if (closeOnOverlayClick) {
onClose(event, "clickedOverlay");
}
},
onKeyDown: function onKeyDown(event) {
if (event.key === "Escape") {
event.stopPropagation();
if (closeOnEsc) {
onClose(event, "pressedEscape");
}
}
}
}, wrapperStyle), _react["default"].createElement(_Box["default"], (0, _extends2["default"])({
ref: _contentRef,
as: "section",
role: "dialog",
"aria-modal": "true",
tabIndex: -1,
outline: 0,
maxWidth: size,
w: "100%",
id: contentId
}, addAriaDescribedby && {
"aria-describedby": bodyId
}, addAriaLabelledby && {
"aria-labelledby": headerId
}, {
pos: "relative",
d: "flex",
flexDir: "column",
zIndex: zIndex,
onClick: (0, _utils.wrapEvent)(onClick, function (event) {
return event.stopPropagation();
})
}, boxStyleProps, contentStyle, props), children));
});
exports.ModalContent = ModalContent;
ModalContent.displayName = "ModalContent"; ////////////////////////////////////////////////////////////////////////
var ModalHeader = (0, _react.forwardRef)(function (props, ref) {
var _useModalContext2 = useModalContext(),
headerId = _useModalContext2.headerId;
return _react["default"].createElement(_Box["default"], (0, _extends2["default"])({
ref: ref,
px: 6,
py: 4,
id: headerId,
as: "header",
position: "relative",
fontSize: "xl",
fontWeight: "semibold"
}, props));
});
exports.ModalHeader = ModalHeader;
ModalHeader.displayName = "ModalHeader"; ////////////////////////////////////////////////////////////////////////
var ModalFooter = (0, _react.forwardRef)(function (props, ref) {
return _react["default"].createElement(_Box["default"], (0, _extends2["default"])({
display: "flex",
justifyContent: "flex-end",
ref: ref,
px: 6,
py: 4,
as: "footer"
}, props));
});
exports.ModalFooter = ModalFooter;
ModalFooter.displayName = "ModalFooter"; ////////////////////////////////////////////////////////////////////////
var ModalBody = (0, _react.forwardRef)(function (props, ref) {
var _useModalContext3 = useModalContext(),
bodyId = _useModalContext3.bodyId,
scrollBehavior = _useModalContext3.scrollBehavior;
var style = {};
if (scrollBehavior === "inside") {
style = {
overflowY: "auto"
};
}
return _react["default"].createElement(_Box["default"], (0, _extends2["default"])({
ref: ref,
id: bodyId,
px: 6,
py: 2,
flex: "1"
}, style, props));
});
exports.ModalBody = ModalBody;
ModalBody.displayName = "ModalBody"; ////////////////////////////////////////////////////////////////////////
var ModalCloseButton = (0, _react.forwardRef)(function (props, ref) {
var _useModalContext4 = useModalContext(),
onClose = _useModalContext4.onClose;
return _react["default"].createElement(_CloseButton["default"], (0, _extends2["default"])({
ref: ref,
onClick: onClose,
position: "absolute",
top: "8px",
right: "12px"
}, props));
});
exports.ModalCloseButton = ModalCloseButton;
ModalCloseButton.displayName = "ModalCloseButton"; ////////////////////////////////////////////////////////////////////////