UNPKG

@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
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); }