UNPKG

office-ui-fabric-react

Version:

Reusable React components for building experiences for Office 365.

94 lines 4.76 kB
import * as tslib_1 from "tslib"; import * as React from 'react'; import { BaseDecorator } from './BaseDecorator'; import { findScrollableParent, getRect, createRef, getWindow } from '../../Utilities'; var RESIZE_DELAY = 500; var MAX_RESIZE_ATTEMPTS = 3; export function withViewport(ComposedComponent) { return /** @class */ (function (_super) { tslib_1.__extends(WithViewportComponent, _super); function WithViewportComponent(props) { var _this = _super.call(this, props) || this; _this._root = createRef(); /* Note: using lambda here because decorators don't seem to work in decorators. */ _this._updateViewport = function (withForceUpdate) { var viewport = _this.state.viewport; var viewportElement = _this._root.current; var scrollElement = findScrollableParent(viewportElement); var scrollRect = getRect(scrollElement); var clientRect = getRect(viewportElement); var updateComponent = function () { if (withForceUpdate && _this._composedComponentInstance) { _this._composedComponentInstance.forceUpdate(); } }; var isSizeChanged = (clientRect && clientRect.width) !== viewport.width || (scrollRect && scrollRect.height) !== viewport.height; if (isSizeChanged && _this._resizeAttempts < MAX_RESIZE_ATTEMPTS && clientRect && scrollRect) { _this._resizeAttempts++; _this.setState({ viewport: { width: clientRect.width, height: scrollRect.height } }, function () { _this._updateViewport(withForceUpdate); }); } else { _this._resizeAttempts = 0; updateComponent(); } }; _this._resizeAttempts = 0; _this.state = { viewport: { width: 0, height: 0 } }; return _this; } WithViewportComponent.prototype.componentDidMount = function () { var skipViewportMeasures = this.props.skipViewportMeasures; this._onAsyncResize = this._async.debounce(this._onAsyncResize, RESIZE_DELAY, { leading: false }); var window = getWindow(); var viewportElement = this._root.current; // ResizeObserver seems always fire even window is not resized. This is // particularly bad when skipViewportMeasures is set when optimizing fixed layout lists. // It will measure and update and re-render the entire list after list is fully rendered. // So fallback to listen to resize event when skipViewportMeasures is set. if (!skipViewportMeasures && window && window.ResizeObserver) { this._viewportResizeObserver = new window.ResizeObserver(this._onAsyncResize); this._viewportResizeObserver.observe(viewportElement); } else { this._events.on(window, 'resize', this._onAsyncResize); } if (!skipViewportMeasures) { this._updateViewport(); } }; WithViewportComponent.prototype.componentWillUnmount = function () { this._events.dispose(); if (this._viewportResizeObserver) { this._viewportResizeObserver.disconnect(); } }; WithViewportComponent.prototype.render = function () { var viewport = this.state.viewport; var skipViewportMeasures = this.props.skipViewportMeasures; var isViewportVisible = skipViewportMeasures || (viewport.width > 0 && viewport.height > 0); return (React.createElement("div", { className: "ms-Viewport", ref: this._root, style: { minWidth: 1, minHeight: 1 } }, isViewportVisible && (React.createElement(ComposedComponent, tslib_1.__assign({ ref: this._updateComposedComponentRef, viewport: viewport }, this.props))))); }; WithViewportComponent.prototype.forceUpdate = function () { this._updateViewport(true); }; WithViewportComponent.prototype._onAsyncResize = function () { this._updateViewport(); }; return WithViewportComponent; }(BaseDecorator)); } //# sourceMappingURL=withViewport.js.map