UNPKG

@atlaskit/modal-dialog

Version:

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

95 lines (93 loc) 3.74 kB
/* scroll-container.tsx generated by @compiled/babel-plugin v0.39.1 */ import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; import "./scroll-container.compiled.css"; import { ax, ix } from "@compiled/react/runtime"; import React, { forwardRef, useEffect, useRef, useState } from 'react'; import { bind } from 'bind-event-listener'; import rafSchedule from 'raf-schd'; import { cx } from '@atlaskit/css'; 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 { Focusable } from '@atlaskit/primitives/compiled'; var keylineColor = "var(--ds-border, #0B120E24)"; var styles = { base: "_kkes1kw7 _1e0c1kw7 _2lx21kw7 _16jlkb7n _6rthze3t _1pfhze3t _12l2ze3t _ahbqze3t _1reo15vq _18m91wug _1jykn7od _wzg61wug", topKeyline: "_mqm21uh4", bottomKeyline: "_179r1uh4" }; var keylineHeight = 2; /** * A container that shows top and bottom keylines when the * content overflows into the scrollable element. */ var ScrollContainer = /*#__PURE__*/forwardRef(function (_ref, ref) { var testId = _ref.testId, children = _ref.children; var scrollableRef = useRef(null); var _useState = useState(false), _useState2 = _slicedToArray(_useState, 2), showTopKeyline = _useState2[0], setTopKeyline = _useState2[1]; var _useState3 = useState(false), _useState4 = _slicedToArray(_useState3, 2), showBottomKeyline = _useState4[0], setBottomKeyline = _useState4[1]; var _useState5 = useState(false), _useState6 = _slicedToArray(_useState5, 2), showContentFocus = _useState6[0], setContentFocus = _useState6[1]; // Schedule a content focus on the target element // WARNING: In theory, `target` may not be available when `rafSchedule` hits in concurrent rendering useEffect(function () { var schedule = rafSchedule(function () { var target = scrollableRef.current; target && setContentFocus(target.scrollHeight > target.clientHeight); }); schedule(); }, [scrollableRef]); var setLazyKeylines = useLazyCallback(rafSchedule(function () { var target = scrollableRef.current; if (target) { var scrollableDistance = target.scrollHeight - target.clientHeight; if (target.previousElementSibling) { setTopKeyline(target.scrollTop > keylineHeight); } if (target.nextElementSibling) { setBottomKeyline(target.scrollTop <= scrollableDistance - keylineHeight); } } })); // On load (and scroll/resize events), we set "keylines" // these border the content to indicate scrollability when content underflows the header or footer useEffect(function () { var target = scrollableRef.current; setLazyKeylines(); var unbindWindowEvent = bind(window, { type: 'resize', listener: setLazyKeylines }); var unbindTargetEvent = target ? bind(target, { type: 'scroll', listener: setLazyKeylines }) : noop; return function () { unbindWindowEvent(); unbindTargetEvent(); }; }, [setLazyKeylines]); return /*#__PURE__*/React.createElement(Focusable, { as: "div", isInset: true // tabindex is allowed here so that keyboard users can scroll content , tabIndex: showContentFocus ? 0 : undefined, role: showContentFocus ? 'region' : undefined, "aria-label": showContentFocus ? 'Scrollable content' : undefined, testId: testId && "".concat(testId, "--scrollable"), ref: mergeRefs([ref, scrollableRef]), xcss: cx(styles.base, showTopKeyline && styles.topKeyline, showBottomKeyline && styles.bottomKeyline) }, children); }); ScrollContainer.displayName = 'ScrollContainer'; export default ScrollContainer;