UNPKG

33.3 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 // Do not add these as node attributes:\n if (prop === 'key' || prop == 'componentWillMount' || prop === 'onComponentDidMount' || prop == 'componentWillUpdate' || prop === 'onComponentDidUpdate' || prop === 'componentWillUnmount') {\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) => {\n parent.removeChild(removeChildren(element, node))\n if (node && node.props && node.props['onComponentDidUnmount']) {\n node.props['onComponentDidUnmount'].call(node.props['onComponentDidUnmount'], parent)\n }\n}\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 {HTMLElement} recycle If a node is provided, reuse it.\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 && 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 || 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 let element\n if (typeof node === 'string' || typeof node === 'number') {\n element = document.createTextNode(node)\n } else if (isSVG = isSVG || node.type === 'svg') {\n element = document.createElementNS('http://www.w3.org/2000/svg', node.type)\n } else {\n element = document.createElement(node.type)\n }\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 // Handle lifecycle hook:\n if (element.mounted && props && props['onComponentDidUpdate']) {\n props['onComponentDidUpdate'].call(props['onComponentDidUpdate'], oldProps, props, element)\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 if (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 } else {\n element = patchElement(\n null, \n null, \n null, \n node\n )\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 *\n * Possible values to pass to new Component are:\n * 1. container - element to render component in.\n * 2. state - data for the component to consume.\n * 2. render - a function to return markup to create.\n * 3. componentWillMount - a callback to execute before the component is mount.\n * 4. componentDidMount - a callback to execute after the component mounts.\n * 5. componentWillUpdate - a callback to execute before the component updates.\n * 6. componentDidUpdate - a callback to execute after the component updates.\n * 7. componentWillUnmount - a callback to execute before the component unmounts.\n *\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 \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) \n this.componentWillMount = props.componentWillMount\n\n if (props.componentDidMount) \n this.componentDidMount = props.componentDidMount\n\n if (props.componentWillUpdate) \n this.componentWillUpdate = props.componentWillUpdate\n\n if (props.componentDidUpdate) \n this.componentDidUpdate = props.componentDidUpdate\n\n if (props.componentWillUnmount) \n 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\n // Create virtual dom and check if component id \n // 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 'pointercancel',\n 'pointerdown',\n 'pointermove',\n 'pointerup',\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 tag 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 if (tag.props && tag.props['onComponentDidMount']) {\n tag.props['onComponentDidMount'].call(tag.props['onComponentDidMount'], element)\n }\n element.mounted = true\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 */\nexport function render(tag, element) {\n return patch(tag, element)\n}\n","/**\n * @description 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 {null|Object} props When using Fragment as a function, props is the first argument. Provide either null or {} as the value for props.\n * @param {any[]} children The siblings to return with the Fragment. This will be an array of sibling elements.\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","call","patchElement","oldNode","recycle","type","newElement","createElement","document","createTextNode","createElementNS","appendChild","insertBefore","nodeValue","oldProps","mounted","oldKeyed","newKeyed","oldElements","oldChildren","oldKey","k","newKey","keyedNode","patch","parentNode","recycleElement","nodeName","Array","prototype","map","nodeType","rAF","window","requestAnimationFrame","webkitRequestAnimationFrame","mozRequestAnimationFrame","msRequestAnimationFrame","cb","setTimeout","dataStore","Date","getTime","Component","selector","container","render","state","this","querySelector","componentShouldUpdate","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":"0LAKA,IAAaA,EAAS,mBAAQC,GAAQA,EAAKC,MAAQD,EAAKC,MAAMC,IAAM,MCCpE,SAAgBC,EAAMC,EAAMC,OACpBC,SACD,IAAIC,KAAKH,IACLG,GAAKH,EAAKG,OAEd,IAAIA,KAAKF,IACLE,GAAKF,EAAKE,UAEZD,ECHT,SAAgBE,EACZC,EACAC,EACAC,EACAC,EACAC,MAGW,QAATH,GAA0B,sBAARA,GAAyC,wBAATA,GAA0C,uBAARA,GAA0C,yBAATA,GAA4C,yBAATA,QACrJ,GAAa,UAATA,GAAqC,iBAAVC,MAC/B,IAAIJ,KAAKJ,EAAMS,EAAUD,GAAQ,KAC9BG,EAAiB,MAATH,GAA6B,MAAZA,EAAMJ,GAAa,GAAKI,EAAMJ,GAChD,MAATA,EAAE,KACIG,GAAMK,YAAYR,EAAGO,KAErBJ,GAAMH,GAAKO,MAMV,cAATJ,IAAsBA,EAAO,SAGpB,4BAATA,IAAoCD,EAAQO,UAAYL,GAI7C,KAAXD,EAAK,IAAwB,KAAXA,EAAK,OAClBA,EAAKO,eAGVP,KAAQD,GAAoB,SAATC,IAAoBG,IACjCH,GAA0B,MAAlBC,EAA0B,GAAKA,EAC7B,MAATA,IAA2B,IAAVA,GAA6B,OAAVA,IAGhC,eAATD,KACMQ,eAAe,+BAAgC,OAAQP,KACvDQ,aAAa,OAAQR,KAEf,SAAVA,IAAkBA,GAAQ,KACtBQ,aAAaT,EAAMC,KAIlB,MAATA,IAA2B,IAAVA,GAA6B,UAAVA,KAC9BS,gBAAgBV,GCjD9B,IAAaW,EAAgB,SAACC,EAAQb,EAAST,KACtCuB,YCJT,SAAgBC,EAAef,EAAST,MACxBA,EAAKC,UAEZ,IAAIM,EAAI,EAAGA,EAAIP,EAAKyB,SAASC,OAAQnB,MACzBE,EAAQkB,WAAWpB,GAAIP,EAAKyB,SAASlB,WAGjDE,EDHYe,CAAef,EAAST,IACvCA,GAAQA,EAAKC,OAASD,EAAKC,MAAL,yBACnBA,MAAL,sBAAoC2B,KAAK5B,EAAKC,MAAL,sBAAqCqB,IEGlF,SAAgBO,EACZP,EACAb,EACAqB,EACA9B,EACA+B,EACAlB,MAEEb,IAAS8B,QACN,GAAe,MAAXA,GAAmBA,EAAQE,OAAShC,EAAKgC,KAAM,KAClDC,ECjBV,SAAgBC,EAAclC,EAAMa,OAC9BJ,WACgB,iBAATT,GAAqC,iBAATA,EAC3BmC,SAASC,eAAepC,IACzBa,EAAQA,GAAuB,QAAdb,EAAKgC,MACrBG,SAASE,gBAAgB,6BAA8BrC,EAAKgC,MAE5DG,SAASD,cAAclC,EAAKgC,UAGlC/B,EAAQD,EAAKC,SACfA,EAAO,KAEJ,IAAIM,EAAI,EAAGA,EAAIP,EAAKyB,SAASC,OAAQnB,MAChC+B,YAAYJ,EAAclC,EAAKyB,SAASlB,GAAIM,QAGjD,IAAIH,KAAQT,IACPQ,EAASC,EAAMT,EAAMS,GAAO,KAAMG,UAIvCJ,EDLcyB,CAAclC,EAAMa,GACnCS,MACKiB,aAAaN,EAAYxB,GACjB,MAAXqB,KACYR,EAAQb,EAASqB,MAGzBG,OACL,GAAoB,MAAhBH,EAAQE,OACTQ,UAAYxC,MACf,EExBT,SACIS,EACAgC,EACAxC,EACAY,OAEG,IAAIH,KAAQP,EAAMsC,EAAUxC,GAE7BA,EAAMS,MACI,UAATA,GAA6B,YAATA,EACjBD,EAAQC,GACR+B,EAAS/B,OAGXD,EACAC,EACAT,EAAMS,GACN+B,EAAS/B,GACTG,GAKFJ,EAAQiC,SAAWzC,GAASA,EAAA,wBAC9B,qBAA8B2B,KAAK3B,EAAA,qBAA+BwC,EAAUxC,EAAOQ,IFEjFA,EACAqB,EAAQ7B,MACRD,EAAKC,MACJY,EAAQA,GAAuB,QAAdb,EAAKgC,cAGnBW,KACAC,KACAC,KACAC,EAAchB,EAAQL,SACtBA,EAAWzB,EAAKyB,SAEblB,EAAI,EAAGA,EAAIuC,EAAYpB,OAAQnB,IAAK,GAC/BA,GAAKE,EAAQkB,WAAWpB,OAE9BwC,EAAShD,EAAO+C,EAAYvC,IACpB,MAAVwC,MACOA,IAAWF,EAAYtC,GAAIuC,EAAYvC,aAIhDA,EAAI,EACJyC,EAAI,EAEDA,EAAIvB,EAASC,QAAQ,KACtBqB,EAAShD,EAAO+C,EAAYvC,IAC5B0C,EAASlD,EAAO0B,EAASuB,OAEzBJ,EAASG,eAKC,MAAVE,GAAkBA,IAAWlD,EAAO+C,EAAYvC,EAAI,OAQ1C,MAAV0C,GAAkBlB,EACN,MAAVgB,MAEAtC,EACAoC,EAAYtC,GACZuC,EAAYvC,GACZkB,EAASuB,GACTjB,EACAlB,gBAKC,KACCqC,EAAYP,EAASM,OAEvBF,IAAWE,KAEXxC,EACAyC,EAAU,GACVA,EAAU,GACVzB,EAASuB,GACTjB,EACAlB,QAGOqC,EAAU,KAEjBzC,EACAA,EAAQ8B,aAAaW,EAAU,GAAIL,EAAYtC,IAC/C2C,EAAU,GACVzB,EAASuB,GACTjB,EACAlB,KAIAJ,EACAoC,EAAYtC,GACZ,KACAkB,EAASuB,GACTjB,EACAlB,KAIKoC,GAAUxB,EAASuB,YArDd,MAAVD,KACYtC,EAASoC,EAAYtC,GAAIuC,EAAYvC,aAyDlDA,EAAIuC,EAAYpB,QACS,MAA1B3B,EAAO+C,EAAYvC,OACPE,EAASoC,EAAYtC,GAAIuC,EAAYvC,YAKlD,IAAIA,KAAKoC,EACPC,EAASrC,MACEE,EAASkC,EAASpC,GAAG,GAAIoC,EAASpC,GAAG,WAIlDE,EGrIT,SAAgB0C,EAAMnD,EAAMS,UACtBA,IAEAA,EAAQ2C,WACR3C,EACgB,MAAhBA,EAAQT,KCTd,SAAgBqD,EAAe5C,MACzBA,GAAWA,EAAQ6C,qBAEb7C,EAAQ6C,SAASrC,gCAEbsC,MAAMC,UAAUC,IAAI7B,KAC5BnB,EAAQgB,SACR,mBAAgC,IAArBhB,EAAQiD,SACfjD,EAAQ+B,UACRa,EAAe5C,MDCjB4C,CAAe5C,GACfA,EAAQT,KACZA,EACgB,MAAhBS,EAAQT,QAGA6B,EACR,KACA,KACA,KACA7B,KAIIA,KAAOA,EAERS,k8CExBHkD,EAAMC,QAAUA,OAAOC,uBACxBD,QAAUA,OAAOE,6BACjBF,QAAUA,OAAOG,0BACjBH,QAAUA,OAAOI,yBACjB,SAASC,UAAaC,WAAWD,EAAI,KAMpCE,GAAY,IAAIC,MAAOC,UA6BhBC,wBAoBCrE,aACLA,IAAOA,WAEPsE,SAAWtE,EAAMuE,WAAa,OAE/BvE,EAAMwE,cAEHA,OAASxE,EAAMwE,QAGlBxE,EAAMyE,aAEHA,MAAQzE,EAAMyE,YAIhB5C,QAAU,KACX6C,KAAKJ,gBAEFC,UAAYrC,SAASyC,cAAcD,KAAKJ,gBAI1CM,uBAAwB,OAGxBnC,SAAU,OAMVjC,QAKDR,EAAM6E,qBACRH,KAAKG,mBAAqB7E,EAAM6E,oBAE9B7E,EAAM8E,oBACRJ,KAAKI,kBAAoB9E,EAAM8E,mBAE7B9E,EAAM+E,sBACRL,KAAKK,oBAAsB/E,EAAM+E,qBAE/B/E,EAAMgF,qBACRN,KAAKM,mBAAqBhF,EAAMgF,oBAE9BhF,EAAMiF,uBACRP,KAAKO,qBAAuBjF,EAAMiF,iEAkC7BC,EAAMC,MACO,mBAATD,EAAqB,KACxBT,EAAQS,EAAKvD,KAAK+C,KAAMA,KAAKD,OACd,mBAAVA,GAA0BA,GAAOC,KAAKU,SAASX,QACrD,GAAInB,MAAM+B,QAAQX,KAAKD,OAAQ,KAC9BA,EAAQC,KAAKD,MACfU,GAAyB,IAAbA,EACiB,WAA3BG,EAAOb,EAAMU,SACVV,MAAQvE,EAAMuE,EAAMU,GAAWD,MAE9BC,GAAYD,OACbT,MAAQA,QAGVA,MAAQA,OAEV,GAA0B,WAAtBa,EAAOZ,KAAKD,OAAoB,KACnCA,EAAQC,KAAKD,WACdA,MAAQvE,EAAMuE,EAAOS,aAErBT,MAAQS,iCAYVA,MACAR,KAAKF,SAILE,KAAKE,wBAAyBF,KAAKjC,cAIpC8C,EAAUb,KAAKD,OACN,IAATS,GAAiBA,IAAMK,EAASL,GAEhCR,KAAKH,WAAuC,iBAAnBG,KAAKH,iBAC3BD,SAAWI,KAAKH,eAChBA,UAAYrC,SAASyC,cAAcD,KAAKH,gBAKzCiB,EAAYd,KAAK7C,QACjB4D,EAAWf,KAAKF,OAWhBkB,EAAOhB,KAAKF,OAAOe,GACrBI,YAEFD,GACGA,EAAK1F,OACL0F,EAAK1F,MAAM4F,IACXlB,KAAKH,cAEDG,KAAKH,WAAaG,KAAKH,UAAUI,kBAAkBe,EAAK1F,MAAM4F,KAKnED,IAASjB,KAAKjC,WACXU,WAAW7B,YAAYqE,QAIzB9D,QAAU6C,KAAKF,OAAOe,QACtB/E,QAAU0C,EACbwB,KAAK7C,QACL6C,KAAKlE,UAEFkE,KAAKjC,oBACHoC,oBAAsBH,KAAKG,mBAAmBH,WAC9CH,UAAUlC,YAAYqC,KAAKlE,cAC3BiC,SAAU,YACVqC,mBAAqBJ,KAAKI,kBAAkBJ,OAI/CA,KAAKjC,SAAWiC,KAAK7C,SAAWgE,EAAmBL,EAAWD,SAC3DR,qBAAuBL,KAAKK,oBAAoBL,WAElDM,oBAAsBa,EAAmBL,EAAWD,IAAWb,KAAKM,mBAAmBN,eA5CnFmB,EAAmBhE,EAASqD,UAC/BR,MAAQoB,KAAKC,UAAUlE,KAAaiE,KAAKC,UAAUN,EAASP,qDAgF7DR,KAAKlE,cACLyE,sBAAwBP,KAAKO,qBAAqBP,OAxBrD,SACA,QACA,WACA,QACA,UACA,WACA,QACA,YACA,aACA,WACA,YACA,UACA,gBACA,cACA,cACA,YACA,SACA,SACA,cACA,WACA,YACA,cAIalB,IAAI,cACZhD,QAAQwF,oBAAoBC,YAE9B1B,UAAUjD,YAAYoD,KAAKlE,cAC3B+D,eAAY2B,MACZ,IAAIjG,KAAOyE,YACPA,KAAKzE,UAEPyE,KAAKD,WACP0B,YAASD,OACTE,aAAUF,wCA5KRxB,KAAKR,iBAQJgB,mBACHhB,GAAagB,IACd,kBAAMmB,EAAKF,wBCnHnB,SAAkBpE,EAAM/B,WAChBsG,KACA5E,wBAF0BF,2DAG5BC,EAASD,EAASC,OAEfA,KAAW,KAAS8E,KAAK/E,EAASC,IAEzC,KAAO6E,EAAM7E,QAAQ,KACb1B,EAAOuG,EAAME,SACfzG,GAAQA,EAAKyG,QACV/E,EAAS1B,EAAK0B,OAAQA,OACnB8E,KAAKxG,EAAK0B,SAED,MAAR1B,IAAyB,IAATA,IAA0B,IAATA,KAC/BwG,KAAKxG,SAIA,mBAATgC,EACFA,EAAK/B,MAAa0B,iBAIhB1B,eACG0B,YCpBK,SAAC+E,EAAKlC,SACQ,iBAAdA,GAA0BrC,SAASyC,cAAcJ,MACpDA,EAAYrC,SAASwE,MACjCpD,MAAM+B,QAAQoB,GAAM,MAAM,IApBhC,gBACOE,QAAU,qDACVC,SAAW,kBACPlC,KAAKiC,cAkBRnG,EAAU0C,EAAMuD,UAClBA,EAAIzG,OAASyG,EAAIzG,MAAJ,uBACXA,MAAJ,oBAAiC2B,KAAK8E,EAAIzG,MAAJ,oBAAkCQ,KAElEiC,SAAU,EACX8B,EAAUlC,YAAY7B,aCnB/B,SAAuBiG,EAAKjG,UACnB0C,EAAMuD,EAAKjG,6BCII,SAACR,EAAOwB,UAAaA"}
\No newline at end of file