UNPKG

@atlaskit/modal-dialog

Version:

A modal dialog displays content that requires user interaction, in a layer above the page.

109 lines (108 loc) 3.95 kB
import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; /** @jsx jsx */ import React, { forwardRef, useEffect, useRef, useState } from 'react'; import { css, jsx } from '@emotion/react'; import { bind } from 'bind-event-listener'; import rafSchedule from 'raf-schd'; import mergeRefs from '@atlaskit/ds-lib/merge-refs'; import noop from '@atlaskit/ds-lib/noop'; import useLazyCallback from '@atlaskit/ds-lib/use-lazy-callback'; import useStateRef from '@atlaskit/ds-lib/use-state-ref'; import FocusRing from '@atlaskit/focus-ring'; import { keylineColor, keylineHeight } from '../constants'; var baseStyles = css({ display: 'inherit', margin: "var(--ds-space-0, 0px)", flex: 'inherit', flexDirection: 'inherit', flexGrow: 1, overflowX: 'hidden', overflowY: 'auto', '@media (min-width: 480px)': { height: 'unset', overflowY: 'auto' } }); var topKeylineStyles = css({ borderTop: "".concat(keylineHeight, "px solid ").concat(keylineColor) }); var bottomKeylineStyles = css({ borderBottom: "".concat(keylineHeight, "px solid ").concat(keylineColor) }); /** * A container that shows top and bottom keylines when the * content overflows into the scrollable element. */ var ScrollContainer = /*#__PURE__*/forwardRef(function (props, ref) { var testId = props.testId, children = props.children; var _useStateRef = useStateRef({ previous: false, next: false }), _useStateRef2 = _slicedToArray(_useStateRef, 2), hasSiblings = _useStateRef2[0], setSiblings = _useStateRef2[1]; var _useState = useState(false), _useState2 = _slicedToArray(_useState, 2), showContentFocus = _useState2[0], setContentFocus = _useState2[1]; var _useState3 = useState(false), _useState4 = _slicedToArray(_useState3, 2), showTopKeyline = _useState4[0], setTopKeyline = _useState4[1]; var _useState5 = useState(false), _useState6 = _slicedToArray(_useState5, 2), showBottomKeyline = _useState6[0], setBottomKeyline = _useState6[1]; var scrollableRef = useRef(null); var setLazySiblings = useLazyCallback(setSiblings); var setLazyContentFocus = useLazyCallback(rafSchedule(function () { var target = scrollableRef.current; target && setContentFocus(target.scrollHeight > target.clientHeight); })); var setLazyKeylines = useLazyCallback(rafSchedule(function () { var target = scrollableRef.current; if (target) { var scrollableDistance = target.scrollHeight - target.clientHeight; if (hasSiblings.current.previous) { setTopKeyline(target.scrollTop > keylineHeight); } if (hasSiblings.current.next) { setBottomKeyline(target.scrollTop <= scrollableDistance - keylineHeight); } } })); useEffect(function () { var target = scrollableRef.current; var unbindWindowEvent = bind(window, { type: 'resize', listener: setLazyKeylines }); var unbindTargetEvent = target ? bind(target, { type: 'scroll', listener: setLazyKeylines }) : noop; setLazyContentFocus(); setLazyKeylines(); setLazySiblings({ previous: Boolean(target === null || target === void 0 ? void 0 : target.previousElementSibling), next: Boolean(target === null || target === void 0 ? void 0 : target.nextElementSibling) }); return function () { unbindWindowEvent(); unbindTargetEvent(); }; }, [setLazyContentFocus, setLazyKeylines, setLazySiblings]); return jsx(FocusRing, { isInset: true }, jsx("div", { // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex tabIndex: showContentFocus ? 0 : undefined, "data-testid": testId && "".concat(testId, "--scrollable"), ref: mergeRefs([ref, scrollableRef]), css: [baseStyles, showTopKeyline && topKeylineStyles, showBottomKeyline && bottomKeylineStyles] }, children)); }); ScrollContainer.displayName = 'ScrollContainer'; export default ScrollContainer;