@aibsweb/faceted-search
Version:
A generalized faceted search application.
124 lines (99 loc) • 5.58 kB
JavaScript
;
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;