office-ui-fabric-react
Version:
Reusable React components for building experiences for Office 365.
150 lines • 6.89 kB
JavaScript
import * as tslib_1 from "tslib";
/* tslint:disable:no-unused-variable */
import * as React from 'react';
import * as ReactDOM from 'react-dom';
/* tslint:enable:no-unused-variable */
import * as PropTypes from 'prop-types';
import { BaseComponent, autobind } from '../../Utilities';
import { StickyPositionType } from './Sticky.types';
var Sticky = /** @class */ (function (_super) {
tslib_1.__extends(Sticky, _super);
function Sticky(props) {
var _this = _super.call(this, props) || this;
_this.state = {
isStickyTop: false,
isStickyBottom: false
};
return _this;
}
Sticky.prototype.componentDidMount = function () {
if (!this.context.scrollablePane) {
throw new TypeError('Expected Sticky to be mounted within ScrollablePane');
}
var scrollablePane = this.context.scrollablePane;
scrollablePane.subscribe(this._onScrollEvent);
this.content = document.createElement('div');
this.content.style.background = this.props.stickyBackgroundColor || this._getBackground();
ReactDOM.render(React.createElement("div", null, this.props.children), this.content);
this.root.appendChild(this.content);
this.context.scrollablePane.notifySubscribers(true);
};
Sticky.prototype.componentWillUnmount = function () {
var _this = this;
var _a = this.state, isStickyTop = _a.isStickyTop, isStickyBottom = _a.isStickyBottom;
var scrollablePane = this.context.scrollablePane;
if (isStickyTop) {
this._resetSticky(function () {
scrollablePane.removeStickyHeader(_this);
});
}
if (isStickyBottom) {
this._resetSticky(function () {
scrollablePane.removeStickyFooter(_this);
});
}
scrollablePane.unsubscribe(this._onScrollEvent);
};
Sticky.prototype.componentDidUpdate = function (prevProps, prevState) {
var _this = this;
var _a = this.state, isStickyTop = _a.isStickyTop, isStickyBottom = _a.isStickyBottom;
var scrollablePane = this.context.scrollablePane;
if (this.props.children !== prevProps.children) {
ReactDOM.render(React.createElement("div", null, this.props.children), this.content);
}
if (isStickyTop && !prevState.isStickyTop) {
this._setSticky(function () {
scrollablePane.addStickyHeader(_this);
});
}
else if (!isStickyTop && prevState.isStickyTop) {
this._resetSticky(function () {
scrollablePane.removeStickyHeader(_this);
});
}
if (isStickyBottom && !prevState.isStickyBottom) {
this._setSticky(function () {
scrollablePane.addStickyFooter(_this);
});
}
else if (!isStickyBottom && prevState.isStickyBottom) {
this._resetSticky(function () {
scrollablePane.removeStickyFooter(_this);
});
}
};
Sticky.prototype.shouldComponentUpdate = function (nextProps, nextState) {
var _a = this.state, isStickyTop = _a.isStickyTop, isStickyBottom = _a.isStickyBottom, placeholderHeight = _a.placeholderHeight;
return isStickyTop !== nextState.isStickyTop ||
isStickyBottom !== nextState.isStickyBottom ||
placeholderHeight !== nextState.placeholderHeight ||
this.props.children !== nextProps.children;
};
Sticky.prototype.setPlaceholderHeight = function (height) {
this.setState({
placeholderHeight: height
});
};
Sticky.prototype.render = function () {
var _a = this.state, isStickyTop = _a.isStickyTop, isStickyBottom = _a.isStickyBottom, placeholderHeight = _a.placeholderHeight;
var isSticky = isStickyTop || isStickyBottom;
return (React.createElement("div", { ref: this._resolveRef('root') },
React.createElement("div", { style: { height: (isSticky ? placeholderHeight : 0) } })));
};
Sticky.prototype._onScrollEvent = function (headerBound, footerBound) {
var _a = this.root.getBoundingClientRect(), top = _a.top, bottom = _a.bottom;
var _b = this.state, isStickyTop = _b.isStickyTop, isStickyBottom = _b.isStickyBottom;
var stickyPosition = this.props.stickyPosition;
var canStickyHeader = stickyPosition === StickyPositionType.Both || stickyPosition === StickyPositionType.Header;
var canStickyFooter = stickyPosition === StickyPositionType.Both || stickyPosition === StickyPositionType.Footer;
this.setState({
isStickyTop: canStickyHeader && ((!isStickyTop && top <= headerBound.bottom) || (isStickyTop && bottom < headerBound.bottom)),
isStickyBottom: canStickyFooter && ((!isStickyBottom && bottom >= footerBound.top) || (isStickyBottom && top > footerBound.top))
});
};
Sticky.prototype._setSticky = function (callback) {
if (this.content.parentElement) {
this.content.parentElement.removeChild(this.content);
}
callback();
};
Sticky.prototype._resetSticky = function (callback) {
var _this = this;
this.root.appendChild(this.content);
setTimeout(function () {
if (_this.props.stickyClassName) {
_this.content.children[0].classList.remove(_this.props.stickyClassName);
}
}, 1);
callback();
};
// Gets background of nearest parent element that has a declared background-color attribute
Sticky.prototype._getBackground = function () {
var curr = this.root;
while (window.getComputedStyle(curr).getPropertyValue('background-color') === 'rgba(0, 0, 0, 0)' ||
window.getComputedStyle(curr).getPropertyValue('background-color') === 'transparent') {
if (curr.tagName === 'HTML') {
// Fallback color if no element has a declared background-color attribute
return null;
}
if (curr.parentElement) {
curr = curr.parentElement;
}
}
return window.getComputedStyle(curr).getPropertyValue('background-color');
};
Sticky.defaultProps = {
stickyPosition: StickyPositionType.Both
};
Sticky.contextTypes = {
scrollablePane: PropTypes.object
};
tslib_1.__decorate([
autobind
], Sticky.prototype, "componentDidMount", null);
tslib_1.__decorate([
autobind
], Sticky.prototype, "_onScrollEvent", null);
return Sticky;
}(BaseComponent));
export { Sticky };
//# sourceMappingURL=Sticky.js.map