/* * This file is part of ORY Editor. * * ORY Editor is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ORY Editor is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with ORY Editor. If not, see . * * @license LGPL-3.0 * @copyright 2016-2018 Aeneas Rekkas * @author Aeneas Rekkas * */ import * as React from 'react'; import onElementResize from 'element-resize-event'; import classNames from 'classnames'; const defaultGetWidth = (element: HTMLElement) => element.clientWidth; const defaultGetHeight = (element: HTMLElement) => element.clientHeight; const Dimensions = ({ getHeight = defaultGetHeight, getWidth = defaultGetWidth, className = null, elementResize = false, } = {}) => ComposedComponent => { type DecoratorProps = {}; type DecoratorState = { containerWidth?: number; containerHeight?: number; }; class Decorator extends React.Component { containerRef: HTMLDivElement; rqf: number; constructor(props: DecoratorProps) { super(props); this.state = {}; } public componentDidMount() { if (!this.containerRef) { throw new Error('Cannot find container div'); } this.updateDimensions(); if (elementResize) { // Experimental: `element-resize-event` fires when an element resizes. // It attaches its own window resize listener and also uses // requestAnimationFrame, so we can just call `this.updateDimensions`. onElementResize(this.containerRef, this.updateDimensions); } else { this.getWindow().addEventListener('resize', this.onResize, false); } } // This cann not be used here because it doesn't listen to state changes. // shouldComponentUpdate = shouldPureComponentUpdate public componentWillUnmount() { this.getWindow().removeEventListener('resize', this.onResize); } public updateDimensions = () => { const container = this.containerRef; const containerWidth = getWidth(container); const containerHeight = getHeight(container); if ( containerWidth !== this.state.containerWidth || containerHeight !== this.state.containerHeight ) { this.setState({ containerWidth, containerHeight }); } } public onResize = () => { if (this.rqf) { return; } this.rqf = this.getWindow().requestAnimationFrame(() => { this.rqf = null; this.updateDimensions(); }); } // If the component is mounted in a different window to the javascript // context, as with https://github.com/JakeGinnivan/react-popout // then the `window` global will be different from the `window` that // contains the component. // Depends on `defaultView` which is not supported { this.containerRef = ref; } render() { return (
); } } return props => ; }; export default Dimensions;