@bigfishtv/cockpit
Version:
81 lines (71 loc) • 1.74 kB
JavaScript
import React, { Component } from 'react'
import PropTypes from 'prop-types'
/**
* This component uses the ResizeObserver API to
* detect when its size changes (due to children)
* and ensures it never shrinks below the tallest
* content height. This is helpful to prevent
* visual jerkiness due to content height shrinking
* and forcing the browser to "scroll up".
*
* Can be used as a normal component which will
* render a div of its own.
*
* <MinimumHeight>
* <Child />
* <Child />
* </MinimumHeight>
*
* Alternative usage is to use a function as a child.
*
* <MinimumHeight>
* {(forwardRef, minHeight) => (
* <main ref={forwardRef} style={{ minHeight }}>
* <Child />
* <Child />
* </main>
* )}
* </MinimumHeight>
*/
export default class MinimumHeight extends Component {
static propTypes = {
minHeight: PropTypes.number,
}
static defaultProps = {
minHeight: 0,
}
state = {
minHeight: this.props.minHeight,
}
componentWillUnmount() {
if (this.ro && this.el) {
this.ro.unobserve(this.el)
}
}
registerElement = el => {
if (!el && this.el && this.ro) {
this.ro.unobserve(this.el)
}
this.el = el
if (this.el && !this.ro) {
this.ro = new window.ResizeObserver(entries => {
const height = entries[0].contentRect.height
if (height > this.state.minHeight) {
this.setState({ minHeight: height })
}
})
this.ro.observe(this.el)
}
}
render() {
if (typeof this.props.children === 'function') {
return this.props.children(this.registerElement, this.state.minHeight)
} else {
return (
<div ref={this.registerElement} style={{ minHeight: this.state.minHeight }}>
{this.props.children}
</div>
)
}
}
}