(function (exports) { 'use strict'; /*! (c) Andrea Giammarchi @webreflection ISC */ (function () { var Lie = typeof Promise === 'function' ? Promise : function (fn) { var queue = [], resolved = 0, value; fn(function ($) { value = $; resolved = 1; queue.splice(0).forEach(then); }); return { then: then }; function then(fn) { return resolved ? setTimeout(fn, 0, value) : queue.push(fn), this; } }; var attributesObserver = function attributesObserver(whenDefined, MutationObserver) { var attributeChanged = function attributeChanged(records) { for (var i = 0, length = records.length; i < length; i++) { dispatch(records[i]); } }; var dispatch = function dispatch(_ref) { var target = _ref.target, attributeName = _ref.attributeName, oldValue = _ref.oldValue; target.attributeChangedCallback(attributeName, oldValue, target.getAttribute(attributeName)); }; return function (target, is) { var attributeFilter = target.constructor.observedAttributes; if (attributeFilter) { whenDefined(is).then(function () { new MutationObserver(attributeChanged).observe(target, { attributes: true, attributeOldValue: true, attributeFilter: attributeFilter }); for (var i = 0, length = attributeFilter.length; i < length; i++) { if (target.hasAttribute(attributeFilter[i])) dispatch({ target: target, attributeName: attributeFilter[i], oldValue: null }); } }); } return target; }; }; var TRUE = true, FALSE = false; var QSA$1 = 'querySelectorAll'; function add(node) { this.observe(node, { subtree: TRUE, childList: TRUE }); } /** * Start observing a generic document or root element. * @param {Function} callback triggered per each dis/connected node * @param {Element?} root by default, the global document to observe * @param {Function?} MO by default, the global MutationObserver * @returns {MutationObserver} */ var notify = function notify(callback, root, MO) { var loop = function loop(nodes, added, removed, connected, pass) { for (var i = 0, length = nodes.length; i < length; i++) { var node = nodes[i]; if (pass || QSA$1 in node) { if (connected) { if (!added.has(node)) { added.add(node); removed["delete"](node); callback(node, connected); } } else if (!removed.has(node)) { removed.add(node); added["delete"](node); callback(node, connected); } if (!pass) loop(node[QSA$1]('*'), added, removed, connected, TRUE); } } }; var observer = new (MO || MutationObserver)(function (records) { for (var added = new Set(), removed = new Set(), i = 0, length = records.length; i < length; i++) { var _records$i = records[i], addedNodes = _records$i.addedNodes, removedNodes = _records$i.removedNodes; loop(removedNodes, added, removed, FALSE, FALSE); loop(addedNodes, added, removed, TRUE, FALSE); } }); observer.add = add; observer.add(root || document); return observer; }; var QSA = 'querySelectorAll'; var _self$1 = self, document$2 = _self$1.document, Element$1 = _self$1.Element, MutationObserver$2 = _self$1.MutationObserver, Set$2 = _self$1.Set, WeakMap$1 = _self$1.WeakMap; var elements = function elements(element) { return QSA in element; }; var filter = [].filter; var qsaObserver = function qsaObserver(options) { var live = new WeakMap$1(); var drop = function drop(elements) { for (var i = 0, length = elements.length; i < length; i++) { live["delete"](elements[i]); } }; var flush = function flush() { var records = observer.takeRecords(); for (var i = 0, length = records.length; i < length; i++) { parse(filter.call(records[i].removedNodes, elements), false); parse(filter.call(records[i].addedNodes, elements), true); } }; var matches = function matches(element) { return element.matches || element.webkitMatchesSelector || element.msMatchesSelector; }; var notifier = function notifier(element, connected) { var selectors; if (connected) { for (var q, m = matches(element), i = 0, length = query.length; i < length; i++) { if (m.call(element, q = query[i])) { if (!live.has(element)) live.set(element, new Set$2()); selectors = live.get(element); if (!selectors.has(q)) { selectors.add(q); options.handle(element, connected, q); } } } } else if (live.has(element)) { selectors = live.get(element); live["delete"](element); selectors.forEach(function (q) { options.handle(element, connected, q); }); } }; var parse = function parse(elements) { var connected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; for (var i = 0, length = elements.length; i < length; i++) { notifier(elements[i], connected); } }; var query = options.query; var root = options.root || document$2; var observer = notify(notifier, root, MutationObserver$2); var attachShadow = Element$1.prototype.attachShadow; if (attachShadow) Element$1.prototype.attachShadow = function (init) { var shadowRoot = attachShadow.call(this, init); observer.add(shadowRoot); return shadowRoot; }; if (query.length) parse(root[QSA](query)); return { drop: drop, flush: flush, observer: observer, parse: parse }; }; var _self = self, document$1 = _self.document, Map = _self.Map, MutationObserver$1 = _self.MutationObserver, Object$1 = _self.Object, Set$1 = _self.Set, WeakMap = _self.WeakMap, Element = _self.Element, HTMLElement = _self.HTMLElement, Node = _self.Node, Error = _self.Error, TypeError = _self.TypeError, Reflect = _self.Reflect; var Promise$1 = self.Promise || Lie; var defineProperty = Object$1.defineProperty, keys = Object$1.keys, getOwnPropertyNames = Object$1.getOwnPropertyNames, setPrototypeOf = Object$1.setPrototypeOf; var legacy = !self.customElements; var expando = function expando(element) { var key = keys(element); var value = []; var length = key.length; for (var i = 0; i < length; i++) { value[i] = element[key[i]]; delete element[key[i]]; } return function () { for (var _i = 0; _i < length; _i++) { element[key[_i]] = value[_i]; } }; }; if (legacy) { var HTMLBuiltIn = function HTMLBuiltIn() { var constructor = this.constructor; if (!classes.has(constructor)) throw new TypeError('Illegal constructor'); var is = classes.get(constructor); if (override) return augment(override, is); var element = createElement.call(document$1, is); return augment(setPrototypeOf(element, constructor.prototype), is); }; var createElement = document$1.createElement; var classes = new Map(); var defined = new Map(); var prototypes = new Map(); var registry = new Map(); var query = []; var handle = function handle(element, connected, selector) { var proto = prototypes.get(selector); if (connected && !proto.isPrototypeOf(element)) { var redefine = expando(element); override = setPrototypeOf(element, proto); try { new proto.constructor(); } finally { override = null; redefine(); } } var method = "".concat(connected ? '' : 'dis', "connectedCallback"); if (method in proto) element[method](); }; var _qsaObserver = qsaObserver({ query: query, handle: handle }), parse = _qsaObserver.parse; var override = null; var whenDefined = function whenDefined(name) { if (!defined.has(name)) { var _, $ = new Lie(function ($) { _ = $; }); defined.set(name, { $: $, _: _ }); } return defined.get(name).$; }; var augment = attributesObserver(whenDefined, MutationObserver$1); defineProperty(self, 'customElements', { configurable: true, value: { define: function define(is, Class) { if (registry.has(is)) throw new Error("the name \"".concat(is, "\" has already been used with this registry")); classes.set(Class, is); prototypes.set(is, Class.prototype); registry.set(is, Class); query.push(is); whenDefined(is).then(function () { parse(document$1.querySelectorAll(is)); }); defined.get(is)._(Class); }, get: function get(is) { return registry.get(is); }, whenDefined: whenDefined } }); defineProperty(HTMLBuiltIn.prototype = HTMLElement.prototype, 'constructor', { value: HTMLBuiltIn }); defineProperty(self, 'HTMLElement', { configurable: true, value: HTMLBuiltIn }); defineProperty(document$1, 'createElement', { configurable: true, value: function value(name, options) { var is = options && options.is; var Class = is ? registry.get(is) : registry.get(name); return Class ? new Class() : createElement.call(document$1, name); } }); // in case ShadowDOM is used through a polyfill, to avoid issues // with builtin extends within shadow roots if (!('isConnected' in Node.prototype)) defineProperty(Node.prototype, 'isConnected', { configurable: true, get: function get() { return !(this.ownerDocument.compareDocumentPosition(this) & this.DOCUMENT_POSITION_DISCONNECTED); } }); } else { try { var LI = function LI() { return self.Reflect.construct(HTMLLIElement, [], LI); }; LI.prototype = HTMLLIElement.prototype; var is = 'extends-li'; self.customElements.define('extends-li', LI, { 'extends': 'li' }); legacy = document$1.createElement('li', { is: is }).outerHTML.indexOf(is) < 0; var _self$customElements = self.customElements, get = _self$customElements.get, _whenDefined = _self$customElements.whenDefined; defineProperty(self.customElements, 'whenDefined', { configurable: true, value: function value(is) { var _this = this; return _whenDefined.call(this, is).then(function (Class) { return Class || get.call(_this, is); }); } }); } catch (o_O) { legacy = !legacy; } } if (legacy) { var parseShadow = function parseShadow(element) { var root = shadowRoots.get(element); _parse(root.querySelectorAll(this), element.isConnected); }; var customElements = self.customElements; var attachShadow = Element.prototype.attachShadow; var _createElement = document$1.createElement; var define = customElements.define, _get = customElements.get; var _ref = Reflect || { construct: function construct(HTMLElement) { return HTMLElement.call(this); } }, construct = _ref.construct; var shadowRoots = new WeakMap(); var shadows = new Set$1(); var _classes = new Map(); var _defined = new Map(); var _prototypes = new Map(); var _registry = new Map(); var shadowed = []; var _query = []; var getCE = function getCE(is) { return _registry.get(is) || _get.call(customElements, is); }; var _handle = function _handle(element, connected, selector) { var proto = _prototypes.get(selector); if (connected && !proto.isPrototypeOf(element)) { var redefine = expando(element); _override = setPrototypeOf(element, proto); try { new proto.constructor(); } finally { _override = null; redefine(); } } var method = "".concat(connected ? '' : 'dis', "connectedCallback"); if (method in proto) element[method](); }; var _qsaObserver2 = qsaObserver({ query: _query, handle: _handle }), _parse = _qsaObserver2.parse; var _qsaObserver3 = qsaObserver({ query: shadowed, handle: function handle(element, connected) { if (shadowRoots.has(element)) { if (connected) shadows.add(element);else shadows["delete"](element); if (_query.length) parseShadow.call(_query, element); } } }), parseShadowed = _qsaObserver3.parse; var _whenDefined2 = function _whenDefined2(name) { if (!_defined.has(name)) { var _, $ = new Promise$1(function ($) { _ = $; }); _defined.set(name, { $: $, _: _ }); } return _defined.get(name).$; }; var _augment = attributesObserver(_whenDefined2, MutationObserver$1); var _override = null; getOwnPropertyNames(self).filter(function (k) { return /^HTML/.test(k); }).forEach(function (k) { var HTMLElement = self[k]; function HTMLBuiltIn() { var constructor = this.constructor; if (!_classes.has(constructor)) throw new TypeError('Illegal constructor'); var _classes$get = _classes.get(constructor), is = _classes$get.is, tag = _classes$get.tag; if (is) { if (_override) return _augment(_override, is); var element = _createElement.call(document$1, tag); element.setAttribute('is', is); return _augment(setPrototypeOf(element, constructor.prototype), is); } else return construct.call(this, HTMLElement, [], constructor); } defineProperty(HTMLBuiltIn.prototype = HTMLElement.prototype, 'constructor', { value: HTMLBuiltIn }); defineProperty(self, k, { value: HTMLBuiltIn }); }); defineProperty(document$1, 'createElement', { configurable: true, value: function value(name, options) { var is = options && options.is; if (is) { var Class = _registry.get(is); if (Class && _classes.get(Class).tag === name) return new Class(); } var element = _createElement.call(document$1, name); if (is) element.setAttribute('is', is); return element; } }); if (attachShadow) Element.prototype.attachShadow = function (init) { var root = attachShadow.call(this, init); shadowRoots.set(this, root); return root; }; defineProperty(customElements, 'get', { configurable: true, value: getCE }); defineProperty(customElements, 'whenDefined', { configurable: true, value: _whenDefined2 }); defineProperty(customElements, 'define', { configurable: true, value: function value(is, Class, options) { if (getCE(is)) throw new Error("'".concat(is, "' has already been defined as a custom element")); var selector; var tag = options && options["extends"]; _classes.set(Class, tag ? { is: is, tag: tag } : { is: '', tag: is }); if (tag) { selector = "".concat(tag, "[is=\"").concat(is, "\"]"); _prototypes.set(selector, Class.prototype); _registry.set(is, Class); _query.push(selector); } else { define.apply(customElements, arguments); shadowed.push(selector = is); } _whenDefined2(is).then(function () { if (tag) { _parse(document$1.querySelectorAll(selector)); shadows.forEach(parseShadow, [selector]); } else parseShadowed(document$1.querySelectorAll(selector)); }); _defined.get(is)._(Class); } }); } })(); var Lie = typeof Promise === 'function' ? Promise : function (fn) { var queue = [], resolved = 0, value; fn(function ($) { value = $; resolved = 1; queue.splice(0).forEach(then); }); return { then: then }; function then(fn) { return resolved ? setTimeout(fn, 0, value) : queue.push(fn), this; } }; var queryHelper = function queryHelper(attr, arr) { return function (element) { return [].reduce.call(element.querySelectorAll('[' + attr + ']'), function (slot, node) { var parentNode = node.parentNode; do { if (parentNode === element) { var name = get(node, attr); slot[name] = arr ? [].concat(slot[name] || [], node) : node; break; } else if (/-/.test(parentNode.tagName) || get(parentNode, 'is')) break; } while (parentNode = parentNode.parentNode); return slot; }, {}); }; }; var get = function get(child, name) { return child.getAttribute(name); }; var has = function has(child, name) { return child.hasAttribute(name); }; var ref$1 = queryHelper('ref', false); var slot = queryHelper('slot', true); var info$1 = null, schedule = new Set(); var invoke = function invoke(effect) { var $ = effect.$, r = effect.r, h = effect.h; if (isFunction(r)) { fx.get(h)["delete"](effect); r(); } if (isFunction(effect.r = $())) fx.get(h).add(effect); }; var runSchedule = function runSchedule() { var previous = schedule; schedule = new Set(); previous.forEach(function (_ref) { var h = _ref.h, c = _ref.c, a = _ref.a, e = _ref.e; // avoid running schedules when the hook is // re-executed before such schedule happens if (e) h.apply(c, a); }); }; var fx = new WeakMap(); var effects = []; var layoutEffects = []; function different(value, i) { return value !== this[i]; } var dropEffect = function dropEffect(hook) { var effects = fx.get(hook); if (effects) wait.then(function () { effects.forEach(function (effect) { effect.r(); effect.r = null; }); effects.clear(); }); }; var getInfo = function getInfo() { return info$1; }; var hasEffect = function hasEffect(hook) { return fx.has(hook); }; var isFunction = function isFunction(f) { return typeof f === 'function'; }; var hooked = function hooked(callback) { var current = { h: hook, c: null, a: null, e: 0, i: 0, s: [] }; return hook; function hook() { var prev = info$1; info$1 = current; current.e = current.i = 0; try { return callback.apply(current.c = this, current.a = arguments); } finally { info$1 = prev; if (effects.length) wait.then(effects.forEach.bind(effects.splice(0), invoke)); if (layoutEffects.length) layoutEffects.splice(0).forEach(invoke); } } }; var reschedule = function reschedule(info) { if (!schedule.has(info)) { info.e = 1; schedule.add(info); wait.then(runSchedule); } }; var wait = new Lie(function ($) { return $(); }); var createContext = function createContext(value) { return { _: new Set(), provide: provide, value: value }; }; var useContext = function useContext(_ref) { var _ = _ref._, value = _ref.value; _.add(getInfo()); return value; }; function provide(newValue) { var _ = this._, value = this.value; if (value !== newValue) { this._ = new Set(); this.value = newValue; _.forEach(function (_ref2) { var h = _ref2.h, c = _ref2.c, a = _ref2.a; h.apply(c, a); }); } } var useCallback = function useCallback(fn, guards) { return useMemo(function () { return fn; }, guards); }; var useMemo = function useMemo(memo, guards) { var info = getInfo(); var i = info.i, s = info.s; if (i === s.length || !guards || guards.some(different, s[i]._)) s[i] = { $: memo(), _: guards }; return s[info.i++].$; }; var createEffect = function createEffect(stack) { return function (callback, guards) { var info = getInfo(); var i = info.i, s = info.s, h = info.h; var call = i === s.length; info.i++; if (call) { if (!fx.has(h)) fx.set(h, new Set()); s[i] = { $: callback, _: guards, r: null, h: h }; } if (call || !guards || guards.some(different, s[i]._)) stack.push(s[i]); s[i].$ = callback; s[i]._ = guards; }; }; var useEffect = createEffect(effects); var useLayoutEffect = createEffect(layoutEffects); var getValue = function getValue(value, f) { return isFunction(f) ? f(value) : f; }; var useReducer = function useReducer(reducer, value, init) { var info = getInfo(); var i = info.i, s = info.s; if (i === s.length) s.push({ $: isFunction(init) ? init(value) : getValue(void 0, value), set: function set(value) { s[i].$ = reducer(s[i].$, value); reschedule(info); } }); var _s$info$i = s[info.i++], $ = _s$info$i.$, set = _s$info$i.set; return [$, set]; }; var useState = function useState(value) { return useReducer(getValue, value); }; var useRef = function useRef(current) { var info = getInfo(); var i = info.i, s = info.s; if (i === s.length) s.push({ current: current }); return s[info.i++]; }; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } var umap = (function (_) { return { // About: get: _.get.bind(_) // It looks like WebKit/Safari didn't optimize bind at all, // so that using bind slows it down by 60%. // Firefox and Chrome are just fine in both cases, // so let's use the approach that works fast everywhere 👍 get: function get(key) { return _.get(key); }, set: function set(key, value) { return _.set(key, value), value; } }; }); var attr = /([^\s\\>"'=]+)\s*=\s*(['"]?)$/; var empty = /^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i; var node = /<[a-z][^>]+$/i; var notNode = />[^<>]*$/; var selfClosing = /<([a-z]+[a-z0-9:._-]*)([^>]*?)(\/>)/ig; var trimEnd = /\s+$/; var isNode = function isNode(template, i) { return 0 < i-- && (node.test(template[i]) || !notNode.test(template[i]) && isNode(template, i)); }; var regular = function regular(original, name, extra) { return empty.test(name) ? original : "<".concat(name).concat(extra.replace(trimEnd, ''), ">").concat(name, ">"); }; var instrument = (function (template, prefix, svg) { var text = []; var length = template.length; var _loop = function _loop(i) { var chunk = template[i - 1]; text.push(attr.test(chunk) && isNode(template, i) ? chunk.replace(attr, function (_, $1, $2) { return "".concat(prefix).concat(i - 1, "=").concat($2 || '"').concat($1).concat($2 ? '' : '"'); }) : "".concat(chunk, "")); }; for (var i = 1; i < length; i++) { _loop(i); } text.push(template[length - 1]); var output = text.join('').trim(); return svg ? output : output.replace(selfClosing, regular); }); var isArray = Array.isArray; var _ref = [], indexOf = _ref.indexOf, slice = _ref.slice; var ELEMENT_NODE = 1; var nodeType = 111; var remove = function remove(_ref) { var firstChild = _ref.firstChild, lastChild = _ref.lastChild; var range = document.createRange(); range.setStartAfter(firstChild); range.setEndAfter(lastChild); range.deleteContents(); return firstChild; }; var diffable = function diffable(node, operation) { return node.nodeType === nodeType ? 1 / operation < 0 ? operation ? remove(node) : node.lastChild : operation ? node.valueOf() : node.firstChild : node; }; var persistent = function persistent(fragment) { var childNodes = fragment.childNodes; var length = childNodes.length; if (length < 2) return length ? childNodes[0] : fragment; var nodes = slice.call(childNodes, 0); var firstChild = nodes[0]; var lastChild = nodes[length - 1]; return { ELEMENT_NODE: ELEMENT_NODE, nodeType: nodeType, firstChild: firstChild, lastChild: lastChild, valueOf: function valueOf() { if (childNodes.length !== length) { var i = 0; while (i < length) { fragment.appendChild(nodes[i++]); } } return fragment; } }; }; /** * ISC License * * Copyright (c) 2020, Andrea Giammarchi, @WebReflection * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /** * @param {Node} parentNode The container where children live * @param {Node[]} a The list of current/live children * @param {Node[]} b The list of future children * @param {(entry: Node, action: number) => Node} get * The callback invoked per each entry related DOM operation. * @param {Node} [before] The optional node used as anchor to insert before. * @returns {Node[]} The same list of future children. */ var udomdiff = (function (parentNode, a, b, get, before) { var bLength = b.length; var aEnd = a.length; var bEnd = bLength; var aStart = 0; var bStart = 0; var map = null; while (aStart < aEnd || bStart < bEnd) { // append head, tail, or nodes in between: fast path if (aEnd === aStart) { // we could be in a situation where the rest of nodes that // need to be added are not at the end, and in such case // the node to `insertBefore`, if the index is more than 0 // must be retrieved, otherwise it's gonna be the first item. var node = bEnd < bLength ? bStart ? get(b[bStart - 1], -0).nextSibling : get(b[bEnd - bStart], 0) : before; while (bStart < bEnd) { parentNode.insertBefore(get(b[bStart++], 1), node); } } // remove head or tail: fast path else if (bEnd === bStart) { while (aStart < aEnd) { // remove the node only if it's unknown or not live if (!map || !map.has(a[aStart])) parentNode.removeChild(get(a[aStart], -1)); aStart++; } } // same node: fast path else if (a[aStart] === b[bStart]) { aStart++; bStart++; } // same tail: fast path else if (a[aEnd - 1] === b[bEnd - 1]) { aEnd--; bEnd--; } // The once here single last swap "fast path" has been removed in v1.1.0 // https://github.com/WebReflection/udomdiff/blob/single-final-swap/esm/index.js#L69-L85 // reverse swap: also fast path else if (a[aStart] === b[bEnd - 1] && b[bStart] === a[aEnd - 1]) { // this is a "shrink" operation that could happen in these cases: // [1, 2, 3, 4, 5] // [1, 4, 3, 2, 5] // or asymmetric too // [1, 2, 3, 4, 5] // [1, 2, 3, 5, 6, 4] var _node = get(a[--aEnd], -1).nextSibling; parentNode.insertBefore(get(b[bStart++], 1), get(a[aStart++], -1).nextSibling); parentNode.insertBefore(get(b[--bEnd], 1), _node); // mark the future index as identical (yeah, it's dirty, but cheap 👍) // The main reason to do this, is that when a[aEnd] will be reached, // the loop will likely be on the fast path, as identical to b[bEnd]. // In the best case scenario, the next loop will skip the tail, // but in the worst one, this node will be considered as already // processed, bailing out pretty quickly from the map index check a[aEnd] = b[bEnd]; } // map based fallback, "slow" path else { // the map requires an O(bEnd - bStart) operation once // to store all future nodes indexes for later purposes. // In the worst case scenario, this is a full O(N) cost, // and such scenario happens at least when all nodes are different, // but also if both first and last items of the lists are different if (!map) { map = new Map(); var i = bStart; while (i < bEnd) { map.set(b[i], i++); } } // if it's a future node, hence it needs some handling if (map.has(a[aStart])) { // grab the index of such node, 'cause it might have been processed var index = map.get(a[aStart]); // if it's not already processed, look on demand for the next LCS if (bStart < index && index < bEnd) { var _i = aStart; // counts the amount of nodes that are the same in the future var sequence = 1; while (++_i < aEnd && _i < bEnd && map.get(a[_i]) === index + sequence) { sequence++; } // effort decision here: if the sequence is longer than replaces // needed to reach such sequence, which would brings again this loop // to the fast path, prepend the difference before a sequence, // and move only the future list index forward, so that aStart // and bStart will be aligned again, hence on the fast path. // An example considering aStart and bStart are both 0: // a: [1, 2, 3, 4] // b: [7, 1, 2, 3, 6] // this would place 7 before 1 and, from that time on, 1, 2, and 3 // will be processed at zero cost if (sequence > index - bStart) { var _node2 = get(a[aStart], 0); while (bStart < index) { parentNode.insertBefore(get(b[bStart++], 1), _node2); } } // if the effort wasn't good enough, fallback to a replace, // moving both source and target indexes forward, hoping that some // similar node will be found later on, to go back to the fast path else { parentNode.replaceChild(get(b[bStart++], 1), get(a[aStart++], -1)); } } // otherwise move the source forward, 'cause there's nothing to do else aStart++; } // this node has no meaning in the future list, so it's more than safe // to remove it, and check the next live node out instead, meaning // that only the live list index should be forwarded else parentNode.removeChild(get(a[aStart++], -1)); } } return b; }); var aria = function aria(node) { return function (values) { for (var key in values) { var name = key === 'role' ? key : "aria-".concat(key); var value = values[key]; if (value == null) node.removeAttribute(name);else node.setAttribute(name, value); } }; }; var attribute = function attribute(node, name) { var oldValue, orphan = true; var attributeNode = document.createAttributeNS(null, name); return function (newValue) { if (oldValue !== newValue) { oldValue = newValue; if (oldValue == null) { if (!orphan) { node.removeAttributeNode(attributeNode); orphan = true; } } else { attributeNode.value = newValue; if (orphan) { node.setAttributeNodeNS(attributeNode); orphan = false; } } } }; }; var _boolean = function _boolean(node, key, oldValue) { return function (newValue) { if (oldValue !== !!newValue) { // when IE won't be around anymore ... // node.toggleAttribute(key, oldValue = !!newValue); if (oldValue = !!newValue) node.setAttribute(key, '');else node.removeAttribute(key); } }; }; var data = function data(_ref) { var dataset = _ref.dataset; return function (values) { for (var key in values) { var value = values[key]; if (value == null) delete dataset[key];else dataset[key] = value; } }; }; var event = function event(node, name) { var oldValue, type = name.slice(2); if (!(name in node) && name.toLowerCase() in node) type = type.toLowerCase(); return function (newValue) { var info = isArray(newValue) ? newValue : [newValue, false]; if (oldValue !== info[0]) { if (oldValue) node.removeEventListener(type, oldValue, info[1]); if (oldValue = info[0]) node.addEventListener(type, oldValue, info[1]); } }; }; var ref = function ref(node) { var oldValue; return function (value) { if (oldValue !== value) { oldValue = value; if (typeof value === 'function') value(node);else value.current = node; } }; }; var setter = function setter(node, key) { return key === 'dataset' ? data(node) : function (value) { node[key] = value; }; }; var text = function text(node) { var oldValue; return function (newValue) { if (oldValue != newValue) { oldValue = newValue; node.textContent = newValue == null ? '' : newValue; } }; }; /*! (c) Andrea Giammarchi - ISC */ var createContent = function (document) { var FRAGMENT = 'fragment'; var TEMPLATE = 'template'; var HAS_CONTENT = ('content' in create(TEMPLATE)); var createHTML = HAS_CONTENT ? function (html) { var template = create(TEMPLATE); template.innerHTML = html; return template.content; } : function (html) { var content = create(FRAGMENT); var template = create(TEMPLATE); var childNodes = null; if (/^[^\S]*?<(col(?:group)?|t(?:head|body|foot|r|d|h))/i.test(html)) { var selector = RegExp.$1; template.innerHTML = '
${data}
` var mapTemplate = function mapTemplate(type, template) { var text = instrument(template, prefix, type === 'svg'); var content = createFragment(text, type); // once instrumented and reproduced as fragment, it's crawled // to find out where each update is in the fragment tree var tw = createWalker(content); var nodes = []; var length = template.length - 1; var i = 0; // updates are searched via unique names, linearly increased across the tree // var search = "".concat(prefix).concat(i); while (i < length) { var node = tw.nextNode(); // if not all updates are bound but there's nothing else to crawl // it means that there is something wrong with the template. if (!node) throw "bad template: ".concat(text); // if the current node is a comment, and it contains isµX // it means the update should take care of any content if (node.nodeType === 8) { // The only comments to be considered are those // which content is exactly the same as the searched one. if (node.data === search) { nodes.push({ type: 'node', path: createPath(node) }); search = "".concat(prefix).concat(++i); } } else { // if the node is not a comment, loop through all its attributes // named isµX and relate attribute updates to this node and the // attribute name, retrieved through node.getAttribute("isµX") // the isµX attribute will be removed as irrelevant for the layout // let svg = -1; while (node.hasAttribute(search)) { nodes.push({ type: 'attr', path: createPath(node), name: node.getAttribute(search) //svg: svg < 0 ? (svg = ('ownerSVGElement' in node ? 1 : 0)) : svg }); node.removeAttribute(search); search = "".concat(prefix).concat(++i); } // if the node was a style, textarea, or others, check its content // and if it is then update tex-only this node if (textOnly.test(node.tagName) && node.textContent.trim() === "")) { node.textContent = ''; nodes.push({ type: 'text', path: createPath(node) }); search = "".concat(prefix).concat(++i); } } } // once all nodes to update, or their attributes, are known, the content // will be cloned in the future to represent the template, and all updates // related to such content retrieved right away without needing to re-crawl // the exact same template, and its content, more than once. return { content: content, nodes: nodes }; }; // if a template is unknown, perform the previous mapping, otherwise grab // its details such as the fragment with all nodes, and updates info. var mapUpdates = function mapUpdates(type, template) { var _ref = cache$2.get(template) || cache$2.set(template, mapTemplate(type, template)), content = _ref.content, nodes = _ref.nodes; // clone deeply the fragment var fragment = importNode.call(document, content, true); // and relate an update handler per each node that needs one var updates = nodes.map(handlers, fragment); // return the fragment and all updates to use within its nodes return { content: fragment, updates: updates }; }; // as html and svg can be nested calls, but no parent node is known // until rendered somewhere, the unroll operation is needed to // discover what to do with each interpolation, which will result // into an update operation. var unroll = function unroll(info, _ref2) { var type = _ref2.type, template = _ref2.template, values = _ref2.values; var length = values.length; // interpolations can contain holes and arrays, so these need // to be recursively discovered unrollValues(info, values, length); var entry = info.entry; // if the cache entry is either null or different from the template // and the type this unroll should resolve, create a new entry // assigning a new content fragment and the list of updates. if (!entry || entry.template !== template || entry.type !== type) info.entry = entry = createEntry(type, template); var _entry = entry, content = _entry.content, updates = _entry.updates, wire = _entry.wire; // even if the fragment and its nodes is not live yet, // it is already possible to update via interpolations values. for (var i = 0; i < length; i++) { updates[i](values[i]); } // if the entry was new, or representing a different template or type, // create a new persistent entity to use during diffing. // This is simply a DOM node, when the template has a single container, // as in ``, or a "wire" in `` and similar cases. return wire || (entry.wire = persistent(content)); }; // the stack retains, per each interpolation value, the cache // related to each interpolation value, or null, if the render // was conditional and the value is not special (Array or Hole) var unrollValues = function unrollValues(_ref3, values, length) { var stack = _ref3.stack; for (var i = 0; i < length; i++) { var hole = values[i]; // each Hole gets unrolled and re-assigned as value // so that domdiff will deal with a node/wire, not with a hole if (hole instanceof Hole) values[i] = unroll(stack[i] || (stack[i] = createCache()), hole); // arrays are recursively resolved so that each entry will contain // also a DOM node or a wire, hence it can be diffed if/when needed else if (isArray(hole)) unrollValues(stack[i] || (stack[i] = createCache()), hole, hole.length); // if the value is nothing special, the stack doesn't need to retain data // this is useful also to cleanup previously retained data, if the value // was a Hole, or an Array, but not anymore, i.e.: // const update = content => html`