UNPKG

31.1 kBSource Map (JSON)View Raw
1{"version":3,"file":"composi.js","sources":["../lib/utils/getKey.js","../lib/utils/mixin.js","../lib/utils/setProp.js","../lib/utils/removeElement.js","../lib/utils/removeChildren.js","../lib/utils/patchElement.js","../lib/utils/createElement.js","../lib/utils/updateElement.js","../lib/patch.js","../lib/utils/recycleElement.js","../lib/component.js","../lib/h.js","../lib/mount.js","../lib/render.js","../lib/fragment.js"],"sourcesContent":["/**\n * @description Function to get a node's key.\n * @param {object} node A virtual node.\n * @returns {string|number} key.\n */\nexport const getKey = node => node && node.props ? node.props.key : null\n","/**\n * @description A function to merge two objects together. The properties of the second object will overwrite any matching properties in the first object.\n * @param {object} obj1 The first object to merge.\n * @param {object} obj2 The second object to merge.\n * @returns {object} Returns a new object of the second object merged with the first.\n */\nexport function mixin(obj1, obj2) {\n const result = {}\n for (let i in obj1) {\n result[i] = obj1[i]\n }\n for (let i in obj2) {\n result[i] = obj2[i]\n }\n return result\n}\n","import {mixin} from './mixin'\n\n/**\n * @description Function to set properties and attributes on element.\n * @param {HTMLElement} element The element to set props on.\n * @param {string} prop The property/attribute.\n * @param {string|number|boolean} value The value of the prop.\n * @param {string|number|boolean} oldValue The original value of the prop.\n * @param {boolean} isSVG Whether this is SVG or not\n * @returns {undefined} void.\n */\nexport function setProp(\n element, \n prop, \n value, \n oldValue, \n isSVG\n ) {\n if (prop === 'key') {\n } else if (prop === 'style' && typeof value !== 'string') {\n for (let i in mixin(oldValue, value)) {\n const style = value == null || value[i] == null ? '' : value[i]\n if (i[0] === '-') {\n element[prop].setProperty(i, style)\n } else {\n element[prop][i] = style\n }\n }\n } else {\n\n // Handle cases where 'className' is used:\n if (prop === 'className') prop = 'class'\n\n // Allow setting innerHTML:\n if (prop === 'dangerouslySetInnerHTML') element.innerHTML = value\n\n // Handle inline events.\n // If they are camel case, convert to lowercase:\n if (prop[0] == 'o' && prop[1] == 'n') {\n prop = prop.toLowerCase()\n }\n\n if (prop in element && prop !== 'list' && !isSVG) {\n element[prop] = value == (null || 'no') ? '' : value\n } else if (value != null && value !== false && value !== 'no') {\n \n // Support SVG 'xlink:href' property:\n if (prop === 'xlink-href') {\n element.setAttributeNS('http://www.w3.org/1999/xlink', 'href', value)\n element.setAttribute('href', value)\n } else {\n if (value === 'true') value = true\n element.setAttribute(prop, value)\n }\n }\n\n if (value == null || value === false || value === 'false') {\n element.removeAttribute(prop)\n }\n }\n}\n","import {removeChildren} from './removeChildren'\n\n/**\n * @description Function to remove element from DOM.\n * @param {HTMLElement} parent The containing element in which the component resides.\n * @param {HTMLElement} element The parent of the element to remove.\n * @param {HTMLElement} node The element to remove.\n * @returns {undefined} void.\n */\nexport const removeElement = (parent, element, node) => parent.removeChild(removeChildren(element, node))\n","/**\n * @description A function to remove the children of a node.\n * @param {HTMLElement} element The parent of the node whose children will be removed.\n * @param {HTMLElement} node The node whose children will be removed.\n * @returns {HTMLElement} element The parent of the removed nodes.\n */\nexport function removeChildren(element, node) {\n const props = node.props\n if (props) {\n for (let i = 0; i < node.children.length; i++) {\n removeChildren(element.childNodes[i], node.children[i])\n }\n }\n return element\n}\n","import {getKey} from './getKey'\nimport {createElement} from './createElement'\nimport {updateElement} from './updateElement'\nimport {removeElement} from './removeElement'\n\n/**\n * @description A function to diff and patch a DOM node with a virtual node.\n * @param {HTMLElement} parent The parent node of the elment being patched.\n * @param {HTMLElement} element The element being patched.\n * @param {object} oldNode A virtual dom node from the previous patch.\n * @param {object} node The current virtual dom node.\n * @param {boolean} recycle A virtual node to check whether to reuse an element or not.\n * @param {boolean} isSVG Whether we are dealing with an SVG element or not.\n * @returns element The patched element.\n */\nexport function patchElement(\n parent,\n element,\n oldNode,\n node,\n recycle,\n isSVG\n ) {\n if (node === oldNode) {\n } else if (oldNode == null || oldNode.type !== node.type) {\n const newElement = createElement(node, isSVG)\n if (parent) {\n parent.insertBefore(newElement, element)\n if (oldNode != null) {\n removeElement(parent, element, oldNode)\n }\n }\n element = newElement\n } else if (oldNode.type == null) {\n element.nodeValue = node\n } else {\n updateElement(\n element,\n oldNode.props,\n node.props,\n (isSVG = isSVG || node.type === 'svg')\n )\n\n const oldKeyed = {}\n const newKeyed = {}\n const oldElements = []\n const oldChildren = oldNode.children\n const children = node.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 k = 0\n\n while (k < children.length) {\n let oldKey = getKey(oldChildren[i])\n let newKey = getKey(children[k])\n\n if (newKeyed[oldKey]) {\n i++\n continue\n }\n\n if (newKey == null || recycle) {\n if (oldKey == null) {\n patchElement(\n element,\n oldElements[i],\n oldChildren[i],\n children[k],\n recycle,\n isSVG\n )\n k++\n }\n i++\n } else {\n const keyedNode = oldKeyed[newKey] || []\n\n if (oldKey === newKey) {\n patchElement(\n element,\n keyedNode[0],\n keyedNode[1],\n children[k],\n recycle,\n isSVG\n )\n i++\n } else if (keyedNode[0]) {\n patchElement(\n element,\n element.insertBefore(keyedNode[0], oldElements[i]),\n keyedNode[1],\n children[k],\n recycle,\n isSVG\n )\n } else {\n patchElement(\n element,\n oldElements[i],\n null,\n children[k],\n recycle,\n isSVG\n )\n }\n\n newKeyed[newKey] = children[k]\n k++\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\n for (let i in oldKeyed) {\n if (!newKeyed[i]) {\n removeElement(element, oldKeyed[i][0], oldKeyed[i][1])\n }\n }\n }\n return element\n}\n","import {setProp} from './setProp'\n\n/**\n * @description Function to convert hyperscript/JSX into DOM nodes.\n * @param {Function} 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 * @returns {HTMLElement}.\n */\nexport function createElement(node, isSVG) {\n const element =\n typeof node === 'string' || typeof node === 'number'\n ? document.createTextNode(node)\n : (isSVG = isSVG || node.type === 'svg')\n ? document.createElementNS('http://www.w3.org/2000/svg', node.type)\n : document.createElement(node.type)\n\n const props = node.props\n if (props) {\n\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","import {mixin} from './mixin'\nimport {setProp} from './setProp'\n\n/**\n * @description A function to update an element based on a virtual dom node.\n * @param {HTMLElement} element The element to update\n * @param {object} oldProps The original props used to create the element.\n * @param {object} props New props generated by the virtual dom.\n * @param {boolean} isSVG Whether we are dealing with SVG or not.\n * @returns {undefined} void.\n */\nexport function updateElement(\n element,\n oldProps,\n props,\n isSVG\n ) {\n for (let prop in mixin(oldProps, props)) {\n if (\n props[prop] !==\n (prop === 'value' || prop === 'checked'\n ? element[prop]\n : oldProps[prop])\n ) {\n setProp(\n element,\n prop,\n props[prop],\n oldProps[prop],\n isSVG\n )\n }\n }\n}\n","import {patchElement} from './utils/patchElement'\nimport {recycleElement} from './utils/recycleElement'\n\n/**\n * @description A function to patch a virtual node agains a DOM element, updating it in the most efficient manner possible.\n * @param {object} node A virtual node. This may be a JSX tag or a hyperscript function.\n * @param {HTMLElement} element The element to patch.\n * @returns {HTMLElement} The updated element.\n */\nexport function patch(node, element) {\n\n element = element\n ? patchElement(\n element.parentNode,\n element,\n element.node == null \n ? recycleElement(element, [].map) \n : element.node,\n node,\n element.node == null\n )\n : patchElement(\n null, \n null, \n null, \n node\n )\n\n element.node = node\n\n return element\n}\n","/**\n * @description A function to recycle/reuse DOM elements when updating existing elements.\n * @param {HTMLElement} element \n * @returns {object} A virtual node of a recyclable element.\n */\nexport function recycleElement(element) {\n if (element && element.nodeName) {\n return {\n type: element.nodeName.toLowerCase(),\n props: {},\n children: Array.prototype.map.call(\n element.children, \n element => element.nodeType === 3\n ? element.nodeValue\n : recycleElement(element)\n )\n }\n }\n}\n","import {h} from './h'\nimport {patch} from './patch'\nimport {mixin} from './utils/mixin'\n\n/**\n * @description A cross-browser normalization/polyfill for requestAnimationFrame.\n */\nconst rAF = window && window.requestAnimationFrame\n || window && window.webkitRequestAnimationFrame\n || window && window.mozRequestAnimationFrame\n || window && window.msRequestAnimationFrame\n || function(cb) { return setTimeout(cb, 16) }\n\n/**\n * @description This is a Time Object used as a key to create a pseudo-private property in the Component class for holding state.\n * @type {Object} dataStore A Date object to use as pseudo-private key to store the component's state.\n */\nconst dataStore = new Date().getTime()\n\n/**\n * @description 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 * @description Constructor for Component class.\n * @typedef {object} props An object of property/values to configure the class instance.\n * @property {string|element} props.container The container element in which to render the component.\n * @property {state} [props.state] The state object of the component. This can be of type boolean, string, number, object or array.\n * @property {function} props.render A function that returns nodes to render to the DOM.\n * @constructs Component\n */\n constructor(props) {\n if (!props) props = {}\n /** @property {string} */\n this.selector = props.container || 'body'\n \n if (props.render) {\n /** @property {Function} */\n this.render = props.render\n }\n \n if (props.state) {\n /** @property {boolean|number|string|object|array} */\n this.state = props.state\n }\n\n /** @property {null, Object} */\n this.oldNode = null\n if (this.selector) {\n /** @property {HTMLElement} */\n this.container = document.querySelector(this.selector)\n }\n /** @property {boolean} */\n this.componentShouldUpdate = true\n \n /** @property {boolean} */\n this.mounted = false\n\n /** \n * @property {HTMLElement|undefined} \n * @default {undefined}\n */\n this.element\n \n /**\n * @description Handle lifecycle hooks.\n */\n if (props.componentWillMount) this.componentWillMount = props.componentWillMount\n \n if (props.componentDidMount) this.componentDidMount = props.componentDidMount\n\n if (props.componentWillUpdate) this.componentWillUpdate = props.componentWillUpdate\n \n if (props.componentDidUpdate) this.componentDidUpdate = props.componentDidUpdate\n \n if (props.componentWillUnmount) this.componentWillUnmount = props.componentWillUnmount\n }\n\n /**\n * @description This is getter to access the component's state using the pseudo-private key dataStore.\n * @returns {boolean|number|string|object|any[]} The component's state\n */\n get state() {\n return this[dataStore]\n }\n\n /**\n * @description 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|array} data Data to set as component state. \n * @returns {undefined} void\n */\n set state(data) {\n this[dataStore] = data\n rAF(() => this.update())\n }\n \n /**\n * @description 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. This 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 * @property Component#setState\n * @param {string|number|boolean|object|array|Function} data - The data to set.\n * @param {number} [position] The index of an array whose data you want to set.\n * @returns {undefined} void\n */\n setState(data, position) {\n if (typeof data === 'function') {\n const state = data.call(this, this.state)\n if (typeof state !== 'function' && !!state) this.setState(state)\n } else if (Array.isArray(this.state)) {\n const state = this.state\n if (position || position === 0) {\n if (typeof state[position] === 'object') {\n this.state = mixin(state[position], data)\n } else {\n state[position] = data\n this.state = state\n }\n } else {\n this.state = state\n }\n } else if (typeof this.state === 'object') {\n const state = this.state\n this.state = mixin(state, data)\n } else {\n this.state = data\n }\n }\n\n /**\n * @description 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 * @property Component#update\n * @param {boolean|number|string|object|array} [data]\n * @returns {undefined} void\n */\n update(data) {\n if (!this.render) return\n\n // If componentShouldUpdate is set to false, 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 // Check if vnode already exists.\n // Used for deciding whether to fire lifecycle events.\n const __oldNode = this.oldNode\n const __render = this.render\n function testIfVNodesDiffer(oldNode, data) {\n if (this && JSON.stringify(oldNode) === JSON.stringify(__render(data))) {\n return false\n } else {\n return true\n }\n }\n // Create virtual dom and check if component id already exists in document.\n const vdom = this.render(__data)\n let elem\n if (\n vdom \n && vdom.props \n && vdom.props.id \n && this.container\n ) {\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 // Patch DOM with component update.\n this.oldNode = this.render(__data)\n this.element = patch(\n this.oldNode,\n this.element\n )\n if (!this.mounted) {\n this.componentWillMount && this.componentWillMount(this)\n this.container.appendChild(this.element)\n this.mounted = true\n this.componentDidMount && this.componentDidMount(this)\n return\n }\n \n if (this.mounted && this.oldNode && testIfVNodesDiffer(__oldNode, __data)) {\n this.componentWillUpdate && this.componentWillUpdate(this)\n }\n this.componentDidUpdate && testIfVNodesDiffer(__oldNode, __data) && this.componentDidUpdate(this)\n }\n \n /**\n * @description Method to destroy component.\n * First unbind events.\n * Then remove component element from DOM.\n * Also null out component properties.\n * @property Component#unmount\n * @returns {undefined} void\n */\n unmount() {\n const self = this\n const eventWhitelist = [\n 'change',\n 'click', \n 'dblclick', \n 'input', \n 'keydown',\n 'keypress', \n 'keyup', \n 'mousedown',\n 'mouseleave',\n 'mouseout', \n 'mouseover',\n 'mouseup', \n 'select', \n 'submit',\n 'touchcancel',\n 'touchend',\n 'touchmove',\n 'touchstart'\n ]\n if (!this.element) return\n this.componentWillUnmount && this.componentWillUnmount(this)\n eventWhitelist.map(event => {\n this.element.removeEventListener(event, this)\n })\n this.container.removeChild(this.element)\n this.container = undefined\n for (let key in this) {\n delete this[key]\n }\n delete this.state\n this.update = undefined\n this.unmount = undefined\n }\n}\n","/**\n * @description Hyperscript function. Enables definition of HTML/SVG using functions.\n * @param {string} type - The name of the HTML or SVG tag to create.\n * @param {object} props - And object of property/value pairs.\n * @param {string|number|boolean|any[]} args - Any child elements.\n * @returns {object} A virtual node describing an element.\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\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 if (typeof type === 'function') {\n return type(props || {}, childNodes)\n } else {\n return {\n type,\n props: props || {},\n children: childNodes\n }\n }\n}\n","import {patch} from './patch'\nimport {h} from './h'\n\n/** \n * Function to throw error message when attempting to insert Fragement tag directly into DOM.\n */\nfunction FragmentError() {\n this.message = 'Cannot insert Fragment directly into DOM.'\n this.toString = function() {\n return this.message\n }\n}\n\n/**\n * @description 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 {function} tag A JSX tag or hyperscript function to render.\n * @param {HTMLElement|boolean} [container] The element into which the tag will be rendered.\n * @returns {HTMLElement} The base element of the rendered tag.\n */\nexport const mount = (tag, container) => {\n container = typeof container === 'string' && document.querySelector(container)\n if (!container) container = document.body\n if (Array.isArray(tag)) throw new FragmentError()\n const element = patch(tag)\n return container.appendChild(element)\n}\n","import {h} from './h'\nimport {patch} from './patch'\n\n/**\n * @description 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!'/>, element)\n * @param {function} tag A JSX tag or hyperscript function to render.\n * @param {HTMLElement|boolean} [element] The element in the DOM which will be updated.\n * @returns {HTMLElement} The base element of the rendered tag.\n */\n export function render(tag, element) {\n return patch(tag, element)\n }\n","/**\n * @description A tag to enable return sibling elements. This is useful for return 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 {null|Object} props This is never used. If using Fragment as a function, provide either null or {} as value.\n * @param {any[]} children The siblings to return with the Fragment.\n * @returns {object[]} An array of virtual nodes.\n */\nexport const Fragment = (props, children) => children\n"],"names":["getKey","node","props","key","mixin","obj1","obj2","result","i","setProp","element","prop","value","oldValue","isSVG","style","setProperty","innerHTML","toLowerCase","setAttributeNS","setAttribute","removeAttribute","removeElement","parent","removeChild","removeChildren","children","length","childNodes","patchElement","oldNode","recycle","type","newElement","createElement","document","createTextNode","createElementNS","appendChild","insertBefore","nodeValue","oldProps","oldKeyed","newKeyed","oldElements","oldChildren","oldKey","k","newKey","keyedNode","patch","parentNode","recycleElement","nodeName","Array","prototype","map","call","nodeType","rAF","window","requestAnimationFrame","webkitRequestAnimationFrame","mozRequestAnimationFrame","msRequestAnimationFrame","cb","setTimeout","dataStore","Date","getTime","Component","selector","container","render","state","this","querySelector","componentShouldUpdate","mounted","componentWillMount","componentDidMount","componentWillUpdate","componentDidUpdate","componentWillUnmount","data","position","setState","isArray","babelHelpers.typeof","__data","__oldNode","__render","vdom","elem","id","testIfVNodesDiffer","JSON","stringify","removeEventListener","event","undefined","update","unmount","_this2","nodes","push","pop","tag","body","message","toString"],"mappings":"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"}
\No newline at end of file