react-responsive-modal 5.2.6 → 6.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,7 +3,6 @@
3
3
  [![npm version](https://img.shields.io/npm/v/react-responsive-modal.svg)](https://www.npmjs.com/package/react-responsive-modal)
4
4
  [![npm downloads per month](https://img.shields.io/npm/dm/react-responsive-modal.svg)](https://www.npmjs.com/package/react-responsive-modal)
5
5
  [![codecov](https://img.shields.io/codecov/c/github/pradel/react-responsive-modal/master.svg)](https://codecov.io/gh/pradel/react-responsive-modal)
6
- [![dependencies Status](https://david-dm.org/pradel/react-responsive-modal/status.svg)](https://david-dm.org/pradel/react-responsive-modal)
7
6
 
8
7
  A simple responsive and accessible react modal.
9
8
 
@@ -13,6 +12,8 @@ A simple responsive and accessible react modal.
13
12
  - Multiple modals.
14
13
  - Accessible modals.
15
14
  - Easily customizable via props.
15
+ - Typescript support
16
+ - [Small bundle size](https://bundlephobia.com/result?p=react-responsive-modal)
16
17
 
17
18
  ## Documentation
18
19
 
@@ -21,12 +22,6 @@ A simple responsive and accessible react modal.
21
22
  - [Usage](https://react-responsive-modal.leopradel.com/#usage)
22
23
  - [Props](https://react-responsive-modal.leopradel.com/#props)
23
24
  - [Licence](https://react-responsive-modal.leopradel.com/#license)
24
- - [Examples](https://react-responsive-modal.leopradel.com/examples)
25
- - [Centered modal](https://react-responsive-modal.leopradel.com/examples#centered-modal)
26
- - [Multiple modal](https://react-responsive-modal.leopradel.com/examples#multiple-modal)
27
- - [Custom styling](https://react-responsive-modal.leopradel.com/examples#custom-styling)
28
- - [Custom animation](https://react-responsive-modal.leopradel.com/examples#custom-animation)
29
- - [Custom container](https://react-responsive-modal.leopradel.com/examples#custom-container)
30
25
 
31
26
  ## Installation
32
27
 
@@ -13,7 +13,7 @@ interface CloseIconProps {
13
13
  classes: {
14
14
  closeButton?: string;
15
15
  };
16
- onClickCloseIcon: () => void;
16
+ onClick: () => void;
17
17
  }
18
- declare const CloseIcon: ({ classes, classNames, styles, id, closeIcon, onClickCloseIcon, }: CloseIconProps) => JSX.Element;
18
+ declare const CloseIcon: ({ classes, classNames, styles, id, closeIcon, onClick, }: CloseIconProps) => JSX.Element;
19
19
  export default CloseIcon;
@@ -1,6 +1,7 @@
1
1
  /// <reference types="react" />
2
2
  interface FocusTrapProps {
3
3
  container?: React.RefObject<HTMLElement> | null;
4
+ initialFocusRef?: React.RefObject<HTMLElement>;
4
5
  }
5
- export declare const FocusTrap: ({ container }: FocusTrapProps) => null;
6
+ export declare const FocusTrap: ({ container, initialFocusRef }: FocusTrapProps) => null;
6
7
  export {};
package/dist/index.d.ts CHANGED
@@ -30,6 +30,8 @@ export interface ModalProps {
30
30
  blockScroll?: boolean;
31
31
  /**
32
32
  * Show the close icon.
33
+ *
34
+ * Default to true.
33
35
  */
34
36
  showCloseIcon?: boolean;
35
37
  /**
@@ -46,28 +48,40 @@ export interface ModalProps {
46
48
  * Default to true.
47
49
  */
48
50
  focusTrapped?: boolean;
51
+ /**
52
+ * Element to focus when focus trap is used.
53
+ *
54
+ * Default to undefined.
55
+ */
56
+ initialFocusRef?: React.RefObject<HTMLElement>;
49
57
  /**
50
58
  * You can specify a container prop which should be of type `Element`.
51
59
  * The portal will be rendered inside that element.
52
60
  * The default behavior will create a div node and render it at the at the end of document.body.
53
61
  */
54
- container?: Element;
62
+ container?: Element | null;
55
63
  /**
56
64
  * An object containing classNames to style the modal.
57
65
  */
58
66
  classNames?: {
67
+ root?: string;
59
68
  overlay?: string;
69
+ overlayAnimationIn?: string;
70
+ overlayAnimationOut?: string;
71
+ modalContainer?: string;
60
72
  modal?: string;
73
+ modalAnimationIn?: string;
74
+ modalAnimationOut?: string;
61
75
  closeButton?: string;
62
76
  closeIcon?: string;
63
- animationIn?: string;
64
- animationOut?: string;
65
77
  };
66
78
  /**
67
79
  * An object containing the styles objects to style the modal.
68
80
  */
69
81
  styles?: {
82
+ root?: React.CSSProperties;
70
83
  overlay?: React.CSSProperties;
84
+ modalContainer?: React.CSSProperties;
71
85
  modal?: React.CSSProperties;
72
86
  closeButton?: React.CSSProperties;
73
87
  closeIcon?: React.CSSProperties;
@@ -75,7 +89,7 @@ export interface ModalProps {
75
89
  /**
76
90
  * Animation duration in milliseconds.
77
91
  *
78
- * Default to 500.
92
+ * Default to 300.
79
93
  */
80
94
  animationDuration?: number;
81
95
  /**
@@ -92,6 +106,10 @@ export interface ModalProps {
92
106
  * ARIA description for modal
93
107
  */
94
108
  ariaDescribedby?: string;
109
+ /**
110
+ * Avoid unpleasant flickering effect when body overflow is hidden. For more information see https://www.npmjs.com/package/body-scroll-lock
111
+ */
112
+ reserveScrollBarGap?: boolean;
95
113
  /**
96
114
  * id attribute for modal
97
115
  */
@@ -114,5 +132,5 @@ export interface ModalProps {
114
132
  onAnimationEnd?: () => void;
115
133
  children?: React.ReactNode;
116
134
  }
117
- export declare const Modal: ({ open, center, blockScroll, closeOnEsc, closeOnOverlayClick, container, showCloseIcon, closeIconId, closeIcon, focusTrapped, animationDuration, classNames, styles, role, ariaDescribedby, ariaLabelledby, modalId, onClose, onEscKeyDown, onOverlayClick, onAnimationEnd, children, }: ModalProps) => React.ReactPortal | null;
135
+ export declare const Modal: React.ForwardRefExoticComponent<ModalProps & React.RefAttributes<HTMLDivElement>>;
118
136
  export default Modal;
@@ -1,26 +1,20 @@
1
- declare const _default: {
2
- /**
3
- * Return the modals array
4
- */
5
- modals: () => {
6
- element: HTMLDivElement;
7
- blockScroll: boolean;
8
- }[];
1
+ import { Ref } from 'react';
2
+ /**
3
+ * Handle the order of the modals.
4
+ * Inspired by the material-ui implementation.
5
+ */
6
+ export declare const modalManager: {
9
7
  /**
10
8
  * Register a new modal
11
9
  */
12
- add: (newModal: HTMLDivElement, blockScroll: boolean) => void;
10
+ add: (newModal: Ref<Element>) => void;
13
11
  /**
14
12
  * Remove a modal
15
13
  */
16
- remove: (oldModal: HTMLDivElement) => void;
14
+ remove: (oldModal: Ref<Element>) => void;
17
15
  /**
18
- * Check if the modal is the first one on the screen
16
+ * When multiple modals are rendered will return true if current modal is the last one
19
17
  */
20
- isTopModal: (modal: HTMLDivElement) => boolean;
18
+ isTopModal: (modal: Ref<Element>) => boolean;
21
19
  };
22
- /**
23
- * Handle the order of the modals.
24
- * Inspired by the material-ui implementation.
25
- */
26
- export default _default;
20
+ export declare function useModalManager(ref: Ref<Element>, open: boolean): void;
@@ -8,7 +8,8 @@ var React = require('react');
8
8
  var React__default = _interopDefault(React);
9
9
  var ReactDom = _interopDefault(require('react-dom'));
10
10
  var cx = _interopDefault(require('classnames'));
11
- var noScroll = _interopDefault(require('no-scroll'));
11
+ var bodyScrollLock = require('body-scroll-lock');
12
+ var useForwardedRef = _interopDefault(require('@bedrock-layout/use-forwarded-ref'));
12
13
 
13
14
  function _extends() {
14
15
  _extends = Object.assign || function (target) {
@@ -34,17 +35,16 @@ var CloseIcon = function CloseIcon(_ref) {
34
35
  styles = _ref.styles,
35
36
  id = _ref.id,
36
37
  closeIcon = _ref.closeIcon,
37
- onClickCloseIcon = _ref.onClickCloseIcon;
38
+ onClick = _ref.onClick;
38
39
  return React__default.createElement("button", {
39
40
  id: id,
40
41
  className: cx(classes.closeButton, classNames == null ? void 0 : classNames.closeButton),
41
42
  style: styles == null ? void 0 : styles.closeButton,
42
- onClick: onClickCloseIcon,
43
+ onClick: onClick,
43
44
  "data-testid": "close-button"
44
45
  }, closeIcon ? closeIcon : React__default.createElement("svg", {
45
46
  className: classNames == null ? void 0 : classNames.closeIcon,
46
47
  style: styles == null ? void 0 : styles.closeIcon,
47
- xmlns: "http://www.w3.org/2000/svg",
48
48
  width: 28,
49
49
  height: 28,
50
50
  viewBox: "0 0 36 36",
@@ -54,74 +54,9 @@ var CloseIcon = function CloseIcon(_ref) {
54
54
  })));
55
55
  };
56
56
 
57
- var _modals = [];
58
- /**
59
- * Handle the order of the modals.
60
- * Inspired by the material-ui implementation.
61
- */
62
-
63
- var modalManager = {
64
- /**
65
- * Return the modals array
66
- */
67
- modals: function modals() {
68
- return _modals;
69
- },
70
-
71
- /**
72
- * Register a new modal
73
- */
74
- add: function add(newModal, blockScroll) {
75
- if (_modals.findIndex(function (modal) {
76
- return modal.element === newModal;
77
- }) === -1) {
78
- _modals.push({
79
- element: newModal,
80
- blockScroll: blockScroll
81
- });
82
- }
83
- },
84
-
85
- /**
86
- * Remove a modal
87
- */
88
- remove: function remove(oldModal) {
89
- var index = _modals.findIndex(function (modal) {
90
- return modal.element === oldModal;
91
- });
92
-
93
- if (index !== -1) {
94
- _modals.splice(index, 1);
95
- }
96
- },
97
-
98
- /**
99
- * Check if the modal is the first one on the screen
100
- */
101
- isTopModal: function isTopModal(modal) {
102
- var _modals2;
103
-
104
- return !!_modals.length && ((_modals2 = _modals[_modals.length - 1]) == null ? void 0 : _modals2.element) === modal;
105
- }
106
- };
107
-
108
57
  var isBrowser = typeof window !== 'undefined';
109
- var blockNoScroll = function blockNoScroll() {
110
- noScroll.on();
111
- };
112
- var unblockNoScroll = function unblockNoScroll() {
113
- // Restore the scroll only if there is no modal on the screen
114
- // We filter the modals that are not affecting the scroll
115
- var modals = modalManager.modals().filter(function (modal) {
116
- return modal.blockScroll;
117
- });
118
-
119
- if (modals.length === 0) {
120
- noScroll.off();
121
- }
122
- };
123
58
 
124
- // https://github.com/alexandrzavalii/focus-trap-js/blob/master/src/index.js v1.0.9
59
+ // https://github.com/alexandrzavalii/focus-trap-js/blob/master/src/index.js v1.1.0
125
60
  var candidateSelectors = ['input', 'select', 'textarea', 'a[href]', 'button', '[tabindex]', 'audio[controls]', 'video[controls]', '[contenteditable]:not([contenteditable="false"])'];
126
61
 
127
62
  function isHidden(node) {
@@ -130,14 +65,34 @@ function isHidden(node) {
130
65
  return node.offsetParent === null || getComputedStyle(node).visibility === 'hidden';
131
66
  }
132
67
 
68
+ function getCheckedRadio(nodes, form) {
69
+ for (var i = 0; i < nodes.length; i++) {
70
+ if (nodes[i].checked && nodes[i].form === form) {
71
+ return nodes[i];
72
+ }
73
+ }
74
+ }
75
+
76
+ function isNotRadioOrTabbableRadio(node) {
77
+ if (node.tagName !== 'INPUT' || node.type !== 'radio' || !node.name) {
78
+ return true;
79
+ }
80
+
81
+ var radioScope = node.form || node.ownerDocument;
82
+ var radioSet = radioScope.querySelectorAll('input[type="radio"][name="' + node.name + '"]');
83
+ var checked = getCheckedRadio(radioSet, node.form);
84
+ return checked === node || checked === undefined && radioSet[0] === node;
85
+ }
86
+
133
87
  function getAllTabbingElements(parentElem) {
88
+ var currentActiveElement = document.activeElement;
134
89
  var tabbableNodes = parentElem.querySelectorAll(candidateSelectors.join(','));
135
90
  var onlyTabbable = [];
136
91
 
137
92
  for (var i = 0; i < tabbableNodes.length; i++) {
138
93
  var node = tabbableNodes[i];
139
94
 
140
- if (!node.disabled && getTabindex(node) > -1 && !isHidden(node)) {
95
+ if (currentActiveElement === node || !node.disabled && getTabindex(node) > -1 && !isHidden(node) && isNotRadioOrTabbableRadio(node)) {
141
96
  onlyTabbable.push(node);
142
97
  }
143
98
  }
@@ -191,7 +146,8 @@ function isContentEditable(node) {
191
146
  }
192
147
 
193
148
  var FocusTrap = function FocusTrap(_ref) {
194
- var container = _ref.container;
149
+ var container = _ref.container,
150
+ initialFocusRef = _ref.initialFocusRef;
195
151
  var refLastFocus = React.useRef();
196
152
  /**
197
153
  * Handle focus lock on the modal
@@ -210,9 +166,7 @@ var FocusTrap = function FocusTrap(_ref) {
210
166
 
211
167
 
212
168
  if (isBrowser && (container == null ? void 0 : container.current)) {
213
- var allTabbingElements = getAllTabbingElements(container.current);
214
-
215
- if (allTabbingElements[0]) {
169
+ var savePreviousFocus = function savePreviousFocus() {
216
170
  // First we save the last focused element
217
171
  // only if it's a focusable element
218
172
  if (candidateSelectors.findIndex(function (selector) {
@@ -222,8 +176,23 @@ var FocusTrap = function FocusTrap(_ref) {
222
176
  }) !== -1) {
223
177
  refLastFocus.current = document.activeElement;
224
178
  }
179
+ };
180
+
181
+ if (initialFocusRef) {
182
+ savePreviousFocus(); // We need to schedule focusing on a next frame - this allows to focus on the modal root
183
+
184
+ requestAnimationFrame(function () {
185
+ var _initialFocusRef$curr;
225
186
 
226
- allTabbingElements[0].focus();
187
+ (_initialFocusRef$curr = initialFocusRef.current) == null ? void 0 : _initialFocusRef$curr.focus();
188
+ });
189
+ } else {
190
+ var allTabbingElements = getAllTabbingElements(container.current);
191
+
192
+ if (allTabbingElements[0]) {
193
+ savePreviousFocus();
194
+ allTabbingElements[0].focus();
195
+ }
227
196
  }
228
197
  }
229
198
 
@@ -236,20 +205,85 @@ var FocusTrap = function FocusTrap(_ref) {
236
205
  (_refLastFocus$current = refLastFocus.current) == null ? void 0 : _refLastFocus$current.focus();
237
206
  }
238
207
  };
239
- }, [container]);
208
+ }, [container, initialFocusRef]);
240
209
  return null;
241
210
  };
242
211
 
212
+ var modals = [];
213
+ /**
214
+ * Handle the order of the modals.
215
+ * Inspired by the material-ui implementation.
216
+ */
217
+
218
+ var modalManager = {
219
+ /**
220
+ * Register a new modal
221
+ */
222
+ add: function add(newModal) {
223
+ modals.push(newModal);
224
+ },
225
+
226
+ /**
227
+ * Remove a modal
228
+ */
229
+ remove: function remove(oldModal) {
230
+ modals = modals.filter(function (modal) {
231
+ return modal !== oldModal;
232
+ });
233
+ },
234
+
235
+ /**
236
+ * When multiple modals are rendered will return true if current modal is the last one
237
+ */
238
+ isTopModal: function isTopModal(modal) {
239
+ return !!modals.length && modals[modals.length - 1] === modal;
240
+ }
241
+ };
242
+ function useModalManager(ref, open) {
243
+ React.useEffect(function () {
244
+ if (open) {
245
+ modalManager.add(ref);
246
+ }
247
+
248
+ return function () {
249
+ modalManager.remove(ref);
250
+ };
251
+ }, [open, ref]);
252
+ }
253
+
254
+ var useScrollLock = function useScrollLock(refModal, open, showPortal, blockScroll, reserveScrollBarGap) {
255
+ var oldRef = React.useRef(null);
256
+ React.useEffect(function () {
257
+ if (open && refModal.current && blockScroll) {
258
+ oldRef.current = refModal.current;
259
+ bodyScrollLock.disableBodyScroll(refModal.current, {
260
+ reserveScrollBarGap: reserveScrollBarGap
261
+ });
262
+ }
263
+
264
+ return function () {
265
+ if (oldRef.current) {
266
+ bodyScrollLock.enableBodyScroll(oldRef.current);
267
+ oldRef.current = null;
268
+ }
269
+ };
270
+ }, [open, showPortal, refModal, blockScroll, reserveScrollBarGap]);
271
+ };
272
+
243
273
  var classes = {
274
+ root: 'react-responsive-modal-root',
244
275
  overlay: 'react-responsive-modal-overlay',
276
+ overlayAnimationIn: 'react-responsive-modal-overlay-in',
277
+ overlayAnimationOut: 'react-responsive-modal-overlay-out',
278
+ modalContainer: 'react-responsive-modal-container',
279
+ modalContainerCenter: 'react-responsive-modal-containerCenter',
245
280
  modal: 'react-responsive-modal-modal',
246
- modalCenter: 'react-responsive-modal-modalCenter',
247
- closeButton: 'react-responsive-modal-closeButton',
248
- animationIn: 'react-responsive-modal-fadeIn',
249
- animationOut: 'react-responsive-modal-fadeOut'
281
+ modalAnimationIn: 'react-responsive-modal-modal-in',
282
+ modalAnimationOut: 'react-responsive-modal-modal-out',
283
+ closeButton: 'react-responsive-modal-closeButton'
250
284
  };
251
- var Modal = function Modal(_ref) {
252
- var _classNames$animation, _classNames$animation2;
285
+ var Modal = /*#__PURE__*/React__default.forwardRef(function (_ref, ref) {
286
+ var _classNames$overlayAn, _classNames$overlayAn2, _classNames$modalAnim, _classNames$modalAnim2;
253
287
 
254
288
  var open = _ref.open,
255
289
  center = _ref.center,
@@ -266,8 +300,10 @@ var Modal = function Modal(_ref) {
266
300
  closeIcon = _ref.closeIcon,
267
301
  _ref$focusTrapped = _ref.focusTrapped,
268
302
  focusTrapped = _ref$focusTrapped === void 0 ? true : _ref$focusTrapped,
303
+ _ref$initialFocusRef = _ref.initialFocusRef,
304
+ initialFocusRef = _ref$initialFocusRef === void 0 ? undefined : _ref$initialFocusRef,
269
305
  _ref$animationDuratio = _ref.animationDuration,
270
- animationDuration = _ref$animationDuratio === void 0 ? 500 : _ref$animationDuratio,
306
+ animationDuration = _ref$animationDuratio === void 0 ? 300 : _ref$animationDuratio,
271
307
  classNames = _ref.classNames,
272
308
  styles = _ref.styles,
273
309
  _ref$role = _ref.role,
@@ -279,7 +315,9 @@ var Modal = function Modal(_ref) {
279
315
  onEscKeyDown = _ref.onEscKeyDown,
280
316
  onOverlayClick = _ref.onOverlayClick,
281
317
  onAnimationEnd = _ref.onAnimationEnd,
282
- children = _ref.children;
318
+ children = _ref.children,
319
+ reserveScrollBarGap = _ref.reserveScrollBarGap;
320
+ var refDialog = useForwardedRef(ref);
283
321
  var refModal = React.useRef(null);
284
322
  var refShouldClose = React.useRef(null);
285
323
  var refContainer = React.useRef(null); // Lazily create the ref instance
@@ -293,15 +331,14 @@ var Modal = function Modal(_ref) {
293
331
 
294
332
  var _useState = React.useState(false),
295
333
  showPortal = _useState[0],
296
- setShowPortal = _useState[1];
334
+ setShowPortal = _useState[1]; // Hook used to manage multiple modals opened at the same time
297
335
 
298
- var handleOpen = function handleOpen() {
299
- modalManager.add(refContainer.current, blockScroll);
300
336
 
301
- if (blockScroll) {
302
- blockNoScroll();
303
- }
337
+ useModalManager(refModal, open); // Hook used to manage the scroll
304
338
 
339
+ useScrollLock(refModal, open, showPortal, blockScroll, reserveScrollBarGap);
340
+
341
+ var handleOpen = function handleOpen() {
305
342
  if (refContainer.current && !container && !document.body.contains(refContainer.current)) {
306
343
  document.body.appendChild(refContainer.current);
307
344
  }
@@ -310,12 +347,6 @@ var Modal = function Modal(_ref) {
310
347
  };
311
348
 
312
349
  var handleClose = function handleClose() {
313
- modalManager.remove(refContainer.current);
314
-
315
- if (blockScroll) {
316
- unblockNoScroll();
317
- }
318
-
319
350
  if (refContainer.current && !container && document.body.contains(refContainer.current)) {
320
351
  document.body.removeChild(refContainer.current);
321
352
  }
@@ -325,7 +356,7 @@ var Modal = function Modal(_ref) {
325
356
 
326
357
  var handleKeydown = function handleKeydown(event) {
327
358
  // Only the last modal need to be escaped when pressing the esc key
328
- if (event.keyCode !== 27 || !modalManager.isTopModal(refContainer.current)) {
359
+ if (event.keyCode !== 27 || !modalManager.isTopModal(refModal)) {
329
360
  return;
330
361
  }
331
362
 
@@ -338,8 +369,8 @@ var Modal = function Modal(_ref) {
338
369
 
339
370
  React.useEffect(function () {
340
371
  return function () {
341
- // When the component is unmounted directly we want to unblock the scroll
342
372
  if (showPortal) {
373
+ // When the modal is closed or removed directly, cleanup the listeners
343
374
  handleClose();
344
375
  }
345
376
  };
@@ -376,10 +407,6 @@ var Modal = function Modal(_ref) {
376
407
  refShouldClose.current = false;
377
408
  };
378
409
 
379
- var handleClickCloseIcon = function handleClickCloseIcon() {
380
- onClose();
381
- };
382
-
383
410
  var handleAnimationEnd = function handleAnimationEnd() {
384
411
  if (!open) {
385
412
  setShowPortal(false);
@@ -389,38 +416,54 @@ var Modal = function Modal(_ref) {
389
416
  };
390
417
 
391
418
  var containerModal = container || refContainer.current;
419
+ var overlayAnimation = open ? (_classNames$overlayAn = classNames == null ? void 0 : classNames.overlayAnimationIn) != null ? _classNames$overlayAn : classes.overlayAnimationIn : (_classNames$overlayAn2 = classNames == null ? void 0 : classNames.overlayAnimationOut) != null ? _classNames$overlayAn2 : classes.overlayAnimationOut;
420
+ var modalAnimation = open ? (_classNames$modalAnim = classNames == null ? void 0 : classNames.modalAnimationIn) != null ? _classNames$modalAnim : classes.modalAnimationIn : (_classNames$modalAnim2 = classNames == null ? void 0 : classNames.modalAnimationOut) != null ? _classNames$modalAnim2 : classes.modalAnimationOut;
392
421
  return showPortal && containerModal ? ReactDom.createPortal(React__default.createElement("div", {
393
- style: _extends({
394
- animation: (open ? (_classNames$animation = classNames == null ? void 0 : classNames.animationIn) != null ? _classNames$animation : classes.animationIn : (_classNames$animation2 = classNames == null ? void 0 : classNames.animationOut) != null ? _classNames$animation2 : classes.animationOut) + " " + animationDuration + "ms"
395
- }, styles == null ? void 0 : styles.overlay),
396
- className: cx(classes.overlay, classNames == null ? void 0 : classNames.overlay),
397
- onClick: handleClickOverlay,
398
- onAnimationEnd: handleAnimationEnd,
399
- "data-testid": "overlay"
422
+ className: cx(classes.root, classNames == null ? void 0 : classNames.root),
423
+ style: styles == null ? void 0 : styles.root,
424
+ "data-testid": "root"
400
425
  }, React__default.createElement("div", {
426
+ className: cx(classes.overlay, classNames == null ? void 0 : classNames.overlay),
427
+ "data-testid": "overlay",
428
+ "aria-hidden": true,
429
+ style: _extends({
430
+ animation: overlayAnimation + " " + animationDuration + "ms"
431
+ }, styles == null ? void 0 : styles.overlay)
432
+ }), React__default.createElement("div", {
401
433
  ref: refModal,
402
- className: cx(classes.modal, center && classes.modalCenter, classNames == null ? void 0 : classNames.modal),
403
- style: styles == null ? void 0 : styles.modal,
434
+ className: cx(classes.modalContainer, center && classes.modalContainerCenter, classNames == null ? void 0 : classNames.modalContainer),
435
+ style: styles == null ? void 0 : styles.modalContainer,
436
+ "data-testid": "modal-container",
437
+ onClick: handleClickOverlay
438
+ }, React__default.createElement("div", {
439
+ ref: refDialog,
440
+ className: cx(classes.modal, classNames == null ? void 0 : classNames.modal),
441
+ style: _extends({
442
+ animation: modalAnimation + " " + animationDuration + "ms"
443
+ }, styles == null ? void 0 : styles.modal),
404
444
  onMouseDown: handleModalEvent,
405
445
  onMouseUp: handleModalEvent,
406
446
  onClick: handleModalEvent,
447
+ onAnimationEnd: handleAnimationEnd,
407
448
  id: modalId,
408
449
  role: role,
409
450
  "aria-modal": "true",
410
451
  "aria-labelledby": ariaLabelledby,
411
452
  "aria-describedby": ariaDescribedby,
412
- "data-testid": "modal"
453
+ "data-testid": "modal",
454
+ tabIndex: -1
413
455
  }, focusTrapped && React__default.createElement(FocusTrap, {
414
- container: refModal
456
+ container: refDialog,
457
+ initialFocusRef: initialFocusRef
415
458
  }), children, showCloseIcon && React__default.createElement(CloseIcon, {
416
459
  classes: classes,
417
460
  classNames: classNames,
418
461
  styles: styles,
419
462
  closeIcon: closeIcon,
420
- onClickCloseIcon: handleClickCloseIcon,
463
+ onClick: onClose,
421
464
  id: closeIconId
422
- }))), containerModal) : null;
423
- };
465
+ })))), containerModal) : null;
466
+ });
424
467
 
425
468
  exports.Modal = Modal;
426
469
  exports.default = Modal;