azure-devops-ui
Version:
React components for building web UI in Azure DevOps
76 lines (75 loc) • 2.77 kB
JavaScript
import "../../CommonImports";
import "../../Core/core.css";
import * as React from "react";
import { EventManagement } from '../../Core/EventManagement';
import { TimerManagement } from '../../Core/TimerManagement';
import { css } from '../../Util';
const ResizeDelayMs = 100;
export class ResponsiveViewport extends React.Component {
constructor(props) {
super(props);
this._onAsyncResize = () => {
this._resize();
};
this._resolveElement = (element) => {
this._element = element;
};
const { initialWidth } = props;
this.events = new EventManagement();
this.timers = new TimerManagement();
this.state = {
activeBreakpoints: initialWidth == null ? [] : this._getActiveBreakpoints(initialWidth)
};
this._onAsyncResize = this.timers.throttle(this._onAsyncResize, ResizeDelayMs, {
leading: false
});
}
componentDidMount() {
this.events.addEventListener(window, "resize", this._onAsyncResize);
// React to initial width
this._onAsyncResize();
}
componentWillUnmount() {
this.events.removeAllListeners();
this.timers.dispose();
}
shouldComponentUpdate(newProps, newState) {
if (this.props !== newProps) {
return true;
}
const newBreakPoints = newState.activeBreakpoints;
const oldBreakPoints = this.state.activeBreakpoints;
return newBreakPoints.length !== oldBreakPoints.length || newBreakPoints.some((b, idx) => b !== oldBreakPoints[idx]);
}
render() {
const { tag = "div", className, children, onRenderContent } = this.props;
const { activeBreakpoints } = this.state;
const content = (onRenderContent && onRenderContent(activeBreakpoints)) || children;
return React.createElement(tag, {
className: css(className, ...(activeBreakpoints && activeBreakpoints.map(x => x.className))),
ref: this._resolveElement
}, content);
}
measure() {
this._resize();
}
_resize() {
const rect = this._element.getBoundingClientRect();
const { width } = rect;
this.setState({
activeBreakpoints: this._getActiveBreakpoints(width)
});
}
_getActiveBreakpoints(width) {
const { breakPoints } = this.props;
return breakPoints.filter(bp => {
if (bp.minWidth >= 0 && width < bp.minWidth) {
return false;
}
if (bp.maxWidth >= 0 && width >= bp.maxWidth) {
return false;
}
return true;
});
}
}