Last active
April 21, 2020 19:16
-
-
Save developit/9d9b01795a9d1c23116497104e25ebfa to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const Component = require('preact/compat').Component; | |
const AUTOBIND_BLACKLIST = { | |
constructor: 1, | |
render: 1, | |
shouldComponentUpdate: 1, | |
componentWillReceiveProps: 1, | |
componentWillUpdate: 1, | |
componentDidUpdate: 1, | |
componentWillMount: 1, | |
componentDidMount: 1, | |
componentWillUnmount: 1, | |
componentDidUnmount: 1 | |
}; | |
function F() { } | |
module.exports = function createClass(obj) { | |
function cl(props, context) { | |
bindAll(this); | |
Component.call(this, props, context); | |
} | |
obj = Object.assign({ constructor: cl }, obj); | |
// We need to apply mixins here so that getDefaultProps is correctly mixed | |
if (obj.mixins) { | |
applyMixins(obj, collateMixins(obj.mixins)); | |
} | |
if (obj.statics) { | |
Object.assign(cl, obj.statics); | |
} | |
if (obj.propTypes) { | |
cl.propTypes = obj.propTypes; | |
} | |
if (obj.defaultProps) { | |
cl.defaultProps = obj.defaultProps; | |
} | |
if (obj.getDefaultProps) { | |
cl.defaultProps = obj.getDefaultProps.call(cl); | |
} | |
F.prototype = Component.prototype; | |
cl.prototype = Object.assign(new F(), obj); | |
cl.displayName = obj.displayName || 'Component'; | |
return cl; | |
} | |
// Flatten an Array of mixins to a map of method name to mixin implementations | |
function collateMixins(mixins) { | |
let keyed = {}; | |
for (let i = 0; i < mixins.length; i++) { | |
let mixin = mixins[i]; | |
for (let key in mixin) { | |
if (mixin.hasOwnProperty(key) && typeof mixin[key] === 'function') { | |
(keyed[key] || (keyed[key] = [])).push(mixin[key]); | |
} | |
} | |
} | |
return keyed; | |
} | |
// apply a mapping of Arrays of mixin methods to a component prototype | |
function applyMixins(proto, mixins) { | |
for (let key in mixins) | |
if (mixins.hasOwnProperty(key)) { | |
proto[key] = multihook( | |
mixins[key].concat(proto[key] || ARR), | |
key === 'getDefaultProps' || key === 'getInitialState' || key === 'getChildContext' | |
); | |
} | |
} | |
function bindAll(ctx) { | |
for (let i in ctx) { | |
let v = ctx[i]; | |
if (typeof v === 'function' && !v.__bound && !AUTOBIND_BLACKLIST.hasOwnProperty(i)) { | |
(ctx[i] = v.bind(ctx)).__bound = true; | |
} | |
} | |
} | |
function callMethod(ctx, m, args) { | |
if (typeof m === 'string') { | |
m = ctx.constructor.prototype[m]; | |
} | |
if (typeof m === 'function') { | |
return m.apply(ctx, args); | |
} | |
} | |
function multihook(hooks, skipDuplicates) { | |
return function () { | |
let ret; | |
for (let i = 0; i < hooks.length; i++) { | |
let r = callMethod(this, hooks[i], arguments); | |
if (skipDuplicates && r != null) { | |
if (!ret) ret = {}; | |
for (let key in r) if (r.hasOwnProperty(key)) { | |
ret[key] = r[key]; | |
} | |
} | |
else if (typeof r !== 'undefined') ret = r; | |
} | |
return ret; | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment