/* * Utility functions */ const requestAnimationFrame = window.requestAnimationFrame || (fn=>setTimeout(fn,30)); function changeContainerHeight() { const cont = document.querySelector('.app-container'); const input = document.querySelector('#container-height'); cont.style.height = input.value + 'px'; } /* * HOC to allow Components to receive their width/height as * props on render. */ const Responsive = (WrappedComponent) => class _Responsive extends React.Component { constructor(props) { super(props); this.state = { width: null, height: null }; this.rafCallback = this.getUpdatedSize.bind(this); } getUpdatedSize() { const node = ReactDOM.findDOMNode(this._comp); let height = node.offsetHeight; let width = node.offsetWidth; if (height != this.state.height || width != this.state.width) { this.setState({ height, width }); } requestAnimationFrame(this.rafCallback); } componentDidMount() { requestAnimationFrame(this.rafCallback); } componentWillUnmount() { cancelInterval(this._interval); } render() { return this._comp = ref} {...this.props} dimensions={{...this.state}} />; } }; /* * Price Component, which should have responsive text sizing * based on it's container's height. */ @Responsive class Price extends React.Component { render() { const { prefix, price, suffix, subtext, subtextPosition = "bottom" } = this.props; const [ dollars, cents = '00' ] = price.split('.'); const subcls = ["subtext", subtextPosition].join(' '); return (
this._container = ref} className={"price"}>
{ prefix }
$
{ dollars }
{ cents } { suffix }
{ subtext }
); } componentDidUpdate() { this.resizeFont(); } resizeFont() { window.requestAnimationFrame(() => { const { width, height } = this.props.dimensions; const factor = this.props.subtext && this.props.subtextPosition == 'bottom' ? .7 : .9; this._container.style.fontSize = (height * factor).toFixed(2) + 'px'; }); } } ReactDOM.render(
, document.getElementById('app') );