(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.Pillar = factory()); }(this, (function () { 'use strict'; /** Virtual DOM Node */ function VNode() {} /** Global options * @public * @namespace options {Object} */ var options = { /** If `true`, `prop` changes trigger synchronous component updates. * @name syncComponentUpdates * @type Boolean * @default true */ //syncComponentUpdates: true, /** Processes all created VNodes. * @param {VNode} vnode A newly-created VNode to normalize/process */ //vnode(vnode) { } /** Hook invoked after a component is mounted. */ // afterMount(component) { } /** Hook invoked after the DOM is updated with a component's latest render. */ // afterUpdate(component) { } /** Hook invoked immediately before a component is unmounted. */ // beforeUnmount(component) { } }; var stack = []; var EMPTY_CHILDREN = []; /** JSX/hyperscript reviver * Benchmarks: https://esbench.com/bench/57ee8f8e330ab09900a1a1a0 * @see http://jasonformat.com/wtf-is-jsx * @public */ function h(nodeName, attributes) { var children = EMPTY_CHILDREN, lastSimple, child, simple, i; for (i = arguments.length; i-- > 2;) { stack.push(arguments[i]); } if (attributes && attributes.children != null) { if (!stack.length) stack.push(attributes.children); delete attributes.children; } while (stack.length) { if ((child = stack.pop()) && child.pop !== undefined) { for (i = child.length; i--;) { stack.push(child[i]); } } else { if (typeof child === 'boolean') child = null; if (simple = typeof nodeName !== 'function') { if (child == null) child = '';else if (typeof child === 'number') child = String(child);else if (typeof child !== 'string') simple = false; } if (simple && lastSimple) { children[children.length - 1] += child; } else if (children === EMPTY_CHILDREN) { children = [child]; } else { children.push(child); } lastSimple = simple; } } var p = new VNode(); p.nodeName = nodeName; p.children = children; p.attributes = attributes == null ? undefined : attributes; p.key = attributes == null ? undefined : attributes.key; // if a "vnode hook" is defined, pass every created VNode to it if (options.vnode !== undefined) options.vnode(p); return p; } /** Copy own-properties from `props` onto `obj`. * @returns obj * @private */ function extend(obj, props) { for (var i in props) { obj[i] = props[i]; }return obj; } /** Call a function asynchronously, as soon as possible. * @param {Function} callback */ var defer = typeof Promise == 'function' ? Promise.resolve().then.bind(Promise.resolve()) : setTimeout; function cloneElement(vnode, props) { return h(vnode.nodeName, extend(extend({}, vnode.attributes), props), arguments.length > 2 ? [].slice.call(arguments, 2) : vnode.children); } // DOM properties that should NOT have "px" added when numeric var IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i; /** Managed queue of dirty components to be re-rendered */ var items = []; function enqueueRender(component) { if (!component._dirty && (component._dirty = true) && items.push(component) == 1) { (options.debounceRendering || defer)(rerender); } } function rerender() { var p, list = items; items = []; while (p = list.pop()) { if (p._dirty) renderComponent(p); } } /** Check if two nodes are equivalent. * @param {Element} node * @param {VNode} vnode * @private */ function isSameNodeType(node, vnode, hydrating) { if (typeof vnode === 'string' || typeof vnode === 'number') { return node.splitText !== undefined; } if (typeof vnode.nodeName === 'string') { return !node._componentConstructor && isNamedNode(node, vnode.nodeName); } return hydrating || node._componentConstructor === vnode.nodeName; } /** Check if an Element has a given normalized name. * @param {Element} node * @param {String} nodeName */ function isNamedNode(node, nodeName) { return node.normalizedNodeName === nodeName || node.nodeName.toLowerCase() === nodeName.toLowerCase(); } /** * Reconstruct Component-style `props` from a VNode. * Ensures default/fallback values from `defaultProps`: * Own-properties of `defaultProps` not present in `vnode.attributes` are added. * @param {VNode} vnode * @returns {Object} props */ function getNodeProps(vnode) { var props = extend({}, vnode.attributes); props.children = vnode.children; var defaultProps = vnode.nodeName.defaultProps; if (defaultProps !== undefined) { for (var i in defaultProps) { if (props[i] === undefined) { props[i] = defaultProps[i]; } } } return props; } /** Create an element with the given nodeName. * @param {String} nodeName * @param {Boolean} [isSvg=false] If `true`, creates an element within the SVG namespace. * @returns {Element} node */ function createNode(nodeName, isSvg) { var node = isSvg ? document.createElementNS('http://www.w3.org/2000/svg', nodeName) : document.createElement(nodeName); node.normalizedNodeName = nodeName; return node; } /** Remove a child node from its parent if attached. * @param {Element} node The node to remove */ function removeNode(node) { var parentNode = node.parentNode; if (parentNode) parentNode.removeChild(node); } /** Set a named attribute on the given Node, with special behavior for some names and event handlers. * If `value` is `null`, the attribute/handler will be removed. * @param {Element} node An element to mutate * @param {string} name The name/key to set, such as an event or attribute name * @param {any} old The last value that was set for this name/node pair * @param {any} value An attribute value, such as a function to be used as an event handler * @param {Boolean} isSvg Are we currently diffing inside an svg? * @private */ function setAccessor(node, name, old, value, isSvg) { if (name === 'className') name = 'class'; if (name === 'key') { // ignore } else if (name === 'ref') { if (old) old(null); if (value) value(node); } else if (name === 'class' && !isSvg) { node.className = value || ''; } else if (name === 'style') { if (!value || typeof value === 'string' || typeof old === 'string') { node.style.cssText = value || ''; } if (value && typeof value === 'object') { if (typeof old !== 'string') { for (var i in old) { if (!(i in value)) node.style[i] = ''; } } for (var i in value) { node.style[i] = typeof value[i] === 'number' && IS_NON_DIMENSIONAL.test(i) === false ? value[i] + 'px' : value[i]; } } } else if (name === 'dangerouslySetInnerHTML') { if (value) node.innerHTML = value.__html || ''; } else if (name[0] == 'o' && name[1] == 'n') { var useCapture = name !== (name = name.replace(/Capture$/, '')); name = name.toLowerCase().substring(2); if (value) { if (!old) node.addEventListener(name, eventProxy, useCapture); } else { node.removeEventListener(name, eventProxy, useCapture); } (node._listeners || (node._listeners = {}))[name] = value; } else if (name !== 'list' && name !== 'type' && !isSvg && name in node) { setProperty(node, name, value == null ? '' : value); if (value == null || value === false) node.removeAttribute(name); } else { var ns = isSvg && name !== (name = name.replace(/^xlink\:?/, '')); if (value == null || value === false) { if (ns) node.removeAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase());else node.removeAttribute(name); } else if (typeof value !== 'function') { if (ns) node.setAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase(), value);else node.setAttribute(name, value); } } } /** Attempt to set a DOM property to the given value. * IE & FF throw for certain property-value combinations. */ function setProperty(node, name, value) { try { node[name] = value; } catch (e) {} } /** Proxy an event to hooked event handlers * @private */ function eventProxy(e) { return this._listeners[e.type](options.event && options.event(e) || e); } /** Queue of components that have been mounted and are awaiting componentDidMount */ var mounts = []; /** Diff recursion count, used to track the end of the diff cycle. */ var diffLevel = 0; /** Global flag indicating if the diff is currently within an SVG */ var isSvgMode = false; /** Global flag indicating if the diff is performing hydration */ var hydrating = false; /** Invoke queued componentDidMount lifecycle methods */ function flushMounts() { var c; while (c = mounts.pop()) { if (options.afterMount) options.afterMount(c); if (c.componentDidMount) c.componentDidMount(); } } /** Apply differences in a given vnode (and it's deep children) to a real DOM Node. * @param {Element} [dom=null] A DOM node to mutate into the shape of the `vnode` * @param {VNode} vnode A VNode (with descendants forming a tree) representing the desired DOM structure * @returns {Element} dom The created/mutated element * @private */ function diff(dom, vnode, context, mountAll, parent, componentRoot) { // diffLevel having been 0 here indicates initial entry into the diff (not a subdiff) if (!diffLevel++) { // when first starting the diff, check if we're diffing an SVG or within an SVG isSvgMode = parent != null && parent.ownerSVGElement !== undefined; // hydration is indicated by the existing element to be diffed not having a prop cache hydrating = dom != null && !('__preactattr_' in dom); } var ret = idiff(dom, vnode, context, mountAll, componentRoot); // append the element if its a new parent if (parent && ret.parentNode !== parent) parent.appendChild(ret); // diffLevel being reduced to 0 means we're exiting the diff if (! --diffLevel) { hydrating = false; // invoke queued componentDidMount lifecycle methods if (!componentRoot) flushMounts(); } return ret; } /** Internals of `diff()`, separated to allow bypassing diffLevel / mount flushing. */ function idiff(dom, vnode, context, mountAll, componentRoot) { var out = dom, prevSvgMode = isSvgMode; // empty values (null, undefined, booleans) render as empty Text nodes if (vnode == null || typeof vnode === 'boolean') vnode = ''; // Fast case: Strings & Numbers create/update Text nodes. if (typeof vnode === 'string' || typeof vnode === 'number') { // update if it's already a Text node: if (dom && dom.splitText !== undefined && dom.parentNode && (!dom._component || componentRoot)) { /* istanbul ignore if */ /* Browser quirk that can't be covered: https://github.com/developit/preact/commit/fd4f21f5c45dfd75151bd27b4c217d8003aa5eb9 */ if (dom.nodeValue != vnode) { dom.nodeValue = vnode; } } else { // it wasn't a Text node: replace it with one and recycle the old Element out = document.createTextNode(vnode); if (dom) { if (dom.parentNode) dom.parentNode.replaceChild(out, dom); recollectNodeTree(dom, true); } } out['__preactattr_'] = true; return out; } // If the VNode represents a Component, perform a component diff: var vnodeName = vnode.nodeName; if (typeof vnodeName === 'function') { return buildComponentFromVNode(dom, vnode, context, mountAll); } // Tracks entering and exiting SVG namespace when descending through the tree. isSvgMode = vnodeName === 'svg' ? true : vnodeName === 'foreignObject' ? false : isSvgMode; // If there's no existing element or it's the wrong type, create a new one: vnodeName = String(vnodeName); if (!dom || !isNamedNode(dom, vnodeName)) { out = createNode(vnodeName, isSvgMode); if (dom) { // move children into the replacement node while (dom.firstChild) { out.appendChild(dom.firstChild); } // if the previous Element was mounted into the DOM, replace it inline if (dom.parentNode) dom.parentNode.replaceChild(out, dom); // recycle the old element (skips non-Element node types) recollectNodeTree(dom, true); } } var fc = out.firstChild, props = out['__preactattr_'], vchildren = vnode.children; if (props == null) { props = out['__preactattr_'] = {}; for (var a = out.attributes, i = a.length; i--;) { props[a[i].name] = a[i].value; } } // Optimization: fast-path for elements containing a single TextNode: if (!hydrating && vchildren && vchildren.length === 1 && typeof vchildren[0] === 'string' && fc != null && fc.splitText !== undefined && fc.nextSibling == null) { if (fc.nodeValue != vchildren[0]) { fc.nodeValue = vchildren[0]; } } // otherwise, if there are existing or new children, diff them: else if (vchildren && vchildren.length || fc != null) { innerDiffNode(out, vchildren, context, mountAll, hydrating || props.dangerouslySetInnerHTML != null); } // Apply attributes/props from VNode to the DOM Element: diffAttributes(out, vnode.attributes, props); // restore previous SVG mode: (in case we're exiting an SVG namespace) isSvgMode = prevSvgMode; return out; } /** Apply child and attribute changes between a VNode and a DOM Node to the DOM. * @param {Element} dom Element whose children should be compared & mutated * @param {Array} vchildren Array of VNodes to compare to `dom.childNodes` * @param {Object} context Implicitly descendant context object (from most recent `getChildContext()`) * @param {Boolean} mountAll * @param {Boolean} isHydrating If `true`, consumes externally created elements similar to hydration */ function innerDiffNode(dom, vchildren, context, mountAll, isHydrating) { var originalChildren = dom.childNodes, children = [], keyed = {}, keyedLen = 0, min = 0, len = originalChildren.length, childrenLen = 0, vlen = vchildren ? vchildren.length : 0, j, c, f, vchild, child; // Build up a map of keyed children and an Array of unkeyed children: if (len !== 0) { for (var i = 0; i < len; i++) { var _child = originalChildren[i], props = _child['__preactattr_'], key = vlen && props ? _child._component ? _child._component.__key : props.key : null; if (key != null) { keyedLen++; keyed[key] = _child; } else if (props || (_child.splitText !== undefined ? isHydrating ? _child.nodeValue.trim() : true : isHydrating)) { children[childrenLen++] = _child; } } } if (vlen !== 0) { for (var i = 0; i < vlen; i++) { vchild = vchildren[i]; child = null; // attempt to find a node based on key matching var key = vchild.key; if (key != null) { if (keyedLen && keyed[key] !== undefined) { child = keyed[key]; keyed[key] = undefined; keyedLen--; } } // attempt to pluck a node of the same type from the existing children else if (!child && min < childrenLen) { for (j = min; j < childrenLen; j++) { if (children[j] !== undefined && isSameNodeType(c = children[j], vchild, isHydrating)) { child = c; children[j] = undefined; if (j === childrenLen - 1) childrenLen--; if (j === min) min++; break; } } } // morph the matched/found/created DOM child to match vchild (deep) child = idiff(child, vchild, context, mountAll); f = originalChildren[i]; if (child && child !== dom && child !== f) { if (f == null) { dom.appendChild(child); } else if (child === f.nextSibling) { removeNode(f); } else { dom.insertBefore(child, f); } } } } // remove unused keyed children: if (keyedLen) { for (var i in keyed) { if (keyed[i] !== undefined) recollectNodeTree(keyed[i], false); } } // remove orphaned unkeyed children: while (min <= childrenLen) { if ((child = children[childrenLen--]) !== undefined) recollectNodeTree(child, false); } } /** Recursively recycle (or just unmount) a node and its descendants. * @param {Node} node DOM node to start unmount/removal from * @param {Boolean} [unmountOnly=false] If `true`, only triggers unmount lifecycle, skips removal */ function recollectNodeTree(node, unmountOnly) { var component = node._component; if (component) { // if node is owned by a Component, unmount that component (ends up recursing back here) unmountComponent(component); } else { // If the node's VNode had a ref function, invoke it with null here. // (this is part of the React spec, and smart for unsetting references) if (node['__preactattr_'] != null && node['__preactattr_'].ref) node['__preactattr_'].ref(null); if (unmountOnly === false || node['__preactattr_'] == null) { removeNode(node); } removeChildren(node); } } /** Recollect/unmount all children. * - we use .lastChild here because it causes less reflow than .firstChild * - it's also cheaper than accessing the .childNodes Live NodeList */ function removeChildren(node) { node = node.lastChild; while (node) { var next = node.previousSibling; recollectNodeTree(node, true); node = next; } } /** Apply differences in attributes from a VNode to the given DOM Element. * @param {Element} dom Element with attributes to diff `attrs` against * @param {Object} attrs The desired end-state key-value attribute pairs * @param {Object} old Current/previous attributes (from previous VNode or element's prop cache) */ function diffAttributes(dom, attrs, old) { var name; // remove attributes no longer present on the vnode by setting them to undefined for (name in old) { if (!(attrs && attrs[name] != null) && old[name] != null) { setAccessor(dom, name, old[name], old[name] = undefined, isSvgMode); } } // add new & update changed attributes for (name in attrs) { if (name !== 'children' && name !== 'innerHTML' && (!(name in old) || attrs[name] !== (name === 'value' || name === 'checked' ? dom[name] : old[name]))) { setAccessor(dom, name, old[name], old[name] = attrs[name], isSvgMode); } } } /** Retains a pool of Components for re-use, keyed on component name. * Note: since component names are not unique or even necessarily available, these are primarily a form of sharding. * @private */ var components = {}; /** Reclaim a component for later re-use by the recycler. */ function collectComponent(component) { var name = component.constructor.name; (components[name] || (components[name] = [])).push(component); } /** Create a component. Normalizes differences between PFC's and classful Components. */ function createComponent(Ctor, props, context) { var list = components[Ctor.name], inst; if (Ctor.prototype && Ctor.prototype.render) { inst = new Ctor(props, context); Component.call(inst, props, context); } else { inst = new Component(props, context); inst.constructor = Ctor; inst.render = doRender; } if (list) { for (var i = list.length; i--;) { if (list[i].constructor === Ctor) { inst.nextBase = list[i].nextBase; list.splice(i, 1); break; } } } return inst; } /** The `.render()` method for a PFC backing instance. */ function doRender(props, state, context) { return this.constructor(props, context); } /** Set a component's `props` (generally derived from JSX attributes). * @param {Object} props * @param {Object} [opts] * @param {boolean} [opts.renderSync=false] If `true` and {@link options.syncComponentUpdates} is `true`, triggers synchronous rendering. * @param {boolean} [opts.render=true] If `false`, no render will be triggered. */ function setComponentProps(component, props, opts, context, mountAll) { if (component._disable) return; component._disable = true; if (component.__ref = props.ref) delete props.ref; if (component.__key = props.key) delete props.key; if (!component.base || mountAll) { if (component.componentWillMount) component.componentWillMount(); } else if (component.componentWillReceiveProps) { component.componentWillReceiveProps(props, context); } if (context && context !== component.context) { if (!component.prevContext) component.prevContext = component.context; component.context = context; } if (!component.prevProps) component.prevProps = component.props; component.props = props; component._disable = false; if (opts !== 0) { if (opts === 1 || options.syncComponentUpdates !== false || !component.base) { renderComponent(component, 1, mountAll); } else { enqueueRender(component); } } if (component.__ref) component.__ref(component); } /** Render a Component, triggering necessary lifecycle events and taking High-Order Components into account. * @param {Component} component * @param {Object} [opts] * @param {boolean} [opts.build=false] If `true`, component will build and store a DOM node if not already associated with one. * @private */ function renderComponent(component, opts, mountAll, isChild) { if (component._disable) return; var props = component.props, state = component.state, context = component.context, previousProps = component.prevProps || props, previousState = component.prevState || state, previousContext = component.prevContext || context, isUpdate = component.base, nextBase = component.nextBase, initialBase = isUpdate || nextBase, initialChildComponent = component._component, skip = false, rendered, inst, cbase; // if updating if (isUpdate) { component.props = previousProps; component.state = previousState; component.context = previousContext; if (opts !== 2 && component.shouldComponentUpdate && component.shouldComponentUpdate(props, state, context) === false) { skip = true; } else if (component.componentWillUpdate) { component.componentWillUpdate(props, state, context); } component.props = props; component.state = state; component.context = context; } component.prevProps = component.prevState = component.prevContext = component.nextBase = null; component._dirty = false; if (!skip) { rendered = component.render(props, state, context); // context to pass to the child, can be updated via (grand-)parent component if (component.getChildContext) { context = extend(extend({}, context), component.getChildContext()); } var childComponent = rendered && rendered.nodeName, toUnmount, base; if (typeof childComponent === 'function') { // set up high order component link var childProps = getNodeProps(rendered); inst = initialChildComponent; if (inst && inst.constructor === childComponent && childProps.key == inst.__key) { setComponentProps(inst, childProps, 1, context, false); } else { toUnmount = inst; component._component = inst = createComponent(childComponent, childProps, context); inst.nextBase = inst.nextBase || nextBase; inst._parentComponent = component; setComponentProps(inst, childProps, 0, context, false); renderComponent(inst, 1, mountAll, true); } base = inst.base; } else { cbase = initialBase; // destroy high order component link toUnmount = initialChildComponent; if (toUnmount) { cbase = component._component = null; } if (initialBase || opts === 1) { if (cbase) cbase._component = null; base = diff(cbase, rendered, context, mountAll || !isUpdate, initialBase && initialBase.parentNode, true); } } if (initialBase && base !== initialBase && inst !== initialChildComponent) { var baseParent = initialBase.parentNode; if (baseParent && base !== baseParent) { baseParent.replaceChild(base, initialBase); if (!toUnmount) { initialBase._component = null; recollectNodeTree(initialBase, false); } } } if (toUnmount) { unmountComponent(toUnmount); } component.base = base; if (base && !isChild) { var componentRef = component, t = component; while (t = t._parentComponent) { (componentRef = t).base = base; } base._component = componentRef; base._componentConstructor = componentRef.constructor; } } if (!isUpdate || mountAll) { mounts.unshift(component); } else if (!skip) { // Ensure that pending componentDidMount() hooks of child components // are called before the componentDidUpdate() hook in the parent. // Note: disabled as it causes duplicate hooks, see https://github.com/developit/preact/issues/750 // flushMounts(); if (component.componentDidUpdate) { component.componentDidUpdate(previousProps, previousState, previousContext); } if (options.afterUpdate) options.afterUpdate(component); } if (component._renderCallbacks != null) { while (component._renderCallbacks.length) { component._renderCallbacks.pop().call(component); } } if (!diffLevel && !isChild) flushMounts(); } /** Apply the Component referenced by a VNode to the DOM. * @param {Element} dom The DOM node to mutate * @param {VNode} vnode A Component-referencing VNode * @returns {Element} dom The created/mutated element * @private */ function buildComponentFromVNode(dom, vnode, context, mountAll) { var c = dom && dom._component, originalComponent = c, oldDom = dom, isDirectOwner = c && dom._componentConstructor === vnode.nodeName, isOwner = isDirectOwner, props = getNodeProps(vnode); while (c && !isOwner && (c = c._parentComponent)) { isOwner = c.constructor === vnode.nodeName; } if (c && isOwner && (!mountAll || c._component)) { setComponentProps(c, props, 3, context, mountAll); dom = c.base; } else { if (originalComponent && !isDirectOwner) { unmountComponent(originalComponent); dom = oldDom = null; } c = createComponent(vnode.nodeName, props, context); if (dom && !c.nextBase) { c.nextBase = dom; // passing dom/oldDom as nextBase will recycle it if unused, so bypass recycling on L229: oldDom = null; } setComponentProps(c, props, 1, context, mountAll); dom = c.base; if (oldDom && dom !== oldDom) { oldDom._component = null; recollectNodeTree(oldDom, false); } } return dom; } /** Remove a component from the DOM and recycle it. * @param {Component} component The Component instance to unmount * @private */ function unmountComponent(component) { if (options.beforeUnmount) options.beforeUnmount(component); var base = component.base; component._disable = true; if (component.componentWillUnmount) component.componentWillUnmount(); component.base = null; // recursively tear down & recollect high-order component children: var inner = component._component; if (inner) { unmountComponent(inner); } else if (base) { if (base['__preactattr_'] && base['__preactattr_'].ref) base['__preactattr_'].ref(null); component.nextBase = base; removeNode(base); collectComponent(component); removeChildren(base); } if (component.__ref) component.__ref(null); } /** Base Component class. * Provides `setState()` and `forceUpdate()`, which trigger rendering. * @public * * @example * class MyFoo extends Component { * render(props, state) { * return
; * } * } */ function Component(props, context) { this._dirty = true; /** @public * @type {object} */ this.context = context; /** @public * @type {object} */ this.props = props; /** @public * @type {object} */ this.state = this.state || {}; } extend(Component.prototype, { /** Returns a `boolean` indicating if the component should re-render when receiving the given `props` and `state`. * @param {object} nextProps * @param {object} nextState * @param {object} nextContext * @returns {Boolean} should the component re-render * @name shouldComponentUpdate * @function */ /** Update component state by copying properties from `state` to `this.state`. * @param {object} state A hash of state properties to update with new values * @param {function} callback A function to be called once component state is updated */ setState: function setState(state, callback) { var s = this.state; if (!this.prevState) this.prevState = extend({}, s); extend(s, typeof state === 'function' ? state(s, this.props) : state); if (callback) (this._renderCallbacks = this._renderCallbacks || []).push(callback); enqueueRender(this); }, /** Immediately perform a synchronous re-render of the component. * @param {function} callback A function to be called after component is re-rendered. * @private */ forceUpdate: function forceUpdate(callback) { if (callback) (this._renderCallbacks = this._renderCallbacks || []).push(callback); renderComponent(this, 2); }, /** Accepts `props` and `state`, and returns a new Virtual DOM tree to build. * Virtual DOM is generally constructed via [JSX](http://jasonformat.com/wtf-is-jsx). * @param {object} props Props (eg: JSX attributes) received from parent element/component * @param {object} state The component's current state * @param {object} context Context object (if a parent component has provided context) * @returns VNode */ render: function render() {} }); /** Render JSX into a `parent` Element. * @param {VNode} vnode A (JSX) VNode to render * @param {Element} parent DOM element to render into * @param {Element} [merge] Attempt to re-use an existing DOM tree rooted at `merge` * @public * * @example * // render a div into : * render(
hello!
, document.body); * * @example * // render a "Thing" component into #foo: * const Thing = ({ name }) => { name }; * render(, document.querySelector('#foo')); */ function render(vnode, parent, merge) { return diff(merge, vnode, {}, false, parent, false); } var preact = { h: h, createElement: h, cloneElement: cloneElement, Component: Component, render: render, rerender: rerender, options: options }; var preact_esm = Object.freeze({ h: h, createElement: h, cloneElement: cloneElement, Component: Component, render: render, rerender: rerender, options: options, default: preact }); /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ /** * Use invariant() to assert state which your program assumes to be true. * * Provide sprintf-style format (only %s is supported) and arguments * to provide information about what broke and what you were * expecting. * * The invariant message will be stripped in production, but the invariant * will remain to ensure logic does not differ in production. */ var validateFormat = function validateFormat(format) {}; { validateFormat = function validateFormat(format) { if (format === undefined) { throw new Error('invariant requires an error message argument'); } }; } function invariant(condition, format, a, b, c, d, e, f) { validateFormat(format); if (!condition) { var error; if (format === undefined) { error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.'); } else { var args = [a, b, c, d, e, f]; var argIndex = 0; error = new Error(format.replace(/%s/g, function () { return args[argIndex++]; })); error.name = 'Invariant Violation'; } error.framesToPop = 1; // we don't care about invariant's own frame throw error; } } var invariant_1 = invariant; var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } var require$$0 = ( preact_esm && preact ) || preact_esm; var preactMarkup = createCommonjsModule(function (module, exports) { (function (global, factory) { module.exports = factory(require$$0); }(commonjsGlobal, function (preact) { var parserDoc = void 0; function parseMarkup(markup, type) { var doc = void 0, mime = type === 'html' ? 'text/html' : 'application/xml', parserError = void 0, wrappedMarkup = void 0, tag = void 0; if (type === 'html') { tag = 'body'; wrappedMarkup = '\n' + markup + ''; } else { tag = 'xml'; wrappedMarkup = '\n' + markup + ''; } try { doc = new DOMParser().parseFromString(wrappedMarkup, mime); } catch (err) { parserError = err; } if (!doc && type === 'html') { doc = parserDoc || (parserDoc = buildParserFrame()); doc.open(); doc.write(wrappedMarkup); doc.close(); } if (!doc) return; var out = doc.getElementsByTagName(tag)[0], fc = out.firstChild; if (markup && !fc) { out.error = 'Document parse failed.'; } if (fc && String(fc.nodeName).toLowerCase() === 'parsererror') { fc.removeChild(fc.firstChild); fc.removeChild(fc.lastChild); out.error = fc.textContent || fc.nodeValue || parserError || 'Unknown error'; out.removeChild(fc); } return out; } function buildParserFrame() { if (document.implementation && document.implementation.createHTMLDocument) { return document.implementation.createHTMLDocument(''); } var frame = document.createElement('iframe'); frame.style.cssText = 'position:absolute; left:0; top:-999em; width:1px; height:1px; overflow:hidden;'; frame.setAttribute('sandbox', 'allow-forms'); document.body.appendChild(frame); return frame.contentWindow.document; } var EMPTY_OBJ$1 = {}; function toVdom(node, visitor, h, options) { walk.visitor = visitor; walk.h = h; walk.options = options || EMPTY_OBJ$1; return walk(node); } function walk(n, index, arr) { if (n.nodeType === 3) { var text = 'textContent' in n ? n.textContent : n.nodeValue || ''; if (walk.options.trim !== false) { var isFirstOrLast = index === 0 || index === arr.length - 1; if (text.match(/^[\s\n]+$/g) && walk.options.trim !== 'all') { text = ' '; } else { text = text.replace(/(^[\s\n]+|[\s\n]+$)/g, walk.options.trim === 'all' || isFirstOrLast ? '' : ' '); } if ((!text || text === ' ') && arr.length > 1 && isFirstOrLast) return null; } return text; } if (n.nodeType !== 1) return null; var nodeName = String(n.nodeName).toLowerCase(); if (nodeName === 'script' && !walk.options.allowScripts) return null; var out = walk.h(nodeName, getProps(n.attributes), walkChildren(n.childNodes)); if (walk.visitor) walk.visitor(out); return out; } function getProps(attrs) { var len = attrs && attrs.length; if (!len) return null; var props = {}; for (var i = 0; i < len; i++) { var _attrs$i = attrs[i]; var name = _attrs$i.name; var value = _attrs$i.value; if (value === '') value = true; if (name.substring(0, 2) === 'on' && walk.options.allowEvents) { value = new Function(value); } props[name] = value; } return props; } function walkChildren(children) { var c = children && Array.prototype.map.call(children, walk).filter(exists); return c && c.length ? c : null; } var exists = function (x) { return x; }; var EMPTY_OBJ = {}; function markupToVdom(markup, type, reviver, map, options) { var dom = parseMarkup(markup, type); if (dom && dom.error) { throw new Error(dom.error); } var body = dom && dom.body || dom; visitor.map = map || EMPTY_OBJ; var vdom = body && toVdom(body, visitor, reviver, options); visitor.map = null; return vdom && vdom.children || null; } function toCamelCase(name) { return name.replace(/-(.)/g, function (match, letter) { return letter.toUpperCase(); }); } function visitor(node) { var name = node.nodeName.toLowerCase(), map = visitor.map; if (map && map.hasOwnProperty(name)) { node.nodeName = map[name]; node.attributes = Object.keys(node.attributes || {}).reduce(function (attrs, attrName) { attrs[toCamelCase(attrName)] = node.attributes[attrName]; return attrs; }, {}); } else { node.nodeName = name.replace(/[^a-z0-9-]/i, ''); } } var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }; var objectWithoutProperties = function (obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }; var possibleConstructorReturn = function (self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }; var customReviver = void 0; var Markup = function (_Component) { inherits(Markup, _Component); function Markup() { classCallCheck(this, Markup); return possibleConstructorReturn(this, _Component.apply(this, arguments)); } Markup.setReviver = function setReviver(h) { customReviver = h; }; Markup.prototype.shouldComponentUpdate = function shouldComponentUpdate(_ref) { var wrap = _ref.wrap; var type = _ref.type; var markup = _ref.markup; var p = this.props; return wrap !== p.wrap || type !== p.type || markup !== p.markup; }; Markup.prototype.setComponents = function setComponents(components) { this.map = {}; if (components) { for (var i in components) { if (components.hasOwnProperty(i)) { var name = i.replace(/([A-Z]+)([A-Z][a-z0-9])|([a-z0-9]+)([A-Z])/g, '$1$3-$2$4').toLowerCase(); this.map[name] = components[i]; } } } }; Markup.prototype.render = function render(_ref2) { var _ref2$wrap = _ref2.wrap; var wrap = _ref2$wrap === undefined ? true : _ref2$wrap; var type = _ref2.type; var markup = _ref2.markup; var components = _ref2.components; var reviver = _ref2.reviver; var onError = _ref2.onError; var allowScripts = _ref2['allow-scripts']; var allowEvents = _ref2['allow-events']; var trim = _ref2.trim; var props = objectWithoutProperties(_ref2, ['wrap', 'type', 'markup', 'components', 'reviver', 'onError', 'allow-scripts', 'allow-events', 'trim']); var h = reviver || this.reviver || this.constructor.prototype.reviver || customReviver || preact.h, vdom = void 0; this.setComponents(components); var options = { allowScripts: allowScripts, allowEvents: allowEvents, trim: trim }; try { vdom = markupToVdom(markup, type, h, this.map, options); } catch (error) { if (onError) { onError({ error: error }); } else if (typeof console !== 'undefined' && console.error) { console.error('preact-markup: ' + error); } } if (wrap === false) return vdom && vdom[0] || null; var c = props.hasOwnProperty('className') ? 'className' : 'class', cl = props[c]; if (!cl) props[c] = 'markup';else if (cl.splice) cl.splice(0, 0, 'markup');else if (typeof cl === 'string') props[c] += ' markup';else if (typeof cl === 'object') cl.markup = true; return h('div', props, vdom || null); }; return Markup; }(preact.Component); return Markup; })); }); var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }; var possibleConstructorReturn = function (self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }; /** * Minimal implementation of Mustache templates * Taken from https://github.com/aishikaty/tiny-mustache */ /* eslint-disable */ function mustache(template, self, parent, invert) { var render = mustache; var output = ''; var i = void 0; function get$$1(ctx, path) { path = path.pop ? path : path.split('.'); ctx = ctx[path.shift()] || ''; return 0 in path ? get$$1(ctx, path) : ctx; } self = Array.isArray(self) ? self : self ? [self] : []; self = invert ? 0 in self ? [] : [1] : self; for (i = 0; i < self.length; i++) { var childCode = ''; var depth = 0; var inverted; var ctx = _typeof(self[i]) === 'object' ? self[i] : {}; ctx = Object.assign({}, parent, ctx); ctx[''] = { '': self[i] }; template.replace(/([\s\S]*?)({{((\/)|(\^)|#)(.*?)}}|$)/g, function (match, code, y, z, close, invert, name) { if (!depth) { output += code.replace(/{{{(.*?)}}}|{{(!?)(&?)(>?)(.*?)}}/g, function (match, raw, comment, isRaw, partial, name) { return raw ? get$$1(ctx, raw) : isRaw ? get$$1(ctx, name) : partial ? render(get$$1(ctx, name), ctx) : !comment ? new Option(get$$1(ctx, name)).innerHTML : ''; }); inverted = invert; } else { childCode += depth && !close || depth > 1 ? match : code; } if (close) { if (! --depth) { name = get$$1(ctx, name); if (/^f/.test(typeof name === 'undefined' ? 'undefined' : _typeof(name))) { output += name.call(ctx, childCode, function (template) { return render(template, ctx); }); } else { output += render(childCode, name, ctx, inverted); } childCode = ''; } } else { ++depth; } }); } return output; } // This is used for emptying VDOM var Null = function Null() { return null; }; /* eslint-disable no-underscore-dangle */ var PillarBaseElement = function (_HTMLElement) { inherits(PillarBaseElement, _HTMLElement); function PillarBaseElement() { var _ref; var _temp, _this, _ret; classCallCheck(this, PillarBaseElement); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this = possibleConstructorReturn(this, (_ref = PillarBaseElement.__proto__ || Object.getPrototypeOf(PillarBaseElement)).call.apply(_ref, [this].concat(args))), _this), _this.props = { flags: {} }, _temp), possibleConstructorReturn(_this, _ret); } createClass(PillarBaseElement, [{ key: 'convertToVdom', /** * Convert to VDOM * * @description Converts given HTML node into a Virtual DOM node * @param {HTMLElement} element - Element to convert * @param {VNode} [node] - Virtual dom node * @returns {PillarConnectedComponent} * @memberof Pillar */ value: function convertToVdom(element, node) { if (element.nodeType === 3) return element.nodeValue; if (element.nodeType !== 1) return null; var attributes = element.attributes, childNodes = element.childNodes; var children = []; this.mapAttributesToProps(attributes); // If we're not using children as placeholder, go through child nodes and parse them too if (!this.props.flags.ignoreChildren) { for (var i = 0; i < childNodes.length; i += 1) { children[i] = this.convertToVdom(childNodes[i], null, true); } } // @REFACTOR? This feels dirty. If not using Shadow DOM, // existing children are appended to, instead of being overwritten by VDOM render. // This works fine, but we need to investigate for a better way to do it. if (!this.useShadow) { for (var _i = 0; _i < childNodes.length; _i += 1) { element.removeChild(childNodes[_i]); } } var ConnectedComponent = void 0; if (node) { ConnectedComponent = this.connectAttrsToProps(node); } else { ConnectedComponent = element.nodeName.toLowerCase(); } var componentProps = node ? this.props : null; return h( ConnectedComponent, componentProps, children ); } /** * Map attributes to props * * @description Goes through element's attributes and maps them to `this.props` and `this.flags` * @param {NamedNodeMap} attributes * @memberof PillarBaseElement */ }, { key: 'mapAttributesToProps', value: function mapAttributesToProps(attributes) { for (var i = 0; i < attributes.length; i += 1) { invariant_1(attributes[i].name !== 'flags', 'Attribute "flags" is reserved'); if (attributes[i].name.indexOf('p:') === -1) { // Map attributes to props var name = PillarBaseElement.dashToCamel(attributes[i].name); this.props[name] = attributes[i].value; } else { // Map flags separately var flagName = PillarBaseElement.dashToCamel(attributes[i].name.replace('p:', '')); this.props.flags[flagName] = attributes[i].value || true; // UIKit-style implicit boolean } } } // Fires when custom element creates }, { key: 'connectedCallback', value: function connectedCallback() { this.initialize(); } // Fires when custom element is destroyed }, { key: 'disconnectedCallback', value: function disconnectedCallback() { render(h(Null, null), this.shadow || this, this.root); } /** * Initialize * @description Initialize Pillar web component * @memberof Pillar */ }, { key: 'initialize', value: function initialize() { var _this2 = this; this.observer = new MutationObserver(function (mutations) { if (_this2.props.flags.protected) { // Lock external mutations invariant_1(false, 'Attempting to change attributes of protected component.'); // @TODO Revert attributes? } else { var newProps = []; mutations.forEach(function (mutation) { var attributeName = mutation.attributeName; newProps.push({ name: attributeName, value: _this2.attributes[attributeName] ? _this2.attributes[attributeName].value : null }); }); _this2.mapAttributesToProps(newProps); if (_this2.passPropsToVdom) { _this2.passPropsToVdom(_this2.props); if (_this2.__pillar__) { // Wait till it's for sure rendered, then pass it to dev tools setTimeout(function () { return _this2.hookToDevTools(_this2.__pillar__); }, 200); } } } }); // Activate observer this.observer.observe(this, { attributes: true, attributeOldValue: true }); if (this.useShadow) { invariant_1(this.useShadow === 'open' || this.useShadow === 'closed', 'Shadow DOM mode is expected to be "open" or "closed", but got %s', this.useShadow); this.shadow = this.attachShadow({ mode: this.useShadow }); } var snapshot = void 0; try { snapshot = this.vdomComponent(this.props); } catch (e) { // VDOM component is a class, so moving on } if (this.vdomComponent.prototype.render || (typeof snapshot === 'undefined' ? 'undefined' : _typeof(snapshot)) === 'object') { this.renderComponent(); } else if (typeof snapshot === 'string') { if (snapshot.charAt(0) === '#') { this.renderTemplate(snapshot.slice(1)); } else { this.renderString(); } } else { invariant_1(false, 'Component must return a JSX element, HTML string or template ID.'); } } /** * Connect element attributes to props * * @description Creates a higher order component that makes element's attributes * available in wrapped component's 'this.props', allowing reacting * to their changes via 'componentWillReceiveProps'. * @param {PillarComponent} WrappedComponent * @returns {PillarConnectedComponent} * @memberof PillarBaseElement */ }, { key: 'connectAttrsToProps', value: function connectAttrsToProps(WrappedComponent) { var element = this; // Higher order component to link props to the outside world return function (_Component) { inherits(PillarConnectedComponent, _Component); function PillarConnectedComponent() { classCallCheck(this, PillarConnectedComponent); var _this3 = possibleConstructorReturn(this, (PillarConnectedComponent.__proto__ || Object.getPrototypeOf(PillarConnectedComponent)).call(this)); element.passPropsToVdom = _this3.reinsertProps.bind(_this3); return _this3; } /** * Reinsert props * * @description Updates props from attributes and triggers re-render of wrapped component * @param {object} attrProps */ createClass(PillarConnectedComponent, [{ key: 'reinsertProps', value: function reinsertProps(attrProps) { this.setState(_extends({}, this.state, { attrProps: attrProps })); } }, { key: 'render', value: function render$$1() { return h(WrappedComponent, _extends({}, this.props, this.state.attrProps)); } }]); return PillarConnectedComponent; }(Component); } /** * DevTools Hook * * @description Hook created element to Pillar DevTools plugin if it exists * @memberof PillarBaseElement */ }, { key: 'hookToDevTools', value: function hookToDevTools(existingId) { if (window.__PILLAR_DEVTOOLS_HOOK__) { console.log('HOOK', existingId, this.__pillar__); var id = existingId || Math.random().toString(36).slice(2); window.__PILLAR_DEVTOOLS_HOOK__.elements[id] = { name: this.localName, props: this.props, useShadow: this.useShadow, innerHTML: this.useShadow ? this.shadow.innerHTML : this.innerHTML, outerHTML: this.useShadow ? this.shadow.outerHTML : this.outerHTML }; if (!window.__PILLAR_DEVTOOLS_HOOK__.attached) { window.__PILLAR_DEVTOOLS_HOOK__.attached = true; } if (!existingId) { this.__pillar__ = id; } else { window.postMessage({ type: 'PILLAR_UPDATE' }, '*'); } } } /** * Render component * * @description Render JSX component. NOTE: This method is only called once. * @memberof PillarBaseElement */ }, { key: 'renderComponent', value: function renderComponent() { this.root = render(this.convertToVdom(this, this.vdomComponent), this.shadow || this, this.root); this.hookToDevTools(); } /** * Render string * * @description Render contents of an HTML string. NOTE: This method is only called once. * @memberof PillarBaseElement */ }, { key: 'renderString', value: function renderString() { var _this4 = this; this.mapAttributesToProps(this.attributes); this.innerHTML = null; this.root = render(h(preactMarkup, { markup: this.vdomComponent(this.props) }), this.shadow || this); this.passPropsToVdom = function (props) { render(h(preactMarkup, { markup: _this4.vdomComponent(props) }), _this4.shadow || _this4, _this4.root); }; this.hookToDevTools(); } /** * Render Template * * * @description Render template tag's content. NOTE: This method is only called once. * @param {any} id - ID of a template tag * @memberof PillarBaseElement */ }, { key: 'renderTemplate', value: function renderTemplate(id) { var _this5 = this; // Get an HTML string for running through Mustache var template = document.getElementById(id).innerHTML; this.mapAttributesToProps(this.attributes); this.innerHTML = null; this.root = render(h(preactMarkup, { markup: mustache(template, this.props), 'allow-scripts': this.allowScripts }), this.shadow || this); this.passPropsToVdom = function (props) { render(h(preactMarkup, { markup: mustache(template, props), 'allow-scripts': _this5.allowScripts }), _this5.shadow || _this5, _this5.root); }; this.hookToDevTools(); } }], [{ key: 'dashToCamel', /** * Dash to Camel case * * @description Convert dash-cased-string to camelCasedString * @static * @param {string} dash - string to convert * @returns {string} * @memberof Pillar */ value: function dashToCamel(dash) { return dash.indexOf('-') < 0 ? dash : dash.toLowerCase().replace(/-[aA-zZ]/g, function (m) { return m[1].toUpperCase(); }); } /** * Camel to Dash case * * @description Convert camelCasedString to dash-cased-string * @static * @param {string} camel - string to convert * @returns {string} * @memberof Pillar */ }, { key: 'camelToDash', value: function camelToDash(camel) { return camel.replace(/([A-Z])/g, '-$1').toLowerCase(); } }]); return PillarBaseElement; }(HTMLElement); var Pillar = function (_Component) { inherits(Pillar, _Component); createClass(Pillar, null, [{ key: 'register', /** * Register tag * * @description Register custom element as an HTML tag with the name specified * @static * @param {any} tagName - Name of an HTML tag to register * @param {Pillar} TargetComponent - Component to register as a tag * @memberof Pillar */ value: function register(TargetComponent, tagName) { var elementOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; if (typeof TargetComponent === 'string') { Pillar.invariant(tagName, 'When using a template tag, you need to explicitly define tag name to register'); } var elementName = tagName || PillarBaseElement.camelToDash(TargetComponent.name).slice(1); Pillar.invariant(!window.customElements.get(elementName), 'Element "' + tagName + '" has already been defined. You can only define element once.'); Pillar.invariant(TargetComponent, 'You need to pass the component to create element from.'); // Define custom element window.customElements.define(elementName, Pillar.createElement(TargetComponent, elementOptions)); } }, { key: 'createElement', value: function createElement(TargetComponent, elementOptions) { return function (_PillarBaseElement) { inherits(PillarElement, _PillarBaseElement); function PillarElement() { classCallCheck(this, PillarElement); var _this2 = possibleConstructorReturn(this, (PillarElement.__proto__ || Object.getPrototypeOf(PillarElement)).call(this)); Object.assign(_this2, elementOptions); // Extend "this" with options Pillar.invariant(typeof TargetComponent === 'string' || typeof TargetComponent === 'function', 'Register method requires a component or template tag ID, but found unexpected %s', typeof TargetComponent === 'undefined' ? 'undefined' : _typeof(TargetComponent)); if (typeof TargetComponent === 'string') { _this2.vdomComponent = function () { return TargetComponent; }; } else { _this2.vdomComponent = TargetComponent; } return _this2; } return PillarElement; }(PillarBaseElement); } }]); function Pillar(props, state) { classCallCheck(this, Pillar); var _this = possibleConstructorReturn(this, (Pillar.__proto__ || Object.getPrototypeOf(Pillar)).call(this, props, state)); _this.validateRender(); _this.flags = _this.props ? _this.props.flags : {}; if (_this.componentWillReceiveProps) { var originalHandler = _this.componentWillReceiveProps.bind(_this); _this.componentWillReceiveProps = function (nextProps, nextState) { _this.flags = nextProps.flags; originalHandler(nextProps, nextState); }; } else { _this.componentWillReceiveProps = function (nextProps) { _this.flags = nextProps.flags; }; } return _this; } /** * Validate render method * @description Makes sure there's only one render method and it's actually a method * @memberof Pillar */ createClass(Pillar, [{ key: 'validateRender', value: function validateRender() { Pillar.invariant(typeof this.render === 'function', 'render() is expected to be a function, but got a type "%s"', _typeof(this.render)); } }]); return Pillar; }(Component); Pillar.invariant = invariant_1; Pillar.h = h; Pillar.register(function (_ref) { var text = _ref.text; return h( 'h1', null, text ); }, 'custom-header'); return Pillar; })));