UNPKG

52.9 kBSource Map (JSON)View Raw
1{"version":3,"file":"composi.js.map","sources":["../lib/utils.js","../lib/vnode.js","../lib/vdom.js","../lib/mount.js","../lib/component.js","../data-store/observer.js","../data-store/dataStore.js","../data-store/dataStore-component.js","../lib/h.js","../lib/unmount.js","../lib/render.js","../lib/fragment.js"],"sourcesContent":["/**\n * Used to determine if a vnode should be recycled.\n * @type {number}\n */\nexport const RECYCLED_NODE = 0\n\n/**\n * Used in a vnode to indicate that it is a DOM node.\n * @type {number}\n */\nexport const ELEMENT_NODE = 1\n\n/**\n * Used in a vnode to indicate that it is a text node.\n * @type {number}\n */\nexport const TEXT_NODE = 3\n\n/**\n * Namespace for SVG elements with `xlink:href` attributes.\n * @type {string}\n */\nexport const XLINK_NS = 'http://www.w3.org/1999/xlink'\n\n/**\n * Namespace for SVG elements.\n * @type {string}\n */\nexport const SVG_NS = 'http://www.w3.org/2000/svg'\n\n/**\n * An empty object. Used as placeholder for `props` in VNode.\n * @type {{}} EMPTY_OBJECT\n */\nexport const EMPTY_OBJECT = {}\n\n/**\n * An empty array. Used for access to array methods.\n * @type {any[]} EMPTY_ARRAY\n */\nexport const EMPTY_ARRAY = []\n\n/**\n * Combine two objects, merging the second into the first. Any properties already existing in the first will be replaced by those of the second. Any properties in the second not in the first will be added to it.\n * @param {Object.<string, any>} firstObject\n * @param {Object.<string, any>} secondObject\n * @return {Object.<string, any>} target\n */\nexport function merge(firstObject, secondObject) {\n const target = {}\n\n for (let i in firstObject) target[i] = firstObject[i]\n for (let j in secondObject) target[j] = secondObject[j]\n\n return target\n}\n\n/**\n * A function to test where something is an object literal or not. Used by Component setState.\n * @param {Object.<string, any>} obj An object literal to test.\n * @return {boolean} boolean\n */\nexport function isObject(obj) {\n if (Array.isArray(obj)) return false\n else if (typeof obj === 'object') return true\n return false\n}\n\n/**\n * A function to test whether the data provided for updating a component creates a new virtual node or not.\n * @typedef {import('./vnode').VNode} VNode\n * @param {VNode} oldVNode The previous virtual node of a component.\n * @param {VNode} newVNode The current virtual node of a component.\n * @return {boolean} boolean\n */\nexport function isSameVNode(oldVNode, newVNode) {\n return JSON.stringify(oldVNode) === JSON.stringify(newVNode)\n}\n\n/**\n * Class to throw error message when attempting to insert Fragement tag directly into DOM.\n * @return {string} message\n */\nexport class FragmentError {\n constructor() {\n this.message = 'Cannot insert Fragment tag directly into DOM.'\n this.toString = function() {\n return this.message\n }\n }\n}\n\n/**\n * Function to create an RFC4122 version 4 compliant uuid.\n * @return {string} string\n */\nexport function uuid() {\n var d = new Date().getTime()\n if (\n typeof performance !== 'undefined' &&\n typeof performance.now === 'function'\n ) {\n d += performance.now() //use high-precision timer if available\n }\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n var r = (d + Math.random() * 16) % 16 | 0\n d = Math.floor(d / 16)\n return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16)\n })\n}\n","import { EMPTY_OBJECT, EMPTY_ARRAY, TEXT_NODE, RECYCLED_NODE } from './utils'\n/**\n * @typedef {Object.<string, any> | {}} Props\n * @property {Children} Props.children\n */\n/**\n * @typedef {VNode[]} Children\n */\n/**\n * @typedef {string | number | Function} Type\n * @typedef {number | string | null} Key\n * @typedef {Object.<string, any>} VNode\n * @property {Type} VNode.type\n * @property {Props} VNode.props\n * @property {Children} VNode.children\n * @property {Element} VNode.element\n * @property {Key} [VNode.key]\n * @property {number} VNode.flag\n */\n/**\n * @param {string | Function} type\n * @param {Props} props\n * @param {Children} children\n * @param {Element} element\n * @param {Key} key\n * @param {number} flag\n * @return {VNode} VNode\n */\n\n/**\n * Create a virtual node with the provided properties.\n * @param {string | Function} type\n * @param {Props} props\n * @param {Children} children\n * @param {Element} element\n * @param {string | number | null} key\n * @param {number} flag\n * @return {VNode} VNode\n */\nexport function createVNode(type, props, children, element, key, flag) {\n return {\n type,\n props,\n children,\n element,\n key,\n flag\n }\n}\n\n/**\n * Create a virtual text node.\n * @param {string} text\n * @param {Element} [element]\n * @return {VNode} VNode\n */\nexport function createTextVNode(text, element) {\n return createVNode(text, EMPTY_OBJECT, EMPTY_ARRAY, element, null, TEXT_NODE)\n}\n\n/**\n * Create a virtual node represeting an element and its children.\n * @param {Element} element\n * @return {VNode} VNode\n */\nexport function vnodeFromElement(element) {\n return createVNode(\n element.nodeName.toLowerCase(),\n EMPTY_OBJECT,\n EMPTY_ARRAY.map.call(element.childNodes, vnodeFromChild),\n element,\n null,\n RECYCLED_NODE\n )\n}\n\n/**\n * Cycle through the child nodes of an element and create virtual nodes of them.\n * @param {Element} element\n * @return {VNode}\n */\nfunction vnodeFromChild(element) {\n if (element.nodeType === 3) {\n return createTextVNode(element.nodeValue, element)\n } else {\n return vnodeFromElement(element)\n }\n}\n","import { RECYCLED_NODE, TEXT_NODE, XLINK_NS, SVG_NS, merge } from './utils'\n\n/**\n * Event proxy for inline events.\n * @param {Event} event\n * @return {any} any\n */\nfunction eventProxy(event) {\n return event.currentTarget['events'][event.type](event)\n}\n\n/**\n * Get the key value of a virtual node.\n * @typedef {import('./vnode').VNode} VNode\n * @param {VNode} node\n * @return {string | number | null}\n */\nfunction getKey(node) {\n return node == null ? null : node.key\n}\n\n/**\n * Create a map of keyed nodes.\n * @typedef {import('./vnode').Children} Children\n * @param {Children} children\n * @param {number} start\n * @param {number} end\n * @return {Object.<string, any>} Object.<string, any>\n */\nfunction createKeyMap(children, start, end) {\n const out = {}\n let key\n let node\n\n for (; start <= end; start++) {\n if ((key = (node = children[start]).key) != null) {\n out[key] = node\n }\n }\n\n return out\n}\n\n/**\n * Update the properties and attributes of a VNode based on new data.\n * @param {Element} element\n * @param {string} prop\n * @param {any} oldValue\n * @param {any} newValue\n * @param {boolean} isSVG\n * @return {void} undefined\n */\nfunction setProp(element, prop, oldValue, newValue, isSVG) {\n if (\n prop === 'style' &&\n typeof newValue === 'object' &&\n !Array.isArray(newValue)\n ) {\n for (let i in merge(oldValue, newValue)) {\n const style = newValue == null || newValue[i] == null ? '' : newValue[i]\n if (i[0] === '-') {\n element[prop].setProperty(i, style)\n } else {\n element[prop][i] = style\n }\n }\n } else if (prop !== 'key') {\n if (prop === 'className') prop = 'class'\n\n if (prop[0] === 'o' && prop[1] === 'n') {\n if (!element['events']) element['events'] = {}\n element['events'][(prop = prop.slice(2).toLowerCase())] = newValue\n\n if (newValue == null) {\n element.removeEventListener(prop, eventProxy)\n } else if (oldValue == null) {\n element.addEventListener(prop, eventProxy)\n }\n } else {\n const nullOrFalse =\n newValue == null ||\n newValue === false ||\n newValue === 'no' ||\n newValue === 'off'\n\n if (\n prop in element &&\n prop !== 'list' &&\n prop !== 'type' &&\n prop !== 'draggable' &&\n prop !== 'spellcheck' &&\n prop !== 'translate' &&\n !isSVG\n ) {\n element[prop] = newValue == null ? '' : newValue\n if (nullOrFalse) {\n element.removeAttribute(prop)\n }\n } else {\n if (prop === 'xlink-href' || prop === 'xlinkHref') {\n element.setAttributeNS(XLINK_NS, 'href', newValue)\n element.setAttribute('href', newValue)\n } else {\n if (nullOrFalse) {\n element.removeAttribute(prop)\n } else {\n element.setAttribute(prop, newValue)\n }\n }\n }\n }\n }\n}\n\n/**\n * Create an element, either node or text, from a VNode.\n * @typedef {Function[]} Lifecycle\n * @param {VNode} vnode\n * @param {Lifecycle} lifecycle\n * @param {boolean} [isSVG]\n * @return {Element}\n */\nexport function createElement(vnode, lifecycle, isSVG) {\n let element\n if (vnode.flag === TEXT_NODE) {\n element = document.createTextNode(/** @type {string} */ (vnode.type))\n } else {\n if ((isSVG = isSVG || vnode.type === 'svg')) {\n element = document.createElementNS(\n SVG_NS,\n /** @type {string} */ (vnode.type)\n )\n } else {\n element = document.createElement(/** @type {string} */ (vnode.type))\n }\n }\n\n const props = vnode.props\n if (props['onmount']) {\n lifecycle.push(function() {\n props['onmount'](element)\n })\n }\n\n for (let i = 0, length = vnode.children.length; i < length; i++) {\n element.appendChild(createElement(vnode.children[i], lifecycle, isSVG))\n }\n\n for (let prop in props) {\n setProp(/** @type {Element} */ (element), prop, null, props[prop], isSVG)\n }\n\n return (vnode.element = /** @type {Element} */ (element))\n}\n\n/**\n * Remove children from a node.\n * @param {VNode} node\n * @return {Element}\n */\nfunction removeChildren(node) {\n for (let i = 0, length = node.children.length; i < length; i++) {\n removeChildren(node.children[i])\n }\n return node.element\n}\n\n/**\n * Remove an element from the DOM.\n * @param {Element} parent\n * @param {VNode} vnode\n * @return {void} undefined\n */\nfunction removeElement(parent, vnode) {\n function done() {\n if (parent && parent.nodeType) parent.removeChild(removeChildren(vnode))\n }\n\n const cb = vnode.props && vnode.props['onunmount']\n if (cb != null) {\n cb(done, vnode.element)\n } else {\n done()\n }\n}\n\n/**\n * Update and element based on new prop values.\n * @typedef {import('./vnode').Props} Props\n * @param {Element} element\n * @param {Props} oldProps\n * @param {Props} newProps\n * @param {Lifecycle} lifecycle\n * @param {boolean} isSVG\n * @param {boolean} isRecycled\n * @return {void} undefined\n */\nfunction updateElement(\n element,\n oldProps,\n newProps,\n lifecycle,\n isSVG,\n isRecycled\n) {\n for (let prop in merge(oldProps, newProps)) {\n if (\n (prop === 'value' || prop === 'checked'\n ? element[prop]\n : oldProps[prop]) !== newProps[prop]\n ) {\n setProp(element, prop, oldProps[prop], newProps[prop], isSVG)\n }\n }\n\n const cb = isRecycled ? newProps['onmount'] : newProps['onupdate']\n if (cb != null) {\n lifecycle.push(function() {\n cb(element, oldProps, newProps)\n })\n }\n}\n\n/**\n * Patch an element based on differences between its old VNode and its new one.\n * @param {Element} parent\n * @param {Element} element\n * @param {VNode} oldVNode\n * @param {VNode} newVNode\n * @param {Lifecycle} lifecycle\n * @param {boolean} [isSVG]\n * @return {VNode}\n */\nexport function patchElement(\n parent,\n element,\n oldVNode,\n newVNode,\n lifecycle,\n isSVG\n) {\n // Abort if vnodes are identical.\n if (newVNode === oldVNode) {\n } else if (\n oldVNode != null &&\n oldVNode.flag === TEXT_NODE &&\n newVNode.flag === TEXT_NODE\n ) {\n if (oldVNode.type !== newVNode.type) {\n element.nodeValue = /** @type {string} */ (newVNode.type)\n }\n } else if (oldVNode == null || oldVNode.type !== newVNode.type) {\n const newElement = parent.insertBefore(\n createElement(newVNode, lifecycle, isSVG),\n element\n )\n\n if (oldVNode != null) removeElement(parent, oldVNode)\n\n element = newElement\n } else {\n updateElement(\n element,\n oldVNode.props,\n newVNode.props,\n lifecycle,\n (isSVG = isSVG || newVNode.type === 'svg'),\n oldVNode.flag === RECYCLED_NODE\n )\n\n let savedNode\n let childNode\n\n let lastKey\n const lastChildren = oldVNode.children\n let lastChildStart = 0\n let lastChildEnd = lastChildren.length - 1\n\n let nextKey\n const nextChildren = newVNode.children\n let nextChildStart = 0\n let nextChildEnd = nextChildren.length - 1\n\n while (nextChildStart <= nextChildEnd && lastChildStart <= lastChildEnd) {\n lastKey = getKey(lastChildren[lastChildStart])\n nextKey = getKey(nextChildren[nextChildStart])\n\n if (lastKey == null || lastKey !== nextKey) break\n\n patchElement(\n element,\n lastChildren[lastChildStart].element,\n lastChildren[lastChildStart],\n nextChildren[nextChildStart],\n lifecycle,\n isSVG\n )\n\n lastChildStart++\n nextChildStart++\n }\n\n while (nextChildStart <= nextChildEnd && lastChildStart <= lastChildEnd) {\n lastKey = getKey(lastChildren[lastChildEnd])\n nextKey = getKey(nextChildren[nextChildEnd])\n\n if (lastKey == null || lastKey !== nextKey) break\n\n patchElement(\n element,\n lastChildren[lastChildEnd].element,\n lastChildren[lastChildEnd],\n nextChildren[nextChildEnd],\n lifecycle,\n isSVG\n )\n\n lastChildEnd--\n nextChildEnd--\n }\n\n if (lastChildStart > lastChildEnd) {\n while (nextChildStart <= nextChildEnd) {\n element.insertBefore(\n createElement(nextChildren[nextChildStart++], lifecycle, isSVG),\n (childNode = lastChildren[lastChildStart]) && childNode.element\n )\n }\n } else if (nextChildStart > nextChildEnd) {\n while (lastChildStart <= lastChildEnd) {\n removeElement(element, lastChildren[lastChildStart++])\n }\n } else {\n let lastKeyed = createKeyMap(lastChildren, lastChildStart, lastChildEnd)\n const nextKeyed = {}\n\n while (nextChildStart <= nextChildEnd) {\n lastKey = getKey((childNode = lastChildren[lastChildStart]))\n nextKey = getKey(nextChildren[nextChildStart])\n\n if (\n nextKeyed[lastKey] ||\n (nextKey != null &&\n nextKey === getKey(lastChildren[lastChildStart + 1]))\n ) {\n if (lastKey == null) {\n removeElement(element, childNode)\n }\n lastChildStart++\n continue\n }\n\n if (nextKey == null || oldVNode.flag === RECYCLED_NODE) {\n if (lastKey == null) {\n patchElement(\n element,\n childNode && childNode.element,\n childNode,\n nextChildren[nextChildStart],\n lifecycle,\n isSVG\n )\n nextChildStart++\n }\n lastChildStart++\n } else {\n if (lastKey === nextKey) {\n patchElement(\n element,\n childNode.element,\n childNode,\n nextChildren[nextChildStart],\n lifecycle,\n isSVG\n )\n nextKeyed[nextKey] = true\n lastChildStart++\n } else {\n if ((savedNode = lastKeyed[nextKey]) != null) {\n patchElement(\n element,\n element.insertBefore(\n savedNode.element,\n childNode && childNode.element\n ),\n savedNode,\n nextChildren[nextChildStart],\n lifecycle,\n isSVG\n )\n nextKeyed[nextKey] = true\n } else {\n patchElement(\n element,\n childNode && childNode.element,\n null,\n nextChildren[nextChildStart],\n lifecycle,\n isSVG\n )\n }\n }\n nextChildStart++\n }\n }\n\n while (lastChildStart <= lastChildEnd) {\n if (getKey((childNode = lastChildren[lastChildStart++])) == null) {\n removeElement(element, childNode)\n }\n }\n\n for (let key in lastKeyed) {\n if (nextKeyed[key] == null) {\n removeElement(element, lastKeyed[key])\n }\n }\n }\n }\n\n newVNode.element = element\n return newVNode\n}\n\n/**\n * Function to either mount an element the first time or patch it in place. This behavior depends on the value of the old VNode. If it is null, a new element will be created, otherwise it compares the new VNode with the old one and patches it.\n * @param {VNode} oldVNode\n * @param {VNode} newVNode\n * @param {Element | string} container\n * @return {VNode} VNode\n */\nexport function patch(newVNode, oldVNode, container) {\n if (typeof container === 'string')\n container = document.querySelector(container)\n const lifecycle = []\n\n patchElement(container, container.children[0], oldVNode, newVNode, lifecycle)\n\n if (newVNode !== oldVNode) {\n while (lifecycle.length > 0) lifecycle.pop()()\n }\n\n return newVNode\n}\n","import { patch } from './vdom'\nimport { vnodeFromElement } from './vnode'\nimport { FragmentError } from './utils'\n\n/**\n * A function to create and inject a virtual node into the document. The node will be appended to the container. The first argument can be either a JSX tag or an h function. After mounting, use the render function and the element returned by mount to udate the DOM.\n * @example \n * \n * ```\n * // Insert Title tag into section:\n * const title = mount(<Title message='Hello World!'/>, 'section').\n * // Update the node with new prop value and reference to DOM from mount:\n * render(<Title message='New stuff'/>, title)\n ```\n * @typedef {import('./vnode').VNode} VNode\n * @param {Object | Function} tag A JSX tag or hyperscript function to render.\n * @param {Element | string} [container] The element into which the tag will be rendered.\n * @param {string | Element} [elementToHydrate] A server-rendered element to hydrate during initial load.\n * @return {VNode} The base element of the rendered tag.\n */\nexport function mount(tag, container, elementToHydrate) {\n if (typeof container === 'string')\n container = document.querySelector(container)\n if (!container) container = document.body\n const lifecycle = []\n if (Array.isArray(tag)) throw new FragmentError()\n\n if (elementToHydrate) {\n if (typeof elementToHydrate === 'string') {\n elementToHydrate = document.querySelector(elementToHydrate)\n }\n const nodeToRecycle = vnodeFromElement(elementToHydrate)\n patch(tag, nodeToRecycle, container)\n } else {\n tag = patch(tag, null, container)\n }\n tag.element['isMounted'] = true\n while (lifecycle.length > 0) lifecycle.pop()()\n return tag\n}\n","import {\n isObject,\n EMPTY_OBJECT,\n EMPTY_ARRAY,\n merge,\n isSameVNode\n} from './utils'\nimport { patch } from './vdom'\nimport { mount } from './mount'\nimport { vnodeFromElement } from './vnode'\n\n/**\n * This is a numeric value derived from the Date object used as a key to create a pseudo-private property in the Component class for holding state.\n * @type {string} dataStore A hex value to use as pseudo-private key to store the component's state.\n */\nconst dataStore = new Date().getTime().toString(16)\n\n/**\n * Component can be instantiated with the new keyword, or extended to create a custom version of the class.\n * @class Class to create a component.\n * \n * @example \n * \n * ```\n * // Extending Component class:\n * class UserList extends Component {\n * constructor(props) {\n * super(props)\n * this.state = users\n * this.container = 'section'\n * }\n * render(users) {\n * return (\n * <ul class='user-list'>\n * {\n * users.map(user => <li>{user.name}</li>)\n * }\n * </ul>\n * )\n * }\n * }\n ```\n */\nexport class Component {\n /**\n * Constructor for Component class.\n * @property {state} [props.state] The state object of the component. This can be of type boolean, string, number, object or array.\n * @property {string} selector A CSS selector describing the DOM container in which to render the component.\n * @property {HTMLElement} container The DOM node in which the component is rendered.\n * @property {boolean} componentShouldUpdate A flag to determine whether a component can render or not. Setting this to false allows you to maipulate a component's state without triggering and automatic render. After setting to true, you may need to execute `update()` on a component instance to force render it.\n * @property {boolean} isMounted A boolean flag that tracks whether a component has been mounted in the DOM or not. This is used internally by Composi, do not touch!\n * @property {Node} element The root or base element of a component's DOM tree. You can use it to register events or as the basis of a component-specific DOM query.\n * @method componentWillMount A callback that is called before a component is mounted in the DOM.\n * @method componentDidMount A callback that is called after a component is mounted in the DOM. Use this to register events, query the component DOM, etc.\n * @method componentWillUpdate A callback that is called before a component is updated. This is not called the first time a component is rendered.\n * @method componentDidUpdate A callback that is called after a component is updated. This is not called the first time a component is rendered.\n * @method componentWillUnmount A callback that is called before a component is unmounted from the DOM. Use this for any environmental cleanup.\n * @method render A method that returns nodes to render to the DOM.¸\n * @method update A method that renders the component template with provided data to the DOM. Data may be provided directly as the primary argument, or it can be derived from the component's state. Data provided as an argument will override use of component state.\n * @method unmount A method to unmount a component from the DOM. This deletes the DOM tree structure starting from the component's base element, and sets the component instance properties to null.\n * @constructs Component\n */\n constructor(props) {\n if (!props) props = {}\n /**\n * @property {Object} props An object literal of options passed to the class constructor during initialization.\n */\n this.props = props\n /**\n * @property {string | HTMLElement} container The HTML element in which the component gets rendered. This can be a CSS selector describing the container or a DOM node reference.\n */\n this.selector = props.container || 'body'\n\n if (props.render) {\n /**\n * @property {Function} render A method to convert markup into DOM nodes to inject in the document. The method itself gets provided at init time by a function provided by the user as an argument, or in the case of extending, a method defined directly on the class extension.\n */\n this.render = props.render\n }\n\n if (props.state) {\n /**\n * @property {boolean | number | string | Object | any[]}\n */\n this.state = props.state\n }\n\n if (this.selector) {\n /**\n * @property {HTMLElement} container The HTML element in which the component gets rendered.\n */\n this.container = document.querySelector(this.selector)\n }\n\n /**\n * @typedef {import('./vnode').VNode} VNode\n * @type {VNode}\n */\n this.currentVNode = null\n\n /**\n * @property {boolean} componentShouldUpdate Determines whether a component should update. Set `componentShouldUpdate` to `false`, make changes, then set `componentShouldUpdate` to `true` and update component with `update` method.\n */\n this.componentShouldUpdate = true\n\n /**\n * @property {boolean} isMounted Indicates whether a component is mounted in the DOM or not. This is used internally, so do not change!\n */\n this.isMounted = false\n\n /**\n * @property {HTMLElement} element The base element of the rendered component. You can use component as the base for comopnent instance specific DOM queries or event registration.\n */\n this.element = null\n\n /**\n * @property {VNode} this.hydrate\n */\n this.hydrate = props.hydrate || null\n\n if (props.componentWillMount)\n /**\n * @property {() => void} componentWillMount A method to execute before the component mounts. The callback gets a reference to the component instance as its argument.\n * @return {void} undefined\n */\n this.componentWillMount = props.componentWillMount\n\n if (props.componentDidMount)\n /**\n * @property {() => void} componentDidMount A method to execute after the component mounts.\n * @return {void} undefined\n */\n this.componentDidMount = props.componentDidMount\n\n if (props.componentWillUpdate)\n /**\n * @property {() => void} componentWillUpdate A method to execute before the component updates. The callback gets a reference to the component instance as its argument.\n * @return {void} undefined\n */\n this.componentWillUpdate = props.componentWillUpdate\n\n if (props.componentDidUpdate)\n /**\n * @property {() => void} componentDidUpdate -A method to execute after the component updates. The callback gets a reference to the component instance as its argument.\n * @return {void} undefined\n */\n this.componentDidUpdate = props.componentDidUpdate\n\n if (props.componentWillUnmount)\n /**\n * @property {() => void} componentWillUnmount A method to execute before the component unmounts. The callback gets a reference to the component instance as its argument.\n * @return {void} undefined\n */\n this.componentWillUnmount = props.componentWillUnmount\n }\n\n /**\n * Start type stubs for Component methods.\n */\n noop() {}\n\n /**\n * @method A method to execute before the component mounts.\n * @param {() => void} [cb] A callback to execute.\n * @return {void} undefined\n */\n componentWillMount(cb) {\n if (cb && typeof cb === 'function') {\n cb.call(cb, this)\n }\n }\n\n /**\n * @method A method to execute after the component mounts.\n * @return {void} undefined\n */\n componentDidMount() {\n this.noop()\n }\n\n /**\n * @method A method to execute before the component updates.\n * @param {() => void} [cb] A callback to execute.\n * @return {void} undefined\n */\n componentWillUpdate(cb) {\n if (cb && typeof cb === 'function') {\n cb.call(cb, this)\n }\n }\n\n /**\n * @method A method to execute after the component updates.\n * @return {void} undefined\n */\n componentDidUpdate() {\n this.noop()\n }\n\n /**\n * @method A method to execute after the component updates.\n * @param {() => void} [cb] A callback to execute.\n * @return {void} undefined\n */\n componentWillUnmount(cb) {\n if (cb && typeof cb === 'function') {\n cb.call(cb, this)\n }\n }\n\n /**\n * @method A method to create a virtual node from data and markup. The returned virtual node will get converted into a node that gets injected in the DOM.\n * @param {*} data\n */\n render(data) {\n return data\n }\n /** End of type stubs */\n\n /**\n * @method This is a getter to access the component's state using the pseudo-private key dataStore.\n * @return {boolean | number | string | Object | any[]} The component's state\n */\n get state() {\n return this[dataStore]\n }\n\n /**\n * @method This is a setter to define the component's state. It uses the dataStore object as a pseudo-private key. It uses requestAnimationFrame to throttle component updates to avoid layout thrashing.\n * @param {string | number | boolean | Object | any[]} data Data to set as component state.\n * @return {void} undefined\n */\n set state(data) {\n this[dataStore] = data\n setTimeout(() => this.update(), 1000 / 60)\n }\n\n /**\n * @method Method to set a component's state. This accepts simple types or Objects. If updating an array, you can pass in the data and the position (number) in the array to update. Optionally you can pass a callback, which receives the state as its argument. You need to return the state changes in order to update the component's state.\n * @example Set state on component:\n * \n * ```\n * this.setState(true)\n * this.setState(0)\n * this.setState({name: 'Joe'})\n * this.setState([1,2,3])\n * this.setState(prevState => prevState + 1)\n ```\n * @param {string | number | boolean | Object | any[] | Function} data The data to set. If a callback is passed as the argument to execute, it gets passed the previous state as its argument. You need to make sure the callback returns the final state or the component will not update.\n * @return {void} undefined\n */\n setState(data) {\n if (typeof data === 'function') {\n let copyOfState\n if (isObject(this.state)) {\n copyOfState = merge(EMPTY_OBJECT, this.state)\n } else if (Array.isArray(this.state)) {\n copyOfState = EMPTY_ARRAY.concat(EMPTY_ARRAY, this.state)\n } else {\n copyOfState = this.state\n }\n const newState = data.call(this, copyOfState)\n if (newState) this.state = newState\n } else if (isObject(this.state) && isObject(data)) {\n const newState = merge(this.state, data)\n this.state = newState\n } else {\n this.state = data\n }\n }\n\n /**\n * @method Function to render component after data changes.\n * If data is passed as argument, it will be used.\n * Otherwise state will be used.\n * @param {boolean | number | string | Object | any[]} [data] By default, data will be the component's current state, otherwise, if data is provided as an argument, that will be used, overriding the state.\n * @return {void} undefined\n */\n update(data) {\n if (!this.render) return\n\n // If componentShouldUpdate is set to false,\n // render one time only.\n // All other updates will be ignored.\n if (!this.componentShouldUpdate && this.isMounted) return\n\n // If data is 0 or non-boolean, use,\n // else use component state.\n let __data = this.state\n if (data !== true && data) __data = data\n\n if (this.container && typeof this.container === 'string') {\n this.selector = this.container\n this.container = document.querySelector(this.container)\n }\n\n if (this.hydrate && !this.isMounted) {\n if (typeof this.hydrate === 'string') {\n this.hydrate = document.querySelector(this.hydrate)\n }\n this.currentVNode = vnodeFromElement(this.hydrate)\n }\n /**\n * @typedef {import('./vnode').VNode} VNode\n * @type {VNode | null}\n */\n const vdom = this.render(__data)\n\n const self = this\n function doneUpdating() {\n self.oldVNode = self.render(__data)\n self.currentVNode = patch(vdom, self.currentVNode, self.container)\n self.element = self.currentVNode.element\n self.isMounted = true\n self.componentDidUpdate()\n }\n\n function doneMounting() {\n self.oldVNode = vdom\n self.currentVNode = mount(vdom, self.container)\n\n self.element = self.currentVNode.element\n self.isMounted = true\n self.componentDidMount()\n }\n\n if (!this.isMounted) {\n // First render, so mount component:\n if (!this.currentVNode) {\n this.componentWillMount(doneMounting)\n } else {\n // Not mounted, but has vnode, so hydrate DOM element:\n this.oldVNode = vdom\n this.currentVNode = patch(vdom, this.currentVNode, this.container)\n this.element = this.currentVNode.element\n this.isMounted = true\n this.componentDidMount()\n }\n\n // If container for component is invalid,\n // log error and exit:\n if (!this.container || this.container.nodeType !== 1) {\n console.error(\n 'The container for this class component is not a valid DOM node. Check the selector provided for the class to make sure it is a valid CSS selector and that the container exists in the DOM. You might be targeting a nonexistent node.'\n )\n }\n return\n } else {\n // The vnodes are identical, so exit:\n if (isSameVNode(vdom, this.oldVNode)) {\n return\n } else {\n // Update mounted component:\n this.componentWillUpdate(doneUpdating)\n }\n }\n }\n\n /**\n * @method Method to destroy a component.\n * First unbind events.\n * Then remove component element from DOM.\n * Also null out component properties.\n * @return {void} undefined\n */\n unmount() {\n if (!this.element) return\n const self = this\n function done() {\n self.container.removeChild(self.element)\n for (let key in self) {\n delete self[key]\n }\n self['__proto__'] = null\n }\n\n this.componentWillUnmount(done)\n }\n}\n","/**\n * Observer class providing two methods: watch and dispatch.\n * It also exposes a method for setting state: `setState`.\n * `setState` works just like the same method on Composi class components.\n * When you use `setState` it sends a message to an instance of DataStoreComponent to update itself.\n */\nexport class Observer {\n constructor() {\n this.events = {};\n }\n\n /**\n * Method to subscribe to a publishing event.\n * @param {string} event \n * @param {Function} callback \n * @return {Object.<string, any>} events\n */\n watch(event, callback) {\n if (!this.events.hasOwnProperty(event)) {\n this.events[event] = [];\n }\n return this.events[event].push(callback);\n }\n\n /**\n * \n * @param {string} event \n * @param {any} data \n * @return {any[]} events\n */\n dispatch(event, data = {}) {\n // There's no event to dispatch to, so bail out:\n if (!this.events.hasOwnProperty(event)) {\n return [];\n }\n return this.events[event].map(callback => callback(data));\n }\n}\n","import { EMPTY_OBJECT, merge, isObject, uuid } from '../lib/utils'\nimport { Observer } from './observer'\n\n/**\n * A uuid to use as the property of the dataStore's state. This creates a pseudo-private\n */\nconst dataStore = uuid()\n\n/**\n * A class to create a dataStore. This is used in conjunction with DataStoreComponent to create stateless components with external state management through a dataStore.\n */\nexport class DataStore {\n constructor(props) {\n this[dataStore] = undefined\n this.observer = new Observer()\n this.state = props.state\n }\n\n /**\n * @method This is a getter to access the component's state using the pseudo-private key dataStore.\n * @return {boolean | number | string | Object | any[]} The component's state\n */\n get state() {\n return this[dataStore]\n }\n\n /**\n * @method This is a setter to define the component's state. It uses the dataStore object as a pseudo-private key. It uses requestAnimationFrame to throttle component updates to avoid layout thrashing.\n * @param {string | number | boolean | Object | any[]} data Data to set as component state.\n * @return {void} undefined\n */\n set state(data) {\n this[dataStore] = data\n this.dispatch('dataStoreStateChanged', this.state)\n }\n\n /**\n * @method This is a method to dispatch an event with data to a DataStoreComponent that is using a dataStore.\n * @param {string} event The name of the event that the component is watching.\n * @param {any} data Any data you want to send to the component.\n */\n dispatch(event, data) {\n this.observer.dispatch(event, data)\n }\n\n /**\n * @method This method sets up an observer to listener for the designated event and do something with any data passed along.\n * @param {string} event The event to watch.\n * @param {any} data Any data that the event callback will need to handle.\n */\n watch(event, data) {\n this.observer.watch(event, data)\n }\n\n /**\n * @method Method to set a dataStore's state. This accepts simple types or Objects. If updating an array, you can pass in the data and the position (number) in the array to update. Optionally you can pass a callback, which receives the state as its argument. You need to return the state changes in order for the component to be updated.\n * @example Set state on a dataStore:\n * \n * ```\n * this.setState(true)\n * this.setState(0)\n * this.setState({name: 'Joe'})\n * this.setState([1,2,3])\n * this.setState(prevState => prevState + 1)\n ```\n * @param {string | number | boolean | Object | any[] | Function} data The data to set. If a callback is passed as the argument to execute, it gets passed the previous state as its argument. You need to make sure the callback returns the final state or the component will not update.\n * @return {void} undefined\n */\n setState(data) {\n if (typeof data === 'function') {\n let copyOfState\n copyOfState = merge(EMPTY_OBJECT, this.state)\n const newState = data.call(this, copyOfState)\n if (newState) this.state = newState\n } else if (isObject(this.state) && isObject(data)) {\n const newState = merge(this.state, data)\n this.state = newState\n }\n }\n}\n","import { DataStore } from './dataStore'\nimport { Component } from '../lib/component'\n\nexport class DataStoreComponent extends Component {\n /**\n * @typedef {Object.<string, any>} Props\n * @property {DataStore} Props.dataStore\n * @param {Props} props \n */\n constructor(props) {\n super(props)\n /**\n * @property {DataStore} dataStore\n */\n this.dataStore = /** @type {DataStore}*/(props.dataStore)\n if (props.dataStore instanceof DataStore) {\n props.dataStore.watch('dataStoreStateChanged', () => this.update(this.dataStore.state))\n }\n }\n}\n","import { createVNode, createTextVNode } from './vnode'\nimport { ELEMENT_NODE } from './utils'\n\n/**\n * Creates a virtual node representing a node or text node to be created.\n * @typedef {import('./vnode').VNode} VNode\n * @param {string | Function} type\n * @param {Object.<string, any>} props\n * @return {VNode}\n */\nexport function h(type, props, ...children) {\n let node\n const tempBox = []\n const childNodes = []\n let length = children.length\n props = props || {}\n const key = props.key\n\n while (length-- > 0) tempBox.push(children[length])\n\n if (props.children != null) {\n if (tempBox.length <= 0) {\n tempBox.push(props.children)\n }\n delete props.children\n }\n\n while (tempBox.length > 0) {\n if (Array.isArray((node = tempBox.pop()))) {\n for (length = node.length; length-- > 0; ) {\n tempBox.push(node[length])\n }\n } else if (node === false || node === true || node == null) {\n } else {\n childNodes.push(typeof node === 'object' ? node : createTextVNode(node))\n }\n }\n delete props.key\n\n if (typeof type === 'function') {\n return type(props, (props.children = childNodes))\n } else {\n return createVNode(type, props, childNodes, null, key, ELEMENT_NODE)\n }\n}\n","/**\n * Function to unmount a mounted functional component. This deletes the base element of the component from the DOM.\n * @example\n * \n * ```\n * // First mount component:\n * let title = mount(<Title message='Hello World!'/>, 'header')\n * // Sometime later unmount it by passing the vnode to unmount:\n * unmount(title)\n ```\n * @typedef {import('./vnode').VNode} VNode\n * @param {VNode} vnode The virtual node of the component to unmount.\n * @return {void} undefined\n */\nexport function unmount(vnode) {\n /**\n * Function to remove the base element of a functional component from the DOM.\n * @return {void} undefined\n */\n function doneUnmounting() {\n vnode.element.parentNode.removeChild(vnode.element)\n vnode.element = null\n }\n if (vnode.props['onunmount']) {\n vnode.props['onunmount'](doneUnmounting, vnode.element)\n } else {\n doneUnmounting()\n }\n}\n","import { patch } from './vdom'\n\n/**\n * A function to update a functional component already mounted in the DOM. The first argument can be either a JSX tag or an h function.\n * @example\n *\n * ```\n * // Update Title tag into section:\n * const element = mount(<Title message='Hello World!'/>, 'section')\n * // Pass the captured element to the render function:\n * render(<Title message='Hello Everyone!'/>, element, 'header')\n * ```\n * @typedef {import('./vnode').VNode} VNode\n * @param {VNode} oldVNode\n * @param {VNode} newVNode\n * @param {Element | string} container\n * @return {VNode} VNode\n */\nexport function render(newVNode, oldVNode, container) {\n return patch(newVNode, oldVNode, container)\n}\n","/**\n * Returns a group of siblings elements for inclusion in another JSX tag.\n * @typedef {import('./vnode').Props} Props\n * @typedef {import('./vnode').Children} Children\n * @param {Props} props\n * @return {Children} children\n */\n/**\n * A tag to enable returning sibling elements. This is useful for returning list items to render in a list or table cells to render in a table row.\n * @example\n * \n * ```\n * <Fragment>\n * <li>A</li>\n * <li>B</li>\n * <li>C</li>\n * </Fragment>\n ```\n * Or functionally:\n * ```\n * Fragment(null, [\n * h('li', {}, 'A'),\n * h('li', {}, 'B'),\n * h('li', {}, 'C')\n * ])\n ```\n * @param {Object} [props] When using Fragment as a function, props is the first argument. Provide either null or {} as the value for props.\n * @param {Children} [children] The siblings to return with the Fragment. This will be an array of sibling elements.\n * @return {VNode[]} An array of virtual nodes.\n */\nexport const Fragment = (props, children) => children\n"],"names":["RECYCLED_NODE","ELEMENT_NODE","TEXT_NODE","XLINK_NS","SVG_NS","EMPTY_OBJECT","EMPTY_ARRAY","merge","firstObject","secondObject","target","i","j","isObject","obj","Array","isArray","FragmentError","message","toString","this","uuid","d","Date","getTime","performance","now","replace","c","r","Math","random","floor","createVNode","type","props","children","element","key","flag","createTextVNode","text","vnodeFromElement","nodeName","toLowerCase","map","call","childNodes","vnodeFromChild","nodeType","nodeValue","eventProxy","event","currentTarget","getKey","node","setProp","prop","oldValue","newValue","isSVG","slice","removeEventListener","addEventListener","nullOrFalse","removeAttribute","setAttributeNS","setAttribute","style","setProperty","createElement","vnode","lifecycle","document","createTextNode","createElementNS","push","length","appendChild","removeElement","parent","done","removeChild","removeChildren","cb","patchElement","oldVNode","newVNode","newElement","insertBefore","oldProps","newProps","isRecycled","savedNode","childNode","lastKey","lastChildren","lastChildStart","lastChildEnd","nextKey","nextChildren","nextChildStart","nextChildEnd","lastKeyed","start","end","out","createKeyMap","nextKeyed","patch","container","querySelector","pop","mount","tag","elementToHydrate","body","dataStore","Component","selector","render","state","currentVNode","componentShouldUpdate","isMounted","hydrate","componentWillMount","componentDidMount","componentWillUpdate","componentDidUpdate","componentWillUnmount","noop","data","copyOfState","concat","newState","__data","vdom","self","error","JSON","stringify","_this","update","Observer","events","callback","hasOwnProperty","DataStore","undefined","observer","dispatch","watch","DataStoreComponent","tempBox","doneUnmounting","parentNode"],"mappings":"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"}
\No newline at end of file