apeman-react-mixins
Version:
React mixin set of apeman.
110 lines (91 loc) • 2.16 kB
JSX
/**
* Mixin to handle resize.
* @mixin ApLayoutMixin
*/
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)