UNPKG

38.8 kBSource Map (JSON)View Raw
1{"version":3,"file":"composi.js.map","sources":["../lib/utils.js","../lib/vdom.js","../lib/component.js","../lib/h.js","../lib/mount.js","../lib/render.js","../lib/fragment.js"],"sourcesContent":["/**\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 * 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 mixin(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 * @typedef {import('./vnode').VNode} VNode\n * @typedef {import('./component').Component} Component\n */\n/**\n * A function to test whether the data provided for updating a component creates a new virtual node or not.\n * @param {VNode} oldNode The previous virtual node of a component.\n * @param {*} data Data to be used when rendering a new virtual node for a component.\n * @param {Component} component A reference to the component being used.\n * @return {boolean} boolean\n */\nexport function isSameNode(oldNode, data, component) {\n if (\n component &&\n JSON.stringify(oldNode) === JSON.stringify(component.render(data))\n ) {\n return true\n }\n return false\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","// @ts-check\nimport { XLINK_NS, SVG_NS, mixin } 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 * Function to get a node's key.\n * @typedef {import('./vnode').VNode} VNode\n * @param {VNode} node A virtual node.\n * @return {string | number | null} key.\n */\nconst getKey = node => (node ? node.key : null)\n\n/**\n * Function to set properties and attributes on element.\n * @param {Element} element The element to set props on.\n * @param {string} prop The property/attribute.\n * @param {any} newValue The new value for the prop.\n * @param {any} oldValue The original value of the prop.\n * @param {boolean} isSVG Whether this is SVG or not\n * @return {void} undefined\n */\nfunction setProp(element, prop, newValue, oldValue, isSVG) {\n // Do not add these as node attributes:\n if (prop === 'key') {\n return\n } else if (\n prop === 'style' &&\n typeof newValue === 'object' &&\n !Array.isArray(newValue)\n ) {\n for (let i in mixin(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 {\n // Convert camel case props to lower case:\n prop = prop.toLowerCase()\n if (prop[0] === 'o' && prop[1] === 'n') {\n if (!element['events']) element['events'] = {}\n\n element['events'][(prop = prop.slice(2))] = newValue\n\n if (newValue == null) {\n element.removeEventListener(prop, eventProxy)\n } else if (oldValue == null) {\n element.addEventListener(prop, eventProxy)\n }\n }\n\n // Handle cases where 'className' is used:\n if (prop === 'classname') {\n prop = 'class'\n }\n\n // Allow setting innerHTML:\n if (prop === 'dangerouslysetinnerhtml') {\n prop = 'innerHTML'\n }\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 } else if (newValue != null && newValue !== 'no' && newValue !== 'off') {\n // Support SVG 'xlink:href' property:\n if (prop === 'xlink-href') {\n element.setAttributeNS(XLINK_NS, 'href', newValue)\n element.setAttribute('href', newValue)\n } else {\n if (newValue === 'true') newValue = ''\n // Set prop as attribute, except dangerouslySetInnerHTML:\n if (prop !== 'dangerouslysetinnerhtml') {\n element.setAttribute(prop, newValue)\n }\n }\n }\n\n if (newValue == null || newValue === 'no' || newValue === 'off') {\n element.removeAttribute(prop)\n }\n }\n}\n\n/**\n * Function to convert hyperscript/JSX into DOM nodes.\n * @param {string | number | Object} node A node to create. This may be a hyperscript function or a JSX tag which gets converted to hyperscript during transpilation.\n * @param {boolean} [isSVG] Whether the node is SVG or not.\n * @return {Node} An element created from a virtual dom object.\n */\nfunction createElement(node, isSVG) {\n let element\n if (typeof node === 'number') node = node.toString()\n if (typeof node === 'string') {\n element = document.createTextNode(node)\n } else if ((isSVG = isSVG || node.type === 'svg')) {\n element = document.createElementNS(SVG_NS, node.type)\n } else {\n element = document.createElement(node.type)\n }\n /**\n * @property {Object.<string, any>} node.props A virtual node stored on the node.\n */\n const props = node.props\n if (props) {\n for (let i = 0; i < node.children.length; i++) {\n element.appendChild(createElement(node.children[i], isSVG))\n }\n\n for (let prop in props) {\n setProp(element, prop, props[prop], null, isSVG)\n }\n }\n\n return element\n}\n\n/**\n * Function to remove element from DOM.\n * @param {Node} parent The containing element in which the component resides.\n * @param {Node} element The parent of the element to remove.\n * @param {Element} node The element to remove.\n * @return {void} undefined\n */\nconst removeElement = (parent, element, node) => {\n const remove = function() {\n parent.removeChild(element)\n }\n const callback =\n (node['props'] && node['props']['onunmount']) ||\n (node['props'] && node['props']['onComponentWillUnmount'])\n if (callback != null) {\n callback(element, remove)\n } else {\n remove()\n }\n}\n\n/**\n * @description A function to update an element based on a virtual dom node.\n * @param {Element} element\n * @param {Object.<string, any>} oldProps The original props used to create the element.\n * @param {Object.<string, any>} newProps New props generated by the virtual dom.\n * @param {boolean} isSVG Whether we are dealing with SVG or not.\n * @function {function(element: Node, oldProps: VNode, props: VNode,isSVG: boolean): void}\n * @return {void} undefined\n */\nfunction updateElement(element, oldProps, newProps, isSVG) {\n for (let prop in mixin(oldProps, newProps)) {\n if (\n newProps[prop] !==\n (prop === 'value' || prop === 'checked' ? element[prop] : oldProps[prop])\n ) {\n setProp(element, prop, newProps[prop], oldProps[prop], isSVG)\n }\n }\n\n // Handle lifecycle hook:\n if (element['mounted'] && newProps && newProps.onComponentDidUpdate) {\n newProps.onComponentDidUpdate.call(\n newProps.onComponentDidUpdate,\n oldProps,\n newProps,\n element\n )\n }\n if (element['mounted'] && newProps && newProps.onupdate) {\n newProps.onupdate.call(newProps.onupdate, oldProps, newProps, element)\n }\n}\n\n/**\n * A function to diff and patch a DOM node with a virtual node.\n * @param {Node} parent The parent node of the elment being patched.\n * @param {Element} element The element being patched.\n * @param {Object} oldVNode A virtual dom node from the previous patch.\n * @param {Object} newVNode The current virtual dom node.\n * @param {boolean} [isSVG] Whether we are dealing with an SVG element or not.\n * @return {Node} element The patched element.\n */\nexport function patchElement(parent, element, oldVNode, newVNode, isSVG) {\n // Short circuit patch if VNodes are identical\n if (newVNode === oldVNode) {\n return\n } else if (oldVNode == null || oldVNode.type !== newVNode.type) {\n const newElement = createElement(newVNode, isSVG)\n if (parent) {\n parent.insertBefore(newElement, element)\n if (oldVNode != null) {\n removeElement(parent, element, oldVNode)\n }\n }\n element = /** @type {Element} */ (newElement)\n } else if (oldVNode.type == null) {\n element.nodeValue = newVNode\n } else {\n updateElement(\n element,\n oldVNode.props,\n newVNode.props,\n (isSVG = isSVG || newVNode.type === 'svg')\n )\n\n const oldKeyed = {}\n const newKeyed = {}\n const oldElements = []\n const oldChildren = oldVNode.children\n const children = newVNode.children\n\n for (let i = 0; i < oldChildren.length; i++) {\n oldElements[i] = element.childNodes[i]\n\n const oldKey = getKey(oldChildren[i])\n if (oldKey != null) {\n oldKeyed[oldKey] = [oldElements[i], oldChildren[i]]\n }\n }\n\n let i = 0\n let j = 0\n\n while (j < children.length) {\n let oldKey = getKey(oldChildren[i])\n let newKey = getKey(children[j])\n\n if (newKeyed[oldKey]) {\n i++\n continue\n }\n\n if (newKey != null && newKey === getKey(oldChildren[i + 1])) {\n if (oldKey == null) {\n removeElement(element, oldElements[i], oldChildren[i])\n }\n i++\n continue\n }\n\n if (newKey == null) {\n if (oldKey == null) {\n patchElement(\n element,\n /** @type {any} */ (oldElements[i]),\n oldChildren[i],\n children[j],\n isSVG\n )\n j++\n }\n i++\n } else {\n const keyedNode = oldKeyed[newKey] || []\n\n if (oldKey === newKey) {\n patchElement(element, keyedNode[0], keyedNode[1], children[j], isSVG)\n i++\n } else if (keyedNode[0]) {\n patchElement(\n element,\n element.insertBefore(keyedNode[0], oldElements[i]),\n keyedNode[1],\n children[j],\n isSVG\n )\n } else {\n patchElement(\n element,\n /** @type {any} */ (oldElements[i]),\n null,\n children[j],\n isSVG\n )\n }\n\n newKeyed[newKey] = children[j]\n j++\n }\n }\n\n while (i < oldChildren.length) {\n if (getKey(oldChildren[i]) == null) {\n removeElement(element, oldElements[i], oldChildren[i])\n }\n i++\n }\n for (let k in oldKeyed) {\n if (!newKeyed[k]) {\n removeElement(element, oldKeyed[k][0], oldKeyed[k][1])\n }\n }\n }\n return element\n}\n\n/**\n * A function to patch a virtual node against a DOM element, updating it in the most efficient manner possible.\n * @param {() => VNode} newVNode A function that returns a virtual node. This may be a JSX tag, which gets converted into a function, or a hyperscript function.\n * @param {Node} [element] The element to patch.\n * @return {Node} The updated element.\n */\nexport function patch(newVNode, element) {\n if (element) {\n patchElement(\n element.parentNode,\n /** @type{Element} */ (element),\n element && element['vnode'],\n newVNode\n )\n } else {\n element = patchElement(null, null, null, newVNode)\n }\n\n element['vnode'] = newVNode\n\n return element\n}\n","import { isObject, isSameNode, mixin } from './utils'\nimport { patch } from './vdom'\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 {number} dataStore A numeric value to use as pseudo-private key to store the component's state.\n */\nconst dataStore = new Date().getTime()\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 * @example New instance of Component class:\n * const title = new Component({\n * container: 'header',\n * state: 'World',\n * render: message => <h1>Hello, {message}!</h1>\n * })\n * @example 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 */\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} mounted 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 * @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} mounted Indicates whether a component is mounted in the DOM or not. This is used internally, so do not change!\n */\n this.mounted = false\n\n /**\n * @property {HTMLElement} this.element\n * @property {Object} this.element.vnode\n */\n this.element = 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. The callback gets a reference to the component instance as its argument.\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 * @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 * @param {() => void} [cb] A callback to execute.\n * @return {void} undefined\n */\n componentDidMount(cb) {\n if (cb && typeof cb === 'function') {\n cb.call(cb, this)\n }\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 * @param {() => void} [cb] A callback to execute.\n * @return {void} undefined\n */\n componentDidUpdate(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 * @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 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())\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\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 * @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 const state = data.call(this, this.state)\n if (state) this.state = state\n } else if (isObject(this.state) && isObject(data)) {\n const state = this.state\n this.state = mixin(state, data)\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.mounted) 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 // Create virtual dom and check if component id\n // already exists in document.\n /**\n * @type {Object.<string, any> | null}\n */\n const vdom = this.render(__data)\n let elem\n if (vdom && vdom.props && vdom.props.id && this.container) {\n elem = this.container && this.container.querySelector(`#${vdom.props.id}`)\n }\n\n // If component element id already exists in DOM,\n // remove it before rendering the component.\n if (elem && !this.mounted) {\n elem.parentNode.removeChild(elem)\n }\n\n // Capture old node to use with isSameNode if component is already mounted:\n const __oldNode = this.element && this.element.vnode\n\n // Short circuit update if VNodes are identical:\n if (isSameNode(__oldNode, __data, this)) return\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 = patch(this.render(__data), this.element)\n if (!this.mounted) {\n this.componentWillMount && this.componentWillMount()\n if (!this.container || this.container.nodeType !== 1) {\n console.error(\n 'The container for a 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 this.container.appendChild(this.element)\n this.mounted = true\n this.componentDidMount && this.componentDidMount()\n return\n }\n\n this.componentWillUpdate && this.componentWillUpdate()\n this.componentDidUpdate && this.componentDidUpdate()\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 this.componentWillUnmount && this.componentWillUnmount()\n this.container.removeChild(this.element)\n this.container = null\n for (let key in this) {\n delete this[key]\n }\n delete this.state\n this.update = null\n this.unmount = null\n }\n}\n","import { createVNode } from './vnode'\n/**\n * @typedef {Object.<string, any>} Props\n */\n/**\n * @typedef {Object} VNode;\n * @property {string | Function} VNode.type;\n * @property {Props} VNode.props;\n * @property {any[]} VNode.children;\n * @property {string | number | null} VNode.key;\n */\n/**\n * Hyperscript function. Enables definition of HTML/SVG using functions.\n * @param {string | Function} type A tag name or function.\n * @param {Object} [props] An Object literal of key-value pairs.\n * @param {any[]} children An array of strings or other arrays.\n * @return {VNode} VNode An object literal of type, props and children.\n *\n * @example Virtual node with string as content:\n * const title = h('h1', {class: 'main-title'}, 'This is the Titel!')\n * @example Virtual node with children:\n * const list = h(\n * 'ul',\n * {class: 'list'},\n * [\n * h('li', {}, 'One'),\n * h('li', {}, 'Two'),\n * h('li', {}, 'Three')\n * ]\n * )\n */\nexport function h(type, props, ...children) {\n const nodes = []\n const childNodes = []\n let length = children.length\n props = props || {}\n let key = props.key || null\n\n // Remove key from props if present:\n delete props.key\n\n while (length-- > 0) nodes.push(children[length])\n\n while (nodes.length) {\n const node = nodes.pop()\n if (node && node.pop) {\n for (length = node.length; length--; ) {\n nodes.push(node[length])\n }\n } else if (node != null && node !== true && node !== false) {\n childNodes.push(node)\n }\n }\n\n children = childNodes\n\n if (typeof type === 'function') {\n return type(props || {}, childNodes)\n } else {\n return createVNode(type, props, children, key)\n }\n}\n","import { patch } from './vdom'\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 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 * @param {Object | Function} tag A JSX tag or hyperscript function to render.\n * @param {Node | string} [container] The element into which the tag will be rendered.\n * @param {HTMLElement} [elementToHydrate] A server-rendered element to hydrate during initial load.\n * @return {Node} The base element of the rendered tag.\n */\nexport const mount = (tag, container, elementToHydrate) => {\n if (typeof container === 'string')\n container = document.querySelector(container)\n if (!container) container = document.body\n if (Array.isArray(tag)) throw new FragmentError()\n const element = patch(tag)\n if (tag.props && tag.props.onComponentDidMount) {\n tag.props.onComponentDidMount.call(tag.props.onComponentDidMount, element)\n }\n if (tag.props && tag.props.onmount) {\n tag.props.onmount.call(tag.props.onmount, element)\n }\n\n element['mounted'] = true\n if (elementToHydrate) {\n if (typeof elementToHydrate === 'string') {\n elementToHydrate = document.querySelector(elementToHydrate)\n }\n elementToHydrate.parentNode.appendChild(element)\n elementToHydrate.parentNode.removeChild(elementToHydrate)\n return element\n } else {\n return container.appendChild(element)\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 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!'/>, 'header')\n * @param {() => import('./h').VNode} tag A JSX tag or hyperscript function to render.\n * @param {Node} [element] The element in the DOM which will be updated.\n * @return {Node} The base element of the rendered tag.\n */\nexport function render(tag, element) {\n return patch(tag, element)\n}\n","/**\n * @typedef {import('./vnode').Props} Props\n * @typedef {import('./vnode').Children} Children\n */\n/**\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 * <Fragment>\n * <li>A</li>\n * <li>B</li>\n * <li>C</li>\n * </Fragment>\n * Or functionally:\n * Fragment(null, [\n * h('li', {}, 'A'),\n * h('li', {}, 'B'),\n * h('li', {}, 'C')\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":["XLINK_NS","SVG_NS","mixin","firstObject","secondObject","target","i","j","isObject","obj","Array","isArray","eventProxy","event","currentTarget","type","getKey","node","key","setProp","element","prop","newValue","oldValue","isSVG","toLowerCase","slice","removeEventListener","addEventListener","setAttributeNS","setAttribute","removeAttribute","style","setProperty","removeElement","parent","remove","removeChild","callback","patchElement","oldVNode","newVNode","newElement","createElement","toString","document","createTextNode","createElementNS","props","children","length","appendChild","insertBefore","nodeValue","oldProps","newProps","onComponentDidUpdate","call","onupdate","oldKeyed","newKeyed","oldElements","oldChildren","childNodes","oldKey","newKey","keyedNode","k","patch","parentNode","dataStore","Date","getTime","Component","selector","container","render","state","this","querySelector","componentShouldUpdate","mounted","componentWillMount","componentDidMount","componentWillUpdate","componentDidUpdate","componentWillUnmount","cb","data","__data","vdom","elem","id","__oldNode","vnode","oldNode","component","JSON","stringify","nodeType","error","update","unmount","_this","nodes","push","pop","tag","elementToHydrate","body","message","onComponentDidMount","onmount"],"mappings":"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"}
\No newline at end of file