office-ui-fabric-react
Version:
Reusable React components for building experiences for Office 365.
213 lines • 10.7 kB
JavaScript
define(["require", "exports", "tslib", "react", "prop-types", "../../Utilities", "./Sticky.types"], function (require, exports, tslib_1, React, PropTypes, Utilities_1, Sticky_types_1) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var Sticky = /** @class */ (function (_super) {
tslib_1.__extends(Sticky, _super);
function Sticky(props) {
var _this = _super.call(this, props) || this;
_this._root = Utilities_1.createRef();
_this._stickyContentTop = Utilities_1.createRef();
_this._stickyContentBottom = Utilities_1.createRef();
_this._nonStickyContent = Utilities_1.createRef();
_this._onScrollEvent = function (container, footerStickyContainer) {
if (_this.root && _this.nonStickyContent) {
_this.distanceFromTop = _this._getNonStickyDistanceFromTop(container);
var isStickyTop = false;
var isStickyBottom = false;
if (_this.canStickyTop) {
var distanceToStickTop = _this.distanceFromTop - _this._getStickyDistanceFromTop();
isStickyTop = distanceToStickTop < container.scrollTop;
}
// Can sticky bottom if the scrollablePane - total sticky footer height is smaller than the sticky's distance from the top of the pane
if (_this.canStickyBottom && container.clientHeight - footerStickyContainer.offsetHeight <= _this.distanceFromTop) {
isStickyBottom = _this.distanceFromTop - container.scrollTop > _this._getStickyDistanceFromTopForFooter(container, footerStickyContainer);
}
_this.setState({
isStickyTop: _this.canStickyTop && isStickyTop,
isStickyBottom: isStickyBottom
});
}
};
_this._getStickyDistanceFromTop = function () {
var distance = 0;
if (_this.stickyContentTop) {
distance = _this.stickyContentTop.offsetTop;
}
return distance;
};
_this._getStickyDistanceFromTopForFooter = function (container, footerStickyVisibleContainer) {
var distance = 0;
if (_this.stickyContentBottom) {
distance = container.clientHeight - footerStickyVisibleContainer.offsetHeight + _this.stickyContentBottom.offsetTop;
}
return distance;
};
_this._getNonStickyDistanceFromTop = function (container) {
var distance = 0;
var currElem = _this.root;
if (currElem) {
while (currElem.offsetParent !== container) {
distance += currElem.offsetTop;
currElem = currElem.offsetParent;
}
if (currElem.offsetParent === container) {
distance += currElem.offsetTop;
}
}
return distance;
};
_this.state = {
isStickyTop: false,
isStickyBottom: false
};
_this.distanceFromTop = 0;
return _this;
}
Object.defineProperty(Sticky.prototype, "root", {
get: function () {
return this._root.current;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Sticky.prototype, "stickyContentTop", {
get: function () {
return this._stickyContentTop.current;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Sticky.prototype, "stickyContentBottom", {
get: function () {
return this._stickyContentBottom.current;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Sticky.prototype, "nonStickyContent", {
get: function () {
return this._nonStickyContent.current;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Sticky.prototype, "canStickyTop", {
get: function () {
return this.props.stickyPosition === Sticky_types_1.StickyPositionType.Both || this.props.stickyPosition === Sticky_types_1.StickyPositionType.Header;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Sticky.prototype, "canStickyBottom", {
get: function () {
return this.props.stickyPosition === Sticky_types_1.StickyPositionType.Both || this.props.stickyPosition === Sticky_types_1.StickyPositionType.Footer;
},
enumerable: true,
configurable: true
});
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);
scrollablePane.addSticky(this);
};
Sticky.prototype.componentWillUnmount = function () {
var scrollablePane = this.context.scrollablePane;
scrollablePane.unsubscribe(this._onScrollEvent);
scrollablePane.removeSticky(this);
};
Sticky.prototype.componentDidUpdate = function (prevProps, prevState) {
var scrollablePane = this.context.scrollablePane;
if (prevState.isStickyTop !== this.state.isStickyTop || prevState.isStickyBottom !== this.state.isStickyBottom) {
scrollablePane.updateStickyRefHeights();
}
};
Sticky.prototype.shouldComponentUpdate = function (nextProps, nextState) {
var _a = this.state, isStickyTop = _a.isStickyTop, isStickyBottom = _a.isStickyBottom;
return isStickyTop !== nextState.isStickyTop ||
isStickyBottom !== nextState.isStickyBottom ||
this.props.stickyPosition !== nextProps.stickyPosition ||
this.props.children !== nextProps.children;
};
Sticky.prototype.render = function () {
var _a = this.state, isStickyTop = _a.isStickyTop, isStickyBottom = _a.isStickyBottom;
return (React.createElement("div", { ref: this._root },
this.canStickyTop &&
React.createElement("div", { className: this.props.stickyClassName, ref: this._stickyContentTop, "aria-hidden": !isStickyTop },
React.createElement("div", { style: this._getStickyPlaceholderHeight(isStickyTop) })),
this.canStickyBottom &&
React.createElement("div", { className: this.props.stickyClassName, ref: this._stickyContentBottom, "aria-hidden": !isStickyBottom },
React.createElement("div", { style: this._getStickyPlaceholderHeight(isStickyBottom) })),
React.createElement("div", { style: this._getNonStickyPlaceholderHeight() }),
React.createElement("div", { ref: this._nonStickyContent, className: isStickyTop || isStickyBottom ? this.props.stickyClassName : undefined, style: this._getContentStyles(isStickyTop || isStickyBottom) }, this.props.children)));
};
Sticky.prototype.addSticky = function (stickyContent) {
if (this.nonStickyContent) {
stickyContent.appendChild(this.nonStickyContent);
}
};
Sticky.prototype.resetSticky = function () {
if (this.nonStickyContent && this.root) {
this.root.appendChild(this.nonStickyContent);
}
};
Sticky.prototype.setDistanceFromTop = function (container) {
this.distanceFromTop = this._getNonStickyDistanceFromTop(container);
};
Sticky.prototype._getContentStyles = function (isSticky) {
return {
backgroundColor: this.props.stickyBackgroundColor || this._getBackground()
};
};
Sticky.prototype._getStickyPlaceholderHeight = function (isSticky) {
var height = this.nonStickyContent ? this.nonStickyContent.offsetHeight : 0;
return {
visibility: isSticky ? 'hidden' : 'visible',
height: isSticky ? 0 : height
};
};
Sticky.prototype._getNonStickyPlaceholderHeight = function () {
var _a = this.state, isStickyTop = _a.isStickyTop, isStickyBottom = _a.isStickyBottom;
if (isStickyTop || isStickyBottom) {
var height = this.nonStickyContent ? this.nonStickyContent.offsetHeight : 0;
return {
height: height
};
}
else {
return {
position: 'absolute'
};
}
};
// Gets background of nearest parent element that has a declared background-color attribute
Sticky.prototype._getBackground = function () {
if (!this.root) {
return undefined;
}
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 undefined;
}
if (curr.parentElement) {
curr = curr.parentElement;
}
}
return window.getComputedStyle(curr).getPropertyValue('background-color');
};
Sticky.defaultProps = {
stickyPosition: Sticky_types_1.StickyPositionType.Both
};
Sticky.contextTypes = {
scrollablePane: PropTypes.object
};
return Sticky;
}(Utilities_1.BaseComponent));
exports.Sticky = Sticky;
});
//# sourceMappingURL=Sticky.js.map