UNPKG

@aibsweb/faceted-search

Version:
124 lines (99 loc) 5.58 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _get = _interopRequireDefault(require("lodash/get")); var _react = _interopRequireWildcard(require("react")); var _pivotHeader = require("./pivot-header"); require("../../../scss/sticky-wrapper.scss"); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj["default"] = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } var onWrapperElementUpdate = function onWrapperElementUpdate(wrapperElement, setOffsetTop) { setOffsetTop((0, _get["default"])(wrapperElement, ['current', 'offsetTop'], 0)); }; /** * Once the component has mounted and the Refs are usable this grabs the component dimensions used to position the header in such a way * that it sticks to the top of the screen while remaining positioned properly. * * @param {object} scrollingElement The element that being positioned to keep the header on screen. * @param {object} wrapperElement The container element used to hold the scrolling elements place. * @param {function} setComponentDimensions State hook for setting the componentDimensions */ var onScrollingElementUpdate = function onScrollingElementUpdate(scrollingElement, wrapperElement, setComponentDimensions) { var dimensions = { height: (0, _get["default"])(scrollingElement, ['current', 'clientHeight'], 0), offsetLeft: (0, _get["default"])(wrapperElement, ['current', 'offsetLeft'], 0) }; setComponentDimensions(dimensions); }; /** * If the sticky wrapper has scrolled offscreen construct the styles necessary to keep it fixed to the top of the screen. * * @param {number} scrollTop The current scrollTop value, used to determine if we've scrolled offscreen. * @param {number} offsetTop The sticky wrapper's offset (in pixels) from the top of the screen. * @param {object} componentDimensions An object containing the dimensions of the sticky header before position was `fixed`. */ var computeStickyPositionStyles = function computeStickyPositionStyles(scrollTop, offsetTop, componentDimensions) { var hasScrolledOffscreen = scrollTop > offsetTop; if (hasScrolledOffscreen) { return { position: 'fixed', top: 0, left: "".concat(componentDimensions.offsetLeft, "px") }; } return componentDimensions; }; /** * This wraps the pivot-header and makes it work like the css rule position: 'sticky' * * @param {object} WrappedComponent The componet to wrap */ var withSticky = function withSticky(WrappedComponent) { return function (props) { var wrapperElementRef = (0, _react.useRef)(null); var scrollingElementRef = (0, _react.useRef)(null); var _useState = (0, _react.useState)(0), _useState2 = _slicedToArray(_useState, 2), offsetTop = _useState2[0], setOffsetTop = _useState2[1]; var _useState3 = (0, _react.useState)({ offsetLeft: 0 }), _useState4 = _slicedToArray(_useState3, 2), componentDimensions = _useState4[0], setComponentDimensions = _useState4[1]; (0, _react.useEffect)(function () { return onWrapperElementUpdate(wrapperElementRef, setOffsetTop); }, [wrapperElementRef.current]); (0, _react.useEffect)(function () { return onScrollingElementUpdate(scrollingElementRef, wrapperElementRef, setComponentDimensions); }, [scrollingElementRef.current]); var inlineSizeStyles = { height: "".concat(componentDimensions.height, "px") }; var stickyPositionStyle = computeStickyPositionStyles(props.scrollTop, offsetTop, componentDimensions); /* .sticky-wrapper holds the header's dimensions and position when the .sticky-wrapper__scrolling-element is fixed to the window via prosition: fixed. The .sticky-wrapper__scrolling-element is styled with position: fixed when the header is scrolled off the top of the screen. */ return _react["default"].createElement("div", { className: "sticky-wrapper", ref: wrapperElementRef, style: inlineSizeStyles }, _react["default"].createElement("div", { className: "sticky-wrapper__scrolling-element", ref: scrollingElementRef, style: stickyPositionStyle }, _react["default"].createElement(WrappedComponent, props))); }; }; var PivotHeaderSticky = withSticky(_pivotHeader.PivotHeader); var _default = PivotHeaderSticky; exports["default"] = _default;