UNPKG

@helpscout/hsds-react

Version:

React component library for Help Scout's Design System

125 lines (106 loc) 4.61 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.default = useScrollShadow; exports.getScrollableSectionsState = getScrollableSectionsState; var _react = require("react"); var _lodash = _interopRequireDefault(require("lodash.throttle")); // very difficult to test with JSDom, some basic interaction is tested in ScrollableContainer /* istanbul ignore file */ var BOX_SHADOW_INITIAL = '0 0 0 1px rgba(0, 0, 0, 0.1)'; var BOX_SHADOW_SCROLLED = '0 0 0 1px rgba(0, 0, 0, 0.1), 0 0 0 5px rgba(0, 0, 0, 0.05)'; function useScrollShadow(_ref) { var bottomRef = _ref.bottomRef, _ref$drawInitialShado = _ref.drawInitialShadowsDelay, drawInitialShadowsDelay = _ref$drawInitialShado === void 0 ? 0 : _ref$drawInitialShado, scrollableRef = _ref.scrollableRef, _ref$shadows = _ref.shadows, shadows = _ref$shadows === void 0 ? {} : _ref$shadows, topRef = _ref.topRef; var initialShadow = shadows.initial || BOX_SHADOW_INITIAL; var scrolledShadow = shadows.scrolled || BOX_SHADOW_SCROLLED; var _useState = (0, _react.useState)(null), isTopScrolled = _useState[0], setIsTopScrolled = _useState[1]; var _useState2 = (0, _react.useState)(null), isBottomScrolled = _useState2[0], setIsBottomScrolled = _useState2[1]; var topElement = getElement(topRef); var bottomElement = getElement(bottomRef); var scrollableElement = getElement(scrollableRef); var scrollableHeight = scrollableElement && scrollableElement.getBoundingClientRect().height; (0, _react.useEffect)(function () { var timeoutID = setTimeout(function () { if (scrollableElement) { var _getScrollableSection = getScrollableSectionsState(scrollableElement), _isBottomScrolled = _getScrollableSection.isBottomScrolled, _isTopScrolled = _getScrollableSection.isTopScrolled; applyShadows(topElement, _isTopScrolled, { initialShadow: initialShadow, scrolledShadow: scrolledShadow }); applyShadows(bottomElement, _isBottomScrolled, { initialShadow: initialShadow, scrolledShadow: scrolledShadow }); setIsTopScrolled(_isTopScrolled); setIsBottomScrolled(_isBottomScrolled); } }, drawInitialShadowsDelay); return function () { clearTimeout(timeoutID); }; }, [drawInitialShadowsDelay, initialShadow, scrolledShadow, topElement, bottomElement, scrollableElement, scrollableHeight]); var handleOnScroll = (0, _lodash.default)(function () { var scrollableElement = getElement(scrollableRef); var _getScrollableSection2 = getScrollableSectionsState(scrollableElement), isTopScrolled = _getScrollableSection2.isTopScrolled, isBottomScrolled = _getScrollableSection2.isBottomScrolled; applyShadows(topElement, isTopScrolled, { initialShadow: initialShadow, scrolledShadow: scrolledShadow }); applyShadows(bottomElement, isBottomScrolled, { initialShadow: initialShadow, scrolledShadow: scrolledShadow }); setIsTopScrolled(isTopScrolled); setIsBottomScrolled(isBottomScrolled); }, 100); return [handleOnScroll, isTopScrolled, isBottomScrolled]; } function getElement(someRef) { if (someRef instanceof HTMLElement) return someRef; return someRef && someRef.current; } function applyShadows(element, isScrolled, _ref2) { var initialShadow = _ref2.initialShadow, scrolledShadow = _ref2.scrolledShadow; if (element) { element.style.boxShadow = 'var(--scroll-shadow)'; if (isScrolled) { element.style.setProperty('--scroll-shadow', scrolledShadow); } else { element.style.setProperty('--scroll-shadow', initialShadow); } } } function getScrollableSectionsState(scrollable) { if (!scrollable) { return { isTopScrolled: false, isBottomScrolled: false }; } var style = window.getComputedStyle(scrollable); var paddingTop = Number.parseInt(style.paddingTop, 10); var paddingBottom = Number.parseInt(style.paddingBottom, 10); var scrollableScrollHeight = scrollable.scrollHeight; var scrollableHeight = scrollable.offsetHeight; var scrollablePaddingTop = paddingTop > 0 ? paddingTop - paddingTop / 2 : 0; var scrollablePaddingBottom = paddingBottom > 0 ? paddingBottom + paddingBottom / 2 : 0; return { isTopScrolled: scrollable.scrollTop - scrollablePaddingTop > 0, isBottomScrolled: scrollable.scrollTop + scrollableHeight + scrollablePaddingBottom < scrollableScrollHeight }; }