preact+timeline+scene实现动画关键帧时间条编辑效果代码

代码语言:html

所属分类:其他

代码描述:preact+timeline+scene实现动画关键帧时间条编辑效果代码算效果代码

代码标签: preact timeline scene 动画 关键帧 时间条 编辑

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
   <style>
       html,body {
    position: relative;
    width: 100%;
    height: 100%;
}
.clapper {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	width: 200px;
	height: 200px;
	z-index: 2;
	transform-origin: 20% 60%;
	will-change: transform;
	-webkit-backface-visibility: hidden;
	-webkit-perspective: 1000;
}

.clapper .clapper-container {
	position: absolute;
	margin: auto;
	width: 200px;
	height: 170px;
	left: -200px;
	right: -200px;
	top: -200px;
	bottom: -200px;
}

.clapper .clapper-container .clapper-body {
	position: relative;
	width: 100%;
	height: 100%;
}

.clapper .stick {
	position: absolute;
	box-sizing: border-box;
	width: 200px;
	height: 32px;
	font-size: 0;
	overflow: hidden;
	white-space: nowrap;
	padding: 5px 8px;
	text-align: center;
	background: #333;
}

.clapper .stick1 {
	transform-origin: 0% 100%;
	border-radius: 5px 5px 0px 0px;
}

.clapper .stick2 {
	top: 30px;
}

.clapper .rect {
	position: relative;
	display: inline-block;
	height: 100%;
	width: 20px;
	background: white;
	vertical-align: top;
	margin: 0px 5px 0px;
	border-radius: 5px;
}

.clapper .stick1 .rect {
	transform: skew(15deg);
}

.clapper .stick2 .rect {
	transform: skew(-15deg);
}

.clapper .top {
	position: absolute;
	top: 0;
	border-radius: 5px 5px 0px 0px;
	width: 100%;
	height: 37%;
}

.clapper .bottom {
	position: absolute;
	bottom: 0;
	width: 100%;
	height: 64%;
	background: #333;
	border-bottom-left-radius: 5px;
	border-bottom-right-radius: 5px;
}

.clapper .circle {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 10%;
	margin: auto;
	width: 70px;
	height: 70px;
	background: white;
	border-radius: 50%;
}

.clapper .play {
	position: absolute;
	left: 50%;
	margin-left: 3px;
	bottom: 7%;
	transform: translate(-50%, -50%);
	width: 32px;
	/* 	overflow: hidden; */
}
.clapper .play svg {
	-webkit-backface-visibility: hidden;
	outline: 1px solid transparent;
}

   </style>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>

  </body>
  <script >
      /*
Copyright (c) 2019 Daybrush
name: preact-timeline
license: MIT
author: Daybrush
repository: git+https://github.com/daybrush/scenejs-timeline.git
version: 0.2.0
*/
(function (factory) {
	typeof define === 'function' && define.amd ? define(factory) :
	factory();
}(function () { 'use strict';

	var process = { env: {NODE_ENV: "production"} };

	var VNode = function VNode() {};

	var options = {};

	var stack = [];

	var EMPTY_CHILDREN = [];

	function h(nodeName, attributes) {
		var children = EMPTY_CHILDREN,
		    lastSimple,
		    child,
		    simple,
		    i;
		for (i = arguments.length; i-- > 2;) {
			stack.push(arguments[i]);
		}
		if (attributes && attributes.children != null) {
			if (!stack.length) stack.push(attributes.children);
			delete attributes.children;
		}
		while (stack.length) {
			if ((child = stack.pop()) && child.pop !== undefined) {
				for (i = child.length; i--;) {
					stack.push(child[i]);
				}
			} else {
				if (typeof child === 'boolean') child = null;

				if (simple = typeof nodeName !== 'function') {
					if (child == null) child = '';else if (typeof child === 'number') child = String(child);else if (typeof child !== 'string') simple = false;
				}

				if (simple && lastSimple) {
					children[children.length - 1] += child;
				} else if (children === EMPTY_CHILDREN) {
					children = [child];
				} else {
					children.push(child);
				}

				lastSimple = simple;
			}
		}

		var p = new VNode();
		p.nodeName = nodeName;
		p.children = children;
		p.attributes = attributes == null ? undefined : attributes;
		p.key = attributes == null ? undefined : attributes.key;

		if (options.vnode !== undefined) options.vnode(p);

		return p;
	}

	function extend(obj, props) {
	  for (var i in props) {
	    obj[i] = props[i];
	  }return obj;
	}

	function applyRef(ref, value) {
	  if (ref != null) {
	    if (typeof ref == 'function') ref(value);else ref.current = value;
	  }
	}

	var defer = typeof Promise == 'function' ? Promise.resolve().then.bind(Promise.resolve()) : setTimeout;

	function cloneElement(vnode, props) {
	  return h(vnode.nodeName, extend(extend({}, vnode.attributes), props), arguments.length > 2 ? [].slice.call(arguments, 2) : vnode.children);
	}

	var IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i;

	var items = [];

	function enqueueRender(component) {
		if (!component._dirty && (component._dirty = true) && items.push(component) == 1) {
			(defer)(rerender);
		}
	}

	function rerender() {
		var p;
		while (p = items.pop()) {
			if (p._dirty) renderComponent(p);
		}
	}

	function isSameNodeType(node, vnode, hydrating) {
		if (typeof vnode === 'string' || typeof vnode === 'number') {
			return node.splitText !== undefined;
		}
		if (typeof vnode.nodeName === 'string') {
			return !node._componentConstructor && isNamedNode(node, vnode.nodeName);
		}
		return hydrating || node._componentConstructor === vnode.nodeName;
	}

	function isNamedNode(node, nodeName) {
		return node.normalizedNodeName === nodeName || node.nodeName.toLowerCase() === nodeName.toLowerCase();
	}

	function getNodeProps(vnode) {
		var props = extend({}, vnode.attributes);
		props.children = vnode.children;

		var defaultProps = vnode.nodeName.defaultProps;
		if (defaultProps !== undefined) {
			for (var i in defaultProps) {
				if (props[i] === undefined) {
					props[i] = defaultProps[i];
				}
			}
		}

		return props;
	}

	function createNode(nodeName, isSvg) {
		var node = isSvg ? document.createElementNS('http://www.w3.org/2000/svg', nodeName) : document.createElement(nodeName);
		node.normalizedNodeName = nodeName;
		return node;
	}

	function removeNode(node) {
		var parentNode = node.parentNode;
		if (parentNode) parentNode.removeChild(node);
	}

	function setAccessor(node, name, old, value, isSvg) {
		if (name === 'className') name = 'class';

		if (name === 'key') ; else if (name === 'ref') {
			applyRef(old, null);
			applyRef(value, node);
		} else if (name === 'class' && !isSvg) {
			node.className = value || '';
		} else if (name === 'style') {
			if (!value || typeof value === 'string' || typeof old === 'string') {
				node.style.cssText = value || '';
			}
			if (value && typeof value === 'object') {
				if (typeof old !== 'string') {
					for (var i in old) {
						if (!(i in value)) node.style[i] = '';
					}
				}
				for (var i in value) {
					node.style[i] = typeof value[i] === 'number' && IS_NON_DIMENSIONAL.test(i) === false ? value[i] + 'px' : value[i];
				}
			}
		} else if (name === 'dangerouslySetInnerHTML') {
			if (value) node.innerHTML = value.__html || '';
		} else if (name[0] == 'o' && name[1] == 'n') {
			var useCapture = name !== (name = name.replace(/Capture$/, ''));
			name = name.toLowerCase().substring(2);
			if (value) {
				if (!old) node.addEventListener(name, eventProxy, useCapture);
			} else {
				node.removeEventListener(name, eventProxy, useCapture);
			}
			(node._listeners || (node._listeners = {}))[name] = value;
		} else if (name !== 'list' && name !== 'type' && !isSvg && name in node) {
			try {
				node[name] = value == null ? '' : value;
			} catch (e) {}
			if ((value == null || value === false) && name != 'spellcheck') node.removeAttribute(name);
		} else {
			var ns = isSvg && name !== (name = name.replace(/^xlink:?/, ''));

			if (value == null || value === false) {
				if (ns) node.removeAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase());else node.removeAttribute(name);
			} else if (typeof value !== 'function') {
				if (ns) node.setAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase(), value);else node.setAttribute(name, value);
			}
		}
	}

	function eventProxy(e) {
		return this._listeners[e.type](options.event && options.event(e) || e);
	}

	var mounts = [];

	var diffLevel = 0;

	var isSvgMode = false;

	var hydrating = false;

	function flushMounts() {
		var c;
		while (c = mounts.shift()) {
			if (c.componentDidMount) c.componentDidMount();
		}
	}

	function diff(dom, vnode, context, mountAll, parent, componentRoot) {
		if (!diffLevel++) {
			isSvgMode = parent != null && parent.ownerSVGElement !== undefined;

			hydrating = dom != null && !('__preactattr_' in dom);
		}

		var ret = idiff(dom, vnode, context, mountAll, componentRoot);

		if (parent && ret.parentNode !== parent) parent.appendChild(ret);

		if (! --diffLevel) {
			hydrating = false;

			if (!componentRoot) flushMounts();
		}

		return ret;
	}

	function idiff(dom, vnode, context, mountAll, componentRoot) {
		var out = dom,
		    prevSvgMode = isSvgMode;

		if (vnode == null || typeof vnode === 'boolean') vnode = '';

		if (typeof vnode === 'string' || typeof vnode === 'number') {
			if (dom && dom.splitText !== undefined && dom.parentNode && (!dom._component || componentRoot)) {
				if (dom.nodeValue != vnode) {
					dom.nodeValue = vnode;
				}
			} else {
				out = document.createTextNode(vnode);
				if (dom) {
					if (dom.parentNode) dom.parentNode.replaceChild(out, dom);
					recollectNodeTree(dom, true);
				}
			}

			out['__preactattr_'] = true;

			return out;
		}

		var vnodeName = vnode.nodeName;
		if (typeof vnodeName === 'function') {
			return buildComponentFromVNode(dom, vnode, context, mountAll);
		}

		isSvgMode = vnodeName === 'svg' ? true : vnodeName === 'foreignObject' ? false : isSvgMode;

		vnodeName = String(vnodeName);
		if (!dom || !isNamedNode(dom, vnodeName)) {
			out = createNode(vnodeName, isSvgMode);

			if (dom) {
				while (dom.firstChild) {
					out.appendChild(dom.firstChild);
				}
				if (dom.parentNode) dom.parentNode.replaceChild(out, dom);

				recollectNodeTree(dom, true);
			}
		}

		var fc = out.firstChild,
		    props = out['__preactattr_'],
		    vchildren = vnode.children;

		if (props == null) {
			props = out['__preactattr_'] = {};
			for (var a = out.attributes, i = a.length; i--;) {
				props[a[i].name] = a[i].value;
			}
		}

		if (!hydrating && vchildren && vchildren.length === 1 && typeof vchildren[0] === 'string' && fc != null && fc.splitText !== undefined && fc.nextSibling == null) {
			if (fc.nodeValue != vchildren[0]) {
				fc.nodeValue = vchildren[0];
			}
		} else if (vchildren && vchildren.length || fc != null) {
				innerDiffNode(out, vchildren, context, mountAll, hydrating || props.dangerouslySetInnerHTML != null);
			}

		diffAttributes(out, vnode.attributes, props);

		isSvgMode = prevSvgMode;

		return out;
	}

	function innerDiffNode(dom, vchildren, context, mountAll, isHydrating) {
		var originalChildren = dom.childNodes,
		    children = [],
		    keyed = {},
		    keyedLen = 0,
		    min = 0,
		    len = originalChildren.length,
		    childrenLen = 0,
		    vlen = vchildren ? vchildren.length : 0,
		    j,
		    c,
		    f,
		    vchild,
		    child;

		if (len !== 0) {
			for (var i = 0; i < len; i++) {
				var _child = originalChildren[i],
				    props = _child['__preactattr_'],
				    key = vlen && props ? _child._component ? _child._component.__key : props.key : null;
				if (key != null) {
					keyedLen++;
					keyed[key] = _child;
				} else if (props || (_child.splitText !== undefined ? isHydrating ? _child.nodeValue.trim() : true : isHydrating)) {
					children[childrenLen++] = _child;
				}
			}
		}

		if (vlen !== 0) {
			for (var i = 0; i < vlen; i++) {
				vchild = vchildren[i];
				child = null;

				var key = vchild.key;
				if (key != null) {
					if (keyedLen && keyed[key] !== undefined) {
						child = keyed[key];
						keyed[key] = undefined;
						keyedLen--;
					}
				} else if (min < childrenLen) {
						for (j = min; j < childrenLen; j++) {
							if (children[j] !== undefined && isSameNodeType(c = children[j], vchild, isHydrating)) {
								child = c;
								children[j] = undefined;
								if (j === childrenLen - 1) childrenLen--;
								if (j === min) min++;
								break;
							}
						}
					}

				child = idiff(child, vchild, context, mountAll);

				f = originalChildren[i];
				if (child && child !== dom && child !== f) {
					if (f == null) {
						dom.appendChild(child);
					} else if (child === f.nextSibling) {
						removeNode(f);
					} else {
						dom.insertBefore(child, f);
					}
				}
			}
		}

		if (keyedLen) {
			for (var i in keyed) {
				if (keyed[i] !== undefined) recollectNodeTree(keyed[i], false);
			}
		}

		while (min <= childrenLen) {
			if ((child = children[childrenLen--]) !== undefined) recollectNodeTree(child, false);
		}
	}

	function recollectNodeTree(node, unmountOnly) {
		var component = node._component;
		if (component) {
			unmountComponent(component);
		} else {
			if (node['__preactattr_'] != null) applyRef(node['__preactattr_'].ref, null);

			if (unmountOnly === false || node['__preactattr_'] == null) {
				removeNode(node);
			}

			removeChildren(node);
		}
	}

	function removeChildren(node) {
		node = node.lastChild;
		while (node) {
			var next = node.previousSibling;
			recollectNodeTree(node, true);
			node = next;
		}
	}

	function diffAttributes(dom, attrs, old) {
		var name;

		for (name in old) {
			if (!(attrs && attrs[name] != null) && old[name] != null) {
				setAccessor(dom, name, old[name], old[name] = undefined, isSvgMode);
			}
		}

		for (name in attrs) {
			if (name !== 'children' && name !== 'innerHTML' && (!(name in old) || attrs[name] !== (name === 'value' || name === 'checked' ? dom[name] : old[name]))) {
				setAccessor(dom, name, old[name], old[name] = attrs[name], isSvgMode);
			}
		}
	}

	var recyclerComponents = [];

	function createComponent(Ctor, props, context) {
		var inst,
		    i = recyclerComponents.length;

		if (Ctor.prototype && Ctor.prototype.render) {
			inst = new Ctor(props, context);
			Component.call(inst, props, context);
		} else {
			inst = new Component(props, context);
			inst.constructor = Ctor;
			inst.render = doRender;
		}

		while (i--) {
			if (recyclerComponents[i].constructor === Ctor) {
				inst.nextBase = recyclerComponents[i].nextBase;
				recyclerComponents.splice(i, 1);
				return inst;
			}
		}

		return inst;
	}

	function doRender(props, state, context) {
		return this.constructor(props, context);
	}

	function setComponentProps(component, props, renderMode, context, mountAll) {
		if (component._disable) return;
		component._disable = true;

		component.__ref = props.ref;
		component.__key = props.key;
		delete props.ref;
		delete props.key;

		if (typeof component.constructor.getDerivedStateFromProps === 'undefined') {
			if (!component.base || mountAll) {
				if (component.componentWillMount) component.componentWillMount();
			} else if (component.componentWillReceiveProps) {
				component.componentWillReceiveProps(props, context);
			}
		}

		if (context && context !== component.context) {
			if (!component.prevContext) component.prevContext = component.context;
			component.context = context;
		}

		if (!component.prevProps) component.prevProps = component.props;
		component.props = props;

		component._disable = false;

		if (renderMode !== 0) {
			if (renderMode === 1 || options.syncComponentUpdates !== false || !component.base) {
				renderComponent(component, 1, mountAll);
			} else {
				enqueueRender(component);
			}
		}

		applyRef(component.__ref, component);
	}

	function renderComponent(component, renderMode, mountAll, isChild) {
		if (component._disable) return;

		var props = component.props,
		    state = component.state,
		    context = component.context,
		    previousProps = component.prevProps || props,
		    previousState = component.prevState || state,
		    previousContext = component.prevContext || context,
		    isUpdate = component.base,
		    nextBase = component.nextBase,
		    initialBase = isUpdate || nextBase,
		    initialChildComponent = component._component,
		    skip = false,
		    snapshot = previousContext,
		    rendered,
		    inst,
		    cbase;

		if (component.constructor.getDerivedStateFromProps) {
			state = extend(extend({}, state), component.constructor.getDerivedStateFromProps(props, state));
			component.state = state;
		}

		if (isUpdate) {
			component.props = previousProps;
			component.state = previousState;
			component.context = previousContext;
			if (renderMode !== 2 && component.shouldComponentUpdate && component.shouldComponentUpdate(props, state, context) === false) {
				skip = true;
			} else if (component.componentWillUpdate) {
				component.componentWillUpdate(props, state, context);
			}
			component.props = props;
			component.state = state;
			component.context = context;
		}

		component.prevProps = component.prevState = component.prevContext = component.nextBase = null;
		component._dirty = false;

		if (!skip) {
			rendered = component.render(props, state, context);

			if (component.getChildContext) {
				context = extend(extend({}, context), component.getChildContext());
			}

			if (isUpdate && component.getSnapshotBeforeUpdate) {
				snapshot = component.getSnapshotBeforeUpdate(previousProps, previousState);
			}

			var childComponent = rendered && rendered.nodeName,
			    toUnmount,
			    base;

			if (typeof childComponent === 'function') {

				var childProps = getNodeProps(rendered);
				inst = initialChildComponent;

				if (inst && inst.constructor === childComponent && childProps.key == inst.__key) {
					setComponentProps(inst, childProps, 1, context, false);
				} else {
					toUnmount = inst;

					component._component = inst = createComponent(childComponent, childProps, context);
					inst.nextBase = inst.nextBase || nextBase;
					inst._parentComponent = component;
					setComponentProps(inst, childProps, 0, context, false);
					renderComponent(inst, 1, mountAll, true);
				}

				base = inst.base;
			} else {
				cbase = initialBase;

				toUnmount = initialChildComponent;
				if (toUnmount) {
					cbase = component._component = null;
				}

				if (initialBase || renderMode === 1) {
					if (cbase) cbase._component = null;
					base = diff(cbase, rendered, context, mountAll || !isUpdate, initialBase && initialBase.parentNode, true);
				}
			}

			if (initialBase && base !== initialBase && inst !== initialChildComponent) {
				var baseParent = initialBase.parentNode;
				if (baseParent && base !== baseParent) {
					baseParent.replaceChild(base, initialBase);

					if (!toUnmount) {
						initialBase._component = null;
						recollectNodeTree(initialBase, false);
					}
				}
			}

			if (toUnmount) {
				unmountComponent(toUnmount);
			}

			component.base = base;
			if (base && !isChild) {
				var componentRef = component,
				    t = component;
				while (t = t._parentComponent) {
					(componentRef = t).base = base;
				}
				base._component = componentRef;
				base._componentConstructor = componentRef.constructor;
			}
		}

		if (!isUpdate || mountAll) {
			mounts.push(component);
		} else if (!skip) {

			if (component.componentDidUpdate) {
				component.componentDidUpdate(previousProps, previousState, snapshot);
			}
		}

		while (component._renderCallbacks.length) {
			component._renderCallbacks.pop().call(component);
		}if (!diffLevel && !isChild) flushMounts();
	}

	function buildComponentFromVNode(dom, vnode, context, mountAll) {
		var c = dom && dom._component,
		    originalComponent = c,
		    oldDom = dom,
		    isDirectOwner = c && dom._componentConstructor === vnode.nodeName,
		    isOwner = isDirectOwner,
		    props = getNodeProps(vnode);
		while (c && !isOwner && (c = c._parentComponent)) {
			isOwner = c.constructor === vnode.nodeName;
		}

		if (c && isOwner && (!mountAll || c._component)) {
			setComponentProps(c, props, 3, context, mountAll);
			dom = c.base;
		} else {
			if (originalComponent && !isDirectOwner) {
				unmountComponent(originalComponent);
				dom = oldDom = null;
			}

			c = createComponent(vnode.nodeName, props, context);
			if (dom && !c.nextBase) {
				c.nextBase = dom;

				oldDom = null;
			}
			setComponentProps(c, props, 1, context, mountAll);
			dom = c.base;

			if (oldDom && dom !== oldDom) {
				oldDom._component = null;
				recollectNodeTree(oldDom, false);
			}
		}

		return dom;
	}

	function unmountComponent(component) {

		var base = component.base;

		component._disable = true;

		if (component.componentWillUnmount) component.componentWillUnmount();

		component.base = null;

		var inner = component._component;
		if (inner) {
			unmountComponent(inner);
		} else if (base) {
			if (base['__preactattr_'] != null) applyRef(base['__preactattr_'].ref, null);

			component.nextBase = base;

			removeNode(base);
			recyclerComponents.push(component);

			removeChildren(base);
		}

		applyRef(component.__ref, null);
	}

	function Component(props, context) {
		this._dirty = true;

		this.context = context;

		this.props = props;

		this.state = this.state || {};

		this._renderCallbacks = [];
	}

	extend(Component.prototype, {
		setState: function setState(state, callback) {
			if (!this.prevState) this.prevState = this.state;
			this.state = extend(extend({}, this.state), typeof state === 'function' ? state(this.state, this.props) : state);
			if (callback) this._renderCallbacks.push(callback);
			enqueueRender(this);
		},
		forceUpdate: function forceUpdate(callback) {
			if (callback) this._renderCallbacks.push(callback);
			renderComponent(this, 2);
		},
		render: function render() {}
	});

	function render(vnode, parent, merge) {
	  return diff(merge, vnode, {}, false, parent, false);
	}

	function createRef() {
		return {};
	}

	/*! *****************************************************************************
	Copyright (c) Microsoft Corporation. All rights reserved.
	Licensed under the Apache License, Version 2.0 (the "License"); you may not use
	this file except in compliance with the License. You may obtain a copy of the
	License at http://www.apache.org/licenses/LICENSE-2.0

	THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
	KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
	WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
	MERCHANTABLITY OR NON-INFRINGEMENT.

	See the Apache Version 2.0 License for specific language governing permissions
	and limitations under the License.
	***************************************************************************** */
	/* global Reflect, Promise */

	var extendStatics = function(d, b) {
	    extendStatics = Object.setPrototypeOf ||
	        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
	        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
	    return extendStatics(d, b);
	};

	function __extends(d, b) {
	    extendStatics(d, b);
	    function __() { this.constructor = d; }
	    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	}

	var __assign = function() {
	    __assign = Object.assign || function __assign(t) {
	        for (var s, i = 1, n = arguments.length; i < n; i++) {
	            s = arguments[i];
	            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
	        }
	        return t;
	    };
	    return __assign.apply(this, arguments);
	};

	var PropTypes = {
	  checkPropTypes: () => {}
	};

	function createEmitter(initialValue, bitmaskFactory) {
	    var registeredUpdaters = [];
	    var value = initialValue;
	    var diff = function (newValue) { return bitmaskFactory(value, newValue) | 0; };
	    return {
	        register: function (updater) {
	            registeredUpdaters.push(updater);
	            updater(value, diff(value));
	        },
	        unregister: function (updater) {
	            registeredUpdaters = registeredUpdaters.filter(function (i) { return i !== updater; });
	        },
	        val: function (newValue) {
	            if (newValue === undefined || newValue == value) {
	                return value;
	            }
	            var bitmask = diff(newValue);
	            value = newValue;
	            registeredUpdaters.forEach(function (up) { return up(newValue, bitmask); });
	            return value;
	        }
	    };
	}
	var noopEmitter = {
	    register: function (_) {
	        console.warn("Consumer used without a Provider");
	    },
	    unregister: function (_) {
	        // do nothing
	    },
	    val: function (_) {
	        //do nothing;
	    }
	};

	/*
	 * Extracts the children from the props and returns an object containing the
	 * only element of the given array (preact always passes children as an array)
	 * or null otherwise. The result contains always a reference to the original
	 * array of children
	 *
	 * @param {RenderableProps<*>} props - the component's properties
	 * @return {{ child: JSX.Element | null, children: JSX.Element[]}}
	 */
	function getOnlyChildAndChildren(props) {
	    var children = props.children;
	    var child = children.length === 1 ? children[0] : null;
	    return { child: child, children: children };
	}

	var __extends$1 = (undefined && undefined.__extends) || (function () {
	    var extendStatics = function (d, b) {
	        extendStatics = Object.setPrototypeOf ||
	            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
	            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
	        return extendStatics(d, b);
	    };
	    return function (d, b) {
	        extendStatics(d, b);
	        function __() { this.constructor = d; }
	        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	    };
	})();
	function getRenderer(props) {
	    var child = getOnlyChildAndChildren(props).child;
	    // TODO: "render" in props check is only done to make TS happy
	    return child || ("render" in props && props.render);
	}
	var MAX_SIGNED_31_BIT_INT = 1073741823;
	var defaultBitmaskFactory = function () { return MAX_SIGNED_31_BIT_INT; };
	var ids = 0;
	function _createContext(value, bitmaskFactory) {
	    var key = "_preactContextProvider-" + ids++;
	    var Provider = /*#__PURE__*/ (function (_super) {
	        __extends$1(Provider, _super);
	        function Provider(props) {
	            var _this = _super.call(this, props) || this;
	            _this._emitter = createEmitter(props.value, bitmaskFactory || defaultBitmaskFactory);
	            return _this;
	        }
	        Provider.prototype.getChildContext = function () {
	            var _a;
	            return _a = {}, _a[key] = this._emitter, _a;
	        };
	        Provider.prototype.componentDidUpdate = function () {
	            this._emitter.val(this.props.value);
	        };
	        Provider.prototype.render = function () {
	            var _a = getOnlyChildAndChildren(this.props), child = _a.child, children = _a.children;
	            if (child) {
	                return child;
	            }
	            // preact does not support fragments,
	            // therefore we wrap the children in a span
	            return h("span", null, children);
	        };
	        return Provider;
	    }(Component));
	    var Consumer = /*#__PURE__*/ (function (_super) {
	        __extends$1(Consumer, _super);
	        function Consumer(props, ctx) {
	            var _this = _super.call(this, props, ctx) || this;
	            _this._updateContext = function (value, bitmask) {
	                var unstable_observedBits = _this.props.unstable_observedBits;
	                var observed = unstable_observedBits === undefined || unstable_observedBits === null
	                    ? MAX_SIGNED_31_BIT_INT
	                    : unstable_observedBits;
	                observed = observed | 0;
	                if ((observed & bitmask) === 0) {
	                    return;
	                }
	                _this.setState({ value: value });
	            };
	            _this.state = { value: _this._getEmitter().val() || value };
	            return _this;
	        }
	        Consumer.prototype.componentDidMount = function () {
	            this._getEmitter().register(this._updateContext);
	        };
	        Consumer.prototype.shouldComponentUpdate = function (nextProps, nextState) {
	            return (this.state.value !== nextState.value ||
	                getRenderer(this.props) !== getRenderer(nextProps));
	        };
	        Consumer.prototype.componentWillUnmount = function () {
	            this._getEmitter().unregister(this._updateContext);
	        };
	        Consumer.prototype.componentDidUpdate = function (_, __, prevCtx) {
	            var previousProvider = prevCtx[key];
	            if (previousProvider === this.context[key]) {
	                return;
	            }
	            (previousProvider || noopEmitter).unregister(this._updateContext);
	            this.componentDidMount();
	        };
	        Consumer.prototype.render = function () {
	            // TODO: "render" in props check is only done to make TS happy
	            var render = "render" in this.props && this.props.render;
	            var r = getRenderer(this.props);
	            if (render && render !== r) {
	                console.warn("Both children and a render function are defined. Children will be used");
	            }
	            if (typeof r === "function") {
	                return r(this.state.value);
	            }
	            console.warn("Consumer is expecting a function as one and only child but didn't find any");
	        };
	        Consumer.prototype._getEmitter = function () {
	            return this.context[key] || noopEmitter;
	        };
	        return Consumer;
	    }(Component));
	    return {
	        Provider: Provider,
	        Consumer: Consumer
	    };
	}
	var createContext = _createContext;

	var version = '15.1.0'; // trick libraries to think we are react

	var ELEMENTS = 'a abbr address area article aside audio b base bdi bdo big blockquote body br button canvas caption cite code col colgroup data datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 head header hgroup hr html i iframe img input ins kbd keygen label legend li link main map mark menu menuitem meta meter nav noscript object ol optgroup option output p param picture pre progress q rp rt ruby s samp script section select small source span strong style sub summary sup table tbody td textarea tfoot th thead time title tr track u ul var video wbr circle clipPath defs ellipse g image line linearGradient mask path pattern polygon polyline radialGradient rect stop svg text tspan'.split(
		' '
	);

	var REACT_ELEMENT_TYPE = (typeof Symbol !== 'undefined' && Symbol.for && Symbol.for('react.element')) || 0xeac7;

	var COMPONENT_WRAPPER_KEY =
		typeof Symbol !== 'undefined' && Symbol.for ? Symbol.for('__preactCompatWrapper') : '__preactCompatWrapper';

	// don't autobind these methods since they already have guaranteed context.
	var AUTOBIND_BLACKLIST = {
		constructor: 1,
		render: 1,
		shouldComponentUpdate: 1,
		componentWillReceiveProps: 1,
		componentWillUpdate: 1,
		componentDidUpdate: 1,
		componentWillMount: 1,
		componentDidMount: 1,
		componentWillUnmount: 1,
		componentDidUnmount: 1
	};

	var CAMEL_PROPS = /^(?:accent|alignment|arabic|baseline|cap|clip|color|fill|flood|font|glyph|horiz|marker|overline|paint|stop|strikethrough|stroke|text|underline|unicode|units|v|vector|vert|word|writing|x)[A-Z]/;

	var BYPASS_HOOK = {};

	/*global process*/
	var DEV = false;
	try {
		DEV = process.env.NODE_ENV !== 'production';
	}
	catch (e) { }

	// a component that renders nothing. Used to replace components for unmountComponentAtNode.
	function EmptyComponent() {
		return null;
	}

	// make react think we're react.
	var VNode$1 = h('a', null).constructor;
	VNode$1.prototype.$$typeof = REACT_ELEMENT_TYPE;
	VNode$1.prototype.preactCompatUpgraded = false;
	VNode$1.prototype.preactCompatNormalized = false;

	Object.defineProperty(VNode$1.prototype, 'type', {
		get: function() {
			return this.nodeName;
		},
		set: function(v) {
			this.nodeName = v;
		},
		configurable: true
	});

	Object.defineProperty(VNode$1.prototype, 'props', {
		get: function() {
			return this.attributes;
		},
		set: function(v) {
			this.attributes = v;
		},
		configurable: true
	});

	var oldEventHook = options.event;
	options.event = function (e) {
		if (oldEventHook) { e = oldEventHook(e); }
		e.persist = Object;
		e.nativeEvent = e;
		return e;
	};

	var oldVnodeHook = options.vnode;
	options.vnode = function (vnode) {
		if (!vnode.preactCompatUpgraded) {
			vnode.preactCompatUpgraded = true;

			var tag = vnode.nodeName,
				attrs = (vnode.attributes = vnode.attributes == null ? {} : extend$1({}, vnode.attributes));

			if (typeof tag === 'function') {
				if (tag[COMPONENT_WRAPPER_KEY] === true || (tag.prototype && 'isReactComponent' in tag.prototype)) {
					if (vnode.children && String(vnode.children) === '') { vnode.children = undefined; }
					if (vnode.children) { attrs.children = vnode.children; }

					if (!vnode.preactCompatNormalized) {
						normalizeVNode(vnode);
					}
					handleComponentVNode(vnode);
				}
			}
			else {
				if (vnode.children && String(vnode.children) === '') { vnode.children = undefined; }
				if (vnode.children) { attrs.children = vnode.children; }

				if (attrs.defaultValue) {
					if (!attrs.value && attrs.value !== 0) {
						attrs.value = attrs.defaultValue;
					}
					delete attrs.defaultValue;
				}

				handleElementVNode(vnode, attrs);
			}
		}

		if (oldVnodeHook) { oldVnodeHook(vnode); }
	};

	function handleComponentVNode(vnode) {
		var tag = vnode.nodeName,
			a = vnode.attributes;

		vnode.attributes = {};
		if (tag.defaultProps) { extend$1(vnode.attributes, tag.defaultProps); }
		if (a) { extend$1(vnode.attributes, a); }
	}

	function handleElementVNode(vnode, a) {
		var shouldSanitize, attrs, i;
		if (a) {
			for (i in a) { if ((shouldSanitize = CAMEL_PROPS.test(i))) { break; } }
			if (shouldSanitize) {
				attrs = vnode.attributes = {};
				for (i in a) {
					if (a.hasOwnProperty(i)) {
						attrs[CAMEL_PROPS.test(i) ? i.replace(/([A-Z0-9])/, '-$1').toLowerCase() : i] = a[i];
					}
				}
			}
		}
	}

	// proxy render() since React returns a Component reference.
	function render$1(vnode, parent, callback) {
		var prev = parent && parent._preactCompatRendered && parent._preactCompatRendered.base;

		// ignore impossible previous renders
		if (prev && prev.parentNode !== parent) { prev = null; }

		// default to first Element child
		if (!prev && parent) { prev = parent.firstElementChild; }

		// remove unaffected siblings
		for (var i = parent.childNodes.length; i--;) {
			if (parent.childNodes[i] !== prev) {
				parent.removeChild(parent.childNodes[i]);
			}
		}

		var out = render(vnode, parent, prev);
		if (parent) { parent._preactCompatRendered = out && (out._component || { base: out }); }
		if (typeof callback === 'function') { callback(); }
		return (out && out._component) || out;
	}

	var ContextProvider = function () {};

	ContextProvider.prototype.getChildContext = function () {
		return this.props.context;
	};
	ContextProvider.prototype.render = function (props) {
		return props.children[0];
	};

	function renderSubtreeIntoContainer(parentComponent, vnode, container, callback) {
		var wrap = h(ContextProvider, { context: parentComponent.context }, vnode);
		var renderContainer = render$1(wrap, container);
		var component = renderContainer._component || renderContainer.base;
		if (callback) { callback.call(component, renderContainer); }
		return component;
	}

	function Portal(props) {
		renderSubtreeIntoContainer(this, props.vnode, props.container);
	}

	function createPortal(vnode, container) {
		return h(Portal, { vnode: vnode, container: container });
	}

	function unmountComponentAtNode(container) {
		var existing = container._preactCompatRendered && container._preactCompatRendered.base;
		if (existing && existing.parentNode === container) {
			render(h(EmptyComponent), container, existing);
			return true;
		}
		return false;
	}

	var ARR = [];

	// This API is completely unnecessary for Preact, so it's basically passthrough.
	var Children = {
		map: function(children, fn, ctx) {
			if (children == null) { return null; }
			children = Children.toArray(children);
			if (ctx && ctx !== children) { fn = fn.bind(ctx); }
			return children.map(fn);
		},
		forEach: function(children, fn, ctx) {
			if (children == null) { return null; }
			children = Children.toArray(children);
			if (ctx && ctx !== children) { fn = fn.bind(ctx); }
			children.forEach(fn);
		},
		count: function(children) {
			return (children && children.length) || 0;
		},
		only: function(children) {
			children = Children.toArray(children);
			if (children.length !== 1) { throw new Error('Children.only() expects only one child.'); }
			return children[0];
		},
		toArray: function(children) {
			if (children == null) { return []; }
			return ARR.concat(children);
		}
	};

	/** Track current render() component for ref assignment */
	var currentComponent;

	function createFactory(type) {
		return createElement.bind(null, type);
	}

	var DOM = {};
	for (var i = ELEMENTS.length; i--;) {
		DOM[ELEMENTS[i]] = createFactory(ELEMENTS[i]);
	}

	function upgradeToVNodes(arr, offset) {
		for (var i = offset || 0; i < arr.length; i++) {
			var obj = arr[i];
			if (Array.isArray(obj)) {
				upgradeToVNodes(obj);
			}
			else if (
				obj &&
				typeof obj === 'object' &&
				!isValidElement(obj) &&
				((obj.props && obj.type) || (obj.attributes && obj.nodeName) || obj.children)
			) {
				arr[i] = createElement(obj.type || obj.nodeName, obj.props || obj.attributes, obj.children);
			}
		}
	}

	function isStatelessComponent(c) {
		return typeof c === 'function' && !(c.prototype && c.prototype.render);
	}

	// wraps stateless functional components in a PropTypes validator
	function wrapStatelessComponent(WrappedComponent) {
		return createClass({
			displayName: WrappedComponent.displayName || WrappedComponent.name,
			render: function() {
				return WrappedComponent(this.props, this.context);
			}
		});
	}

	function statelessComponentHook(Ctor) {
		var Wrapped = Ctor[COMPONENT_WRAPPER_KEY];
		if (Wrapped) { return Wrapped === true ? Ctor : Wrapped; }

		Wrapped = wrapStatelessComponent(Ctor);

		Object.defineProperty(Wrapped, COMPONENT_WRAPPER_KEY, { configurable: true, value: true });
		Wrapped.displayName = Ctor.displayName;
		Wrapped.propTypes = Ctor.propTypes;
		Wrapped.defaultProps = Ctor.defaultProps;

		Object.defineProperty(Ctor, COMPONENT_WRAPPER_KEY, { configurable: true, value: Wrapped });

		return Wrapped;
	}

	function createElement() {
		var args = [], len = arguments.length;
		while ( len-- ) args[ len ] = arguments[ len ];

		upgradeToVNodes(args, 2);
		return normalizeVNode(h.apply(void 0, args));
	}

	function normalizeVNode(vnode) {
		vnode.preactCompatNormalized = true;

		applyClassName(vnode);

		if (isStatelessComponent(vnode.nodeName)) {
			vnode.nodeName = statelessComponentHook(vnode.nodeName);
		}

		var ref = vnode.attributes.ref,
			type = ref && typeof ref;
		if (currentComponent && (type === 'string' || type === 'number')) {
			vnode.attributes.ref = createStringRefProxy(ref, currentComponent);
		}

		applyEventNormalization(vnode);

		return vnode;
	}

	function cloneElement$1(element, props) {
		var children = [], len = arguments.length - 2;
		while ( len-- > 0 ) children[ len ] = arguments[ len + 2 ];

		if (!isValidElement(element)) { return element; }
		var elementProps = element.attributes || element.props;
		var node = h(
			element.nodeName || element.type,
			extend$1({}, elementProps),
			element.children || (elementProps && elementProps.children)
		);
		// Only provide the 3rd argument if needed.
		// Arguments 3+ overwrite element.children in preactCloneElement
		var cloneArgs = [node, props];
		if (children && children.length) {
			cloneArgs.push(children);
		}
		else if (props && props.children) {
			cloneArgs.push(props.children);
		}
		return normalizeVNode(cloneElement.apply(void 0, cloneArgs));
	}

	function isValidElement(element) {
		return element && (element instanceof VNode$1 || element.$$typeof === REACT_ELEMENT_TYPE);
	}

	function createStringRefProxy(name, component) {
		return (
			component._refProxies[name] ||
			(component._refProxies[name] = function (resolved) {
				if (component && component.refs) {
					component.refs[name] = resolved;
					if (resolved === null) {
						delete component._refProxies[name];
						component = null;
					}
				}
			})
		);
	}

	function applyEventNormalization(ref) {
		var nodeName = ref.nodeName;
		var attributes = ref.attributes;

		if (!attributes || typeof nodeName !== 'string') { return; }
		var props = {};
		for (var i in attributes) {
			props[i.toLowerCase()] = i;
		}
		if (props.ondoubleclick) {
			attributes.ondblclick = attributes[props.ondoubleclick];
			delete attributes[props.ondoubleclick];
		}
		// for *textual inputs* (incl textarea), normalize `onChange` -> `onInput`:
		if (
			props.onchange &&
			(nodeName === 'textarea' || (nodeName.toLowerCase() === 'input' && !/^fil|che|rad/i.test(attributes.type)))
		) {
			var normalized = props.oninput || 'oninput';
			if (!attributes[normalized]) {
				attributes[normalized] = multihook([attributes[normalized], attributes[props.onchange]]);
				delete attributes[props.onchange];
			}
		}
	}

	function applyClassName(vnode) {
		var a = vnode.attributes || (vnode.attributes = {});
		classNameDescriptor.enumerable = 'className' in a;
		if (a.className) { a.class = a.className; }
		Object.defineProperty(a, 'className', classNameDescriptor);
	}

	var classNameDescriptor = {
		configurable: true,
		get: function() {
			return this.class;
		},
		set: function(v) {
			this.class = v;
		}
	};

	function extend$1(base, props) {
		var arguments$1 = arguments;

		for (var i = 1, obj = (void 0); i < arguments.length; i++) {
			if ((obj = arguments$1[i])) {
				for (var key in obj) {
					if (obj.hasOwnProperty(key)) {
						base[key] = obj[key];
					}
				}
			}
		}
		return base;
	}

	function shallowDiffers(a, b) {
		for (var i in a) { if (!(i in b)) { return true; } }
		for (var i$1 in b) { if (a[i$1] !== b[i$1]) { return true; } }
		return false;
	}

	function findDOMNode(component) {
		return (component && (component.base || (component.nodeType === 1 && component))) || null;
	}

	function F() { }

	function createClass(obj) {
		function cl(props, context) {
			bindAll(this);
			Component$1.call(this, props, context, BYPASS_HOOK);
			newComponentHook.call(this, props, context);
		}

		obj = extend$1({ constructor: cl }, obj);

		// We need to apply mixins here so that getDefaultProps is correctly mixed
		if (obj.mixins) {
			applyMixins(obj, collateMixins(obj.mixins));
		}
		if (obj.statics) {
			extend$1(cl, obj.statics);
		}
		if (obj.propTypes) {
			cl.propTypes = obj.propTypes;
		}
		if (obj.defaultProps) {
			cl.defaultProps = obj.defaultProps;
		}
		if (obj.getDefaultProps) {
			cl.defaultProps = obj.getDefaultProps.call(cl);
		}

		F.prototype = Component$1.prototype;
		cl.prototype = extend$1(new F(), obj);

		cl.displayName = obj.displayName || 'Component';

		return cl;
	}

	// Flatten an Array of mixins to a map of method name to mixin implementations
	function collateMixins(mixins) {
		var keyed = {};
		for (var i = 0; i < mixins.length; i++) {
			var mixin = mixins[i];
			for (var key in mixin) {
				if (mixin.hasOwnProperty(key) && typeof mixin[key] === 'function') {
					(keyed[key] || (keyed[key] = [])).push(mixin[key]);
				}
			}
		}
		return keyed;
	}

	// apply a mapping of Arrays of mixin methods to a component prototype
	function applyMixins(proto, mixins) {
		for (var key in mixins)
			{ if (mixins.hasOwnProperty(key)) {
				proto[key] = multihook(
					mixins[key].concat(proto[key] || ARR),
					key === 'getDefaultProps' || key === 'getInitialState' || key === 'getChildContext'
				);
			} }
	}

	function bindAll(ctx) {
		for (var i in ctx) {
			var v = ctx[i];
			if (typeof v === 'function' && !v.__bound && !AUTOBIND_BLACKLIST.hasOwnProperty(i)) {
				(ctx[i] = v.bind(ctx)).__bound = true;
			}
		}
	}

	function callMethod(ctx, m, args) {
		if (typeof m === 'string') {
			m = ctx.constructor.prototype[m];
		}
		if (typeof m === 'function') {
			return m.apply(ctx, args);
		}
	}

	function multihook(hooks, skipDuplicates) {
		return function () {
			var arguments$1 = arguments;
			var this$1 = this;

			var ret;
			for (var i = 0; i < hooks.length; i++) {
				var r = callMethod(this$1, hooks[i], arguments$1);

				if (skipDuplicates && r != null) {
					if (!ret) { ret = {}; }
					for (var key in r)
						{ if (r.hasOwnProperty(key)) {
							ret[key] = r[key];
						} }
				}
				else if (typeof r !== 'undefined') { ret = r; }
			}
			return ret;
		};
	}

	function newComponentHook(props, context) {
		propsHook.call(this, props, context);
		this.componentWillReceiveProps = multihook([
			propsHook,
			this.componentWillReceiveProps || 'componentWillReceiveProps'
		]);
		this.render = multihook([propsHook, beforeRender, this.render || 'render', afterRender]);
	}

	function propsHook(props, context) {
		if (!props) { return; }

		// React annoyingly special-cases single children, and some react components are ridiculously strict about this.
		var c = props.children;
		if (
			c &&
			Array.isArray(c) &&
			c.length === 1 &&
			(typeof c[0] === 'string' || typeof c[0] === 'function' || c[0] instanceof VNode$1)
		) {
			props.children = c[0];

			// but its totally still going to be an Array.
			if (props.children && typeof props.children === 'object') {
				props.children.length = 1;
				props.children[0] = props.children;
			}
		}

		// add proptype checking
		if (DEV) {
			var ctor = typeof this === 'function' ? this : this.constructor,
				propTypes = this.propTypes || ctor.propTypes;
			var displayName = this.displayName || ctor.name;
		}
	}

	function beforeRender(props) {
		currentComponent = this;
	}

	function afterRender() {
		if (currentComponent === this) {
			currentComponent = null;
		}
	}

	function Component$1(props, context, opts) {
		Component.call(this, props, context);
		this.state = this.getInitialState ? this.getInitialState() : {};
		this.refs = {};
		this._refProxies = {};
		if (opts !== BYPASS_HOOK) {
			newComponentHook.call(this, props, context);
		}
	}
	extend$1((Component$1.prototype = new Component()), {
		constructor: Component$1,

		isReactComponent: {},

		replaceState: function(state, callback) {
			var this$1 = this;

			this.setState(state, callback);
			for (var i in this$1.state) {
				if (!(i in state)) {
					delete this$1.state[i];
				}
			}
		},

		getDOMNode: function() {
			return this.base;
		},

		isMounted: function() {
			return !!this.base;
		}
	});

	function PureComponent(props, context) {
		Component$1.call(this, props, context);
	}
	F.prototype = Component$1.prototype;
	PureComponent.prototype = new F();
	PureComponent.prototype.isPureReactComponent = true;
	PureComponent.prototype.shouldComponentUpdate = function (props, state) {
		return shallowDiffers(this.props, props) || shallowDiffers(this.state, state);
	};

	function unstable_batchedUpdates(callback) {
		callback();
	}

	var index = {
		version: version,
		DOM: DOM,
		PropTypes: PropTypes,
		Children: Children,
		render: render$1,
		hydrate: render$1,
		createClass: createClass,
		createContext: createContext,
		createPortal: createPortal,
		createFactory: createFactory,
		createElement: createElement,
		cloneElement: cloneElement$1,
		createRef: createRef,
		isValidElement: isValidElement,
		findDOMNode: findDOMNode,
		unmountComponentAtNode: unmountComponentAtNode,
		Component: Component$1,
		PureComponent: PureComponent,
		unstable_renderSubtreeIntoContainer: renderSubtreeIntoContainer,
		unstable_batchedUpdates: unstable_batchedUpdates,
		__spread: extend$1
	};

	/*
	Copyright (c) 2018 Daybrush
	@name: @daybrush/utils
	license: MIT
	author: Daybrush
	repository: https://github.com/daybrush/utils
	@version 0.10.0
	*/
	/**
	* @namespace
	* @name Consts
	*/

	/**
	* get string "rgb"
	* @memberof Color
	* @example
	import {RGB} from "@daybrush/utils";

	console.log(RGB); // "rgb"
	*/
	var RGB = "rgb";
	/**
	* get string "rgba"
	* @memberof Color
	* @example
	import {RGBA} from "@daybrush/utils";

	console.log(RGBA); // "rgba"
	*/

	var RGBA = "rgba";
	/**
	* get string "hsl"
	* @memberof Color
	* @example
	import {HSL} from "@daybrush/utils";

	console.log(HSL); // "hsl"
	*/

	var HSL = "hsl";
	/**
	* get string "hsla"
	* @memberof Color
	* @example
	import {HSLA} from "@daybrush/utils";

	console.log(HSLA); // "hsla"
	*/

	var HSLA = "hsla";
	/**
	* gets an array of color models.
	* @memberof Color
	* @example
	import {COLOR_MODELS} from "@daybrush/utils";

	console.log(COLOR_MODELS); // ["rgb", "rgba", "hsl", "hsla"];
	*/

	var COLOR_MODELS = [RGB, RGBA, HSL, HSLA];
	/**
	* get string "function"
	* @memberof Consts
	* @example
	import {FUNCTION} from "@daybrush/utils";

	console.log(FUNCTION); // "function"
	*/

	var FUNCTION = "function";
	/**
	* get string "property"
	* @memberof Consts
	* @example
	import {PROPERTY} from "@daybrush/utils";

	console.log(PROPERTY); // "property"
	*/

	var PROPERTY = "property";
	/**
	* get string "array"
	* @memberof Consts
	* @example
	import {ARRAY} from "@daybrush/utils";

	console.log(ARRAY); // "array"
	*/

	var ARRAY = "array";
	/**
	* get string "object"
	* @memberof Consts
	* @example
	import {OBJECT} from "@daybrush/utils";

	console.log(OBJECT); // "object"
	*/

	var OBJECT = "object";
	/**
	* get string "string"
	* @memberof Consts
	* @example
	import {STRING} from "@daybrush/utils";

	console.log(STRING); // "string"
	*/

	var STRING = "string";
	/**
	* get string "number"
	* @memberof Consts
	* @example
	import {NUMBER} from "@daybrush/utils";

	console.log(NUMBER); // "number"
	*/

	var NUMBER = "number";
	/**
	* get string "undefined"
	* @memberof Consts
	* @example
	import {UNDEFINED} from "@daybrush/utils";

	console.log(UNDEFINED); // "undefined"
	*/

	var UNDEFINED = "undefined";
	/**
	* Check whether the environment is window or node.js.
	* @memberof Consts
	* @example
	import {IS_WINDOW} from "@daybrush/utils";

	console.log(IS_WINDOW); // false in node.js
	console.log(IS_WINDOW); // true in browser
	*/

	var IS_WINDOW = typeof window !== UNDEFINED;
	/**
	* Check whether the environment is window or node.js.
	* @memberof Consts
	* @name document
	* @example
	import {IS_WINDOW} from "@daybrush/utils";

	console.log(IS_WINDOW); // false in node.js
	console.log(IS_WINDOW); // true in browser
	*/

	var doc = typeof document !== UNDEFINED && document;
	var prefixes = ["webkit", "ms", "moz", "o"];
	/**
	 * @namespace CrossBrowser
	 */

	/**
	* Get a CSS property with a vendor prefix that supports cross browser.
	* @function
	* @param {string} property - A CSS property
	* @return {string} CSS property with cross-browser vendor prefix
	* @memberof CrossBrowser
	* @example
	import {getCrossBrowserProperty} from "@daybrush/utils";

	console.log(getCrossBrowserProperty("transform")); // "transform", "-ms-transform", "-webkit-transform"
	console.log(getCrossBrowserProperty("filter")); // "filter", "-webkit-filter"
	*/

	var getCrossBrowserProperty =
	/*#__PURE__*/
	function (property) {
	  if (!doc) {
	    return "";
	  }

	  var styles = (doc.body || doc.documentElement).style;
	  var length = prefixes.length;

	  if (typeof styles[property] !== UNDEFINED) {
	    return property;
	  }

	  for (var i = 0; i < length; ++i) {
	    var name = "-" + prefixes[i] + "-" + property;

	    if (typeof styles[name] !== UNDEFINED) {
	      return name;
	    }
	  }

	  return "";
	};
	/**
	* get string "transfrom" with the vendor prefix.
	* @memberof CrossBrowser
	* @example
	import {TRANSFORM} from "@daybrush/utils";

	console.log(TRANSFORM); // "transform", "-ms-transform", "-webkit-transform"
	*/

	var TRANSFORM =
	/*#__PURE__*/
	getCrossBrowserProperty("transform");
	/**
	* get string "filter" with the vendor prefix.
	* @memberof CrossBrowser
	* @example
	import {FILTER} from "@daybrush/utils";

	console.log(FILTER); // "filter", "-ms-filter", "-webkit-filter"
	*/

	var FILTER =
	/*#__PURE__*/
	getCrossBrowserProperty("filter");
	/**
	* get string "animation" with the vendor prefix.
	* @memberof CrossBrowser
	* @example
	import {ANIMATION} from "@daybrush/utils";

	console.log(ANIMATION); // "animation", "-ms-animation", "-webkit-animation"
	*/

	var ANIMATION =
	/*#__PURE__*/
	getCrossBrowserProperty("animation");
	/**
	* get string "keyframes" with the vendor prefix.
	* @memberof CrossBrowser
	* @example
	import {KEYFRAMES} from "@daybrush/utils";

	console.log(KEYFRAMES); // "keyframes", "-ms-keyframes", "-webkit-keyframes"
	*/

	var KEYFRAMES =
	/*#__PURE__*/
	ANIMATION.replace("animation", "keyframes");

	/**
	* @namespace
	* @name Utils
	*/

	/**
	 * Returns the inner product of two numbers(`a1`, `a2`) by two criteria(`b1`, `b2`).
	 * @memberof Utils
	 * @param - The first number
	 * @param - The second number
	 * @param - The first number to base on the inner product
	 * @param - The second number to base on the inner product
	 * @return - Returns the inner product
	import { dot } from "@daybrush/utils";

	console.log(dot(0, 15, 2, 3)); // 6
	console.log(dot(5, 15, 2, 3)); // 9
	console.log(dot(5, 15, 1, 1)); // 10
	 */

	function dot(a1, a2, b1, b2) {
	  return (a1 * b2 + a2 * b1) / (b1 + b2);
	}
	/**
	* Check the type that the value is undefined.
	* @memberof Utils
	* @param {string} value - Value to check the type
	* @return {boolean} true if the type is correct, false otherwise
	* @example
	import {isUndefined} from "@daybrush/utils";

	console.log(isUndefined(undefined)); // true
	console.log(isUndefined("")); // false
	console.log(isUndefined(1)); // false
	console.log(isUndefined(null)); // false
	*/

	function isUndefined(value) {
	  return typeof value === UNDEFINED;
	}
	/**
	* Check the type that the value is object.
	* @memberof Utils
	* @param {string} value - Value to check the type
	* @return {} true if the type is correct, false otherwise
	* @example
	import {isObject} from "@daybrush/utils";

	console.log(isObject({})); // true
	console.log(isObject(undefined)); // false
	console.log(isObject("")); // false
	console.log(isObject(null)); // false
	*/

	function isObject(value) {
	  return value && typeof value === OBJECT;
	}
	/**
	* Check the type that the value is isArray.
	* @memberof Utils
	* @param {string} value - Value to check the type
	* @return {} true if the type is correct, false otherwise
	* @example
	import {isArray} from "@daybrush/utils";

	console.log(isArray([])); // true
	console.log(isArray({})); // false
	console.log(isArray(undefined)); // false
	console.log(isArray(null)); // false
	*/

	function isArray(value) {
	  return Array.isArray(value);
	}
	/**
	* Check the type that the value is string.
	* @memberof Utils
	* @param {string} value - Value to check the type
	* @return {} true if the type is correct, false otherwise
	* @example
	import {isString} from "@daybrush/utils";

	console.log(isString("1234")); // true
	console.log(isString(undefined)); // false
	console.log(isString(1)); // false
	console.log(isString(null)); // false
	*/

	function isString(value) {
	  return typeof value === STRING;
	}
	/**
	* Check the type that the value is function.
	* @memberof Utils
	* @param {string} value - Value to check the type
	* @return {} true if the type is correct, false otherwise
	* @example
	import {isFunction} from "@daybrush/utils";

	console.log(isFunction(function a() {})); // true
	console.log(isFunction(() => {})); // true
	console.log(isFunction("1234")); // false
	console.log(isFunction(1)); // false
	console.log(isFunction(null)); // false
	*/

	function isFunction(value) {
	  return typeof value === FUNCTION;
	}
	/**
	* divide text by space.
	* @memberof Utils
	* @param {string} text - text to divide
	* @return {Array} divided texts
	* @example
	import {spliceSpace} from "@daybrush/utils";

	console.log(splitSpace("a b c d e f g"));
	// ["a", "b", "c", "d", "e", "f", "g"]
	console.log(splitSpace("'a,b' c 'd,e' f g"));
	// ["'a,b'", "c", "'d,e'", "f", "g"]
	*/

	function splitSpace(text) {
	  // divide comma(,)
	  var matches = text.match(/("[^"]*")|('[^']*')|([^\s()]*(?:\((?:[^()]*|\([^()]*\))*\))[^\s()]*)|\S+/g);
	  return matches || [];
	}
	/**
	* divide text by comma.
	* @memberof Utils
	* @param {string} text - text to divide
	* @return {Array} divided texts
	* @example
	import {splitComma} from "@daybrush/utils";

	console.log(splitComma("a,b,c,d,e,f,g"));
	// ["a", "b", "c", "d", "e", "f", "g"]
	console.log(splitComma("'a,b',c,'d,e',f,g"));
	// ["'a,b'", "c", "'d,e'", "f", "g"]
	*/

	function splitComma(text) {
	  // divide comma(,)
	  // "[^"]*"|'[^']*'
	  var matches = text.match(/("[^"]*"|'[^']*'|[^,\s()]*\((?:[^()]*|\([^()]*\))*\)[^,\s()]*|[^,])+/g);
	  return matches ? matches.map(function (str) {
	    return str.trim();
	  }) : [];
	}
	/**
	* divide text by bracket "(", ")".
	* @memberof Utils
	* @param {string} text - text to divide
	* @return {object} divided texts
	* @example
	import {splitBracket} from "@daybrush/utils";

	console.log(splitBracket("a(1, 2)"));
	// {prefix: "a", value: "1, 2", suffix: ""}
	console.log(splitBracket("a(1, 2)b"));
	// {prefix: "a", value: "1, 2", suffix: "b"}
	*/

	function splitBracket(text) {
	  var matches = /([^(]*)\(([\s\S]*)\)([\s\S]*)/g.exec(text);

	  if (!matches || matches.length < 4) {
	    return {};
	  } else {
	    return {
	      prefix: matches[1],
	      value: matches[2],
	      suffix: matches[3]
	    };
	  }
	}
	/**
	* divide text by number and unit.
	* @memberof Utils
	* @param {string} text - text to divide
	* @return {} divided texts
	* @example
	import {splitUnit} from "@daybrush/utils";

	console.log(splitUnit("10px"));
	// {prefix: "", value: 10, unit: "px"}
	console.log(splitUnit("-10px"));
	// {prefix: "", value: -10, unit: "px"}
	console.log(splitUnit("a10%"));
	// {prefix: "a", value: 10, unit: "%"}
	*/

	function splitUnit(text) {
	  var matches = /^([^\d|e|\-|\+]*)((?:\d|\.|-|e-|e\+)+)(\S*)$/g.exec(text);

	  if (!matches) {
	    return {
	      prefix: "",
	      unit: "",
	      value: NaN
	    };
	  }

	  var prefix = matches[1];
	  var value = matches[2];
	  var unit = matches[3];
	  return {
	    prefix: prefix,
	    unit: unit,
	    value: parseFloat(value)
	  };
	}
	/**
	* transform strings to camel-case
	* @memberof Utils
	* @param {String} text - string
	* @return {String} camel-case string
	* @example
	import {camelize} from "@daybrush/utils";

	console.log(camelize("transform-origin")); // transformOrigin
	console.log(camelize("abcd_efg")); // abcdEfg
	console.log(camelize("abcd efg")); // abcdEfg
	*/

	function camelize(str) {
	  return str.replace(/[\s-_]([a-z])/g, function (all, letter) {
	    return letter.toUpperCase();
	  });
	}
	/**
	* transform a camelized string into a lowercased string.
	* @memberof Utils
	* @param {string} text - a camel-cased string
	* @param {string} [separator="-"] - a separator
	* @return {string}  a lowercased string
	* @example
	import {decamelize} from "@daybrush/utils";

	console.log(decamelize("transformOrigin")); // transform-origin
	console.log(decamelize("abcdEfg", "_")); // abcd_efg
	*/

	function decamelize(str, separator) {
	  if (separator === void 0) {
	    separator = "-";
	  }

	  return str.replace(/([a-z])([A-Z])/g, function (all, letter, letter2) {
	    return "" + letter + separator + letter2.toLowerCase();
	  });
	}
	/**
	* transforms something in an array into an array.
	* @memberof Utils
	* @param - Array form
	* @return an array
	* @example
	import {toArray} from "@daybrush/utils";

	const arr1 = toArray(document.querySelectorAll(".a")); // Element[]
	const arr2 = toArray(document.querySelectorAll<HTMLElement>(".a")); // HTMLElement[]
	*/

	function toArray(value) {
	  return [].slice.call(value);
	}
	/**
	* Date.now() method
	* @memberof CrossBrowser
	* @return {number} milliseconds
	* @example
	import {now} from "@daybrush/utils";

	console.log(now()); // 12121324241(milliseconds)
	*/

	function now() {
	  return Date.now ? Date.now() : new Date().getTime();
	}
	/**
	* Returns the index of the first element in the array that satisfies the provided testing function.
	* @function
	* @memberof CrossBrowser
	* @param - The array `findIndex` was called upon.
	* @param - A function to execute on each value in the array until the function returns true, indicating that the satisfying element was found.
	* @param - Returns defaultIndex if not found by the function.
	* @example
	import { findIndex } from "@daybrush/utils";

	findIndex([{a: 1}, {a: 2}, {a: 3}, {a: 4}], ({ a }) => a === 2); // 1
	*/

	function findIndex(arr, callback, defaultIndex) {
	  if (defaultIndex === void 0) {
	    defaultIndex = -1;
	  }

	  var length = arr.length;

	  for (var i = 0; i < length; ++i) {
	    if (callback(arr[i], i, arr)) {
	      return i;
	    }
	  }

	  return defaultIndex;
	}
	/**
	* Returns the value of the first element in the array that satisfies the provided testing function.
	* @function
	* @memberof CrossBrowser
	* @param - The array `find` was called upon.
	* @param - A function to execute on each value in the array,
	* @param - Returns defalutValue if not found by the function.
	* @example
	import { find } from "@daybrush/utils";

	find([{a: 1}, {a: 2}, {a: 3}, {a: 4}], ({ a }) => a === 2); // {a: 2}
	*/

	function find(arr, callback, defalutValue) {
	  var index = findIndex(arr, callback);
	  return index > -1 ? arr[index] : defalutValue;
	}
	/**
	* window.requestAnimationFrame() method with cross browser.
	* @function
	* @memberof CrossBrowser
	* @param {FrameRequestCallback} callback - The function to call when it's time to update your animation for the next repaint.
	* @return {number} id
	* @example
	import {requestAnimationFrame} from "@daybrush/utils";

	requestAnimationFrame((timestamp) => {
	  console.log(timestamp);
	});
	*/

	var requestAnimationFrame =
	/*#__PURE__*/
	function () {
	  var firstTime = now();
	  var raf = IS_WINDOW && (window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame);
	  return raf ? raf.bind(window) : function (callback) {
	    var currTime = now();
	    var id = window.setTimeout(function () {
	      callback(currTime - firstTime);
	    }, 1000 / 60);
	    return id;
	  };
	}();
	/**
	* window.cancelAnimationFrame() method with cross browser.
	* @function
	* @memberof CrossBrowser
	* @param {number} handle - the id obtained through requestAnimationFrame method
	* @return {void}
	* @example
	import { requestAnimationFrame, cancelAnimationFrame } from "@daybrush/utils";

	const id = requestAnimationFrame((timestamp) => {
	  console.log(timestamp);
	});

	cancelAnimationFrame(id);
	*/

	var cancelAnimationFrame =
	/*#__PURE__*/
	function () {
	  var caf = IS_WINDOW && (window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.msCancelAnimationFrame);
	  return caf ? caf.bind(window) : function (handle) {
	    clearTimeout(handle);
	  };
	}();

	/**
	* @namespace
	* @name Color
	*/

	/**
	* Remove the # from the hex color.
	* @memberof Color
	* @param {} hex - hex color
	* @return {} hex color
	* @example
	import {cutHex} from "@daybrush/utils";

	console.log(cutHex("#000000")) // "000000"
	*/

	function cutHex(hex) {
	  return hex.replace("#", "");
	}
	/**
	* convert hex color to rgb color.
	* @memberof Color
	* @param {} hex - hex color
	* @return {} rgb color
	* @example
	import {hexToRGBA} from "@daybrush/utils";

	console.log(hexToRGBA("#00000005"));
	// [0, 0, 0, 1]
	console.log(hexToRGBA("#201045"));
	// [32, 16, 69, 1]
	*/

	function hexToRGBA(hex) {
	  var h = cutHex(hex);
	  var r = parseInt(h.substring(0, 2), 16);
	  var g = parseInt(h.substring(2, 4), 16);
	  var b = parseInt(h.substring(4, 6), 16);
	  var a = parseInt(h.substring(6, 8), 16) / 255;

	  if (isNaN(a)) {
	    a = 1;
	  }

	  return [r, g, b, a];
	}
	/**
	* convert 3(or 4)-digit hex color to 6(or 8)-digit hex color.
	* @memberof Color
	* @param {} hex - 3(or 4)-digit hex color
	* @return {} 6(or 8)-digit hex color
	* @example
	import {toFullHex} from "@daybrush/utils";

	console.log(toFullHex("#123")); // "#112233"
	console.log(toFullHex("#123a")); // "#112233aa"
	*/

	function toFullHex(h) {
	  var r = h.charAt(1);
	  var g = h.charAt(2);
	  var b = h.charAt(3);
	  var a = h.charAt(4);
	  var arr = ["#", r, r, g, g, b, b, a, a];
	  return arr.join("");
	}
	/**
	* convert hsl color to rgba color.
	* @memberof Color
	* @param {} hsl - hsl color(hue: 0 ~ 360, saturation: 0 ~ 1, lightness: 0 ~ 1, alpha: 0 ~ 1)
	* @return {} rgba color
	* @example
	import {hslToRGBA} from "@daybrush/utils";

	console.log(hslToRGBA([150, 0.5, 0.4]));
	// [51, 153, 102, 1]
	*/

	function hslToRGBA(hsl) {
	  var h = hsl[0];
	  var s = hsl[1];
	  var l = hsl[2];

	  if (h < 0) {
	    h += Math.floor((Math.abs(h) + 360) / 360) * 360;
	  }

	  h %= 360;
	  var c = (1 - Math.abs(2 * l - 1)) * s;
	  var x = c * (1 - Math.abs(h / 60 % 2 - 1));
	  var m = l - c / 2;
	  var rgb;

	  if (h < 60) {
	    rgb = [c, x, 0];
	  } else if (h < 120) {
	    rgb = [x, c, 0];
	  } else if (h < 180) {
	    rgb = [0, c, x];
	  } else if (h < 240) {
	    rgb = [0, x, c];
	  } else if (h < 300) {
	    rgb = [x, 0, c];
	  } else if (h < 360) {
	    rgb = [c, 0, x];
	  }

	  var result = [Math.round((rgb[0] + m) * 255), Math.round((rgb[1] + m) * 255), Math.round((rgb[2] + m) * 255), hsl.length > 3 ? hsl[3] : 1];
	  return result;
	}
	/**
	* convert string to rgba color.
	* @memberof Color
	* @param {} - 3-hex(#000), 4-hex(#0000) 6-hex(#000000), 8-hex(#00000000) or RGB(A), or HSL(A)
	* @return {} rgba color
	* @example
	import {stringToRGBA} from "@daybrush/utils";

	console.log(stringToRGBA("#000000")); // [0, 0, 0, 1]
	console.log(stringToRGBA("rgb(100, 100, 100)")); // [100, 100, 100, 1]
	console.log(stringToRGBA("hsl(150, 0.5, 0.4)")); // [51, 153, 102, 1]
	*/

	function stringToRGBA(color) {
	  if (color.charAt(0) === "#") {
	    if (color.length === 4 || color.length === 5) {
	      return hexToRGBA(toFullHex(color));
	    } else {
	      return hexToRGBA(color);
	    }
	  } else if (color.indexOf("(") !== -1) {
	    // in bracket.
	    var _a = splitBracket(color),
	        prefix = _a.prefix,
	        value = _a.value;

	    if (!prefix || !value) {
	      return;
	    }

	    var arr = splitComma(value);
	    var colorArr = [];
	    var length = arr.length;

	    switch (prefix) {
	      case RGB:
	      case RGBA:
	        for (var i = 0; i < length; ++i) {
	          colorArr[i] = parseFloat(arr[i]);
	        }

	        return colorArr;

	      case HSL:
	      case HSLA:
	        for (var i = 0; i < length; ++i) {
	          if (arr[i].indexOf("%") !== -1) {
	            colorArr[i] = parseFloat(arr[i]) / 100;
	          } else {
	            colorArr[i] = parseFloat(arr[i]);
	          }
	        } // hsl, hsla to rgba


	        return hslToRGBA(colorArr);
	    }
	  }

	  return;
	}

	/**
	 * Returns all element descendants of node that
	 * match selectors.
	 */

	/**
	 * Checks if the specified class value exists in the element's class attribute.
	 * @memberof DOM
	 * @param - A DOMString containing one or more selectors to match
	 * @param - If multi is true, a DOMString containing one or more selectors to match against.
	 * @example
	import {$} from "@daybrush/utils";

	console.log($("div")); // div element
	console.log($("div", true)); // [div, div] elements
	*/

	function $(selectors, multi) {
	  return multi ? doc.querySelectorAll(selectors) : doc.querySelector(selectors);
	}
	/**
	* Checks if the specified class value exists in the element's class attribute.
	* @memberof DOM
	* @param element - target
	* @param className - the class name to search
	* @return {boolean} return false if the class is not found.
	* @example
	import {hasClass} from "@daybrush/utils";

	console.log(hasClass(element, "start")); // true or false
	*/

	function hasClass(element, className) {
	  if (element.classList) {
	    return element.classList.contains(className);
	  }

	  return !!element.className.match(new RegExp("(\\s|^)" + className + "(\\s|$)"));
	}
	/**
	* Add the specified class value. If these classe already exist in the element's class attribute they are ignored.
	* @memberof DOM
	* @param element - target
	* @param className - the class name to add
	* @example
	import {addClass} from "@daybrush/utils";

	addClass(element, "start");
	*/

	function addClass(element, className) {
	  if (element.classList) {
	    element.classList.add(className);
	  } else {
	    element.className += " " + className;
	  }
	}
	/**
	* Removes the specified class value.
	* @memberof DOM
	* @param element - target
	* @param className - the class name to remove
	* @example
	import {removeClass} from "@daybrush/utils";

	removeClass(element, "start");
	*/

	function removeClass(element, className) {
	  if (element.classList) {
	    element.classList.remove(className);
	  } else {
	    var reg = new RegExp("(\\s|^)" + className + "(\\s|$)");
	    element.className = element.className.replace(reg, " ");
	  }
	}
	/**
	* Gets the CSS properties from the element.
	* @memberof DOM
	* @param elements - elements
	* @param properites - the CSS properties
	* @return returns CSS properties and values.
	* @example
	import {fromCSS} from "@daybrush/utils";

	console.log(fromCSS(element, ["left", "opacity", "top"])); // {"left": "10px", "opacity": 1, "top": "10px"}
	*/

	function fromCSS(elements, properties) {
	  if (!elements || !properties || !properties.length) {
	    return {};
	  }

	  var element;

	  if (elements instanceof Element) {
	    element = elements;
	  } else if (elements.length) {
	    element = elements[0];
	  } else {
	    return {};
	  }

	  var cssObject = {};
	  var styles = window.getComputedStyle(element);
	  var length = properties.length;

	  for (var i = 0; i < length; ++i) {
	    cssObject[properties[i]] = styles[properties[i]];
	  }

	  return cssObject;
	}
	/**
	* Sets up a function that will be called whenever the specified event is delivered to the target
	* @memberof DOM
	* @param - event target
	* @param - A case-sensitive string representing the event type to listen for.
	* @param - The object which receives a notification (an object that implements the Event interface) when an event of the specified type occurs
	* @param - An options object that specifies characteristics about the event listener. The available options are:
	* @example
	import {addEvent} from "@daybrush/utils";

	addEvent(el, "click", e => {
	  console.log(e);
	});
	*/

	function addEvent(el, type, listener, options) {
	  el.addEventListener(type, listener, options);
	}
	/**
	* removes from the EventTarget an event listener previously registered with EventTarget.addEventListener()
	* @memberof DOM
	* @param - event target
	* @param - A case-sensitive string representing the event type to listen for.
	* @param - The EventListener function of the event handler to remove from the event target.
	* @example
	import {addEvent, removeEvent} from "@daybrush/utils";
	const listener = e => {
	  console.log(e);
	};
	addEvent(el, "click", listener);
	removeEvent(el, "click", listener);
	*/

	function removeEvent(el, type, listener) {
	  el.removeEventListener(type, listener);
	}

	/*
	Copyright (c) 2017 NAVER Corp.
	@egjs/component project is licensed under the MIT license

	@egjs/component JavaScript library
	https://naver.github.io/egjs-component

	@version 2.1.2
	*/
	/**
	 * Copyright (c) 2015 NAVER Corp.
	 * egjs projects are licensed under the MIT license
	 */
	function isUndefined$1(value) {
	  return typeof value === "undefined";
	}
	/**
	 * A class used to manage events in a component
	 * @ko 컴포넌트의 이벤트을 관리할 수 있게 하는 클래스
	 * @alias eg.Component
	 */


	var Component$2 =
	/*#__PURE__*/
	function () {
	  var Component =
	  /*#__PURE__*/
	  function () {
	    /**
	    * Version info string
	    * @ko 버전정보 문자열
	    * @name VERSION
	    * @static
	    * @type {String}
	    * @example
	    * eg.Component.VERSION;  // ex) 2.0.0
	    * @memberof eg.Component
	    */

	    /**
	     * @support {"ie": "7+", "ch" : "latest", "ff" : "latest",  "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.1+ (except 3.x)"}
	     */
	    function Component() {
	      this._eventHandler = {};
	      this.options = {};
	    }
	    /**
	     * Triggers a custom event.
	     * @ko 커스텀 이벤트를 발생시킨다
	     * @param {String} eventName The name of the custom event to be triggered <ko>발생할 커스텀 이벤트의 이름</ko>
	     * @param {Object} customEvent Event data to be sent when triggering a custom event <ko>커스텀 이벤트가 발생할 때 전달할 데이터</ko>
	     * @return {Boolean} Indicates whether the event has occurred. If the stop() method is called by a custom event handler, it will return false and prevent the event from occurring. <a href="https://github.com/naver/egjs-component/wiki/How-to-make-Component-event-design%3F">Ref</a> <ko>이벤트 발생 여부. 커스텀 이벤트 핸들러에서 stop() 메서드를 호출하면 'false'를 반환하고 이벤트 발생을 중단한다. <a href="https://github.com/naver/egjs-component/wiki/How-to-make-Component-event-design%3F">참고</a></ko>
	     * @example
	    class Some extends eg.Component {
	     some(){
	     	if(this.trigger("beforeHi")){ // When event call to stop return false.
	    	this.trigger("hi");// fire hi event.
	     	}
	     }
	    }
	    const some = new Some();
	    some.on("beforeHi", (e) => {
	    if(condition){
	    	e.stop(); // When event call to stop, `hi` event not call.
	    }
	    });
	    some.on("hi", (e) => {
	    // `currentTarget` is component instance.
	    console.log(some === e.currentTarget); // true
	    });
	    // If you want to more know event design. You can see article.
	    // https://github.com/naver/egjs-component/wiki/How-to-make-Component-event-design%3F
	     */


	    var _proto = Component.prototype;

	    _proto.trigger = function trigger(eventName, customEvent) {
	      if (customEvent === void 0) {
	        customEvent = {};
	      }

	      var handlerList = this._eventHandler[eventName] || [];
	      var hasHandlerList = handlerList.length > 0;

	      if (!hasHandlerList) {
	        return true;
	      } // If detach method call in handler in first time then handler list calls.


	      handlerList = handlerList.concat();
	      customEvent.eventType = eventName;
	      var isCanceled = false;
	      var arg = [customEvent];
	      var i = 0;

	      customEvent.stop = function () {
	        isCanceled = true;
	      };

	      customEvent.currentTarget = this;

	      for (var _len = arguments.length, restParam = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
	        restParam[_key - 2] = arguments[_key];
	      }

	      if (restParam.length >= 1) {
	        arg = arg.concat(restParam);
	      }

	      for (i = 0; handlerList[i]; i++) {
	        handlerList[i].apply(this, arg);
	      }

	      return !isCanceled;
	    };
	    /**
	     * Executed event just one time.
	     * @ko 이벤트가 한번만 실행된다.
	     * @param {eventName} eventName The name of the event to be attached <ko>등록할 이벤트의 이름</ko>
	     * @param {Function} handlerToAttach The handler function of the event to be attached <ko>등록할 이벤트의 핸들러 함수</ko>
	     * @return {eg.Component} An instance of a component itself<ko>컴포넌트 자신의 인스턴스</ko>
	     * @example
	    class Some extends eg.Component {
	     hi() {
	       alert("hi");
	     }
	     thing() {
	       this.once("hi", this.hi);
	     }
	    }
	    var some = new Some();
	    some.thing();
	    some.trigger("hi");
	    // fire alert("hi");
	    some.trigger("hi");
	    // Nothing happens
	     */


	    _proto.once = function once(eventName, handlerToAttach) {
	      if (typeof eventName === "object" && isUndefined$1(handlerToAttach)) {
	        var eventHash = eventName;
	        var i;

	        for (i in eventHash) {
	          this.once(i, eventHash[i]);
	        }

	        return this;
	      } else if (typeof eventName === "string" && typeof handlerToAttach === "function") {
	        var self = this;
	        this.on(eventName, function listener() {
	          for (var _len2 = arguments.length, arg = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
	            arg[_key2] = arguments[_key2];
	          }

	          handlerToAttach.apply(self, arg);
	          self.off(eventName, listener);
	        });
	      }

	      return this;
	    };
	    /**
	     * Checks whether an event has been attached to a component.
	     * @ko 컴포넌트에 이벤트가 등록됐는지 확인한다.
	     * @param {String} eventName The name of the event to be attached <ko>등록 여부를 확인할 이벤트의 이름</ko>
	     * @return {Boolean} Indicates whether the event is attached. <ko>이벤트 등록 여부</ko>
	     * @example
	    class Some extends eg.Component {
	     some() {
	       this.hasOn("hi");// check hi event.
	     }
	    }
	     */


	    _proto.hasOn = function hasOn(eventName) {
	      return !!this._eventHandler[eventName];
	    };
	    /**
	     * Attaches an event to a component.
	     * @ko 컴포넌트에 이벤트를 등록한다.
	     * @param {eventName} eventName The name of the event to be attached <ko>등록할 이벤트의 이름</ko>
	     * @param {Function} handlerToAttach The handler function of the event to be attached <ko>등록할 이벤트의 핸들러 함수</ko>
	     * @return {eg.Component} An instance of a component itself<ko>컴포넌트 자신의 인스턴스</ko>
	     * @example
	    class Some extends eg.Component {
	     hi() {
	       console.log("hi");
	     }
	     some() {
	       this.on("hi",this.hi); //attach event
	     }
	    }
	    */


	    _proto.on = function on(eventName, handlerToAttach) {
	      if (typeof eventName === "object" && isUndefined$1(handlerToAttach)) {
	        var eventHash = eventName;
	        var name;

	        for (name in eventHash) {
	          this.on(name, eventHash[name]);
	        }

	        return this;
	      } else if (typeof eventName === "string" && typeof handlerToAttach === "function") {
	        var handlerList = this._eventHandler[eventName];

	        if (isUndefined$1(handlerList)) {
	          this._eventHandler[eventName] = [];
	          handlerList = this._eventHandler[eventName];
	        }

	        handlerList.push(handlerToAttach);
	      }

	      return this;
	    };
	    /**
	     * Detaches an event from the component.
	     * @ko 컴포넌트에 등록된 이벤트를 해제한다
	     * @param {eventName} eventName The name of the event to be detached <ko>해제할 이벤트의 이름</ko>
	     * @param {Function} handlerToDetach The handler function of the event to be detached <ko>해제할 이벤트의 핸들러 함수</ko>
	     * @return {eg.Component} An instance of a component itself <ko>컴포넌트 자신의 인스턴스</ko>
	     * @example
	    class Some extends eg.Component {
	     hi() {
	       console.log("hi");
	     }
	     some() {
	       this.off("hi",this.hi); //detach event
	     }
	    }
	     */


	    _proto.off = function off(eventName, handlerToDetach) {
	      // All event detach.
	      if (isUndefined$1(eventName)) {
	        this._eventHandler = {};
	        return this;
	      } // All handler of specific event detach.


	      if (isUndefined$1(handlerToDetach)) {
	        if (typeof eventName === "string") {
	          this._eventHandler[eventName] = undefined;
	          return this;
	        } else {
	          var eventHash = eventName;
	          var name;

	          for (name in eventHash) {
	            this.off(name, eventHash[name]);
	          }

	          return this;
	        }
	      } // The handler of specific event detach.


	      var handlerList = this._eventHandler[eventName];

	      if (handlerList) {
	        var k;
	        var handlerFunction;

	        for (k = 0; (handlerFunction = handlerList[k]) !== undefined; k++) {
	          if (handlerFunction === handlerToDetach) {
	            handlerList = handlerList.splice(k, 1);
	            break;
	          }
	        }
	      }

	      return this;
	    };

	    return Component;
	  }();

	  Component.VERSION = "2.1.2";
	  return Component;
	}();

	/*
	Copyright (c) 2019 Daybrush
	name: keycon
	license: MIT
	author: Daybrush
	repository: git+https://github.com/daybrush/keycon.git
	version: 0.2.2
	*/

	/*! *****************************************************************************
	Copyright (c) Microsoft Corporation. All rights reserved.
	Licensed under the Apache License, Version 2.0 (the "License"); you may not use
	this file except in compliance with the License. You may obtain a copy of the
	License at http://www.apache.org/licenses/LICENSE-2.0

	THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
	KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
	WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
	MERCHANTABLITY OR NON-INFRINGEMENT.

	See the Apache Version 2.0 License for specific language governing permissions
	and limitations under the License.
	***************************************************************************** */

	/* global Reflect, Promise */
	var extendStatics$1 = function (d, b) {
	  extendStatics$1 = Object.setPrototypeOf || {
	    __proto__: []
	  } instanceof Array && function (d, b) {
	    d.__proto__ = b;
	  } || function (d, b) {
	    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
	  };

	  return extendStatics$1(d, b);
	};

	function __extends$2(d, b) {
	  extendStatics$1(d, b);

	  function __() {
	    this.constructor = d;
	  }

	  d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
	}

	function createCommonjsModule(fn, module) {
	  return module = {
	    exports: {}
	  }, fn(module, module.exports), module.exports;
	}

	var keycode = createCommonjsModule(function (module, exports) {
	// Source: http://jsfiddle.net/vWx8V/
	// http://stackoverflow.com/questions/5603195/full-list-of-javascript-keycodes

	/**
	 * Conenience method returns corresponding value for given keyName or keyCode.
	 *
	 * @param {Mixed} keyCode {Number} or keyName {String}
	 * @return {Mixed}
	 * @api public
	 */
	function keyCode(searchInput) {
	  // Keyboard Events
	  if (searchInput && 'object' === typeof searchInput) {
	    var hasKeyCode = searchInput.which || searchInput.keyCode || searchInput.charCode;
	    if (hasKeyCode) searchInput = hasKeyCode;
	  } // Numbers


	  if ('number' === typeof searchInput) return names[searchInput]; // Everything else (cast to string)

	  var search = String(searchInput); // check codes

	  var foundNamedKey = codes[search.toLowerCase()];
	  if (foundNamedKey) return foundNamedKey; // check aliases

	  var foundNamedKey = aliases[search.toLowerCase()];
	  if (foundNamedKey) return foundNamedKey; // weird character?

	  if (search.length === 1) return search.charCodeAt(0);
	  return undefined;
	}
	/**
	 * Compares a keyboard event with a given keyCode or keyName.
	 *
	 * @param {Event} event Keyboard event that should be tested
	 * @param {Mixed} keyCode {Number} or keyName {String}
	 * @return {Boolean}
	 * @api public
	 */


	keyCode.isEventKey = function isEventKey(event, nameOrCode) {
	  if (event && 'object' === typeof event) {
	    var keyCode = event.which || event.keyCode || event.charCode;

	    if (keyCode === null || keyCode === undefined) {
	      return false;
	    }

	    if (typeof nameOrCode === 'string') {
	      // check codes
	      var foundNamedKey = codes[nameOrCode.toLowerCase()];

	      if (foundNamedKey) {
	        return foundNamedKey === keyCode;
	      } // check aliases


	      var foundNamedKey = aliases[nameOrCode.toLowerCase()];

	      if (foundNamedKey) {
	        return foundNamedKey === keyCode;
	      }
	    } else if (typeof nameOrCode === 'number') {
	      return nameOrCode === keyCode;
	    }

	    return false;
	  }
	};

	exports = module.exports = keyCode;
	/**
	 * Get by name
	 *
	 *   exports.code['enter'] // => 13
	 */

	var codes = exports.code = exports.codes = {
	  'backspace': 8,
	  'tab': 9,
	  'enter': 13,
	  'shift': 16,
	  'ctrl': 17,
	  'alt': 18,
	  'pause/break': 19,
	  'caps lock': 20,
	  'esc': 27,
	  'space': 32,
	  'page up': 33,
	  'page down': 34,
	  'end': 35,
	  'home': 36,
	  'left': 37,
	  'up': 38,
	  'right': 39,
	  'down': 40,
	  'insert': 45,
	  'delete': 46,
	  'command': 91,
	  'left command': 91,
	  'right command': 93,
	  'numpad *': 106,
	  'numpad +': 107,
	  'numpad -': 109,
	  'numpad .': 110,
	  'numpad /': 111,
	  'num lock': 144,
	  'scroll lock': 145,
	  'my computer': 182,
	  'my calculator': 183,
	  ';': 186,
	  '=': 187,
	  ',': 188,
	  '-': 189,
	  '.': 190,
	  '/': 191,
	  '`': 192,
	  '[': 219,
	  '\\': 220,
	  ']': 221,
	  "'": 222 // Helper aliases

	};
	var aliases = exports.aliases = {
	  'windows': 91,
	  '⇧': 16,
	  '⌥': 18,
	  '⌃': 17,
	  '⌘': 91,
	  'ctl': 17,
	  'control': 17,
	  'option': 18,
	  'pause': 19,
	  'break': 19,
	  'caps': 20,
	  'return': 13,
	  'escape': 27,
	  'spc': 32,
	  'spacebar': 32,
	  'pgup': 33,
	  'pgdn': 34,
	  'ins': 45,
	  'del': 46,
	  'cmd': 91
	  /*!
	   * Programatically add the following
	   */
	  // lower case chars

	};

	for (i = 97; i < 123; i++) codes[String.fromCharCode(i)] = i - 32; // numbers


	for (var i = 48; i < 58; i++) codes[i - 48] = i; // function keys


	for (i = 1; i < 13; i++) codes['f' + i] = i + 111; // numpad keys


	for (i = 0; i < 10; i++) codes['numpad ' + i] = i + 96;
	/**
	 * Get by code
	 *
	 *   exports.name[13] // => 'Enter'
	 */


	var names = exports.names = exports.title = {}; // title for backward compat
	// Create reverse mapping

	for (i in codes) names[codes[i]] = i; // Add aliases


	for (var alias in aliases) {
	  codes[alias] = aliases[alias];
	}
	});
	var keycode_1 = keycode.code;
	var keycode_2 = keycode.codes;
	var keycode_3 = keycode.aliases;
	var keycode_4 = keycode.names;
	var keycode_5 = keycode.title;

	/*
	Copyright (c) 2018 Daybrush
	@name: @daybrush/utils
	license: MIT
	author: Daybrush
	repository: https://github.com/daybrush/utils
	@version 0.7.1
	*/
	/**
	* get string "string"
	* @memberof Consts
	* @example
	import {STRING} from "@daybrush/utils";

	console.log(STRING); // "string"
	*/

	var STRING$1 = "string";
	/**
	* Check the type that the value is isArray.
	* @memberof Utils
	* @param {string} value - Value to check the type
	* @return {} true if the type is correct, false otherwise
	* @example
	import {isArray} from "@daybrush/utils";

	console.log(isArray([])); // true
	console.log(isArray({})); // false
	console.log(isArray(undefined)); // false
	console.log(isArray(null)); // false
	*/


	function isArray$1(value) {
	  return Array.isArray(value);
	}
	/**
	* Check the type that the value is string.
	* @memberof Utils
	* @param {string} value - Value to check the type
	* @return {} true if the type is correct, false otherwise
	* @example
	import {isString} from "@daybrush/utils";

	console.log(isString("1234")); // true
	console.log(isString(undefined)); // false
	console.log(isString(1)); // false
	console.log(isString(null)); // false
	*/


	function isString$1(value) {
	  return typeof value === STRING$1;
	}
	/**
	* Sets up a function that will be called whenever the specified event is delivered to the target
	* @memberof DOM
	* @param - event target
	* @param - A case-sensitive string representing the event type to listen for.
	* @param - The object which receives a notification (an object that implements the Event interface) when an event of the specified type occurs
	* @param - An options object that specifies characteristics about the event listener. The available options are:
	* @example
	import {addEvent} from "@daybrush/utils";

	addEvent(el, "click", e => {
	  console.log(e);
	});
	*/


	function addEvent$1(el, type, listener, options) {
	  el.addEventListener(type, listener, options);
	}

	var codeData = {
	  "+": "plus",
	  "left command": "meta",
	  "right command": "meta"
	};
	var keysSort = {
	  shift: 1,
	  ctrl: 2,
	  alt: 3,
	  meta: 4
	};

	function getKey(keyCode) {
	  var key = keycode_4[keyCode] || "";

	  for (var name in codeData) {
	    key = key.replace(name, codeData[name]);
	  }

	  return key.replace(/\s/g, "");
	}

	function getCombi(e, key) {
	  var keys = [e.shiftKey && "shift", e.ctrlKey && "ctrl", e.altKey && "alt", e.metaKey && "meta"];
	  keys.indexOf(key) === -1 && keys.push(key);
	  return keys.filter(Boolean);
	}

	function getArrangeCombi(keys) {
	  var arrangeKeys = keys.slice();
	  arrangeKeys.sort(function (prev, next) {
	    var prevScore = keysSort[prev] || 5;
	    var nextScore = keysSort[next] || 5;
	    return prevScore - nextScore;
	  });
	  return arrangeKeys;
	}
	/**
	 */


	var KeyController =
	/*#__PURE__*/
	function (_super) {
	  __extends$2(KeyController, _super);
	  /**
	   *
	   */


	  function KeyController(container) {
	    if (container === void 0) {
	      container = window;
	    }

	    var _this = _super.call(this) || this;
	    /**
	     */


	    _this.ctrlKey = false;
	    /**
	     */

	    _this.altKey = false;
	    /**
	     *
	     */

	    _this.shiftKey = false;
	    /**
	     *
	     */

	    _this.metaKey = false;

	    _this.clear = function () {
	      _this.ctrlKey = false;
	      _this.altKey = false;
	      _this.shiftKey = false;
	      _this.metaKey = false;
	    };

	    _this.keydownEvent = function (e) {
	      _this.triggerEvent("keydown", e);
	    };

	    _this.keyupEvent = function (e) {
	      _this.triggerEvent("keyup", e);
	    };

	    addEvent$1(container, "blur", _this.clear);
	    addEvent$1(container, "keydown", _this.keydownEvent);
	    addEvent$1(container, "keyup", _this.keyupEvent);
	    return _this;
	  }
	  /**
	   *
	   */


	  var __proto = KeyController.prototype;

	  __proto.keydown = function (comb, callback) {
	    return this.addEvent("keydown", comb, callback);
	  };
	  /**
	   *
	   */


	  __proto.keyup = function (comb, callback) {
	    return this.addEvent("keyup", comb, callback);
	  };

	  __proto.addEvent = function (type, comb, callback) {
	    if (isArray$1(comb)) {
	      this.on(type + "." + getArrangeCombi(comb).join("."), callback);
	    } else if (isString$1(comb)) {
	      this.on(type + "." + comb, callback);
	    } else {
	      this.on(type, comb);
	    }

	    return this;
	  };

	  __proto.triggerEvent = function (type, e) {
	    this.ctrlKey = e.ctrlKey;
	    this.shiftKey = e.shiftKey;
	    this.altKey = e.altKey;
	    this.metaKey = e.metaKey;
	    var key = getKey(e.keyCode);
	    var isToggle = key === "ctrl" || key === "shift" || key === "meta" || key === "alt";
	    var param = {
	      key: key,
	      isToggle: isToggle,
	      inputEvent: e,
	      keyCode: e.keyCode,
	      ctrlKey: e.ctrlKey,
	      altKey: e.altKey,
	      shiftKey: e.shiftKey,
	      metaKey: e.metaKey
	    };
	    this.trigger(type, param);
	    this.trigger(type + "." + key, param);
	    var combi = getCombi(e, key);
	    combi.length > 1 && this.trigger(type + "." + combi.join("."), param);
	  };

	  return KeyController;
	}(Component$2);

	/*
	Copyright (c) 2019 Daybrush
	name: @daybrush/drag
	license: MIT
	author: Daybrush
	repository: git+https://github.com/daybrush/drag.git
	version: 0.4.2
	*/
	function setDrag(el, options) {
	  var flag = false;
	  var startX = 0;
	  var startY = 0;
	  var prevX = 0;
	  var prevY = 0;
	  var datas = {};
	  var isDrag = false;
	  var _a = options.container,
	      container = _a === void 0 ? el : _a,
	      dragstart = options.dragstart,
	      drag = options.drag,
	      dragend = options.dragend,
	      _b = options.events,
	      events = _b === void 0 ? ["touch", "mouse"] : _b;
	  var isTouch = events.indexOf("touch") > -1;
	  var isMouse = events.indexOf("mouse") > -1;

	  function getPosition(e) {
	    return e.touches && e.touches.length ? e.touches[0] : e;
	  }

	  function onDragStart(e) {
	    flag = true;
	    isDrag = false;

	    var _a = getPosition(e),
	        clientX = _a.clientX,
	        clientY = _a.clientY;

	    startX = clientX;
	    startY = clientY;
	    prevX = clientX;
	    prevY = clientY;
	    datas = {};
	    (dragstart && dragstart({
	      datas: datas,
	      inputEvent: e,
	      clientX: clientX,
	      clientY: clientY
	    })) === false && (flag = false);
	    flag && e.preventDefault();
	  }

	  function onDrag(e) {
	    if (!flag) {
	      return;
	    }

	    var _a = getPosition(e),
	        clientX = _a.clientX,
	        clientY = _a.clientY;

	    var deltaX = clientX - prevX;
	    var deltaY = clientY - prevY;

	    if (!deltaX && !deltaY) {
	      return;
	    }

	    isDrag = true;
	    drag && drag({
	      datas: datas,
	      clientX: clientX,
	      clientY: clientY,
	      deltaX: deltaX,
	      deltaY: deltaY,
	      distX: clientX - startX,
	      distY: clientY - startY,
	      inputEvent: e
	    });
	    prevX = clientX;
	    prevY = clientY;
	  }

	  function onDragEnd(e) {
	    if (!flag) {
	      return;
	    }

	    flag = false;
	    dragend && dragend({
	      datas: datas,
	      isDrag: isDrag,
	      inputEvent: e,
	      clientX: prevX,
	      clientY: prevY,
	      distX: prevX - startX,
	      distY: prevY - startY
	    });
	  }

	  if (isMouse) {
	    el.addEventListener("mousedown", onDragStart);
	    container.addEventListener("mousemove", onDrag);
	    container.addEventListener("mouseup", onDragEnd); // container.addEventListener("mouseleave", onDragEnd);
	  }

	  if (isTouch) {
	    el.addEventListener("touchstart", onDragStart);
	    container.addEventListener("touchmove", onDrag);
	    container.addEventListener("touchend", onDragEnd);
	  }
	}

	/*! Hammer.JS - v2.0.15 - 2019-04-04
	 * http://naver.github.io/egjs
	 *
	 * Forked By Naver egjs
	 * Copyright (c) hammerjs
	 * Licensed under the MIT license */
	function _extends() {
	  _extends = Object.assign || function (target) {
	    for (var i = 1; i < arguments.length; i++) {
	      var source = arguments[i];

	      for (var key in source) {
	        if (Object.prototype.hasOwnProperty.call(source, key)) {
	          target[key] = source[key];
	        }
	      }
	    }

	    return target;
	  };

	  return _extends.apply(this, arguments);
	}

	function _inheritsLoose(subClass, superClass) {
	  subClass.prototype = Object.create(superClass.prototype);
	  subClass.prototype.constructor = subClass;
	  subClass.__proto__ = superClass;
	}

	function _assertThisInitialized(self) {
	  if (self === void 0) {
	    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
	  }

	  return self;
	}

	/**
	 * @private
	 * extend object.
	 * means that properties in dest will be overwritten by the ones in src.
	 * @param {Object} target
	 * @param {...Object} objects_to_assign
	 * @returns {Object} target
	 */
	var assign;

	if (typeof Object.assign !== 'function') {
	  assign = function assign(target) {
	    if (target === undefined || target === null) {
	      throw new TypeError('Cannot convert undefined or null to object');
	    }

	    var output = Object(target);

	    for (var index = 1; index < arguments.length; index++) {
	      var source = arguments[index];

	      if (source !== undefined && source !== null) {
	        for (var nextKey in source) {
	          if (source.hasOwnProperty(nextKey)) {
	            output[nextKey] = source[nextKey];
	          }
	        }
	      }
	    }

	    return output;
	  };
	} else {
	  assign = Object.assign;
	}

	var assign$1 = assign;

	var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o'];
	var TEST_ELEMENT = typeof document === "undefined" ? {
	  style: {}
	} : document.createElement('div');
	var TYPE_FUNCTION = 'function';
	var round = Math.round,
	    abs = Math.abs;
	var now$1 = Date.now;

	/**
	 * @private
	 * get the prefixed property
	 * @param {Object} obj
	 * @param {String} property
	 * @returns {String|Undefined} prefixed
	 */

	function prefixed(obj, property) {
	  var prefix;
	  var prop;
	  var camelProp = property[0].toUpperCase() + property.slice(1);
	  var i = 0;

	  while (i < VENDOR_PREFIXES.length) {
	    prefix = VENDOR_PREFIXES[i];
	    prop = prefix ? prefix + camelProp : property;

	    if (prop in obj) {
	      return prop;
	    }

	    i++;
	  }

	  return undefined;
	}

	/* eslint-disable no-new-func, no-nested-ternary */
	var win;

	if (typeof window === "undefined") {
	  // window is undefined in node.js
	  win = {};
	} else {
	  win = window;
	}

	var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction');
	var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined;
	function getTouchActionProps() {
	  if (!NATIVE_TOUCH_ACTION) {
	    return false;
	  }

	  var touchMap = {};
	  var cssSupports = win.CSS && win.CSS.supports;
	  ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function (val) {
	    // If css.supports is not supported but there is native touch-action assume it supports
	    // all values. This is the case for IE 10 and 11.
	    return touchMap[val] = cssSupports ? win.CSS.supports('touch-action', val) : true;
	  });
	  return touchMap;
	}

	var TOUCH_ACTION_COMPUTE = 'compute';
	var TOUCH_ACTION_AUTO = 'auto';
	var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented

	var TOUCH_ACTION_NONE = 'none';
	var TOUCH_ACTION_PAN_X = 'pan-x';
	var TOUCH_ACTION_PAN_Y = 'pan-y';
	var TOUCH_ACTION_MAP = getTouchActionProps();

	var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
	var SUPPORT_TOUCH = 'ontouchstart' in win;
	var SUPPORT_POINTER_EVENTS = prefixed(win, 'PointerEvent') !== undefined;
	var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);
	var INPUT_TYPE_TOUCH = 'touch';
	var INPUT_TYPE_PEN = 'pen';
	var INPUT_TYPE_MOUSE = 'mouse';
	var INPUT_TYPE_KINECT = 'kinect';
	var COMPUTE_INTERVAL = 25;
	var INPUT_START = 1;
	var INPUT_MOVE = 2;
	var INPUT_END = 4;
	var INPUT_CANCEL = 8;
	var DIRECTION_NONE = 1;
	var DIRECTION_LEFT = 2;
	var DIRECTION_RIGHT = 4;
	var DIRECTION_UP = 8;
	var DIRECTION_DOWN = 16;
	var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT;
	var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN;
	var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;
	var PROPS_XY = ['x', 'y'];
	var PROPS_CLIENT_XY = ['clientX', 'clientY'];

	/**
	 * @private
	 * walk objects and arrays
	 * @param {Object} obj
	 * @param {Function} iterator
	 * @param {Object} context
	 */
	function each(obj, iterator, context) {
	  var i;

	  if (!obj) {
	    return;
	  }

	  if (obj.forEach) {
	    obj.forEach(iterator, context);
	  } else if (obj.length !== undefined) {
	    i = 0;

	    while (i < obj.length) {
	      iterator.call(context, obj[i], i, obj);
	      i++;
	    }
	  } else {
	    for (i in obj) {
	      obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj);
	    }
	  }
	}

	/**
	 * @private
	 * let a boolean value also be a function that must return a boolean
	 * this first item in args will be used as the context
	 * @param {Boolean|Function} val
	 * @param {Array} [args]
	 * @returns {Boolean}
	 */

	function boolOrFn(val, args) {
	  if (typeof val === TYPE_FUNCTION) {
	    return val.apply(args ? args[0] || undefined : undefined, args);
	  }

	  return val;
	}

	/**
	 * @private
	 * small indexOf wrapper
	 * @param {String} str
	 * @param {String} find
	 * @returns {Boolean} found
	 */
	function inStr(str, find) {
	  return str.indexOf(find) > -1;
	}

	/**
	 * @private
	 * when the touchActions are collected they are not a valid value, so we need to clean things up. *
	 * @param {String} actions
	 * @returns {*}
	 */

	function cleanTouchActions(actions) {
	  // none
	  if (inStr(actions, TOUCH_ACTION_NONE)) {
	    return TOUCH_ACTION_NONE;
	  }

	  var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X);
	  var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); // if both pan-x and pan-y are set (different recognizers
	  // for different directions, e.g. horizontal pan but vertical swipe?)
	  // we need none (as otherwise with pan-x pan-y combined none of these
	  // recognizers will work, since the browser would handle all panning

	  if (hasPanX && hasPanY) {
	    return TOUCH_ACTION_NONE;
	  } // pan-x OR pan-y


	  if (hasPanX || hasPanY) {
	    return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y;
	  } // manipulation


	  if (inStr(actions, TOUCH_ACTION_MANIPULATION)) {
	    return TOUCH_ACTION_MANIPULATION;
	  }

	  return TOUCH_ACTION_AUTO;
	}

	/**
	 * @private
	 * Touch Action
	 * sets the touchAction property or uses the js alternative
	 * @param {Manager} manager
	 * @param {String} value
	 * @constructor
	 */

	var TouchAction =
	/*#__PURE__*/
	function () {
	  function TouchAction(manager, value) {
	    this.manager = manager;
	    this.set(value);
	  }
	  /**
	   * @private
	   * set the touchAction value on the element or enable the polyfill
	   * @param {String} value
	   */


	  var _proto = TouchAction.prototype;

	  _proto.set = function set(value) {
	    // find out the touch-action by the event handlers
	    if (value === TOUCH_ACTION_COMPUTE) {
	      value = this.compute();
	    }

	    if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) {
	      this.manager.element.style[PREFIXED_TOUCH_ACTION] = value;
	    }

	    this.actions = value.toLowerCase().trim();
	  };
	  /**
	   * @private
	   * just re-set the touchAction value
	   */


	  _proto.update = function update() {
	    this.set(this.manager.options.touchAction);
	  };
	  /**
	   * @private
	   * compute the value for the touchAction property based on the recognizer's settings
	   * @returns {String} value
	   */


	  _proto.compute = function compute() {
	    var actions = [];
	    each(this.manager.recognizers, function (recognizer) {
	      if (boolOrFn(recognizer.options.enable, [recognizer])) {
	        actions = actions.concat(recognizer.getTouchAction());
	      }
	    });
	    return cleanTouchActions(actions.join(' '));
	  };
	  /**
	   * @private
	   * this method is called on each input cycle and provides the preventing of the browser behavior
	   * @param {Object} input
	   */


	  _proto.preventDefaults = function preventDefaults(input) {
	    var srcEvent = input.srcEvent;
	    var direction = input.offsetDirection; // if the touch action did prevented once this session

	    if (this.manager.session.prevented) {
	      srcEvent.preventDefault();
	      return;
	    }

	    var actions = this.actions;
	    var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE];
	    var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y];
	    var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X];

	    if (hasNone) {
	      // do not prevent defaults if this is a tap gesture
	      var isTapPointer = input.pointers.length === 1;
	      var isTapMovement = input.distance < 2;
	      var isTapTouchTime = input.deltaTime < 250;

	      if (isTapPointer && isTapMovement && isTapTouchTime) {
	        return;
	      }
	    }

	    if (hasPanX && hasPanY) {
	      // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent
	      return;
	    }

	    if (hasNone || hasPanY && direction & DIRECTION_HORIZONTAL || hasPanX && direction & DIRECTION_VERTICAL) {
	      return this.preventSrc(srcEvent);
	    }
	  };
	  /**
	   * @private
	   * call preventDefault to prevent the browser's default behavior (scrolling in most cases)
	   * @param {Object} srcEvent
	   */


	  _proto.preventSrc = function preventSrc(srcEvent) {
	    this.manager.session.prevented = true;
	    srcEvent.preventDefault();
	  };

	  return TouchAction;
	}();

	/**
	 * @private
	 * find if a node is in the given parent
	 * @method hasParent
	 * @param {HTMLElement} node
	 * @param {HTMLElement} parent
	 * @return {Boolean} found
	 */
	function hasParent(node, parent) {
	  while (node) {
	    if (node === parent) {
	      return true;
	    }

	    node = node.parentNode;
	  }

	  return false;
	}

	/**
	 * @private
	 * get the center of all the pointers
	 * @param {Array} pointers
	 * @return {Object} center contains `x` and `y` properties
	 */

	function getCenter(pointers) {
	  var pointersLength = pointers.length; // no need to loop when only one touch

	  if (pointersLength === 1) {
	    return {
	      x: round(pointers[0].clientX),
	      y: round(pointers[0].clientY)
	    };
	  }

	  var x = 0;
	  var y = 0;
	  var i = 0;

	  while (i < pointersLength) {
	    x += pointers[i].clientX;
	    y += pointers[i].clientY;
	    i++;
	  }

	  return {
	    x: round(x / pointersLength),
	    y: round(y / pointersLength)
	  };
	}

	/**
	 * @private
	 * create a simple clone from the input used for storage of firstInput and firstMultiple
	 * @param {Object} input
	 * @returns {Object} clonedInputData
	 */

	function simpleCloneInputData(input) {
	  // make a simple copy of the pointers because we will get a reference if we don't
	  // we only need clientXY for the calculations
	  var pointers = [];
	  var i = 0;

	  while (i < input.pointers.length) {
	    pointers[i] = {
	      clientX: round(input.pointers[i].clientX),
	      clientY: round(input.pointers[i].clientY)
	    };
	    i++;
	  }

	  return {
	    timeStamp: now$1(),
	    pointers: pointers,
	    center: getCenter(pointers),
	    deltaX: input.deltaX,
	    deltaY: input.deltaY
	  };
	}

	/**
	 * @private
	 * calculate the absolute distance between two points
	 * @param {Object} p1 {x, y}
	 * @param {Object} p2 {x, y}
	 * @param {Array} [props] containing x and y keys
	 * @return {Number} distance
	 */

	function getDistance(p1, p2, props) {
	  if (!props) {
	    props = PROPS_XY;
	  }

	  var x = p2[props[0]] - p1[props[0]];
	  var y = p2[props[1]] - p1[props[1]];
	  return Math.sqrt(x * x + y * y);
	}

	/**
	 * @private
	 * calculate the angle between two coordinates
	 * @param {Object} p1
	 * @param {Object} p2
	 * @param {Array} [props] containing x and y keys
	 * @return {Number} angle
	 */

	function getAngle(p1, p2, props) {
	  if (!props) {
	    props = PROPS_XY;
	  }

	  var x = p2[props[0]] - p1[props[0]];
	  var y = p2[props[1]] - p1[props[1]];
	  return Math.atan2(y, x) * 180 / Math.PI;
	}

	/**
	 * @private
	 * get the direction between two points
	 * @param {Number} x
	 * @param {Number} y
	 * @return {Number} direction
	 */

	function getDirection(x, y) {
	  if (x === y) {
	    return DIRECTION_NONE;
	  }

	  if (abs(x) >= abs(y)) {
	    return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
	  }

	  return y < 0 ? DIRECTION_UP : DIRECTION_DOWN;
	}

	function computeDeltaXY(session, input) {
	  var center = input.center; // let { offsetDelta:offset = {}, prevDelta = {}, prevInput = {} } = session;
	  // jscs throwing error on defalut destructured values and without defaults tests fail

	  var offset = session.offsetDelta || {};
	  var prevDelta = session.prevDelta || {};
	  var prevInput = session.prevInput || {};

	  if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) {
	    prevDelta = session.prevDelta = {
	      x: prevInput.deltaX || 0,
	      y: prevInput.deltaY || 0
	    };
	    offset = session.offsetDelta = {
	      x: center.x,
	      y: center.y
	    };
	  }

	  input.deltaX = prevDelta.x + (center.x - offset.x);
	  input.deltaY = prevDelta.y + (center.y - offset.y);
	}

	/**
	 * @private
	 * calculate the velocity between two points. unit is in px per ms.
	 * @param {Number} deltaTime
	 * @param {Number} x
	 * @param {Number} y
	 * @return {Object} velocity `x` and `y`
	 */
	function getVelocity(deltaTime, x, y) {
	  return {
	    x: x / deltaTime || 0,
	    y: y / deltaTime || 0
	  };
	}

	/**
	 * @private
	 * calculate the scale factor between two pointersets
	 * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
	 * @param {Array} start array of pointers
	 * @param {Array} end array of pointers
	 * @return {Number} scale
	 */

	function getScale(start, end) {
	  return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY);
	}

	/**
	 * @private
	 * calculate the rotation degrees between two pointersets
	 * @param {Array} start array of pointers
	 * @param {Array} end array of pointers
	 * @return {Number} rotation
	 */

	function getRotation(start, end) {
	  return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY);
	}

	/**
	 * @private
	 * velocity is calculated every x ms
	 * @param {Object} session
	 * @param {Object} input
	 */

	function computeIntervalInputData(session, input) {
	  var last = session.lastInterval || input;
	  var deltaTime = input.timeStamp - last.timeStamp;
	  var velocity;
	  var velocityX;
	  var velocityY;
	  var direction;

	  if (input.eventType !== INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) {
	    var deltaX = input.deltaX - last.deltaX;
	    var deltaY = input.deltaY - last.deltaY;
	    var v = getVelocity(deltaTime, deltaX, deltaY);
	    velocityX = v.x;
	    velocityY = v.y;
	    velocity = abs(v.x) > abs(v.y) ? v.x : v.y;
	    direction = getDirection(deltaX, deltaY);
	    session.lastInterval = input;
	  } else {
	    // use latest velocity info if it doesn't overtake a minimum period
	    velocity = last.velocity;
	    velocityX = last.velocityX;
	    velocityY = last.velocityY;
	    direction = last.direction;
	  }

	  input.velocity = velocity;
	  input.velocityX = velocityX;
	  input.velocityY = velocityY;
	  input.direction = direction;
	}

	/**
	* @private
	 * extend the data with some usable properties like scale, rotate, velocity etc
	 * @param {Object} manager
	 * @param {Object} input
	 */

	function computeInputData(manager, input) {
	  var session = manager.session;
	  var pointers = input.pointers;
	  var pointersLength = pointers.length; // store the first input to calculate the distance and direction

	  if (!session.firstInput) {
	    session.firstInput = simpleCloneInputData(input);
	  } // to compute scale and rotation we need to store the multiple touches


	  if (pointersLength > 1 && !session.firstMultiple) {
	    session.firstMultiple = simpleCloneInputData(input);
	  } else if (pointersLength === 1) {
	    session.firstMultiple = false;
	  }

	  var firstInput = session.firstInput,
	      firstMultiple = session.firstMultiple;
	  var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center;
	  var center = input.center = getCenter(pointers);
	  input.timeStamp = now$1();
	  input.deltaTime = input.timeStamp - firstInput.timeStamp;
	  input.angle = getAngle(offsetCenter, center);
	  input.distance = getDistance(offsetCenter, center);
	  computeDeltaXY(session, input);
	  input.offsetDirection = getDirection(input.deltaX, input.deltaY);
	  var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY);
	  input.overallVelocityX = overallVelocity.x;
	  input.overallVelocityY = overallVelocity.y;
	  input.overallVelocity = abs(overallVelocity.x) > abs(overallVelocity.y) ? overallVelocity.x : overallVelocity.y;
	  input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1;
	  input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0;
	  input.maxPointers = !session.prevInput ? input.pointers.length : input.pointers.length > session.prevInput.maxPointers ? input.pointers.length : session.prevInput.maxPointers;
	  computeIntervalInputData(session, input); // find the correct target

	  var target = manager.element;

	  if (hasParent(input.srcEvent.target, target)) {
	    target = input.srcEvent.target;
	  }

	  input.target = target;
	}

	/**
	 * @private
	 * handle input events
	 * @param {Manager} manager
	 * @param {String} eventType
	 * @param {Object} input
	 */

	function inputHandler(manager, eventType, input) {
	  var pointersLen = input.pointers.length;
	  var changedPointersLen = input.changedPointers.length;
	  var isFirst = eventType & INPUT_START && pointersLen - changedPointersLen === 0;
	  var isFinal = eventType & (INPUT_END | INPUT_CANCEL) && pointersLen - changedPointersLen === 0;
	  input.isFirst = !!isFirst;
	  input.isFinal = !!isFinal;

	  if (isFirst) {
	    manager.session = {};
	  } // source event is the normalized value of the domEvents
	  // like 'touchstart, mouseup, pointerdown'


	  input.eventType = eventType; // compute scale, rotation etc

	  computeInputData(manager, input); // emit secret event

	  manager.emit('hammer.input', input);
	  manager.recognize(input);
	  manager.session.prevInput = input;
	}

	/**
	 * @private
	 * split string on whitespace
	 * @param {String} str
	 * @returns {Array} words
	 */
	function splitStr(str) {
	  return str.trim().split(/\s+/g);
	}

	/**
	 * @private
	 * addEventListener with multiple events at once
	 * @param {EventTarget} target
	 * @param {String} types
	 * @param {Function} handler
	 */

	function addEventListeners(target, types, handler) {
	  each(splitStr(types), function (type) {
	    target.addEventListener(type, handler, false);
	  });
	}

	/**
	 * @private
	 * removeEventListener with multiple events at once
	 * @param {EventTarget} target
	 * @param {String} types
	 * @param {Function} handler
	 */

	function removeEventListeners(target, types, handler) {
	  each(splitStr(types), function (type) {
	    target.removeEventListener(type, handler, false);
	  });
	}

	/**
	 * @private
	 * get the window object of an element
	 * @param {HTMLElement} element
	 * @returns {DocumentView|Window}
	 */
	function getWindowForElement(element) {
	  var doc = element.ownerDocument || element;
	  return doc.defaultView || doc.parentWindow || window;
	}

	/**
	 * @private
	 * create new input type manager
	 * @param {Manager} manager
	 * @param {Function} callback
	 * @returns {Input}
	 * @constructor
	 */

	var Input =
	/*#__PURE__*/
	function () {
	  function Input(manager, callback) {
	    var self = this;
	    this.manager = manager;
	    this.callback = callback;
	    this.element = manager.element;
	    this.target = manager.options.inputTarget; // smaller wrapper around the handler, for the scope and the enabled state of the manager,
	    // so when disabled the input events are completely bypassed.

	    this.domHandler = function (ev) {
	      if (boolOrFn(manager.options.enable, [manager])) {
	        self.handler(ev);
	      }
	    };

	    this.init();
	  }
	  /**
	   * @private
	   * should handle the inputEvent data and trigger the callback
	   * @virtual
	   */


	  var _proto = Input.prototype;

	  _proto.handler = function handler() {};
	  /**
	   * @private
	   * bind the events
	   */


	  _proto.init = function init() {
	    this.evEl && addEventListeners(this.element, this.evEl, this.domHandler);
	    this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler);
	    this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
	  };
	  /**
	   * @private
	   * unbind the events
	   */


	  _proto.destroy = function destroy() {
	    this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler);
	    this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler);
	    this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
	  };

	  return Input;
	}();

	/**
	 * @private
	 * find if a array contains the object using indexOf or a simple polyFill
	 * @param {Array} src
	 * @param {String} find
	 * @param {String} [findByKey]
	 * @return {Boolean|Number} false when not found, or the index
	 */
	function inArray(src, find, findByKey) {
	  if (src.indexOf && !findByKey) {
	    return src.indexOf(find);
	  } else {
	    var i = 0;

	    while (i < src.length) {
	      if (findByKey && src[i][findByKey] == find || !findByKey && src[i] === find) {
	        // do not use === here, test fails
	        return i;
	      }

	      i++;
	    }

	    return -1;
	  }
	}

	var POINTER_INPUT_MAP = {
	  pointerdown: INPUT_START,
	  pointermove: INPUT_MOVE,
	  pointerup: INPUT_END,
	  pointercancel: INPUT_CANCEL,
	  pointerout: INPUT_CANCEL
	}; // in IE10 the pointer types is defined as an enum

	var IE10_POINTER_TYPE_ENUM = {
	  2: INPUT_TYPE_TOUCH,
	  3: INPUT_TYPE_PEN,
	  4: INPUT_TYPE_MOUSE,
	  5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816

	};
	var POINTER_ELEMENT_EVENTS = 'pointerdown';
	var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel'; // IE10 has prefixed support, and case-sensitive

	if (win.MSPointerEvent && !win.PointerEvent) {
	  POINTER_ELEMENT_EVENTS = 'MSPointerDown';
	  POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel';
	}
	/**
	 * @private
	 * Pointer events input
	 * @constructor
	 * @extends Input
	 */


	var PointerEventInput =
	/*#__PURE__*/
	function (_Input) {
	  _inheritsLoose(PointerEventInput, _Input);

	  function PointerEventInput() {
	    var _this;

	    var proto = PointerEventInput.prototype;
	    proto.evEl = POINTER_ELEMENT_EVENTS;
	    proto.evWin = POINTER_WINDOW_EVENTS;
	    _this = _Input.apply(this, arguments) || this;
	    _this.store = _this.manager.session.pointerEvents = [];
	    return _this;
	  }
	  /**
	   * @private
	   * handle mouse events
	   * @param {Object} ev
	   */


	  var _proto = PointerEventInput.prototype;

	  _proto.handler = function handler(ev) {
	    var store = this.store;
	    var removePointer = false;
	    var eventTypeNormalized = ev.type.toLowerCase().replace('ms', '');
	    var eventType = POINTER_INPUT_MAP[eventTypeNormalized];
	    var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType;
	    var isTouch = pointerType === INPUT_TYPE_TOUCH; // get index of the event in the store

	    var storeIndex = inArray(store, ev.pointerId, 'pointerId'); // start and mouse must be down

	    if (eventType & INPUT_START && (ev.button === 0 || isTouch)) {
	      if (storeIndex < 0) {
	        store.push(ev);
	        storeIndex = store.length - 1;
	      }
	    } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
	      removePointer = true;
	    } // it not found, so the pointer hasn't been down (so it's probably a hover)


	    if (storeIndex < 0) {
	      return;
	    } // update the event in the store


	    store[storeIndex] = ev;
	    this.callback(this.manager, eventType, {
	      pointers: store,
	      changedPointers: [ev],
	      pointerType: pointerType,
	      srcEvent: ev
	    });

	    if (removePointer) {
	      // remove from the store
	      store.splice(storeIndex, 1);
	    }
	  };

	  return PointerEventInput;
	}(Input);

	/**
	 * @private
	 * convert array-like objects to real arrays
	 * @param {Object} obj
	 * @returns {Array}
	 */
	function toArray$1(obj) {
	  return Array.prototype.slice.call(obj, 0);
	}

	/**
	 * @private
	 * unique array with objects based on a key (like 'id') or just by the array's value
	 * @param {Array} src [{id:1},{id:2},{id:1}]
	 * @param {String} [key]
	 * @param {Boolean} [sort=False]
	 * @returns {Array} [{id:1},{id:2}]
	 */

	function uniqueArray(src, key, sort) {
	  var results = [];
	  var values = [];
	  var i = 0;

	  while (i < src.length) {
	    var val = key ? src[i][key] : src[i];

	    if (inArray(values, val) < 0) {
	      results.push(src[i]);
	    }

	    values[i] = val;
	    i++;
	  }

	  if (sort) {
	    if (!key) {
	      results = results.sort();
	    } else {
	      results = results.sort(function (a, b) {
	        return a[key] > b[key];
	      });
	    }
	  }

	  return results;
	}

	var TOUCH_INPUT_MAP = {
	  touchstart: INPUT_START,
	  touchmove: INPUT_MOVE,
	  touchend: INPUT_END,
	  touchcancel: INPUT_CANCEL
	};
	var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel';
	/**
	 * @private
	 * Multi-user touch events input
	 * @constructor
	 * @extends Input
	 */

	var TouchInput =
	/*#__PURE__*/
	function (_Input) {
	  _inheritsLoose(TouchInput, _Input);

	  function TouchInput() {
	    var _this;

	    TouchInput.prototype.evTarget = TOUCH_TARGET_EVENTS;
	    _this = _Input.apply(this, arguments) || this;
	    _this.targetIds = {}; // this.evTarget = TOUCH_TARGET_EVENTS;

	    return _this;
	  }

	  var _proto = TouchInput.prototype;

	  _proto.handler = function handler(ev) {
	    var type = TOUCH_INPUT_MAP[ev.type];
	    var touches = getTouches.call(this, ev, type);

	    if (!touches) {
	      return;
	    }

	    this.callback(this.manager, type, {
	      pointers: touches[0],
	      changedPointers: touches[1],
	      pointerType: INPUT_TYPE_TOUCH,
	      srcEvent: ev
	    });
	  };

	  return TouchInput;
	}(Input);

	function getTouches(ev, type) {
	  var allTouches = toArray$1(ev.touches);
	  var targetIds = this.targetIds; // when there is only one touch, the process can be simplified

	  if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) {
	    targetIds[allTouches[0].identifier] = true;
	    return [allTouches, allTouches];
	  }

	  var i;
	  var targetTouches;
	  var changedTouches = toArray$1(ev.changedTouches);
	  var changedTargetTouches = [];
	  var target = this.target; // get target touches from touches

	  targetTouches = allTouches.filter(function (touch) {
	    return hasParent(touch.target, target);
	  }); // collect touches

	  if (type === INPUT_START) {
	    i = 0;

	    while (i < targetTouches.length) {
	      targetIds[targetTouches[i].identifier] = true;
	      i++;
	    }
	  } // filter changed touches to only contain touches that exist in the collected target ids


	  i = 0;

	  while (i < changedTouches.length) {
	    if (targetIds[changedTouches[i].identifier]) {
	      changedTargetTouches.push(changedTouches[i]);
	    } // cleanup removed touches


	    if (type & (INPUT_END | INPUT_CANCEL)) {
	      delete targetIds[changedTouches[i].identifier];
	    }

	    i++;
	  }

	  if (!changedTargetTouches.length) {
	    return;
	  }

	  return [// merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel'
	  uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true), changedTargetTouches];
	}

	var MOUSE_INPUT_MAP = {
	  mousedown: INPUT_START,
	  mousemove: INPUT_MOVE,
	  mouseup: INPUT_END
	};
	var MOUSE_ELEMENT_EVENTS = 'mousedown';
	var MOUSE_WINDOW_EVENTS = 'mousemove mouseup';
	/**
	 * @private
	 * Mouse events input
	 * @constructor
	 * @extends Input
	 */

	var MouseInput =
	/*#__PURE__*/
	function (_Input) {
	  _inheritsLoose(MouseInput, _Input);

	  function MouseInput() {
	    var _this;

	    var proto = MouseInput.prototype;
	    proto.evEl = MOUSE_ELEMENT_EVENTS;
	    proto.evWin = MOUSE_WINDOW_EVENTS;
	    _this = _Input.apply(this, arguments) || this;
	    _this.pressed = false; // mousedown state

	    return _this;
	  }
	  /**
	   * @private
	   * handle mouse events
	   * @param {Object} ev
	   */


	  var _proto = MouseInput.prototype;

	  _proto.handler = function handler(ev) {
	    var eventType = MOUSE_INPUT_MAP[ev.type]; // on start we want to have the left mouse button down

	    if (eventType & INPUT_START && ev.button === 0) {
	      this.pressed = true;
	    }

	    if (eventType & INPUT_MOVE && ev.which !== 1) {
	      eventType = INPUT_END;
	    } // mouse must be down


	    if (!this.pressed) {
	      return;
	    }

	    if (eventType & INPUT_END) {
	      this.pressed = false;
	    }

	    this.callback(this.manager, eventType, {
	      pointers: [ev],
	      changedPointers: [ev],
	      pointerType: INPUT_TYPE_MOUSE,
	      srcEvent: ev
	    });
	  };

	  return MouseInput;
	}(Input);

	/**
	 * @private
	 * Combined touch and mouse input
	 *
	 * Touch has a higher priority then mouse, and while touching no mouse events are allowed.
	 * This because touch devices also emit mouse events while doing a touch.
	 *
	 * @constructor
	 * @extends Input
	 */

	var DEDUP_TIMEOUT = 2500;
	var DEDUP_DISTANCE = 25;

	function setLastTouch(eventData) {
	  var _eventData$changedPoi = eventData.changedPointers,
	      touch = _eventData$changedPoi[0];

	  if (touch.identifier === this.primaryTouch) {
	    var lastTouch = {
	      x: touch.clientX,
	      y: touch.clientY
	    };
	    var lts = this.lastTouches;
	    this.lastTouches.push(lastTouch);

	    var removeLastTouch = function removeLastTouch() {
	      var i = lts.indexOf(lastTouch);

	      if (i > -1) {
	        lts.splice(i, 1);
	      }
	    };

	    setTimeout(removeLastTouch, DEDUP_TIMEOUT);
	  }
	}

	function recordTouches(eventType, eventData) {
	  if (eventType & INPUT_START) {
	    this.primaryTouch = eventData.changedPointers[0].identifier;
	    setLastTouch.call(this, eventData);
	  } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
	    setLastTouch.call(this, eventData);
	  }
	}

	function isSyntheticEvent(eventData) {
	  var x = eventData.srcEvent.clientX;
	  var y = eventData.srcEvent.clientY;

	  for (var i = 0; i < this.lastTouches.length; i++) {
	    var t = this.lastTouches[i];
	    var dx = Math.abs(x - t.x);
	    var dy = Math.abs(y - t.y);

	    if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) {
	      return true;
	    }
	  }

	  return false;
	}

	var TouchMouseInput =
	/*#__PURE__*/
	function () {
	  var TouchMouseInput =
	  /*#__PURE__*/
	  function (_Input) {
	    _inheritsLoose(TouchMouseInput, _Input);

	    function TouchMouseInput(_manager, callback) {
	      var _this;

	      _this = _Input.call(this, _manager, callback) || this;

	      _this.handler = function (manager, inputEvent, inputData) {
	        var isTouch = inputData.pointerType === INPUT_TYPE_TOUCH;
	        var isMouse = inputData.pointerType === INPUT_TYPE_MOUSE;

	        if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) {
	          return;
	        } // when we're in a touch event, record touches to  de-dupe synthetic mouse event


	        if (isTouch) {
	          recordTouches.call(_assertThisInitialized(_assertThisInitialized(_this)), inputEvent, inputData);
	        } else if (isMouse && isSyntheticEvent.call(_assertThisInitialized(_assertThisInitialized(_this)), inputData)) {
	          return;
	        }

	        _this.callback(manager, inputEvent, inputData);
	      };

	      _this.touch = new TouchInput(_this.manager, _this.handler);
	      _this.mouse = new MouseInput(_this.manager, _this.handler);
	      _this.primaryTouch = null;
	      _this.lastTouches = [];
	      return _this;
	    }
	    /**
	     * @private
	     * handle mouse and touch events
	     * @param {Hammer} manager
	     * @param {String} inputEvent
	     * @param {Object} inputData
	     */


	    var _proto = TouchMouseInput.prototype;

	    /**
	     * @private
	     * remove the event listeners
	     */
	    _proto.destroy = function destroy() {
	      this.touch.destroy();
	      this.mouse.destroy();
	    };

	    return TouchMouseInput;
	  }(Input);

	  return TouchMouseInput;
	}();

	/**
	 * @private
	 * create new input type manager
	 * called by the Manager constructor
	 * @param {Hammer} manager
	 * @returns {Input}
	 */

	function createInputInstance(manager) {
	  var Type; // let inputClass = manager.options.inputClass;

	  var inputClass = manager.options.inputClass;

	  if (inputClass) {
	    Type = inputClass;
	  } else if (SUPPORT_POINTER_EVENTS) {
	    Type = PointerEventInput;
	  } else if (SUPPORT_ONLY_TOUCH) {
	    Type = TouchInput;
	  } else if (!SUPPORT_TOUCH) {
	    Type = MouseInput;
	  } else {
	    Type = TouchMouseInput;
	  }

	  return new Type(manager, inputHandler);
	}

	/**
	 * @private
	 * if the argument is an array, we want to execute the fn on each entry
	 * if it aint an array we don't want to do a thing.
	 * this is used by all the methods that accept a single and array argument.
	 * @param {*|Array} arg
	 * @param {String} fn
	 * @param {Object} [context]
	 * @returns {Boolean}
	 */

	function invokeArrayArg(arg, fn, context) {
	  if (Array.isArray(arg)) {
	    each(arg, context[fn], context);
	    return true;
	  }

	  return false;
	}

	var STATE_POSSIBLE = 1;
	var STATE_BEGAN = 2;
	var STATE_CHANGED = 4;
	var STATE_ENDED = 8;
	var STATE_RECOGNIZED = STATE_ENDED;
	var STATE_CANCELLED = 16;
	var STATE_FAILED = 32;

	/**
	 * @private
	 * get a unique id
	 * @returns {number} uniqueId
	 */
	var _uniqueId = 1;
	function uniqueId() {
	  return _uniqueId++;
	}

	/**
	 * @private
	 * get a recognizer by name if it is bound to a manager
	 * @param {Recognizer|String} otherRecognizer
	 * @param {Recognizer} recognizer
	 * @returns {Recognizer}
	 */
	function getRecognizerByNameIfManager(otherRecognizer, recognizer) {
	  var manager = recognizer.manager;

	  if (manager) {
	    return manager.get(otherRecognizer);
	  }

	  return otherRecognizer;
	}

	/**
	 * @private
	 * get a usable string, used as event postfix
	 * @param {constant} state
	 * @returns {String} state
	 */

	function stateStr(state) {
	  if (state & STATE_CANCELLED) {
	    return 'cancel';
	  } else if (state & STATE_ENDED) {
	    return 'end';
	  } else if (state & STATE_CHANGED) {
	    return 'move';
	  } else if (state & STATE_BEGAN) {
	    return 'start';
	  }

	  return '';
	}

	/**
	 * @private
	 * Recognizer flow explained; *
	 * All recognizers have the initial state of POSSIBLE when a input session starts.
	 * The definition of a input session is from the first input until the last input, with all it's movement in it. *
	 * Example session for mouse-input: mousedown -> mousemove -> mouseup
	 *
	 * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed
	 * which determines with state it should be.
	 *
	 * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to
	 * POSSIBLE to give it another change on the next cycle.
	 *
	 *               Possible
	 *                  |
	 *            +-----+---------------+
	 *            |                     |
	 *      +-----+-----+               |
	 *      |           |               |
	 *   Failed      Cancelled          |
	 *                          +-------+------+
	 *                          |              |
	 *                      Recognized       Began
	 *                                         |
	 *                                      Changed
	 *                                         |
	 *                                  Ended/Recognized
	 */

	/**
	 * @private
	 * Recognizer
	 * Every recognizer needs to extend from this class.
	 * @constructor
	 * @param {Object} options
	 */

	var Recognizer =
	/*#__PURE__*/
	function () {
	  function Recognizer(options) {
	    if (options === void 0) {
	      options = {};
	    }

	    this.options = _extends({
	      enable: true
	    }, options);
	    this.id = uniqueId();
	    this.manager = null; // default is enable true

	    this.state = STATE_POSSIBLE;
	    this.simultaneous = {};
	    this.requireFail = [];
	  }
	  /**
	   * @private
	   * set options
	   * @param {Object} options
	   * @return {Recognizer}
	   */


	  var _proto = Recognizer.prototype;

	  _proto.set = function set(options) {
	    assign$1(this.options, options); // also update the touchAction, in case something changed about the directions/enabled state

	    this.manager && this.manager.touchAction.update();
	    return this;
	  };
	  /**
	   * @private
	   * recognize simultaneous with an other recognizer.
	   * @param {Recognizer} otherRecognizer
	   * @returns {Recognizer} this
	   */


	  _proto.recognizeWith = function recognizeWith(otherRecognizer) {
	    if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) {
	      return this;
	    }

	    var simultaneous = this.simultaneous;
	    otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);

	    if (!simultaneous[otherRecognizer.id]) {
	      simultaneous[otherRecognizer.id] = otherRecognizer;
	      otherRecognizer.recognizeWith(this);
	    }

	    return this;
	  };
	  /**
	   * @private
	   * drop the simultaneous link. it doesnt remove the link on the other recognizer.
	   * @param {Recognizer} otherRecognizer
	   * @returns {Recognizer} this
	   */


	  _proto.dropRecognizeWith = function dropRecognizeWith(otherRecognizer) {
	    if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) {
	      return this;
	    }

	    otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
	    delete this.simultaneous[otherRecognizer.id];
	    return this;
	  };
	  /**
	   * @private
	   * recognizer can only run when an other is failing
	   * @param {Recognizer} otherRecognizer
	   * @returns {Recognizer} this
	   */


	  _proto.requireFailure = function requireFailure(otherRecognizer) {
	    if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) {
	      return this;
	    }

	    var requireFail = this.requireFail;
	    otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);

	    if (inArray(requireFail, otherRecognizer) === -1) {
	      requireFail.push(otherRecognizer);
	      otherRecognizer.requireFailure(this);
	    }

	    return this;
	  };
	  /**
	   * @private
	   * drop the requireFailure link. it does not remove the link on the other recognizer.
	   * @param {Recognizer} otherRecognizer
	   * @returns {Recognizer} this
	   */


	  _proto.dropRequireFailure = function dropRequireFailure(otherRecognizer) {
	    if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) {
	      return this;
	    }

	    otherRecognizer = getRecogn.........完整代码请登录后点击上方下载按钮下载查看

网友评论0