UNPKG

14.9 kBJavaScriptView Raw
1"use strict";
2
3var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
4
5var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
6
7exports.__esModule = true;
8exports.ModalCloseButton = exports.ModalBody = exports.ModalFooter = exports.ModalHeader = exports.ModalContent = exports.ModalOverlay = exports.Modal = void 0;
9
10var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
12var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
13
14var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
15
16var _react = _interopRequireWildcard(require("react"));
17
18var _bodyScrollLock = require("body-scroll-lock");
19
20var _cjs = _interopRequireDefault(require("react-focus-lock/dist/cjs"));
21
22var _utils = require("../utils");
23
24var _Box = _interopRequireDefault(require("../Box"));
25
26var _Portal = _interopRequireDefault(require("../Portal"));
27
28var _CloseButton = _interopRequireDefault(require("../CloseButton"));
29
30var _ariaHidden = require("aria-hidden");
31
32var _autoId = require("@reach/auto-id");
33
34var _ColorModeProvider = require("../ColorModeProvider");
35
36var _exenv = _interopRequireDefault(require("exenv"));
37
38function 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; }
39
40function _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; }
41
42////////////////////////////////////////////////////////////////////////
43var canUseDOM = _exenv["default"].canUseDOM;
44var ModalContext = (0, _react.createContext)({});
45
46var useModalContext = function useModalContext() {
47 return (0, _react.useContext)(ModalContext);
48}; ////////////////////////////////////////////////////////////////////////
49
50
51function useAriaHider(_ref) {
52 var isOpen = _ref.isOpen,
53 id = _ref.id,
54 enableInert = _ref.enableInert,
55 _ref$container = _ref.container,
56 container = _ref$container === void 0 ? canUseDOM ? document.body : null : _ref$container;
57 var mountRef = (0, _react.useRef)(canUseDOM ? document.getElementById(id) || document.createElement("div") : null);
58 (0, _react.useEffect)(function () {
59 var undoAriaHidden = null;
60 var mountNode = mountRef.current;
61
62 if (isOpen && canUseDOM) {
63 mountRef.current.id = id;
64 container.appendChild(mountRef.current);
65
66 if (enableInert) {
67 undoAriaHidden = (0, _ariaHidden.hideOthers)(mountNode);
68 }
69 }
70
71 return function () {
72 if (enableInert && undoAriaHidden != null) {
73 undoAriaHidden();
74 }
75
76 if (mountNode.parentElement) {
77 mountNode.parentElement.removeChild(mountNode);
78 }
79 };
80 }, [isOpen, id, enableInert, container]);
81 return mountRef;
82} ////////////////////////////////////////////////////////////////////////
83
84
85var Modal = function Modal(_ref2) {
86 var isOpen = _ref2.isOpen,
87 initialFocusRef = _ref2.initialFocusRef,
88 finalFocusRef = _ref2.finalFocusRef,
89 onClose = _ref2.onClose,
90 _ref2$blockScrollOnMo = _ref2.blockScrollOnMount,
91 blockScrollOnMount = _ref2$blockScrollOnMo === void 0 ? true : _ref2$blockScrollOnMo,
92 _ref2$closeOnEsc = _ref2.closeOnEsc,
93 closeOnEsc = _ref2$closeOnEsc === void 0 ? true : _ref2$closeOnEsc,
94 _ref2$closeOnOverlayC = _ref2.closeOnOverlayClick,
95 closeOnOverlayClick = _ref2$closeOnOverlayC === void 0 ? true : _ref2$closeOnOverlayC,
96 _ref2$useInert = _ref2.useInert,
97 useInert = _ref2$useInert === void 0 ? true : _ref2$useInert,
98 _ref2$scrollBehavior = _ref2.scrollBehavior,
99 scrollBehavior = _ref2$scrollBehavior === void 0 ? "outside" : _ref2$scrollBehavior,
100 isCentered = _ref2.isCentered,
101 _ref2$addAriaLabels = _ref2.addAriaLabels,
102 addAriaLabels = _ref2$addAriaLabels === void 0 ? true : _ref2$addAriaLabels,
103 preserveScrollBarGap = _ref2.preserveScrollBarGap,
104 _ref2$formatIds = _ref2.formatIds,
105 formatIds = _ref2$formatIds === void 0 ? function (id) {
106 return {
107 content: "modal-" + id,
108 header: "modal-" + id + "-header",
109 body: "modal-" + id + "-body"
110 };
111 } : _ref2$formatIds,
112 container = _ref2.container,
113 _ref2$returnFocusOnCl = _ref2.returnFocusOnClose,
114 returnFocusOnClose = _ref2$returnFocusOnCl === void 0 ? true : _ref2$returnFocusOnCl,
115 children = _ref2.children,
116 id = _ref2.id,
117 _ref2$size = _ref2.size,
118 size = _ref2$size === void 0 ? "md" : _ref2$size;
119 var contentRef = (0, _react.useRef)(null);
120 var uuid = (0, _autoId.useId)();
121
122 var _id = id || uuid;
123
124 var contentId = formatIds(_id)["content"];
125 var headerId = formatIds(_id)["header"];
126 var bodyId = formatIds(_id)["body"];
127 var portalId = "chakra-portal-" + _id;
128 var addAriaLabelledby = false;
129 var addAriaDescribedby = false;
130
131 if (typeof addAriaLabels === "object") {
132 addAriaLabelledby = addAriaLabels["header"];
133 addAriaDescribedby = addAriaLabels["body"];
134 }
135
136 if (typeof addAriaLabels === "boolean") {
137 addAriaLabelledby = addAriaLabels;
138 addAriaDescribedby = addAriaLabels;
139 }
140
141 (0, _react.useEffect)(function () {
142 var dialogNode = contentRef.current;
143
144 if (isOpen && blockScrollOnMount) {
145 (0, _bodyScrollLock.disableBodyScroll)(dialogNode, {
146 reserveScrollBarGap: preserveScrollBarGap
147 });
148 }
149
150 return function () {
151 return (0, _bodyScrollLock.enableBodyScroll)(dialogNode);
152 };
153 }, [isOpen, blockScrollOnMount, preserveScrollBarGap]);
154 (0, _react.useEffect)(function () {
155 var func = function func(event) {
156 if (event.key === "Escape" && closeOnEsc) {
157 onClose(event, "pressedEscape");
158 }
159 };
160
161 if (isOpen && !closeOnOverlayClick) {
162 canUseDOM && document.addEventListener("keydown", func);
163 }
164
165 return function () {
166 canUseDOM && document.removeEventListener("keydown", func);
167 };
168 }, [isOpen, onClose, closeOnOverlayClick, closeOnEsc]);
169 var mountRef = useAriaHider({
170 isOpen: isOpen,
171 id: portalId,
172 enableInert: useInert,
173 container: container
174 });
175 var context = {
176 isOpen: isOpen,
177 initialFocusRef: initialFocusRef,
178 onClose: onClose,
179 blockScrollOnMount: blockScrollOnMount,
180 closeOnEsc: closeOnEsc,
181 closeOnOverlayClick: closeOnOverlayClick,
182 returnFocusOnClose: returnFocusOnClose,
183 contentRef: contentRef,
184 scrollBehavior: scrollBehavior,
185 isCentered: isCentered,
186 headerId: headerId,
187 bodyId: bodyId,
188 contentId: contentId,
189 size: size,
190 addAriaLabelledby: addAriaLabelledby,
191 addAriaDescribedby: addAriaDescribedby
192 };
193 var activateFocusLock = (0, _react.useCallback)(function () {
194 if (initialFocusRef && initialFocusRef.current) {
195 initialFocusRef.current.focus();
196 } else {
197 if (contentRef.current) {
198 var focusables = (0, _utils.getFocusables)(contentRef.current);
199
200 if (focusables.length === 0) {
201 contentRef.current.focus();
202 }
203 }
204 }
205 }, [initialFocusRef]);
206 var deactivateFocusLock = (0, _react.useCallback)(function () {
207 if (finalFocusRef && finalFocusRef.current) {
208 finalFocusRef.current.focus();
209 }
210 }, [finalFocusRef]);
211 if (!isOpen) return null;
212 return _react["default"].createElement(ModalContext.Provider, {
213 value: context
214 }, _react["default"].createElement(_Portal["default"], {
215 container: mountRef.current
216 }, _react["default"].createElement(_cjs["default"], {
217 returnFocus: returnFocusOnClose && !finalFocusRef,
218 onActivation: activateFocusLock,
219 onDeactivation: deactivateFocusLock
220 }, children)));
221}; ////////////////////////////////////////////////////////////////////////
222
223
224exports.Modal = Modal;
225
226var ModalOverlay = _react["default"].forwardRef(function (props, ref) {
227 return _react["default"].createElement(_Box["default"], (0, _extends2["default"])({
228 pos: "fixed",
229 bg: "rgba(0,0,0,0.4)",
230 left: "0",
231 top: "0",
232 w: "100vw",
233 h: "100vh",
234 ref: ref,
235 zIndex: "overlay",
236 onClick: (0, _utils.wrapEvent)(props.onClick, function (event) {
237 event.stopPropagation();
238 })
239 }, props));
240});
241
242exports.ModalOverlay = ModalOverlay;
243ModalOverlay.displayName = "ModalOverlay"; ////////////////////////////////////////////////////////////////////////
244
245var ModalContent = _react["default"].forwardRef(function (_ref3, ref) {
246 var onClick = _ref3.onClick,
247 children = _ref3.children,
248 _ref3$zIndex = _ref3.zIndex,
249 zIndex = _ref3$zIndex === void 0 ? "modal" : _ref3$zIndex,
250 noStyles = _ref3.noStyles,
251 props = (0, _objectWithoutPropertiesLoose2["default"])(_ref3, ["onClick", "children", "zIndex", "noStyles"]);
252
253 var _useModalContext = useModalContext(),
254 contentRef = _useModalContext.contentRef,
255 onClose = _useModalContext.onClose,
256 isCentered = _useModalContext.isCentered,
257 bodyId = _useModalContext.bodyId,
258 headerId = _useModalContext.headerId,
259 contentId = _useModalContext.contentId,
260 size = _useModalContext.size,
261 closeOnEsc = _useModalContext.closeOnEsc,
262 addAriaLabelledby = _useModalContext.addAriaLabelledby,
263 addAriaDescribedby = _useModalContext.addAriaDescribedby,
264 scrollBehavior = _useModalContext.scrollBehavior,
265 closeOnOverlayClick = _useModalContext.closeOnOverlayClick;
266
267 var _contentRef = (0, _utils.useForkRef)(ref, contentRef);
268
269 var _useColorMode = (0, _ColorModeProvider.useColorMode)(),
270 colorMode = _useColorMode.colorMode;
271
272 var colorModeStyles = {
273 light: {
274 bg: "white",
275 shadow: "0 7px 14px 0 rgba(0,0,0, 0.1), 0 3px 6px 0 rgba(0, 0, 0, .07)"
276 },
277 dark: {
278 bg: "gray.700",
279 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"
280 }
281 };
282 var boxStyleProps = colorModeStyles[colorMode];
283 var wrapperStyle = {};
284 var contentStyle = {};
285
286 if (isCentered) {
287 wrapperStyle = {
288 display: "flex",
289 alignItems: "center",
290 justifyContent: "center"
291 };
292 } else {
293 contentStyle = {
294 top: "3.75rem",
295 mx: "auto"
296 };
297 }
298
299 if (scrollBehavior === "inside") {
300 wrapperStyle = _objectSpread({}, wrapperStyle, {
301 maxHeight: "calc(100vh - 7.5rem)",
302 overflow: "hidden",
303 top: "3.75rem"
304 });
305 contentStyle = _objectSpread({}, contentStyle, {
306 height: "100%",
307 top: 0
308 });
309 }
310
311 if (scrollBehavior === "outside") {
312 wrapperStyle = _objectSpread({}, wrapperStyle, {
313 overflowY: "auto",
314 overflowX: "hidden"
315 });
316 contentStyle = _objectSpread({}, contentStyle, {
317 my: "3.75rem",
318 top: 0
319 });
320 }
321
322 if (noStyles) {
323 wrapperStyle = {};
324 contentStyle = {};
325 }
326
327 return _react["default"].createElement(_Box["default"], (0, _extends2["default"])({
328 pos: "fixed",
329 left: "0",
330 top: "0",
331 w: "100%",
332 h: "100%",
333 zIndex: zIndex,
334 onClick: function onClick(event) {
335 event.stopPropagation();
336
337 if (closeOnOverlayClick) {
338 onClose(event, "clickedOverlay");
339 }
340 },
341 onKeyDown: function onKeyDown(event) {
342 if (event.key === "Escape") {
343 event.stopPropagation();
344
345 if (closeOnEsc) {
346 onClose(event, "pressedEscape");
347 }
348 }
349 }
350 }, wrapperStyle), _react["default"].createElement(_Box["default"], (0, _extends2["default"])({
351 ref: _contentRef,
352 as: "section",
353 role: "dialog",
354 "aria-modal": "true",
355 tabIndex: -1,
356 outline: 0,
357 maxWidth: size,
358 w: "100%",
359 id: contentId
360 }, addAriaDescribedby && {
361 "aria-describedby": bodyId
362 }, addAriaLabelledby && {
363 "aria-labelledby": headerId
364 }, {
365 pos: "relative",
366 d: "flex",
367 flexDir: "column",
368 zIndex: zIndex,
369 onClick: (0, _utils.wrapEvent)(onClick, function (event) {
370 return event.stopPropagation();
371 })
372 }, boxStyleProps, contentStyle, props), children));
373});
374
375exports.ModalContent = ModalContent;
376ModalContent.displayName = "ModalContent"; ////////////////////////////////////////////////////////////////////////
377
378var ModalHeader = (0, _react.forwardRef)(function (props, ref) {
379 var _useModalContext2 = useModalContext(),
380 headerId = _useModalContext2.headerId;
381
382 return _react["default"].createElement(_Box["default"], (0, _extends2["default"])({
383 ref: ref,
384 px: 6,
385 py: 4,
386 id: headerId,
387 as: "header",
388 position: "relative",
389 fontSize: "xl",
390 fontWeight: "semibold"
391 }, props));
392});
393exports.ModalHeader = ModalHeader;
394ModalHeader.displayName = "ModalHeader"; ////////////////////////////////////////////////////////////////////////
395
396var ModalFooter = (0, _react.forwardRef)(function (props, ref) {
397 return _react["default"].createElement(_Box["default"], (0, _extends2["default"])({
398 display: "flex",
399 justifyContent: "flex-end",
400 ref: ref,
401 px: 6,
402 py: 4,
403 as: "footer"
404 }, props));
405});
406exports.ModalFooter = ModalFooter;
407ModalFooter.displayName = "ModalFooter"; ////////////////////////////////////////////////////////////////////////
408
409var ModalBody = (0, _react.forwardRef)(function (props, ref) {
410 var _useModalContext3 = useModalContext(),
411 bodyId = _useModalContext3.bodyId,
412 scrollBehavior = _useModalContext3.scrollBehavior;
413
414 var style = {};
415
416 if (scrollBehavior === "inside") {
417 style = {
418 overflowY: "auto"
419 };
420 }
421
422 return _react["default"].createElement(_Box["default"], (0, _extends2["default"])({
423 ref: ref,
424 id: bodyId,
425 px: 6,
426 py: 2,
427 flex: "1"
428 }, style, props));
429});
430exports.ModalBody = ModalBody;
431ModalBody.displayName = "ModalBody"; ////////////////////////////////////////////////////////////////////////
432
433var ModalCloseButton = (0, _react.forwardRef)(function (props, ref) {
434 var _useModalContext4 = useModalContext(),
435 onClose = _useModalContext4.onClose;
436
437 return _react["default"].createElement(_CloseButton["default"], (0, _extends2["default"])({
438 ref: ref,
439 onClick: onClose,
440 position: "absolute",
441 top: "8px",
442 right: "12px"
443 }, props));
444});
445exports.ModalCloseButton = ModalCloseButton;
446ModalCloseButton.displayName = "ModalCloseButton"; ////////////////////////////////////////////////////////////////////////
\No newline at end of file