@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
JavaScript
/* 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;