@awsui/components-react
Version:
AWS UI is a collection of [React](https://reactjs.org/) components that help create intuitive, responsive, and accessible user experiences for web applications. It is developed by Amazon Web Services (AWS). This work is available under the terms of the [A
73 lines (72 loc) • 4.31 kB
JavaScript
import { __assign, __rest } from "tslib";
import React, { useEffect, useRef } from 'react';
import { createPortal } from 'react-dom';
import FocusLock from 'react-focus-lock';
import clsx from 'clsx';
import { getBaseProps } from '../internal/base-component';
import { fireNonCancelableEvent } from '../internal/events';
import { KeyCode } from '../internal/keycode';
import { useUniqueId } from '../internal/hooks/use-unique-id';
import { Button, Header } from '../index';
import { useContainerBreakpoints } from '../internal/hooks/container-queries';
import styles from './styles.css.js';
import { disableBodyScrolling, enableBodyScrolling } from './body-scroll';
import { useTelemetry } from '../internal/hooks/use-telemetry';
export default function Modal(_a) {
var _b;
var _c = _a.size, size = _c === void 0 ? 'medium' : _c, visible = _a.visible, _d = _a.closeAriaLabel, closeAriaLabel = _d === void 0 ? '' : _d, header = _a.header, children = _a.children, footer = _a.footer, onDismiss = _a.onDismiss, _e = _a.modalRoot, modalRoot = _e === void 0 ? document.body : _e, rest = __rest(_a, ["size", "visible", "closeAriaLabel", "header", "children", "footer", "onDismiss", "modalRoot"]);
useTelemetry('Modal');
var instanceUniqueId = useUniqueId();
var headerId = (rest.id || instanceUniqueId) + "-header";
var rootRef = useRef(null);
var dialogRef = useRef(null);
var focusLockRef = useRef(null);
var initiallyFocusedElementRef = useRef(undefined);
var _f = useContainerBreakpoints(['xs']), breakpoint = _f[0], overlayRef = _f[1];
var baseProps = getBaseProps(rest);
useEffect(function () {
return function () {
onDeactivation();
enableBodyScrolling();
};
}, []);
useEffect(function () {
if (visible) {
disableBodyScrolling();
}
else {
enableBodyScrolling();
}
}, [visible]);
useEffect(function () {
if (visible && rootRef.current) {
rootRef.current.scrollTop = 0;
}
}, [visible]);
var onActivation = function () {
initiallyFocusedElementRef.current = document.activeElement;
};
var onDeactivation = function () {
var _a;
(_a = initiallyFocusedElementRef.current) === null || _a === void 0 ? void 0 : _a.focus();
initiallyFocusedElementRef.current = undefined;
};
var dismiss = function (reason) { return fireNonCancelableEvent(onDismiss, { reason: reason }); };
var onOverlayClick = function () { return dismiss('overlay'); };
var onCloseButtonClick = function () { return dismiss('closeButton'); };
var escKeyHandler = function (event) {
if (event.keyCode === KeyCode.escape) {
dismiss('keyboard');
}
};
return createPortal(React.createElement("div", __assign({}, baseProps, { className: clsx(styles.root, (_b = {}, _b[styles.hidden] = !visible, _b), baseProps.className), role: "dialog", "aria-modal": true, "aria-labelledby": headerId, ref: rootRef }),
React.createElement("div", { className: styles.overlay, onClick: onOverlayClick, ref: overlayRef }),
React.createElement(FocusLock, { disabled: !visible, autoFocus: true, className: styles['focus-lock'], ref: focusLockRef, onActivation: onActivation, onDeactivation: onDeactivation },
React.createElement("div", { className: clsx(styles.dialog, styles[size], styles["breakpoint-" + breakpoint]), onKeyDown: escKeyHandler, tabIndex: -1, ref: dialogRef },
React.createElement("div", { className: styles.container },
React.createElement("div", { id: headerId, className: styles.header },
React.createElement(Header, { variant: "h2", className: styles['inner-header'], actions: React.createElement(Button, { ariaLabel: closeAriaLabel, className: styles['dismiss-control'], variant: "icon", iconName: "close", formAction: "none", onClick: onCloseButtonClick }) },
React.createElement("span", { className: styles['header--text'] }, header))),
React.createElement("div", { className: styles.content }, children),
footer && React.createElement("div", { className: styles.footer }, footer))))), modalRoot);
}