UNPKG

apeman-react-mixins

Version:
110 lines (91 loc) 2.16 kB
/** * Mixin to handle resize. * @mixin ApLayoutMixin */ 'use strict' import React, {PropTypes as types} from 'react' import deepEqual from 'deep-equal' import defaults from 'defaults' const LAYOUT_INTERVAL = 80 export class ApLayoutEvent { constructor (values) { const s = this Object.assign(s, values) } } /** @lends ApLayoutMixin */ const ApLayoutMixin = { // -------------------- // Custom // -------------------- $apLayoutMixed: true, /** * Reserve layout. */ layout (immidate) { const s = this let { props } = s clearTimeout(s._layoutTimer) s._layoutTimer = setTimeout(() => { if (!s.isMounted()) { return } let layouts = s.calcLayouts && s.calcLayouts() let changed = !deepEqual(s.layouts, layouts) if (changed) { s.componentWillLayout(layouts) s.layouts = layouts s.forceUpdate() if (props.onLayout) { let event = new ApLayoutEvent({ layouts }) props.onLayout(event) } s.componentDidLayout(layouts) } }, immidate ? 0 : LAYOUT_INTERVAL) }, // -------------------- // Specs // -------------------- propTypes: { onLayout: types.func }, // -------------------- // Lifecycle // -------------------- componentWillMount () { const s = this if (s.getInitialLayouts) { s.layouts = s.getInitialLayouts() } let noop = () => undefined defaults(s, { componentWillLayout: noop, componentDidLayout: noop }) }, componentDidMount () { const s = this if (!s.calcLayouts) { console.warn('[ApLayoutMixin] Should implement .calcLayouts()') } window.addEventListener('resize', s.layout) s.layout(true) }, componentWillReceiveProps (nextProps) { const s = this s.layout() }, componentWillUnmount () { const s = this clearTimeout(s._layoutTimer) window.removeEventListener('resize', s.layout) delete s._layoutTimer }, // -------------------- // Private // -------------------- layouts: null, _layoutTimer: null } export default Object.freeze(ApLayoutMixin)