@shopgate/engage
Version:
Shopgate's ENGAGE library.
97 lines (94 loc) • 3.54 kB
JavaScript
import React, { useState, forwardRef, useEffect } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { useScrollDirectionChange } from '@shopgate/engage/core/hooks';
import { root, scrolledIn, scrolledOut, transition } from "./style";
/* eslint-disable react/prop-types */
/**
* A container component that hides its content on scroll down and shows it on scroll up.
*
* @param {Object} props The component props.
* @param {boolean} [props.hideOnScroll] Toggle hide-on-scroll (default: true).
* @param {number} [props.scrollOffset] Pixels to scroll before toggling (default: 100).
* @param {boolean} [props.onlyShowAtTop] When set to true, the component content will not be shown
* till the user scrolls to the top of the page again.
* @param {number} [props.onlyShowAtTopOffset] Pixel threshold from the top of the page at which the
* component content will reappear when `showOnScrollToTop` is enabled. The content shows again once
* the scroll position is less than or equal to this value.
* @param {Function} [props.onChange] Callback function that is called when the header changes
* @param {string} [props.className] Extra CSS classes on the root element.
* @param {Object} [props.classes] Override internal class names.
* @param {string} [props.classes.scrolledIn] Override class for the scrolled-in state
* (content is hidden).
* @param {string} [props.classes.scrolledOut] Override class for the scrolled-out state
* (content is visible).
* visibility. Contains a boolean indicating whether the header is visible.
* @param {React.ReactNode} props.children Content of the header.
* @param {React.Ref<HTMLDivElement>} ref Forwarded ref to the header `<div>`.
* @returns {JSX.Element}
*/
import { jsx as _jsx } from "react/jsx-runtime";
function ScrollHeaderBase({
className,
children,
hideOnScroll = true,
scrollOffset = 100,
onlyShowAtTop = false,
onlyShowAtTopOffset = 0,
onChange,
classes
}, ref) {
const [shouldHideHeader, setShouldHideHeader] = useState(false);
useScrollDirectionChange({
enabled: hideOnScroll,
offset: scrollOffset,
onlyFireOnScrollUpAtTop: onlyShowAtTop,
onlyFireOnScrollUpAtTopOffset: onlyShowAtTopOffset,
onScrollDown: () => {
setShouldHideHeader(true);
},
onScrollUp: () => {
setShouldHideHeader(false);
}
});
useEffect(() => {
if (typeof onChange !== 'function') {
return;
}
onChange(!shouldHideHeader);
}, [onChange, shouldHideHeader]);
return /*#__PURE__*/_jsx("div", {
ref: ref,
className: classNames(root, transition, className, {
[classNames(scrolledIn, classes?.scrolledIn)]: !shouldHideHeader,
[classNames(scrolledOut, classes?.scrolledOut)]: shouldHideHeader
}),
children: children
});
}
/* eslint-enable react/prop-types */
const ScrollHeader = /*#__PURE__*/forwardRef(ScrollHeaderBase);
ScrollHeader.displayName = 'ScrollHeader';
ScrollHeader.propTypes = {
children: PropTypes.node.isRequired,
classes: PropTypes.shape({
scrolledIn: PropTypes.string,
scrolledOut: PropTypes.string
}),
className: PropTypes.string,
hideOnScroll: PropTypes.bool,
onChange: PropTypes.func,
onlyShowAtTop: PropTypes.bool,
onlyShowAtTopOffset: PropTypes.number,
scrollOffset: PropTypes.number
};
ScrollHeader.defaultProps = {
className: null,
hideOnScroll: true,
scrollOffset: 100,
classes: {},
onChange: null,
onlyShowAtTop: false,
onlyShowAtTopOffset: 0
};
export default ScrollHeader;