UNPKG

react-sticky-header

Version:

Lightweight sticky header made for React that works with both colours and images.

171 lines (146 loc) 5.93 kB
import _Object$getPrototypeOf from 'babel-runtime/core-js/object/get-prototype-of'; import _classCallCheck from 'babel-runtime/helpers/classCallCheck'; import _createClass from 'babel-runtime/helpers/createClass'; import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn'; import _inherits from 'babel-runtime/helpers/inherits'; import React, { Component } from 'react'; function addEvent(event, cb) { window.addEventListener(event, cb, false); return function () { return window.removeEventListener(event, cb, false); }; } var _class; var _temp2; var noop = function noop() {}; var ReactStickyHeader = (_temp2 = _class = function (_Component) { _inherits(ReactStickyHeader, _Component); function ReactStickyHeader() { var _ref; var _temp, _this, _ret; _classCallCheck(this, ReactStickyHeader); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = ReactStickyHeader.__proto__ || _Object$getPrototypeOf(ReactStickyHeader)).call.apply(_ref, [this].concat(args))), _this), _this._detatch = noop, _this._rafExecuting = false, _this.state = { isSticky: _this.props.headerOnly }, _this.calculateStickyState = function () { if (_this._rafExecuting) { return; } _this._rafExecuting = true; requestAnimationFrame(function () { var stickyHeaderHeight = _this._fixed.offsetHeight; var headerContainer = _this._root.offsetHeight; var headerContainerBoundingBox = _this._root.getBoundingClientRect(); var stickyOffset = _this.props.stickyOffset; var pastStickyThreshold = headerContainer + headerContainerBoundingBox.top - stickyHeaderHeight <= (stickyOffset || 0); if (pastStickyThreshold && !_this.state.isSticky) { _this.setState({ isSticky: true }); _this.props.onSticky(true); } else if (!pastStickyThreshold && _this.state.isSticky) { _this.setState({ isSticky: false }); _this.props.onSticky(false); } _this._rafExecuting = false; }); }, _this.onResize = function () { // We want to flush a re-render incase the children have changed size from CSS. _this.setState({}); // We want to check if because of a resize the header is now sticky or not. _this.calculateStickyState(); }, _temp), _possibleConstructorReturn(_this, _ret); } // eslint-disable-next-line react/sort-comp _createClass(ReactStickyHeader, [{ key: 'componentDidMount', value: function componentDidMount() { this.initialise(); // Force state change as we need to calculate the header background containers. // eslint-disable-next-line react/no-did-mount-set-state this.setState({}); } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { this._detatch(); } }, { key: 'componentWillReceiveProps', value: function componentWillReceiveProps(nextProps) { if (nextProps.headerOnly !== this.props.headerOnly) { this.calculateStickyState(); } } }, { key: 'initialise', value: function initialise() { var _this2 = this; if (this._initialised) { return; } var detatchScroll = addEvent('scroll', this.calculateStickyState); var detatchResize = addEvent('resize', this.onResize); this._detatch = function () { [detatchScroll, detatchResize].forEach(function (detatch) { return detatch(); }); _this2._initialised = false; }; this.calculateStickyState(); this._initialised = true; } }, { key: 'render', value: function render() { var _this3 = this; var backgroundUrl = this.props.backgroundImage && 'url(\'' + this.props.backgroundImage + '\')'; var headerClassName = 'ReactStickyHeader_root' + (this.props.className ? ' ' + this.props.className : ''); var rootClassName = '' + headerClassName + (this.state.isSticky ? ' is-sticky' : ''); var headerContainerHeight = this._root && this._root.offsetHeight; var fixedHeaderHeight = this._fixed && this._fixed.offsetHeight; return React.createElement( 'header', { className: rootClassName, ref: function ref(e) { return _this3._root = e; } }, React.createElement( 'div', { className: 'ReactStickyHeader_fixed', ref: function ref(e) { return _this3._fixed = e; } }, this.props.header ), React.createElement('div', { className: 'ReactStickyHeader_midground', style: { height: headerContainerHeight || fixedHeaderHeight, top: fixedHeaderHeight, backgroundImage: backgroundUrl, backgroundColor: this.props.backgroundColor } }), this.props.headerOnly && React.createElement('div', { style: { height: fixedHeaderHeight } }), this.props.headerOnly || React.createElement('div', { className: 'ReactStickyHeader_background-bg', style: { backgroundImage: backgroundUrl, backgroundColor: this.props.backgroundColor } }), this.props.headerOnly || React.createElement('div', { className: 'ReactStickyHeader_foreground', style: { opacity: this.state.isSticky ? 0 : 1, backgroundImage: backgroundUrl, backgroundColor: this.props.backgroundColor } }), this.props.headerOnly || this.props.children ); } }]); return ReactStickyHeader; }(Component), _class.defaultProps = { onSticky: noop, headerOnly: false }, _temp2); export default ReactStickyHeader; //# sourceMappingURL=index.es6.js.map