text: (function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@webbitjs/store')) :
    typeof define === 'function' && define.amd ? define(['exports', '@webbitjs/store'], factory) :
    (global = global || self, factory(global.webbit = {}, global.webbitStore));
  }(this, (function (exports, store) { 'use strict';
  
    function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
      try {
        var info = gen[key](arg);
        var value = info.value;
      } catch (error) {
        reject(error);
        return;
      }
  
      if (info.done) {
        resolve(value);
      } else {
        Promise.resolve(value).then(_next, _throw);
      }
    }
  
    function _asyncToGenerator(fn) {
      return function () {
        var self = this,
            args = arguments;
        return new Promise(function (resolve, reject) {
          var gen = fn.apply(self, args);
  
          function _next(value) {
            asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
          }
  
          function _throw(err) {
            asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
          }
  
          _next(undefined);
        });
      };
    }
  
    function _defineProperty(obj, key, value) {
      if (key in obj) {
        Object.defineProperty(obj, key, {
          value: value,
          enumerable: true,
          configurable: true,
          writable: true
        });
      } else {
        obj[key] = value;
      }
  
      return obj;
    }
  
    function ownKeys(object, enumerableOnly) {
      var keys = Object.keys(object);
  
      if (Object.getOwnPropertySymbols) {
        var symbols = Object.getOwnPropertySymbols(object);
        if (enumerableOnly) symbols = symbols.filter(function (sym) {
          return Object.getOwnPropertyDescriptor(object, sym).enumerable;
        });
        keys.push.apply(keys, symbols);
      }
  
      return keys;
    }
  
    function _objectSpread2(target) {
      for (var i = 1; i < arguments.length; i++) {
        var source = arguments[i] != null ? arguments[i] : {};
  
        if (i % 2) {
          ownKeys(Object(source), true).forEach(function (key) {
            _defineProperty(target, key, source[key]);
          });
        } else if (Object.getOwnPropertyDescriptors) {
          Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
        } else {
          ownKeys(Object(source)).forEach(function (key) {
            Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
          });
        }
      }
  
      return target;
    }
  
    /**
     * Turns a camelCase string to kebab-case
     * 
     * https://gist.github.com/nblackburn/875e6ff75bc8ce171c758bf75f304707#gistcomment-2993938
     *
     * @param {string} string 
     */
    var camelToKebab = string => {
      return string.replace(/([a-z0-9])([A-Z])/g, '$1-$2').replace(/([A-Z])([A-Z])(?=[a-z])/g, '$1-$2').toLowerCase();
    };
  
    var registered = {};
    var webbits = {};
    var createdListeners = [];
    var anyDefinedListeners = [];
    var _isCloning = false;
  
    function isInstanceOfWebbit(constructor) {
      if (!(constructor instanceof Object)) {
        return false;
      }
  
      return constructor.__WEBBIT_CLASSNAME__ === 'Webbit';
    }
  
    var registry = {
      define: (name, constructor, options) => {
        if (customElements.get(name)) {
          return;
        }
  
        if (!isInstanceOfWebbit(constructor)) {
          return;
        }
  
        var webbitProperties = constructor.properties || {};
  
        for (var propName in webbitProperties) {
          var prop = webbitProperties[propName];
  
          if (typeof prop.reflect === 'undefined') {
            prop.reflect = true;
          }
  
          if (typeof prop.attribute === 'undefined') {
            prop.attribute = camelToKebab(propName);
          }
  
          prop.canConnectToSources = !!(prop.reflect && prop.attribute);
  
          if (typeof prop.category === 'undefined') {
            var metadata = constructor.metadata || {};
            prop.category = metadata.displayName || name;
          }
  
          if (typeof prop.inputType === 'undefined') {
            prop.inputType = prop.type.name;
          }
        }
  
        Object.defineProperty(constructor, 'properties', {
          get() {
            return _objectSpread2({}, webbitProperties, {
              sourceProvider: {
                type: String,
                attribute: 'source-provider',
                reflect: true
              },
              sourceKey: {
                type: String,
                attribute: 'source-key',
                reflect: true
              },
              fromProperties: {
                type: Array,
                attribute: 'from-properties',
                reflect: true
              },
              webbitId: {
                type: String,
                attribute: 'webbit-id',
                reflect: true
              }
            });
          }
  
        });
        registered[name] = constructor;
        customElements.define(name, constructor, options);
        anyDefinedListeners.forEach(callback => {
          callback(name, constructor);
        });
      },
      whenDefined: name => {
        return new Promise(resolve => {
          customElements.whenDefined(name).then(() => {
            if (name in registered) {
              resolve();
            }
          });
        });
      },
      whenAnyDefined: listener => {
        if (typeof listener === 'function') {
          anyDefinedListeners.push(listener);
        }
      },
      get: name => {
        return registered[name];
      },
      getRegisteredNames: () => {
        return Object.keys(registered);
      },
      getMetadata: name => {
        var component = registered[name];
  
        if (!component) {
          return null;
        }
  
        return _objectSpread2({
          displayName: name,
          category: 'Uncategorized',
          description: 'Just another web component.',
          documentationLink: null,
          slots: ['default'],
          resizable: {
            left: true,
            right: true,
            bottom: true,
            top: true
          },
          minSize: {
            width: 20,
            height: 20
          },
          movable: true,
          layout: 'absolute',
          dashboardHtml: false
        }, component.metadata);
      },
      _generateWebbitId: (webbit, desiredId) => {
        var baseName = desiredId ? desiredId : webbit.nodeName.toLowerCase();
  
        if (typeof webbits[baseName] === 'undefined') {
          return baseName;
        }
  
        var webbitCount = Object.keys(webbits).length;
  
        for (var i = 0; i < webbitCount; i++) {
          var id = "".concat(baseName, " #").concat(i + 2);
  
          if (typeof webbits[id] === 'undefined') {
            return id;
          }
        }
  
        return null;
      },
      _changedWebbitId: (oldWebbitId, newWebbitId, webbit) => {
        if (typeof webbits[oldWebbitId] === 'undefined') {
          throw new Error("Webbit with ID '".concat(oldWebbitId, "' doesn't exist."));
        }
  
        if (typeof newWebbitId !== 'string' || newWebbitId.length === 0) {
          throw new Error("Webbit ID '".concat(newWebbitId, "' is not a string of length 1 or more characters"));
        }
  
        if (newWebbitId in webbits) {
          throw new Error("Webbit with ID '".concat(newWebbitId, "' has already been created."));
        }
  
        webbits[newWebbitId] = webbit;
        delete webbits[oldWebbitId];
      },
      _created: (webbitId, webbit) => {
        if (typeof webbitId !== 'string' || webbitId.length === 0) {
          throw new Error("Webbit ID '".concat(webbitId, "' is not a string of length 1 or more characters"));
        }
  
        if (webbitId in webbits) {
          throw new Error("Webbit with ID '".concat(webbitId, "' has already been created."));
        }
  
        webbits[webbitId] = webbit;
        createdListeners.forEach(callback => {
          callback(webbitId, webbit);
        });
      },
      getWebbit: webbitId => {
        return webbits[webbitId];
      },
      hasWebbit: webbitId => {
        return webbitId in webbits;
      },
      getWebbitIds: () => {
        return Object.keys(webbits);
      },
      whenCreated: listener => {
        if (typeof listener === 'function') {
          createdListeners.push(listener);
        }
      },
      setCloning: cloning => {
        _isCloning = cloning;
      },
      isCloning: () => {
        return _isCloning;
      }
    };
    window.webbitRegistry = window.webbitRegistry || registry;
  
    /**
     * @license
     * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
     * This code may only be used under the BSD style license found at
     * http://polymer.github.io/LICENSE.txt
     * The complete set of authors may be found at
     * http://polymer.github.io/AUTHORS.txt
     * The complete set of contributors may be found at
     * http://polymer.github.io/CONTRIBUTORS.txt
     * Code distributed by Google as part of the polymer project is also
     * subject to an additional IP rights grant found at
     * http://polymer.github.io/PATENTS.txt
     */
    var directives = new WeakMap();
    var isDirective = o => {
      return typeof o === 'function' && directives.has(o);
    };
  
    /**
     * @license
     * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
     * This code may only be used under the BSD style license found at
     * http://polymer.github.io/LICENSE.txt
     * The complete set of authors may be found at
     * http://polymer.github.io/AUTHORS.txt
     * The complete set of contributors may be found at
     * http://polymer.github.io/CONTRIBUTORS.txt
     * Code distributed by Google as part of the polymer project is also
     * subject to an additional IP rights grant found at
     * http://polymer.github.io/PATENTS.txt
     */
  
    /**
     * True if the custom elements polyfill is in use.
     */
    var isCEPolyfill = window.customElements !== undefined && window.customElements.polyfillWrapFlushCallback !== undefined;
    /**
     * Reparents nodes, starting from `start` (inclusive) to `end` (exclusive),
     * into another container (could be the same container), before `before`. If
     * `before` is null, it appends the nodes to the container.
     */
  
    var reparentNodes = function reparentNodes(container, start) {
      var end = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var before = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
  
      while (start !== end) {
        var n = start.nextSibling;
        container.insertBefore(start, before);
        start = n;
      }
    };
    /**
     * Removes nodes, starting from `start` (inclusive) to `end` (exclusive), from
     * `container`.
     */
  
    var removeNodes = function removeNodes(container, start) {
      var end = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
  
      while (start !== end) {
        var n = start.nextSibling;
        container.removeChild(start);
        start = n;
      }
    };
  
    /**
     * @license
     * Copyright (c) 2018 The Polymer Project Authors. All rights reserved.
     * This code may only be used under the BSD style license found at
     * http://polymer.github.io/LICENSE.txt
     * The complete set of authors may be found at
     * http://polymer.github.io/AUTHORS.txt
     * The complete set of contributors may be found at
     * http://polymer.github.io/CONTRIBUTORS.txt
     * Code distributed by Google as part of the polymer project is also
     * subject to an additional IP rights grant found at
     * http://polymer.github.io/PATENTS.txt
     */
  
    /**
     * A sentinel value that signals that a value was handled by a directive and
     * should not be written to the DOM.
     */
    var noChange = {};
    /**
     * A sentinel value that signals a NodePart to fully clear its content.
     */
  
    var nothing = {};
  
    /**
     * @license
     * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
     * This code may only be used under the BSD style license found at
     * http://polymer.github.io/LICENSE.txt
     * The complete set of authors may be found at
     * http://polymer.github.io/AUTHORS.txt
     * The complete set of contributors may be found at
     * http://polymer.github.io/CONTRIBUTORS.txt
     * Code distributed by Google as part of the polymer project is also
     * subject to an additional IP rights grant found at
     * http://polymer.github.io/PATENTS.txt
     */
  
    /**
     * An expression marker with embedded unique key to avoid collision with
     * possible text in templates.
     */
    var marker = "{{lit-".concat(String(Math.random()).slice(2), "}}");
    /**
     * An expression marker used text-positions, multi-binding attributes, and
     * attributes with markup-like text values.
     */
  
    var nodeMarker = "<!--".concat(marker, "-->");
    var markerRegex = new RegExp("".concat(marker, "|").concat(nodeMarker));
    /**
     * Suffix appended to all bound attribute names.
     */
  
    var boundAttributeSuffix = '$lit$';
    /**
     * An updateable Template that tracks the location of dynamic parts.
     */
  
    class Template {
      constructor(result, element) {
        this.parts = [];
        this.element = element;
        var nodesToRemove = [];
        var stack = []; // Edge needs all 4 parameters present; IE11 needs 3rd parameter to be null
  
        var walker = document.createTreeWalker(element.content, 133
        /* NodeFilter.SHOW_{ELEMENT|COMMENT|TEXT} */
        , null, false); // Keeps track of the last index associated with a part. We try to delete
        // unnecessary nodes, but we never want to associate two different parts
        // to the same index. They must have a constant node between.
  
        var lastPartIndex = 0;
        var index = -1;
        var partIndex = 0;
        var {
          strings,
          values: {
            length
          }
        } = result;
  
        while (partIndex < length) {
          var node = walker.nextNode();
  
          if (node === null) {
            // We've exhausted the content inside a nested template element.
            // Because we still have parts (the outer for-loop), we know:
            // - There is a template in the stack
            // - The walker will find a nextNode outside the template
            walker.currentNode = stack.pop();
            continue;
          }
  
          index++;
  
          if (node.nodeType === 1
          /* Node.ELEMENT_NODE */
          ) {
              if (node.hasAttributes()) {
                var attributes = node.attributes;
                var {
                  length: _length
                } = attributes; // Per
                // https://developer.mozilla.org/en-US/docs/Web/API/NamedNodeMap,
                // attributes are not guaranteed to be returned in document order.
                // In particular, Edge/IE can return them out of order, so we cannot
                // assume a correspondence between part index and attribute index.
  
                var count = 0;
  
                for (var i = 0; i < _length; i++) {
                  if (endsWith(attributes[i].name, boundAttributeSuffix)) {
                    count++;
                  }
                }
  
                while (count-- > 0) {
                  // Get the template literal section leading up to the first
                  // expression in this attribute
                  var stringForPart = strings[partIndex]; // Find the attribute name
  
                  var name = lastAttributeNameRegex.exec(stringForPart)[2]; // Find the corresponding attribute
                  // All bound attributes have had a suffix added in
                  // TemplateResult#getHTML to opt out of special attribute
                  // handling. To look up the attribute value we also need to add
                  // the suffix.
  
                  var attributeLookupName = name.toLowerCase() + boundAttributeSuffix;
                  var attributeValue = node.getAttribute(attributeLookupName);
                  node.removeAttribute(attributeLookupName);
                  var statics = attributeValue.split(markerRegex);
                  this.parts.push({
                    type: 'attribute',
                    index,
                    name,
                    strings: statics
                  });
                  partIndex += statics.length - 1;
                }
              }
  
              if (node.tagName === 'TEMPLATE') {
                stack.push(node);
                walker.currentNode = node.content;
              }
            } else if (node.nodeType === 3
          /* Node.TEXT_NODE */
          ) {
              var data = node.data;
  
              if (data.indexOf(marker) >= 0) {
                var parent = node.parentNode;
  
                var _strings = data.split(markerRegex);
  
                var lastIndex = _strings.length - 1; // Generate a new text node for each literal section
                // These nodes are also used as the markers for node parts
  
                for (var _i = 0; _i < lastIndex; _i++) {
                  var insert = void 0;
                  var s = _strings[_i];
  
                  if (s === '') {
                    insert = createMarker();
                  } else {
                    var match = lastAttributeNameRegex.exec(s);
  
                    if (match !== null && endsWith(match[2], boundAttributeSuffix)) {
                      s = s.slice(0, match.index) + match[1] + match[2].slice(0, -boundAttributeSuffix.length) + match[3];
                    }
  
                    insert = document.createTextNode(s);
                  }
  
                  parent.insertBefore(insert, node);
                  this.parts.push({
                    type: 'node',
                    index: ++index
                  });
                } // If there's no text, we must insert a comment to mark our place.
                // Else, we can trust it will stick around after cloning.
  
  
                if (_strings[lastIndex] === '') {
                  parent.insertBefore(createMarker(), node);
                  nodesToRemove.push(node);
                } else {
                  node.data = _strings[lastIndex];
                } // We have a part for each match found
  
  
                partIndex += lastIndex;
              }
            } else if (node.nodeType === 8
          /* Node.COMMENT_NODE */
          ) {
              if (node.data === marker) {
                var _parent = node.parentNode; // Add a new marker node to be the startNode of the Part if any of
                // the following are true:
                //  * We don't have a previousSibling
                //  * The previousSibling is already the start of a previous part
  
                if (node.previousSibling === null || index === lastPartIndex) {
                  index++;
  
                  _parent.insertBefore(createMarker(), node);
                }
  
                lastPartIndex = index;
                this.parts.push({
                  type: 'node',
                  index
                }); // If we don't have a nextSibling, keep this node so we have an end.
                // Else, we can remove it to save future costs.
  
                if (node.nextSibling === null) {
                  node.data = '';
                } else {
                  nodesToRemove.push(node);
                  index--;
                }
  
                partIndex++;
              } else {
                var _i2 = -1;
  
                while ((_i2 = node.data.indexOf(marker, _i2 + 1)) !== -1) {
                  // Comment node has a binding marker inside, make an inactive part
                  // The binding won't work, but subsequent bindings will
                  // TODO (justinfagnani): consider whether it's even worth it to
                  // make bindings in comments work
                  this.parts.push({
                    type: 'node',
                    index: -1
                  });
                  partIndex++;
                }
              }
            }
        } // Remove text binding nodes after the walk to not disturb the TreeWalker
  
  
        for (var n of nodesToRemove) {
          n.parentNode.removeChild(n);
        }
      }
  
    }
  
    var endsWith = (str, suffix) => {
      var index = str.length - suffix.length;
      return index >= 0 && str.slice(index) === suffix;
    };
  
    var isTemplatePartActive = part => part.index !== -1; // Allows `document.createComment('')` to be renamed for a
    // small manual size-savings.
  
    var createMarker = () => document.createComment('');
    /**
     * This regex extracts the attribute name preceding an attribute-position
     * expression. It does this by matching the syntax allowed for attributes
     * against the string literal directly preceding the expression, assuming that
     * the expression is in an attribute-value position.
     *
     * See attributes in the HTML spec:
     * https://www.w3.org/TR/html5/syntax.html#elements-attributes
     *
     * " \x09\x0a\x0c\x0d" are HTML space characters:
     * https://www.w3.org/TR/html5/infrastructure.html#space-characters
     *
     * "\0-\x1F\x7F-\x9F" are Unicode control characters, which includes every
     * space character except " ".
     *
     * So an attribute is:
     *  * The name: any character except a control character, space character, ('),
     *    ("), ">", "=", or "/"
     *  * Followed by zero or more space characters
     *  * Followed by "="
     *  * Followed by zero or more space characters
     *  * Followed by:
     *    * Any character except space, ('), ("), "<", ">", "=", (`), or
     *    * (") then any non-("), or
     *    * (') then any non-(')
     */
  
    var lastAttributeNameRegex = /([ \x09\x0a\x0c\x0d])([^\0-\x1F\x7F-\x9F "'>=/]+)([ \x09\x0a\x0c\x0d]*=[ \x09\x0a\x0c\x0d]*(?:[^ \x09\x0a\x0c\x0d"'`<>=]*|"[^"]*|'[^']*))$/;
  
    /**
     * @license
     * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
     * This code may only be used under the BSD style license found at
     * http://polymer.github.io/LICENSE.txt
     * The complete set of authors may be found at
     * http://polymer.github.io/AUTHORS.txt
     * The complete set of contributors may be found at
     * http://polymer.github.io/CONTRIBUTORS.txt
     * Code distributed by Google as part of the polymer project is also
     * subject to an additional IP rights grant found at
     * http://polymer.github.io/PATENTS.txt
     */
    /**
     * An instance of a `Template` that can be attached to the DOM and updated
     * with new values.
     */
  
    class TemplateInstance {
      constructor(template, processor, options) {
        this.__parts = [];
        this.template = template;
        this.processor = processor;
        this.options = options;
      }
  
      update(values) {
        var i = 0;
  
        for (var part of this.__parts) {
          if (part !== undefined) {
            part.setValue(values[i]);
          }
  
          i++;
        }
  
        for (var _part of this.__parts) {
          if (_part !== undefined) {
            _part.commit();
          }
        }
      }
  
      _clone() {
        // There are a number of steps in the lifecycle of a template instance's
        // DOM fragment:
        //  1. Clone - create the instance fragment
        //  2. Adopt - adopt into the main document
        //  3. Process - find part markers and create parts
        //  4. Upgrade - upgrade custom elements
        //  5. Update - set node, attribute, property, etc., values
        //  6. Connect - connect to the document. Optional and outside of this
        //     method.
        //
        // We have a few constraints on the ordering of these steps:
        //  * We need to upgrade before updating, so that property values will pass
        //    through any property setters.
        //  * We would like to process before upgrading so that we're sure that the
        //    cloned fragment is inert and not disturbed by self-modifying DOM.
        //  * We want custom elements to upgrade even in disconnected fragments.
        //
        // Given these constraints, with full custom elements support we would
        // prefer the order: Clone, Process, Adopt, Upgrade, Update, Connect
        //
        // But Safari dooes not implement CustomElementRegistry#upgrade, so we
        // can not implement that order and still have upgrade-before-update and
        // upgrade disconnected fragments. So we instead sacrifice the
        // process-before-upgrade constraint, since in Custom Elements v1 elements
        // must not modify their light DOM in the constructor. We still have issues
        // when co-existing with CEv0 elements like Polymer 1, and with polyfills
        // that don't strictly adhere to the no-modification rule because shadow
        // DOM, which may be created in the constructor, is emulated by being placed
        // in the light DOM.
        //
        // The resulting order is on native is: Clone, Adopt, Upgrade, Process,
        // Update, Connect. document.importNode() performs Clone, Adopt, and Upgrade
        // in one step.
        //
        // The Custom Elements v1 polyfill supports upgrade(), so the order when
        // polyfilled is the more ideal: Clone, Process, Adopt, Upgrade, Update,
        // Connect.
        var fragment = isCEPolyfill ? this.template.element.content.cloneNode(true) : document.importNode(this.template.element.content, true);
        var stack = [];
        var parts = this.template.parts; // Edge needs all 4 parameters present; IE11 needs 3rd parameter to be null
  
        var walker = document.createTreeWalker(fragment, 133
        /* NodeFilter.SHOW_{ELEMENT|COMMENT|TEXT} */
        , null, false);
        var partIndex = 0;
        var nodeIndex = 0;
        var part;
        var node = walker.nextNode(); // Loop through all the nodes and parts of a template
  
        while (partIndex < parts.length) {
          part = parts[partIndex];
  
          if (!isTemplatePartActive(part)) {
            this.__parts.push(undefined);
  
            partIndex++;
            continue;
          } // Progress the tree walker until we find our next part's node.
          // Note that multiple parts may share the same node (attribute parts
          // on a single element), so this loop may not run at all.
  
  
          while (nodeIndex < part.index) {
            nodeIndex++;
  
            if (node.nodeName === 'TEMPLATE') {
              stack.push(node);
              walker.currentNode = node.content;
            }
  
            if ((node = walker.nextNode()) === null) {
              // We've exhausted the content inside a nested template element.
              // Because we still have parts (the outer for-loop), we know:
              // - There is a template in the stack
              // - The walker will find a nextNode outside the template
              walker.currentNode = stack.pop();
              node = walker.nextNode();
            }
          } // We've arrived at our part's node.
  
  
          if (part.type === 'node') {
            var _part2 = this.processor.handleTextExpression(this.options);
  
            _part2.insertAfterNode(node.previousSibling);
  
            this.__parts.push(_part2);
          } else {
            this.__parts.push(...this.processor.handleAttributeExpressions(node, part.name, part.strings, this.options));
          }
  
          partIndex++;
        }
  
        if (isCEPolyfill) {
          document.adoptNode(fragment);
          customElements.upgrade(fragment);
        }
  
        return fragment;
      }
  
    }
  
    /**
     * @license
     * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
     * This code may only be used under the BSD style license found at
     * http://polymer.github.io/LICENSE.txt
     * The complete set of authors may be found at
     * http://polymer.github.io/AUTHORS.txt
     * The complete set of contributors may be found at
     * http://polymer.github.io/CONTRIBUTORS.txt
     * Code distributed by Google as part of the polymer project is also
     * subject to an additional IP rights grant found at
     * http://polymer.github.io/PATENTS.txt
     */
    var commentMarker = " ".concat(marker, " ");
    /**
     * The return type of `html`, which holds a Template and the values from
     * interpolated expressions.
     */
  
    class TemplateResult {
      constructor(strings, values, type, processor) {
        this.strings = strings;
        this.values = values;
        this.type = type;
        this.processor = processor;
      }
      /**
       * Returns a string of HTML used to create a `<template>` element.
       */
  
  
      getHTML() {
        var l = this.strings.length - 1;
        var html = '';
        var isCommentBinding = false;
  
        for (var i = 0; i < l; i++) {
          var s = this.strings[i]; // For each binding we want to determine the kind of marker to insert
          // into the template source before it's parsed by the browser's HTML
          // parser. The marker type is based on whether the expression is in an
          // attribute, text, or comment poisition.
          //   * For node-position bindings we insert a comment with the marker
          //     sentinel as its text content, like <!--{{lit-guid}}-->.
          //   * For attribute bindings we insert just the marker sentinel for the
          //     first binding, so that we support unquoted attribute bindings.
          //     Subsequent bindings can use a comment marker because multi-binding
          //     attributes must be quoted.
          //   * For comment bindings we insert just the marker sentinel so we don't
          //     close the comment.
          //
          // The following code scans the template source, but is *not* an HTML
          // parser. We don't need to track the tree structure of the HTML, only
          // whether a binding is inside a comment, and if not, if it appears to be
          // the first binding in an attribute.
  
          var commentOpen = s.lastIndexOf('<!--'); // We're in comment position if we have a comment open with no following
          // comment close. Because <-- can appear in an attribute value there can
          // be false positives.
  
          isCommentBinding = (commentOpen > -1 || isCommentBinding) && s.indexOf('-->', commentOpen + 1) === -1; // Check to see if we have an attribute-like sequence preceeding the
          // expression. This can match "name=value" like structures in text,
          // comments, and attribute values, so there can be false-positives.
  
          var attributeMatch = lastAttributeNameRegex.exec(s);
  
          if (attributeMatch === null) {
            // We're only in this branch if we don't have a attribute-like
            // preceeding sequence. For comments, this guards against unusual
            // attribute values like <div foo="<!--${'bar'}">. Cases like
            // <!-- foo=${'bar'}--> are handled correctly in the attribute branch
            // below.
            html += s + (isCommentBinding ? commentMarker : nodeMarker);
          } else {
            // For attributes we use just a marker sentinel, and also append a
            // $lit$ suffix to the name to opt-out of attribute-specific parsing
            // that IE and Edge do for style and certain SVG attributes.
            html += s.substr(0, attributeMatch.index) + attributeMatch[1] + attributeMatch[2] + boundAttributeSuffix + attributeMatch[3] + marker;
          }
        }
  
        html += this.strings[l];
        return html;
      }
  
      getTemplateElement() {
        var template = document.createElement('template');
        template.innerHTML = this.getHTML();
        return template;
      }
  
    }
    /**
     * A TemplateResult for SVG fragments.
     *
     * This class wraps HTML in an `<svg>` tag in order to parse its contents in the
     * SVG namespace, then modifies the template to remove the `<svg>` tag so that
     * clones only container the original fragment.
     */
  
    class SVGTemplateResult extends TemplateResult {
      getHTML() {
        return "<svg>".concat(super.getHTML(), "</svg>");
      }
  
      getTemplateElement() {
        var template = super.getTemplateElement();
        var content = template.content;
        var svgElement = content.firstChild;
        content.removeChild(svgElement);
        reparentNodes(content, svgElement.firstChild);
        return template;
      }
  
    }
  
    /**
     * @license
     * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
     * This code may only be used under the BSD style license found at
     * http://polymer.github.io/LICENSE.txt
     * The complete set of authors may be found at
     * http://polymer.github.io/AUTHORS.txt
     * The complete set of contributors may be found at
     * http://polymer.github.io/CONTRIBUTORS.txt
     * Code distributed by Google as part of the polymer project is also
     * subject to an additional IP rights grant found at
     * http://polymer.github.io/PATENTS.txt
     */
    var isPrimitive = value => {
      return value === null || !(typeof value === 'object' || typeof value === 'function');
    };
    var isIterable = value => {
      return Array.isArray(value) || // tslint:disable-next-line:no-any
      !!(value && value[Symbol.iterator]);
    };
    /**
     * Writes attribute values to the DOM for a group of AttributeParts bound to a
     * single attibute. The value is only set once even if there are multiple parts
     * for an attribute.
     */
  
    class AttributeCommitter {
      constructor(element, name, strings) {
        this.dirty = true;
        this.element = element;
        this.name = name;
        this.strings = strings;
        this.parts = [];
  
        for (var i = 0; i < strings.length - 1; i++) {
          this.parts[i] = this._createPart();
        }
      }
      /**
       * Creates a single part. Override this to create a differnt type of part.
       */
  
  
      _createPart() {
        return new AttributePart(this);
      }
  
      _getValue() {
        var strings = this.strings;
        var l = strings.length - 1;
        var text = '';
  
        for (var i = 0; i < l; i++) {
          text += strings[i];
          var part = this.parts[i];
  
          if (part !== undefined) {
            var v = part.value;
  
            if (isPrimitive(v) || !isIterable(v)) {
              text += typeof v === 'string' ? v : String(v);
            } else {
              for (var t of v) {
                text += typeof t === 'string' ? t : String(t);
              }
            }
          }
        }
  
        text += strings[l];
        return text;
      }
  
      commit() {
        if (this.dirty) {
          this.dirty = false;
          this.element.setAttribute(this.name, this._getValue());
        }
      }
  
    }
    /**
     * A Part that controls all or part of an attribute value.
     */
  
    class AttributePart {
      constructor(committer) {
        this.value = undefined;
        this.committer = committer;
      }
  
      setValue(value) {
        if (value !== noChange && (!isPrimitive(value) || value !== this.value)) {
          this.value = value; // If the value is a not a directive, dirty the committer so that it'll
          // call setAttribute. If the value is a directive, it'll dirty the
          // committer if it calls setValue().
  
          if (!isDirective(value)) {
            this.committer.dirty = true;
          }
        }
      }
  
      commit() {
        while (isDirective(this.value)) {
          var directive = this.value;
          this.value = noChange;
          directive(this);
        }
  
        if (this.value === noChange) {
          return;
        }
  
        this.committer.commit();
      }
  
    }
    /**
     * A Part that controls a location within a Node tree. Like a Range, NodePart
     * has start and end locations and can set and update the Nodes between those
     * locations.
     *
     * NodeParts support several value types: primitives, Nodes, TemplateResults,
     * as well as arrays and iterables of those types.
     */
  
    class NodePart {
      constructor(options) {
        this.value = undefined;
        this.__pendingValue = undefined;
        this.options = options;
      }
      /**
       * Appends this part into a container.
       *
       * This part must be empty, as its contents are not automatically moved.
       */
  
  
      appendInto(container) {
        this.startNode = container.appendChild(createMarker());
        this.endNode = container.appendChild(createMarker());
      }
      /**
       * Inserts this part after the `ref` node (between `ref` and `ref`'s next
       * sibling). Both `ref` and its next sibling must be static, unchanging nodes
       * such as those that appear in a literal section of a template.
       *
       * This part must be empty, as its contents are not automatically moved.
       */
  
  
      insertAfterNode(ref) {
        this.startNode = ref;
        this.endNode = ref.nextSibling;
      }
      /**
       * Appends this part into a parent part.
       *
       * This part must be empty, as its contents are not automatically moved.
       */
  
  
      appendIntoPart(part) {
        part.__insert(this.startNode = createMarker());
  
        part.__insert(this.endNode = createMarker());
      }
      /**
       * Inserts this part after the `ref` part.
       *
       * This part must be empty, as its contents are not automatically moved.
       */
  
  
      insertAfterPart(ref) {
        ref.__insert(this.startNode = createMarker());
  
        this.endNode = ref.endNode;
        ref.endNode = this.startNode;
      }
  
      setValue(value) {
        this.__pendingValue = value;
      }
  
      commit() {
        while (isDirective(this.__pendingValue)) {
          var directive = this.__pendingValue;
          this.__pendingValue = noChange;
          directive(this);
        }
  
        var value = this.__pendingValue;
  
        if (value === noChange) {
          return;
        }
  
        if (isPrimitive(value)) {
          if (value !== this.value) {
            this.__commitText(value);
          }
        } else if (value instanceof TemplateResult) {
          this.__commitTemplateResult(value);
        } else if (value instanceof Node) {
          this.__commitNode(value);
        } else if (isIterable(value)) {
          this.__commitIterable(value);
        } else if (value === nothing) {
          this.value = nothing;
          this.clear();
        } else {
          // Fallback, will render the string representation
          this.__commitText(value);
        }
      }
  
      __insert(node) {
        this.endNode.parentNode.insertBefore(node, this.endNode);
      }
  
      __commitNode(value) {
        if (this.value === value) {
          return;
        }
  
        this.clear();
  
        this.__insert(value);
  
        this.value = value;
      }
  
      __commitText(value) {
        var node = this.startNode.nextSibling;
        value = value == null ? '' : value; // If `value` isn't already a string, we explicitly convert it here in case
        // it can't be implicitly converted - i.e. it's a symbol.
  
        var valueAsString = typeof value === 'string' ? value : String(value);
  
        if (node === this.endNode.previousSibling && node.nodeType === 3
        /* Node.TEXT_NODE */
        ) {
            // If we only have a single text node between the markers, we can just
            // set its value, rather than replacing it.
            // TODO(justinfagnani): Can we just check if this.value is primitive?
            node.data = valueAsString;
          } else {
          this.__commitNode(document.createTextNode(valueAsString));
        }
  
        this.value = value;
      }
  
      __commitTemplateResult(value) {
        var template = this.options.templateFactory(value);
  
        if (this.value instanceof TemplateInstance && this.value.template === template) {
          this.value.update(value.values);
        } else {
          // Make sure we propagate the template processor from the TemplateResult
          // so that we use its syntax extension, etc. The template factory comes
          // from the render function options so that it can control template
          // caching and preprocessing.
          var instance = new TemplateInstance(template, value.processor, this.options);
  
          var fragment = instance._clone();
  
          instance.update(value.values);
  
          this.__commitNode(fragment);
  
          this.value = instance;
        }
      }
  
      __commitIterable(value) {
        // For an Iterable, we create a new InstancePart per item, then set its
        // value to the item. This is a little bit of overhead for every item in
        // an Iterable, but it lets us recurse easily and efficiently update Arrays
        // of TemplateResults that will be commonly returned from expressions like:
        // array.map((i) => html`${i}`), by reusing existing TemplateInstances.
        // If _value is an array, then the previous render was of an
        // iterable and _value will contain the NodeParts from the previous
        // render. If _value is not an array, clear this part and make a new
        // array for NodeParts.
        if (!Array.isArray(this.value)) {
          this.value = [];
          this.clear();
        } // Lets us keep track of how many items we stamped so we can clear leftover
        // items from a previous render
  
  
        var itemParts = this.value;
        var partIndex = 0;
        var itemPart;
  
        for (var item of value) {
          // Try to reuse an existing part
          itemPart = itemParts[partIndex]; // If no existing part, create a new one
  
          if (itemPart === undefined) {
            itemPart = new NodePart(this.options);
            itemParts.push(itemPart);
  
            if (partIndex === 0) {
              itemPart.appendIntoPart(this);
            } else {
              itemPart.insertAfterPart(itemParts[partIndex - 1]);
            }
          }
  
          itemPart.setValue(item);
          itemPart.commit();
          partIndex++;
        }
  
        if (partIndex < itemParts.length) {
          // Truncate the parts array so _value reflects the current state
          itemParts.length = partIndex;
          this.clear(itemPart && itemPart.endNode);
        }
      }
  
      clear() {
        var startNode = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.startNode;
        removeNodes(this.startNode.parentNode, startNode.nextSibling, this.endNode);
      }
  
    }
    /**
     * Implements a boolean attribute, roughly as defined in the HTML
     * specification.
     *
     * If the value is truthy, then the attribute is present with a value of
     * ''. If the value is falsey, the attribute is removed.
     */
  
    class BooleanAttributePart {
      constructor(element, name, strings) {
        this.value = undefined;
        this.__pendingValue = undefined;
  
        if (strings.length !== 2 || strings[0] !== '' || strings[1] !== '') {
          throw new Error('Boolean attributes can only contain a single expression');
        }
  
        this.element = element;
        this.name = name;
        this.strings = strings;
      }
  
      setValue(value) {
        this.__pendingValue = value;
      }
  
      commit() {
        while (isDirective(this.__pendingValue)) {
          var directive = this.__pendingValue;
          this.__pendingValue = noChange;
          directive(this);
        }
  
        if (this.__pendingValue === noChange) {
          return;
        }
  
        var value = !!this.__pendingValue;
  
        if (this.value !== value) {
          if (value) {
            this.element.setAttribute(this.name, '');
          } else {
            this.element.removeAttribute(this.name);
          }
  
          this.value = value;
        }
  
        this.__pendingValue = noChange;
      }
  
    }
    /**
     * Sets attribute values for PropertyParts, so that the value is only set once
     * even if there are multiple parts for a property.
     *
     * If an expression controls the whole property value, then the value is simply
     * assigned to the property under control. If there are string literals or
     * multiple expressions, then the strings are expressions are interpolated into
     * a string first.
     */
  
    class PropertyCommitter extends AttributeCommitter {
      constructor(element, name, strings) {
        super(element, name, strings);
        this.single = strings.length === 2 && strings[0] === '' && strings[1] === '';
      }
  
      _createPart() {
        return new PropertyPart(this);
      }
  
      _getValue() {
        if (this.single) {
          return this.parts[0].value;
        }
  
        return super._getValue();
      }
  
      commit() {
        if (this.dirty) {
          this.dirty = false; // tslint:disable-next-line:no-any
  
          this.element[this.name] = this._getValue();
        }
      }
  
    }
    class PropertyPart extends AttributePart {} // Detect event listener options support. If the `capture` property is read
    // from the options object, then options are supported. If not, then the thrid
    // argument to add/removeEventListener is interpreted as the boolean capture
    // value so we should only pass the `capture` property.
  
    var eventOptionsSupported = false;
  
    try {
      var options = {
        get capture() {
          eventOptionsSupported = true;
          return false;
        }
  
      }; // tslint:disable-next-line:no-any
  
      window.addEventListener('test', options, options); // tslint:disable-next-line:no-any
  
      window.removeEventListener('test', options, options);
    } catch (_e) {}
  
    class EventPart {
      constructor(element, eventName, eventContext) {
        this.value = undefined;
        this.__pendingValue = undefined;
        this.element = element;
        this.eventName = eventName;
        this.eventContext = eventContext;
  
        this.__boundHandleEvent = e => this.handleEvent(e);
      }
  
      setValue(value) {
        this.__pendingValue = value;
      }
  
      commit() {
        while (isDirective(this.__pendingValue)) {
          var directive = this.__pendingValue;
          this.__pendingValue = noChange;
          directive(this);
        }
  
        if (this.__pendingValue === noChange) {
          return;
        }
  
        var newListener = this.__pendingValue;
        var oldListener = this.value;
        var shouldRemoveListener = newListener == null || oldListener != null && (newListener.capture !== oldListener.capture || newListener.once !== oldListener.once || newListener.passive !== oldListener.passive);
        var shouldAddListener = newListener != null && (oldListener == null || shouldRemoveListener);
  
        if (shouldRemoveListener) {
          this.element.removeEventListener(this.eventName, this.__boundHandleEvent, this.__options);
        }
  
        if (shouldAddListener) {
          this.__options = getOptions(newListener);
          this.element.addEventListener(this.eventName, this.__boundHandleEvent, this.__options);
        }
  
        this.value = newListener;
        this.__pendingValue = noChange;
      }
  
      handleEvent(event) {
        if (typeof this.value === 'function') {
          this.value.call(this.eventContext || this.element, event);
        } else {
          this.value.handleEvent(event);
        }
      }
  
    } // We copy options because of the inconsistent behavior of browsers when reading
    // the third argument of add/removeEventListener. IE11 doesn't support options
    // at all. Chrome 41 only reads `capture` if the argument is an object.
  
    var getOptions = o => o && (eventOptionsSupported ? {
      capture: o.capture,
      passive: o.passive,
      once: o.once
    } : o.capture);
  
    /**
     * @license
     * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
     * This code may only be used under the BSD style license found at
     * http://polymer.github.io/LICENSE.txt
     * The complete set of authors may be found at
     * http://polymer.github.io/AUTHORS.txt
     * The complete set of contributors may be found at
     * http://polymer.github.io/CONTRIBUTORS.txt
     * Code distributed by Google as part of the polymer project is also
     * subject to an additional IP rights grant found at
     * http://polymer.github.io/PATENTS.txt
     */
    /**
     * Creates Parts when a template is instantiated.
     */
  
    class DefaultTemplateProcessor {
      /**
       * Create parts for an attribute-position binding, given the event, attribute
       * name, and string literals.
       *
       * @param element The element containing the binding
       * @param name  The attribute name
       * @param strings The string literals. There are always at least two strings,
       *   event for fully-controlled bindings with a single expression.
       */
      handleAttributeExpressions(element, name, strings, options) {
        var prefix = name[0];
  
        if (prefix === '.') {
          var _committer = new PropertyCommitter(element, name.slice(1), strings);
  
          return _committer.parts;
        }
  
        if (prefix === '@') {
          return [new EventPart(element, name.slice(1), options.eventContext)];
        }
  
        if (prefix === '?') {
          return [new BooleanAttributePart(element, name.slice(1), strings)];
        }
  
        var committer = new AttributeCommitter(element, name, strings);
        return committer.parts;
      }
      /**
       * Create parts for a text-position binding.
       * @param templateFactory
       */
  
  
      handleTextExpression(options) {
        return new NodePart(options);
      }
  
    }
    var defaultTemplateProcessor = new DefaultTemplateProcessor();
  
    /**
     * @license
     * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
     * This code may only be used under the BSD style license found at
     * http://polymer.github.io/LICENSE.txt
     * The complete set of authors may be found at
     * http://polymer.github.io/AUTHORS.txt
     * The complete set of contributors may be found at
     * http://polymer.github.io/CONTRIBUTORS.txt
     * Code distributed by Google as part of the polymer project is also
     * subject to an additional IP rights grant found at
     * http://polymer.github.io/PATENTS.txt
     */
    /**
     * The default TemplateFactory which caches Templates keyed on
     * result.type and result.strings.
     */
  
    function templateFactory(result) {
      var templateCache = templateCaches.get(result.type);
  
      if (templateCache === undefined) {
        templateCache = {
          stringsArray: new WeakMap(),
          keyString: new Map()
        };
        templateCaches.set(result.type, templateCache);
      }
  
      var template = templateCache.stringsArray.get(result.strings);
  
      if (template !== undefined) {
        return template;
      } // If the TemplateStringsArray is new, generate a key from the strings
      // This key is shared between all templates with identical content
  
  
      var key = result.strings.join(marker); // Check if we already have a Template for this key
  
      template = templateCache.keyString.get(key);
  
      if (template === undefined) {
        // If we have not seen this key before, create a new Template
        template = new Template(result, result.getTemplateElement()); // Cache the Template for this key
  
        templateCache.keyString.set(key, template);
      } // Cache all future queries for this TemplateStringsArray
  
  
      templateCache.stringsArray.set(result.strings, template);
      return template;
    }
    var templateCaches = new Map();
  
    /**
     * @license
     * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
     * This code may only be used under the BSD style license found at
     * http://polymer.github.io/LICENSE.txt
     * The complete set of authors may be found at
     * http://polymer.github.io/AUTHORS.txt
     * The complete set of contributors may be found at
     * http://polymer.github.io/CONTRIBUTORS.txt
     * Code distributed by Google as part of the polymer project is also
     * subject to an additional IP rights grant found at
     * http://polymer.github.io/PATENTS.txt
     */
    var parts = new WeakMap();
    /**
     * Renders a template result or other value to a container.
     *
     * To update a container with new values, reevaluate the template literal and
     * call `render` with the new result.
     *
     * @param result Any value renderable by NodePart - typically a TemplateResult
     *     created by evaluating a template tag like `html` or `svg`.
     * @param container A DOM parent to render to. The entire contents are either
     *     replaced, or efficiently updated if the same result type was previous
     *     rendered there.
     * @param options RenderOptions for the entire render tree rendered to this
     *     container. Render options must *not* change between renders to the same
     *     container, as those changes will not effect previously rendered DOM.
     */
  
    var render = (result, container, options) => {
      var part = parts.get(container);
  
      if (part === undefined) {
        removeNodes(container, container.firstChild);
        parts.set(container, part = new NodePart(Object.assign({
          templateFactory
        }, options)));
        part.appendInto(container);
      }
  
      part.setValue(result);
      part.commit();
    };
  
    /**
     * @license
     * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
     * This code may only be used under the BSD style license found at
     * http://polymer.github.io/LICENSE.txt
     * The complete set of authors may be found at
     * http://polymer.github.io/AUTHORS.txt
     * The complete set of contributors may be found at
     * http://polymer.github.io/CONTRIBUTORS.txt
     * Code distributed by Google as part of the polymer project is also
     * subject to an additional IP rights grant found at
     * http://polymer.github.io/PATENTS.txt
     */
    // This line will be used in regexes to search for lit-html usage.
    // TODO(justinfagnani): inject version number at build time
  
    (window['litHtmlVersions'] || (window['litHtmlVersions'] = [])).push('1.1.2');
    /**
     * Interprets a template literal as an HTML template that can efficiently
     * render to and update a container.
     */
  
    var html = function html(strings) {
      for (var _len = arguments.length, values = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
        values[_key - 1] = arguments[_key];
      }
  
      return new TemplateResult(strings, values, 'html', defaultTemplateProcessor);
    };
    /**
     * Interprets a template literal as an SVG template that can efficiently
     * render to and update a container.
     */
  
    var svg = function svg(strings) {
      for (var _len2 = arguments.length, values = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
        values[_key2 - 1] = arguments[_key2];
      }
  
      return new SVGTemplateResult(strings, values, 'svg', defaultTemplateProcessor);
    };
  
    /**
     * @license
     * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
     * This code may only be used under the BSD style license found at
     * http://polymer.github.io/LICENSE.txt
     * The complete set of authors may be found at
     * http://polymer.github.io/AUTHORS.txt
     * The complete set of contributors may be found at
     * http://polymer.github.io/CONTRIBUTORS.txt
     * Code distributed by Google as part of the polymer project is also
     * subject to an additional IP rights grant found at
     * http://polymer.github.io/PATENTS.txt
     */
    var walkerNodeFilter = 133
    /* NodeFilter.SHOW_{ELEMENT|COMMENT|TEXT} */
    ;
    /**
     * Removes the list of nodes from a Template safely. In addition to removing
     * nodes from the Template, the Template part indices are updated to match
     * the mutated Template DOM.
     *
     * As the template is walked the removal state is tracked and
     * part indices are adjusted as needed.
     *
     * div
     *   div#1 (remove) <-- start removing (removing node is div#1)
     *     div
     *       div#2 (remove)  <-- continue removing (removing node is still div#1)
     *         div
     * div <-- stop removing since previous sibling is the removing node (div#1,
     * removed 4 nodes)
     */
  
    function removeNodesFromTemplate(template, nodesToRemove) {
      var {
        element: {
          content
        },
        parts
      } = template;
      var walker = document.createTreeWalker(content, walkerNodeFilter, null, false);
      var partIndex = nextActiveIndexInTemplateParts(parts);
      var part = parts[partIndex];
      var nodeIndex = -1;
      var removeCount = 0;
      var nodesToRemoveInTemplate = [];
      var currentRemovingNode = null;
  
      while (walker.nextNode()) {
        nodeIndex++;
        var node = walker.currentNode; // End removal if stepped past the removing node
  
        if (node.previousSibling === currentRemovingNode) {
          currentRemovingNode = null;
        } // A node to remove was found in the template
  
  
        if (nodesToRemove.has(node)) {
          nodesToRemoveInTemplate.push(node); // Track node we're removing
  
          if (currentRemovingNode === null) {
            currentRemovingNode = node;
          }
        } // When removing, increment count by which to adjust subsequent part indices
  
  
        if (currentRemovingNode !== null) {
          removeCount++;
        }
  
        while (part !== undefined && part.index === nodeIndex) {
          // If part is in a removed node deactivate it by setting index to -1 or
          // adjust the index as needed.
          part.index = currentRemovingNode !== null ? -1 : part.index - removeCount; // go to the next active part.
  
          partIndex = nextActiveIndexInTemplateParts(parts, partIndex);
          part = parts[partIndex];
        }
      }
  
      nodesToRemoveInTemplate.forEach(n => n.parentNode.removeChild(n));
    }
  
    var countNodes = node => {
      var count = node.nodeType === 11
      /* Node.DOCUMENT_FRAGMENT_NODE */
      ? 0 : 1;
      var walker = document.createTreeWalker(node, walkerNodeFilter, null, false);
  
      while (walker.nextNode()) {
        count++;
      }
  
      return count;
    };
  
    var nextActiveIndexInTemplateParts = function nextActiveIndexInTemplateParts(parts) {
      var startIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1;
  
      for (var i = startIndex + 1; i < parts.length; i++) {
        var part = parts[i];
  
        if (isTemplatePartActive(part)) {
          return i;
        }
      }
  
      return -1;
    };
    /**
     * Inserts the given node into the Template, optionally before the given
     * refNode. In addition to inserting the node into the Template, the Template
     * part indices are updated to match the mutated Template DOM.
     */
  
  
    function insertNodeIntoTemplate(template, node) {
      var refNode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var {
        element: {
          content
        },
        parts
      } = template; // If there's no refNode, then put node at end of template.
      // No part indices need to be shifted in this case.
  
      if (refNode === null || refNode === undefined) {
        content.appendChild(node);
        return;
      }
  
      var walker = document.createTreeWalker(content, walkerNodeFilter, null, false);
      var partIndex = nextActiveIndexInTemplateParts(parts);
      var insertCount = 0;
      var walkerIndex = -1;
  
      while (walker.nextNode()) {
        walkerIndex++;
        var walkerNode = walker.currentNode;
  
        if (walkerNode === refNode) {
          insertCount = countNodes(node);
          refNode.parentNode.insertBefore(node, refNode);
        }
  
        while (partIndex !== -1 && parts[partIndex].index === walkerIndex) {
          // If we've inserted the node, simply adjust all subsequent parts
          if (insertCount > 0) {
            while (partIndex !== -1) {
              parts[partIndex].index += insertCount;
              partIndex = nextActiveIndexInTemplateParts(parts, partIndex);
            }
  
            return;
          }
  
          partIndex = nextActiveIndexInTemplateParts(parts, partIndex);
        }
      }
    }
  
    /**
     * @license
     * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
     * This code may only be used under the BSD style license found at
     * http://polymer.github.io/LICENSE.txt
     * The complete set of authors may be found at
     * http://polymer.github.io/AUTHORS.txt
     * The complete set of contributors may be found at
     * http://polymer.github.io/CONTRIBUTORS.txt
     * Code distributed by Google as part of the polymer project is also
     * subject to an additional IP rights grant found at
     * http://polymer.github.io/PATENTS.txt
     */
  
    var getTemplateCacheKey = (type, scopeName) => "".concat(type, "--").concat(scopeName);
  
    var compatibleShadyCSSVersion = true;
  
    if (typeof window.ShadyCSS === 'undefined') {
      compatibleShadyCSSVersion = false;
    } else if (typeof window.ShadyCSS.prepareTemplateDom === 'undefined') {
      console.warn("Incompatible ShadyCSS version detected. " + "Please update to at least @webcomponents/webcomponentsjs@2.0.2 and " + "@webcomponents/shadycss@1.3.1.");
      compatibleShadyCSSVersion = false;
    }
    /**
     * Template factory which scopes template DOM using ShadyCSS.
     * @param scopeName {string}
     */
  
  
    var shadyTemplateFactory = scopeName => result => {
      var cacheKey = getTemplateCacheKey(result.type, scopeName);
      var templateCache = templateCaches.get(cacheKey);
  
      if (templateCache === undefined) {
        templateCache = {
          stringsArray: new WeakMap(),
          keyString: new Map()
        };
        templateCaches.set(cacheKey, templateCache);
      }
  
      var template = templateCache.stringsArray.get(result.strings);
  
      if (template !== undefined) {
        return template;
      }
  
      var key = result.strings.join(marker);
      template = templateCache.keyString.get(key);
  
      if (template === undefined) {
        var element = result.getTemplateElement();
  
        if (compatibleShadyCSSVersion) {
          window.ShadyCSS.prepareTemplateDom(element, scopeName);
        }
  
        template = new Template(result, element);
        templateCache.keyString.set(key, template);
      }
  
      templateCache.stringsArray.set(result.strings, template);
      return template;
    };
  
    var TEMPLATE_TYPES = ['html', 'svg'];
    /**
     * Removes all style elements from Templates for the given scopeName.
     */
  
    var removeStylesFromLitTemplates = scopeName => {
      TEMPLATE_TYPES.forEach(type => {
        var templates = templateCaches.get(getTemplateCacheKey(type, scopeName));
  
        if (templates !== undefined) {
          templates.keyString.forEach(template => {
            var {
              element: {
                content
              }
            } = template; // IE 11 doesn't support the iterable param Set constructor
  
            var styles = new Set();
            Array.from(content.querySelectorAll('style')).forEach(s => {
              styles.add(s);
            });
            removeNodesFromTemplate(template, styles);
          });
        }
      });
    };
  
    var shadyRenderSet = new Set();
    /**
     * For the given scope name, ensures that ShadyCSS style scoping is performed.
     * This is done just once per scope name so the fragment and template cannot
     * be modified.
     * (1) extracts styles from the rendered fragment and hands them to ShadyCSS
     * to be scoped and appended to the document
     * (2) removes style elements from all lit-html Templates for this scope name.
     *
     * Note, <style> elements can only be placed into templates for the
     * initial rendering of the scope. If <style> elements are included in templates
     * dynamically rendered to the scope (after the first scope render), they will
     * not be scoped and the <style> will be left in the template and rendered
     * output.
     */
  
    var prepareTemplateStyles = (scopeName, renderedDOM, template) => {
      shadyRenderSet.add(scopeName); // If `renderedDOM` is stamped from a Template, then we need to edit that
      // Template's underlying template element. Otherwise, we create one here
      // to give to ShadyCSS, which still requires one while scoping.
  
      var templateElement = !!template ? template.element : document.createElement('template'); // Move styles out of rendered DOM and store.
  
      var styles = renderedDOM.querySelectorAll('style');
      var {
        length
      } = styles; // If there are no styles, skip unnecessary work
  
      if (length === 0) {
        // Ensure prepareTemplateStyles is called to support adding
        // styles via `prepareAdoptedCssText` since that requires that
        // `prepareTemplateStyles` is called.
        //
        // ShadyCSS will only update styles containing @apply in the template
        // given to `prepareTemplateStyles`. If no lit Template was given,
        // ShadyCSS will not be able to update uses of @apply in any relevant
        // template. However, this is not a problem because we only create the
        // template for the purpose of supporting `prepareAdoptedCssText`,
        // which doesn't support @apply at all.
        window.ShadyCSS.prepareTemplateStyles(templateElement, scopeName);
        return;
      }
  
      var condensedStyle = document.createElement('style'); // Collect styles into a single style. This helps us make sure ShadyCSS
      // manipulations will not prevent us from being able to fix up template
      // part indices.
      // NOTE: collecting styles is inefficient for browsers but ShadyCSS
      // currently does this anyway. When it does not, this should be changed.
  
      for (var i = 0; i < length; i++) {
        var _style = styles[i];
  
        _style.parentNode.removeChild(_style);
  
        condensedStyle.textContent += _style.textContent;
      } // Remove styles from nested templates in this scope.
  
  
      removeStylesFromLitTemplates(scopeName); // And then put the condensed style into the "root" template passed in as
      // `template`.
  
      var content = templateElement.content;
  
      if (!!template) {
        insertNodeIntoTemplate(template, condensedStyle, content.firstChild);
      } else {
        content.insertBefore(condensedStyle, content.firstChild);
      } // Note, it's important that ShadyCSS gets the template that `lit-html`
      // will actually render so that it can update the style inside when
      // needed (e.g. @apply native Shadow DOM case).
  
  
      window.ShadyCSS.prepareTemplateStyles(templateElement, scopeName);
      var style = content.querySelector('style');
  
      if (window.ShadyCSS.nativeShadow && style !== null) {
        // When in native Shadow DOM, ensure the style created by ShadyCSS is
        // included in initially rendered output (`renderedDOM`).
        renderedDOM.insertBefore(style.cloneNode(true), renderedDOM.firstChild);
      } else if (!!template) {
        // When no style is left in the template, parts will be broken as a
        // result. To fix this, we put back the style node ShadyCSS removed
        // and then tell lit to remove that node from the template.
        // There can be no style in the template in 2 cases (1) when Shady DOM
        // is in use, ShadyCSS removes all styles, (2) when native Shadow DOM
        // is in use ShadyCSS removes the style if it contains no content.
        // NOTE, ShadyCSS creates its own style so we can safely add/remove
        // `condensedStyle` here.
        content.insertBefore(condensedStyle, content.firstChild);
        var removes = new Set();
        removes.add(condensedStyle);
        removeNodesFromTemplate(template, removes);
      }
    };
    /**
     * Extension to the standard `render` method which supports rendering
     * to ShadowRoots when the ShadyDOM (https://github.com/webcomponents/shadydom)
     * and ShadyCSS (https://github.com/webcomponents/shadycss) polyfills are used
     * or when the webcomponentsjs
     * (https://github.com/webcomponents/webcomponentsjs) polyfill is used.
     *
     * Adds a `scopeName` option which is used to scope element DOM and stylesheets
     * when native ShadowDOM is unavailable. The `scopeName` will be added to
     * the class attribute of all rendered DOM. In addition, any style elements will
     * be automatically re-written with this `scopeName` selector and moved out
     * of the rendered DOM and into the document `<head>`.
     *
     * It is common to use this render method in conjunction with a custom element
     * which renders a shadowRoot. When this is done, typically the element's
     * `localName` should be used as the `scopeName`.
     *
     * In addition to DOM scoping, ShadyCSS also supports a basic shim for css
     * custom properties (needed only on older browsers like IE11) and a shim for
     * a deprecated feature called `@apply` that supports applying a set of css
     * custom properties to a given location.
     *
     * Usage considerations:
     *
     * * Part values in `<style>` elements are only applied the first time a given
     * `scopeName` renders. Subsequent changes to parts in style elements will have
     * no effect. Because of this, parts in style elements should only be used for
     * values that will never change, for example parts that set scope-wide theme
     * values or parts which render shared style elements.
     *
     * * Note, due to a limitation of the ShadyDOM polyfill, rendering in a
     * custom element's `constructor` is not supported. Instead rendering should
     * either done asynchronously, for example at microtask timing (for example
     * `Promise.resolve()`), or be deferred until the first time the element's
     * `connectedCallback` runs.
     *
     * Usage considerations when using shimmed custom properties or `@apply`:
     *
     * * Whenever any dynamic changes are made which affect
     * css custom properties, `ShadyCSS.styleElement(element)` must be called
     * to update the element. There are two cases when this is needed:
     * (1) the element is connected to a new parent, (2) a class is added to the
     * element that causes it to match different custom properties.
     * To address the first case when rendering a custom element, `styleElement`
     * should be called in the element's `connectedCallback`.
     *
     * * Shimmed custom properties may only be defined either for an entire
     * shadowRoot (for example, in a `:host` rule) or via a rule that directly
     * matches an element with a shadowRoot. In other words, instead of flowing from
     * parent to child as do native css custom properties, shimmed custom properties
     * flow only from shadowRoots to nested shadowRoots.
     *
     * * When using `@apply` mixing css shorthand property names with
     * non-shorthand names (for example `border` and `border-width`) is not
     * supported.
     */
  
  
    var render$1 = (result, container, options) => {
      if (!options || typeof options !== 'object' || !options.scopeName) {
        throw new Error('The `scopeName` option is required.');
      }
  
      var scopeName = options.scopeName;
      var hasRendered = parts.has(container);
      var needsScoping = compatibleShadyCSSVersion && container.nodeType === 11
      /* Node.DOCUMENT_FRAGMENT_NODE */
      && !!container.host; // Handle first render to a scope specially...
  
      var firstScopeRender = needsScoping && !shadyRenderSet.has(scopeName); // On first scope render, render into a fragment; this cannot be a single
      // fragment that is reused since nested renders can occur synchronously.
  
      var renderContainer = firstScopeRender ? document.createDocumentFragment() : container;
      render(result, renderContainer, Object.assign({
        templateFactory: shadyTemplateFactory(scopeName)
      }, options)); // When performing first scope render,
      // (1) We've rendered into a fragment so that there's a chance to
      // `prepareTemplateStyles` before sub-elements hit the DOM
      // (which might cause them to render based on a common pattern of
      // rendering in a custom element's `connectedCallback`);
      // (2) Scope the template with ShadyCSS one time only for this scope.
      // (3) Render the fragment into the container and make sure the
      // container knows its `part` is the one we just rendered. This ensures
      // DOM will be re-used on subsequent renders.
  
      if (firstScopeRender) {
        var part = parts.get(renderContainer);
        parts.delete(renderContainer); // ShadyCSS might have style sheets (e.g. from `prepareAdoptedCssText`)
        // that should apply to `renderContainer` even if the rendered value is
        // not a TemplateInstance. However, it will only insert scoped styles
        // into the document if `prepareTemplateStyles` has already been called
        // for the given scope name.
  
        var template = part.value instanceof TemplateInstance ? part.value.template : undefined;
        prepareTemplateStyles(scopeName, renderContainer, template);
        removeNodes(container, container.firstChild);
        container.appendChild(renderContainer);
        parts.set(container, part);
      } // After elements have hit the DOM, update styling if this is the
      // initial render to this container.
      // This is needed whenever dynamic changes are made so it would be
      // safest to do every render; however, this would regress performance
      // so we leave it up to the user to call `ShadyCSS.styleElement`
      // for dynamic changes.
  
  
      if (!hasRendered && needsScoping) {
        window.ShadyCSS.styleElement(container.host);
      }
    };
  
    /**
     * @license
     * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
     * This code may only be used under the BSD style license found at
     * http://polymer.github.io/LICENSE.txt
     * The complete set of authors may be found at
     * http://polymer.github.io/AUTHORS.txt
     * The complete set of contributors may be found at
     * http://polymer.github.io/CONTRIBUTORS.txt
     * Code distributed by Google as part of the polymer project is also
     * subject to an additional IP rights grant found at
     * http://polymer.github.io/PATENTS.txt
     */
    var _a;
    /**
     * When using Closure Compiler, JSCompiler_renameProperty(property, object) is
     * replaced at compile time by the munged name for object[property]. We cannot
     * alias this function, so we have to use a small shim that has the same
     * behavior when not compiling.
     */
  
  
    window.JSCompiler_renameProperty = (prop, _obj) => prop;
  
    var defaultConverter = {
      toAttribute(value, type) {
        switch (type) {
          case Boolean:
            return value ? '' : null;
  
          case Object:
          case Array:
            // if the value is `null` or `undefined` pass this through
            // to allow removing/no change behavior.
            return value == null ? value : JSON.stringify(value);
        }
  
        return value;
      },
  
      fromAttribute(value, type) {
        switch (type) {
          case Boolean:
            return value !== null;
  
          case Number:
            return value === null ? null : Number(value);
  
          case Object:
          case Array:
            return JSON.parse(value);
        }
  
        return value;
      }
  
    };
    /**
     * Change function that returns true if `value` is different from `oldValue`.
     * This method is used as the default for a property's `hasChanged` function.
     */
  
    var notEqual = (value, old) => {
      // This ensures (old==NaN, value==NaN) always returns false
      return old !== value && (old === old || value === value);
    };
    var defaultPropertyDeclaration = {
      attribute: true,
      type: String,
      converter: defaultConverter,
      reflect: false,
      hasChanged: notEqual
    };
    var microtaskPromise = Promise.resolve(true);
    var STATE_HAS_UPDATED = 1;
    var STATE_UPDATE_REQUESTED = 1 << 2;
    var STATE_IS_REFLECTING_TO_ATTRIBUTE = 1 << 3;
    var STATE_IS_REFLECTING_TO_PROPERTY = 1 << 4;
    var STATE_HAS_CONNECTED = 1 << 5;
    /**
     * The Closure JS Compiler doesn't currently have good support for static
     * property semantics where "this" is dynamic (e.g.
     * https://github.com/google/closure-compiler/issues/3177 and others) so we use
     * this hack to bypass any rewriting by the compiler.
     */
  
    var finalized = 'finalized';
    /**
     * Base element class which manages element properties and attributes. When
     * properties change, the `update` method is asynchronously called. This method
     * should be supplied by subclassers to render updates as desired.
     */
  
    class UpdatingElement extends HTMLElement {
      constructor() {
        super();
        this._updateState = 0;
        this._instanceProperties = undefined;
        this._updatePromise = microtaskPromise;
        this._hasConnectedResolver = undefined;
        /**
         * Map with keys for any properties that have changed since the last
         * update cycle with previous values.
         */
  
        this._changedProperties = new Map();
        /**
         * Map with keys of properties that should be reflected when updated.
         */
  
        this._reflectingProperties = undefined;
        this.initialize();
      }
      /**
       * Returns a list of attributes corresponding to the registered properties.
       * @nocollapse
       */
  
  
      static get observedAttributes() {
        // note: piggy backing on this to ensure we're finalized.
        this.finalize();
        var attributes = []; // Use forEach so this works even if for/of loops are compiled to for loops
        // expecting arrays
  
        this._classProperties.forEach((v, p) => {
          var attr = this._attributeNameForProperty(p, v);
  
          if (attr !== undefined) {
            this._attributeToPropertyMap.set(attr, p);
  
            attributes.push(attr);
          }
        });
  
        return attributes;
      }
      /**
       * Ensures the private `_classProperties` property metadata is created.
       * In addition to `finalize` this is also called in `createProperty` to
       * ensure the `@property` decorator can add property metadata.
       */
  
      /** @nocollapse */
  
  
      static _ensureClassProperties() {
        // ensure private storage for property declarations.
        if (!this.hasOwnProperty(JSCompiler_renameProperty('_classProperties', this))) {
          this._classProperties = new Map(); // NOTE: Workaround IE11 not supporting Map constructor argument.
  
          var superProperties = Object.getPrototypeOf(this)._classProperties;
  
          if (superProperties !== undefined) {
            superProperties.forEach((v, k) => this._classProperties.set(k, v));
          }
        }
      }
      /**
       * Creates a property accessor on the element prototype if one does not exist.
       * The property setter calls the property's `hasChanged` property option
       * or uses a strict identity check to determine whether or not to request
       * an update.
       * @nocollapse
       */
  
  
      static createProperty(name) {
        var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultPropertyDeclaration;
  
        // Note, since this can be called by the `@property` decorator which
        // is called before `finalize`, we ensure storage exists for property
        // metadata.
        this._ensureClassProperties();
  
        this._classProperties.set(name, options); // Do not generate an accessor if the prototype already has one, since
        // it would be lost otherwise and that would never be the user's intention;
        // Instead, we expect users to call `requestUpdate` themselves from
        // user-defined accessors. Note that if the super has an accessor we will
        // still overwrite it
  
  
        if (options.noAccessor || this.prototype.hasOwnProperty(name)) {
          return;
        }
  
        var key = typeof name === 'symbol' ? Symbol() : "__".concat(name);
        Object.defineProperty(this.prototype, name, {
          // tslint:disable-next-line:no-any no symbol in index
          get() {
            return this[key];
          },
  
          set(value) {
            var oldValue = this[name];
            this[key] = value;
  
            this._requestUpdate(name, oldValue);
          },
  
          configurable: true,
          enumerable: true
        });
      }
      /**
       * Creates property accessors for registered properties and ensures
       * any superclasses are also finalized.
       * @nocollapse
       */
  
  
      static finalize() {
        // finalize any superclasses
        var superCtor = Object.getPrototypeOf(this);
  
        if (!superCtor.hasOwnProperty(finalized)) {
          superCtor.finalize();
        }
  
        this[finalized] = true;
  
        this._ensureClassProperties(); // initialize Map populated in observedAttributes
  
  
        this._attributeToPropertyMap = new Map(); // make any properties
        // Note, only process "own" properties since this element will inherit
        // any properties defined on the superClass, and finalization ensures
        // the entire prototype chain is finalized.
  
        if (this.hasOwnProperty(JSCompiler_renameProperty('properties', this))) {
          var props = this.properties; // support symbols in properties (IE11 does not support this)
  
          var propKeys = [...Object.getOwnPropertyNames(props), ...(typeof Object.getOwnPropertySymbols === 'function' ? Object.getOwnPropertySymbols(props) : [])]; // This for/of is ok because propKeys is an array
  
          for (var p of propKeys) {
            // note, use of `any` is due to TypeSript lack of support for symbol in
            // index types
            // tslint:disable-next-line:no-any no symbol in index
            this.createProperty(p, props[p]);
          }
        }
      }
      /**
       * Returns the property name for the given attribute `name`.
       * @nocollapse
       */
  
  
      static _attributeNameForProperty(name, options) {
        var attribute = options.attribute;
        return attribute === false ? undefined : typeof attribute === 'string' ? attribute : typeof name === 'string' ? name.toLowerCase() : undefined;
      }
      /**
       * Returns true if a property should request an update.
       * Called when a property value is set and uses the `hasChanged`
       * option for the property if present or a strict identity check.
       * @nocollapse
       */
  
  
      static _valueHasChanged(value, old) {
        var hasChanged = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : notEqual;
        return hasChanged(value, old);
      }
      /**
       * Returns the property value for the given attribute value.
       * Called via the `attributeChangedCallback` and uses the property's
       * `converter` or `converter.fromAttribute` property option.
       * @nocollapse
       */
  
  
      static _propertyValueFromAttribute(value, options) {
        var type = options.type;
        var converter = options.converter || defaultConverter;
        var fromAttribute = typeof converter === 'function' ? converter : converter.fromAttribute;
        return fromAttribute ? fromAttribute(value, type) : value;
      }
      /**
       * Returns the attribute value for the given property value. If this
       * returns undefined, the property will *not* be reflected to an attribute.
       * If this returns null, the attribute will be removed, otherwise the
       * attribute will be set to the value.
       * This uses the property's `reflect` and `type.toAttribute` property options.
       * @nocollapse
       */
  
  
      static _propertyValueToAttribute(value, options) {
        if (options.reflect === undefined) {
          return;
        }
  
        var type = options.type;
        var converter = options.converter;
        var toAttribute = converter && converter.toAttribute || defaultConverter.toAttribute;
        return toAttribute(value, type);
      }
      /**
       * Performs element initialization. By default captures any pre-set values for
       * registered properties.
       */
  
  
      initialize() {
        this._saveInstanceProperties(); // ensures first update will be caught by an early access of
        // `updateComplete`
  
  
        this._requestUpdate();
      }
      /**
       * Fixes any properties set on the instance before upgrade time.
       * Otherwise these would shadow the accessor and break these properties.
       * The properties are stored in a Map which is played back after the
       * constructor runs. Note, on very old versions of Safari (<=9) or Chrome
       * (<=41), properties created for native platform properties like (`id` or
       * `name`) may not have default values set in the element constructor. On
       * these browsers native properties appear on instances and therefore their
       * default value will overwrite any element default (e.g. if the element sets
       * this.id = 'id' in the constructor, the 'id' will become '' since this is
       * the native platform default).
       */
  
  
      _saveInstanceProperties() {
        // Use forEach so this works even if for/of loops are compiled to for loops
        // expecting arrays
        this.constructor._classProperties.forEach((_v, p) => {
          if (this.hasOwnProperty(p)) {
            var value = this[p];
            delete this[p];
  
            if (!this._instanceProperties) {
              this._instanceProperties = new Map();
            }
  
            this._instanceProperties.set(p, value);
          }
        });
      }
      /**
       * Applies previously saved instance properties.
       */
  
  
      _applyInstanceProperties() {
        // Use forEach so this works even if for/of loops are compiled to for loops
        // expecting arrays
        // tslint:disable-next-line:no-any
        this._instanceProperties.forEach((v, p) => this[p] = v);
  
        this._instanceProperties = undefined;
      }
  
      connectedCallback() {
        this._updateState = this._updateState | STATE_HAS_CONNECTED; // Ensure first connection completes an update. Updates cannot complete
        // before connection and if one is pending connection the
        // `_hasConnectionResolver` will exist. If so, resolve it to complete the
        // update, otherwise requestUpdate.
  
        if (this._hasConnectedResolver) {
          this._hasConnectedResolver();
  
          this._hasConnectedResolver = undefined;
        }
      }
      /**
       * Allows for `super.disconnectedCallback()` in extensions while
       * reserving the possibility of making non-breaking feature additions
       * when disconnecting at some point in the future.
       */
  
  
      disconnectedCallback() {}
      /**
       * Synchronizes property values when attributes change.
       */
  
  
      attributeChangedCallback(name, old, value) {
        if (old !== value) {
          this._attributeToProperty(name, value);
        }
      }
  
      _propertyToAttribute(name, value) {
        var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : defaultPropertyDeclaration;
        var ctor = this.constructor;
  
        var attr = ctor._attributeNameForProperty(name, options);
  
        if (attr !== undefined) {
          var attrValue = ctor._propertyValueToAttribute(value, options); // an undefined value does not change the attribute.
  
  
          if (attrValue === undefined) {
            return;
          } // Track if the property is being reflected to avoid
          // setting the property again via `attributeChangedCallback`. Note:
          // 1. this takes advantage of the fact that the callback is synchronous.
          // 2. will behave incorrectly if multiple attributes are in the reaction
          // stack at time of calling. However, since we process attributes
          // in `update` this should not be possible (or an extreme corner case
          // that we'd like to discover).
          // mark state reflecting
  
  
          this._updateState = this._updateState | STATE_IS_REFLECTING_TO_ATTRIBUTE;
  
          if (attrValue == null) {
            this.removeAttribute(attr);
          } else {
            this.setAttribute(attr, attrValue);
          } // mark state not reflecting
  
  
          this._updateState = this._updateState & ~STATE_IS_REFLECTING_TO_ATTRIBUTE;
        }
      }
  
      _attributeToProperty(name, value) {
        // Use tracking info to avoid deserializing attribute value if it was
        // just set from a property setter.
        if (this._updateState & STATE_IS_REFLECTING_TO_ATTRIBUTE) {
          return;
        }
  
        var ctor = this.constructor;
  
        var propName = ctor._attributeToPropertyMap.get(name);
  
        if (propName !== undefined) {
          var options = ctor._classProperties.get(propName) || defaultPropertyDeclaration; // mark state reflecting
  
          this._updateState = this._updateState | STATE_IS_REFLECTING_TO_PROPERTY;
          this[propName] = // tslint:disable-next-line:no-any
          ctor._propertyValueFromAttribute(value, options); // mark state not reflecting
  
          this._updateState = this._updateState & ~STATE_IS_REFLECTING_TO_PROPERTY;
        }
      }
      /**
       * This private version of `requestUpdate` does not access or return the
       * `updateComplete` promise. This promise can be overridden and is therefore
       * not free to access.
       */
  
  
      _requestUpdate(name, oldValue) {
        var shouldRequestUpdate = true; // If we have a property key, perform property update steps.
  
        if (name !== undefined) {
          var ctor = this.constructor;
          var options = ctor._classProperties.get(name) || defaultPropertyDeclaration;
  
          if (ctor._valueHasChanged(this[name], oldValue, options.hasChanged)) {
            if (!this._changedProperties.has(name)) {
              this._changedProperties.set(name, oldValue);
            } // Add to reflecting properties set.
            // Note, it's important that every change has a chance to add the
            // property to `_reflectingProperties`. This ensures setting
            // attribute + property reflects correctly.
  
  
            if (options.reflect === true && !(this._updateState & STATE_IS_REFLECTING_TO_PROPERTY)) {
              if (this._reflectingProperties === undefined) {
                this._reflectingProperties = new Map();
              }
  
              this._reflectingProperties.set(name, options);
            }
          } else {
            // Abort the request if the property should not be considered changed.
            shouldRequestUpdate = false;
          }
        }
  
        if (!this._hasRequestedUpdate && shouldRequestUpdate) {
          this._enqueueUpdate();
        }
      }
      /**
       * Requests an update which is processed asynchronously. This should
       * be called when an element should update based on some state not triggered
       * by setting a property. In this case, pass no arguments. It should also be
       * called when manually implementing a property setter. In this case, pass the
       * property `name` and `oldValue` to ensure that any configured property
       * options are honored. Returns the `updateComplete` Promise which is resolved
       * when the update completes.
       *
       * @param name {PropertyKey} (optional) name of requesting property
       * @param oldValue {any} (optional) old value of requesting property
       * @returns {Promise} A Promise that is resolved when the update completes.
       */
  
  
      requestUpdate(name, oldValue) {
        this._requestUpdate(name, oldValue);
  
        return this.updateComplete;
      }
      /**
       * Sets up the element to asynchronously update.
       */
  
  
      _enqueueUpdate() {
        var _this = this;
  
        return _asyncToGenerator(function* () {
          // Mark state updating...
          _this._updateState = _this._updateState | STATE_UPDATE_REQUESTED;
          var resolve;
          var reject;
          var previousUpdatePromise = _this._updatePromise;
          _this._updatePromise = new Promise((res, rej) => {
            resolve = res;
            reject = rej;
          });
  
          try {
            // Ensure any previous update has resolved before updating.
            // This `await` also ensures that property changes are batched.
            yield previousUpdatePromise;
          } catch (e) {} // Ignore any previous errors. We only care that the previous cycle is
          // done. Any error should have been handled in the previous update.
          // Make sure the element has connected before updating.
  
  
          if (!_this._hasConnected) {
            yield new Promise(res => _this._hasConnectedResolver = res);
          }
  
          try {
            var result = _this.performUpdate(); // If `performUpdate` returns a Promise, we await it. This is done to
            // enable coordinating updates with a scheduler. Note, the result is
            // checked to avoid delaying an additional microtask unless we need to.
  
  
            if (result != null) {
              yield result;
            }
          } catch (e) {
            reject(e);
          }
  
          resolve(!_this._hasRequestedUpdate);
        })();
      }
  
      get _hasConnected() {
        return this._updateState & STATE_HAS_CONNECTED;
      }
  
      get _hasRequestedUpdate() {
        return this._updateState & STATE_UPDATE_REQUESTED;
      }
  
      get hasUpdated() {
        return this._updateState & STATE_HAS_UPDATED;
      }
      /**
       * Performs an element update. Note, if an exception is thrown during the
       * update, `firstUpdated` and `updated` will not be called.
       *
       * You can override this method to change the timing of updates. If this
       * method is overridden, `super.performUpdate()` must be called.
       *
       * For instance, to schedule updates to occur just before the next frame:
       *
       * ```
       * protected async performUpdate(): Promise<unknown> {
       *   await new Promise((resolve) => requestAnimationFrame(() => resolve()));
       *   super.performUpdate();
       * }
       * ```
       */
  
  
      performUpdate() {
        // Mixin instance properties once, if they exist.
        if (this._instanceProperties) {
          this._applyInstanceProperties();
        }
  
        var shouldUpdate = false;
        var changedProperties = this._changedProperties;
  
        try {
          shouldUpdate = this.shouldUpdate(changedProperties);
  
          if (shouldUpdate) {
            this.update(changedProperties);
          }
        } catch (e) {
          // Prevent `firstUpdated` and `updated` from running when there's an
          // update exception.
          shouldUpdate = false;
          throw e;
        } finally {
          // Ensure element can accept additional updates after an exception.
          this._markUpdated();
        }
  
        if (shouldUpdate) {
          if (!(this._updateState & STATE_HAS_UPDATED)) {
            this._updateState = this._updateState | STATE_HAS_UPDATED;
            this.firstUpdated(changedProperties);
          }
  
          this.updated(changedProperties);
        }
      }
  
      _markUpdated() {
        this._changedProperties = new Map();
        this._updateState = this._updateState & ~STATE_UPDATE_REQUESTED;
      }
      /**
       * Returns a Promise that resolves when the element has completed updating.
       * The Promise value is a boolean that is `true` if the element completed the
       * update without triggering another update. The Promise result is `false` if
       * a property was set inside `updated()`. If the Promise is rejected, an
       * exception was thrown during the update.
       *
       * To await additional asynchronous work, override the `_getUpdateComplete`
       * method. For example, it is sometimes useful to await a rendered element
       * before fulfilling this Promise. To do this, first await
       * `super._getUpdateComplete()`, then any subsequent state.
       *
       * @returns {Promise} The Promise returns a boolean that indicates if the
       * update resolved without triggering another update.
       */
  
  
      get updateComplete() {
        return this._getUpdateComplete();
      }
      /**
       * Override point for the `updateComplete` promise.
       *
       * It is not safe to override the `updateComplete` getter directly due to a
       * limitation in TypeScript which means it is not possible to call a
       * superclass getter (e.g. `super.updateComplete.then(...)`) when the target
       * language is ES5 (https://github.com/microsoft/TypeScript/issues/338).
       * This method should be overridden instead. For example:
       *
       *   class MyElement extends LitElement {
       *     async _getUpdateComplete() {
       *       await super._getUpdateComplete();
       *       await this._myChild.updateComplete;
       *     }
       *   }
       */
  
  
      _getUpdateComplete() {
        return this._updatePromise;
      }
      /**
       * Controls whether or not `update` should be called when the element requests
       * an update. By default, this method always returns `true`, but this can be
       * customized to control when to update.
       *
       * * @param _changedProperties Map of changed properties with old values
       */
  
  
      shouldUpdate(_changedProperties) {
        return true;
      }
      /**
       * Updates the element. This method reflects property values to attributes.
       * It can be overridden to render and keep updated element DOM.
       * Setting properties inside this method will *not* trigger
       * another update.
       *
       * * @param _changedProperties Map of changed properties with old values
       */
  
  
      update(_changedProperties) {
        if (this._reflectingProperties !== undefined && this._reflectingProperties.size > 0) {
          // Use forEach so this works even if for/of loops are compiled to for
          // loops expecting arrays
          this._reflectingProperties.forEach((v, k) => this._propertyToAttribute(k, this[k], v));
  
          this._reflectingProperties = undefined;
        }
      }
      /**
       * Invoked whenever the element is updated. Implement to perform
       * post-updating tasks via DOM APIs, for example, focusing an element.
       *
       * Setting properties inside this method will trigger the element to update
       * again after this update cycle completes.
       *
       * * @param _changedProperties Map of changed properties with old values
       */
  
  
      updated(_changedProperties) {}
      /**
       * Invoked when the element is first updated. Implement to perform one time
       * work on the element after update.
       *
       * Setting properties inside this method will trigger the element to update
       * again after this update cycle completes.
       *
       * * @param _changedProperties Map of changed properties with old values
       */
  
  
      firstUpdated(_changedProperties) {}
  
    }
    _a = finalized;
    /**
     * Marks class as having finished creating properties.
     */
  
    UpdatingElement[_a] = true;
  
    /**
     * @license
     * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
     * This code may only be used under the BSD style license found at
     * http://polymer.github.io/LICENSE.txt
     * The complete set of authors may be found at
     * http://polymer.github.io/AUTHORS.txt
     * The complete set of contributors may be found at
     * http://polymer.github.io/CONTRIBUTORS.txt
     * Code distributed by Google as part of the polymer project is also
     * subject to an additional IP rights grant found at
     * http://polymer.github.io/PATENTS.txt
     */
    var legacyCustomElement = (tagName, clazz) => {
      window.customElements.define(tagName, clazz); // Cast as any because TS doesn't recognize the return type as being a
      // subtype of the decorated class when clazz is typed as
      // `Constructor<HTMLElement>` for some reason.
      // `Constructor<HTMLElement>` is helpful to make sure the decorator is
      // applied to elements however.
      // tslint:disable-next-line:no-any
  
      return clazz;
    };
  
    var standardCustomElement = (tagName, descriptor) => {
      var {
        kind,
        elements
      } = descriptor;
      return {
        kind,
        elements,
  
        // This callback is called once the class is otherwise fully defined
        finisher(clazz) {
          window.customElements.define(tagName, clazz);
        }
  
      };
    };
    /**
     * Class decorator factory that defines the decorated class as a custom element.
     *
     * @param tagName the name of the custom element to define
     */
  
  
    var customElement = tagName => classOrDescriptor => typeof classOrDescriptor === 'function' ? legacyCustomElement(tagName, classOrDescriptor) : standardCustomElement(tagName, classOrDescriptor);
  
    var standardProperty = (options, element) => {
      // When decorating an accessor, pass it through and add property metadata.
      // Note, the `hasOwnProperty` check in `createProperty` ensures we don't
      // stomp over the user's accessor.
      if (element.kind === 'method' && element.descriptor && !('value' in element.descriptor)) {
        return Object.assign({}, element, {
          finisher(clazz) {
            clazz.createProperty(element.key, options);
          }
  
        });
      } else {
        // createProperty() takes care of defining the property, but we still
        // must return some kind of descriptor, so return a descriptor for an
        // unused prototype field. The finisher calls createProperty().
        return {
          kind: 'field',
          key: Symbol(),
          placement: 'own',
          descriptor: {},
  
          // When @babel/plugin-proposal-decorators implements initializers,
          // do this instead of the initializer below. See:
          // https://github.com/babel/babel/issues/9260 extras: [
          //   {
          //     kind: 'initializer',
          //     placement: 'own',
          //     initializer: descriptor.initializer,
          //   }
          // ],
          initializer() {
            if (typeof element.initializer === 'function') {
              this[element.key] = element.initializer.call(this);
            }
          },
  
          finisher(clazz) {
            clazz.createProperty(element.key, options);
          }
  
        };
      }
    };
  
    var legacyProperty = (options, proto, name) => {
      proto.constructor.createProperty(name, options);
    };
    /**
     * A property decorator which creates a LitElement property which reflects a
     * corresponding attribute value. A `PropertyDeclaration` may optionally be
     * supplied to configure property features.
     *
     * @ExportDecoratedItems
     */
  
  
    function property(options) {
      // tslint:disable-next-line:no-any decorator
      return (protoOrDescriptor, name) => name !== undefined ? legacyProperty(options, protoOrDescriptor, name) : standardProperty(options, protoOrDescriptor);
    }
    /**
     * A property decorator that converts a class property into a getter that
     * executes a querySelector on the element's renderRoot.
     *
     * @ExportDecoratedItems
     */
  
    function query(selector) {
      return (protoOrDescriptor, // tslint:disable-next-line:no-any decorator
      name) => {
        var descriptor = {
          get() {
            return this.renderRoot.querySelector(selector);
          },
  
          enumerable: true,
          configurable: true
        };
        return name !== undefined ? legacyQuery(descriptor, protoOrDescriptor, name) : standardQuery(descriptor, protoOrDescriptor);
      };
    }
    /**
     * A property decorator that converts a class property into a getter
     * that executes a querySelectorAll on the element's renderRoot.
     *
     * @ExportDecoratedItems
     */
  
    function queryAll(selector) {
      return (protoOrDescriptor, // tslint:disable-next-line:no-any decorator
      name) => {
        var descriptor = {
          get() {
            return this.renderRoot.querySelectorAll(selector);
          },
  
          enumerable: true,
          configurable: true
        };
        return name !== undefined ? legacyQuery(descriptor, protoOrDescriptor, name) : standardQuery(descriptor, protoOrDescriptor);
      };
    }
  
    var legacyQuery = (descriptor, proto, name) => {
      Object.defineProperty(proto, name, descriptor);
    };
  
    var standardQuery = (descriptor, element) => ({
      kind: 'method',
      placement: 'prototype',
      key: element.key,
      descriptor
    });
  
    var standardEventOptions = (options, element) => {
      return Object.assign({}, element, {
        finisher(clazz) {
          Object.assign(clazz.prototype[element.key], options);
        }
  
      });
    };
  
    var legacyEventOptions = // tslint:disable-next-line:no-any legacy decorator
    (options, proto, name) => {
      Object.assign(proto[name], options);
    };
    /**
     * Adds event listener options to a method used as an event listener in a
     * lit-html template.
     *
     * @param options An object that specifis event listener options as accepted by
     * `EventTarget#addEventListener` and `EventTarget#removeEventListener`.
     *
     * Current browsers support the `capture`, `passive`, and `once` options. See:
     * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Parameters
     *
     * @example
     *
     *     class MyElement {
     *
     *       clicked = false;
     *
     *       render() {
     *         return html`<div @click=${this._onClick}`><button></button></div>`;
     *       }
     *
     *       @eventOptions({capture: true})
     *       _onClick(e) {
     *         this.clicked = true;
     *       }
     *     }
     */
  
  
    var eventOptions = options => // Return value typed as any to prevent TypeScript from complaining that
    // standard decorator function signature does not match TypeScript decorator
    // signature
    // TODO(kschaaf): unclear why it was only failing on this decorator and not
    // the others
    (protoOrDescriptor, name) => name !== undefined ? legacyEventOptions(options, protoOrDescriptor, name) : standardEventOptions(options, protoOrDescriptor);
  
    /**
    @license
    Copyright (c) 2019 The Polymer Project Authors. All rights reserved.
    This code may only be used under the BSD style license found at
    http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
    http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
    found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
    part of the polymer project is also subject to an additional IP rights grant
    found at http://polymer.github.io/PATENTS.txt
    */
    var supportsAdoptingStyleSheets = 'adoptedStyleSheets' in Document.prototype && 'replace' in CSSStyleSheet.prototype;
    var constructionToken = Symbol();
    class CSSResult {
      constructor(cssText, safeToken) {
        if (safeToken !== constructionToken) {
          throw new Error('CSSResult is not constructable. Use `unsafeCSS` or `css` instead.');
        }
  
        this.cssText = cssText;
      } // Note, this is a getter so that it's lazy. In practice, this means
      // stylesheets are not created until the first element instance is made.
  
  
      get styleSheet() {
        if (this._styleSheet === undefined) {
          // Note, if `adoptedStyleSheets` is supported then we assume CSSStyleSheet
          // is constructable.
          if (supportsAdoptingStyleSheets) {
            this._styleSheet = new CSSStyleSheet();
  
            this._styleSheet.replaceSync(this.cssText);
          } else {
            this._styleSheet = null;
          }
        }
  
        return this._styleSheet;
      }
  
      toString() {
        return this.cssText;
      }
  
    }
    /**
     * Wrap a value for interpolation in a css tagged template literal.
     *
     * This is unsafe because untrusted CSS text can be used to phone home
     * or exfiltrate data to an attacker controlled site. Take care to only use
     * this with trusted input.
     */
  
    var unsafeCSS = value => {
      return new CSSResult(String(value), constructionToken);
    };
  
    var textFromCSSResult = value => {
      if (value instanceof CSSResult) {
        return value.cssText;
      } else if (typeof value === 'number') {
        return value;
      } else {
        throw new Error("Value passed to 'css' function must be a 'css' function result: ".concat(value, ". Use 'unsafeCSS' to pass non-literal values, but\n            take care to ensure page security."));
      }
    };
    /**
     * Template tag which which can be used with LitElement's `style` property to
     * set element styles. For security reasons, only literal string values may be
     * used. To incorporate non-literal values `unsafeCSS` may be used inside a
     * template string part.
     */
  
  
    var css = function css(strings) {
      for (var _len = arguments.length, values = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
        values[_key - 1] = arguments[_key];
      }
  
      var cssText = values.reduce((acc, v, idx) => acc + textFromCSSResult(v) + strings[idx + 1], strings[0]);
      return new CSSResult(cssText, constructionToken);
    };
  
    /**
     * @license
     * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
     * This code may only be used under the BSD style license found at
     * http://polymer.github.io/LICENSE.txt
     * The complete set of authors may be found at
     * http://polymer.github.io/AUTHORS.txt
     * The complete set of contributors may be found at
     * http://polymer.github.io/CONTRIBUTORS.txt
     * Code distributed by Google as part of the polymer project is also
     * subject to an additional IP rights grant found at
     * http://polymer.github.io/PATENTS.txt
     */
    // This line will be used in regexes to search for LitElement usage.
    // TODO(justinfagnani): inject version number at build time
  
    (window['litElementVersions'] || (window['litElementVersions'] = [])).push('2.2.1');
    /**
     * Minimal implementation of Array.prototype.flat
     * @param arr the array to flatten
     * @param result the accumlated result
     */
  
    function arrayFlat(styles) {
      var result = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  
      for (var i = 0, length = styles.length; i < length; i++) {
        var value = styles[i];
  
        if (Array.isArray(value)) {
          arrayFlat(value, result);
        } else {
          result.push(value);
        }
      }
  
      return result;
    }
    /** Deeply flattens styles array. Uses native flat if available. */
  
  
    var flattenStyles = styles => styles.flat ? styles.flat(Infinity) : arrayFlat(styles);
  
    class LitElement extends UpdatingElement {
      /** @nocollapse */
      static finalize() {
        // The Closure JS Compiler does not always preserve the correct "this"
        // when calling static super methods (b/137460243), so explicitly bind.
        super.finalize.call(this); // Prepare styling that is stamped at first render time. Styling
        // is built from user provided `styles` or is inherited from the superclass.
  
        this._styles = this.hasOwnProperty(JSCompiler_renameProperty('styles', this)) ? this._getUniqueStyles() : this._styles || [];
      }
      /** @nocollapse */
  
  
      static _getUniqueStyles() {
        // Take care not to call `this.styles` multiple times since this generates
        // new CSSResults each time.
        // TODO(sorvell): Since we do not cache CSSResults by input, any
        // shared styles will generate new stylesheet objects, which is wasteful.
        // This should be addressed when a browser ships constructable
        // stylesheets.
        var userStyles = this.styles;
        var styles = [];
  
        if (Array.isArray(userStyles)) {
          var flatStyles = flattenStyles(userStyles); // As a performance optimization to avoid duplicated styling that can
          // occur especially when composing via subclassing, de-duplicate styles
          // preserving the last item in the list. The last item is kept to
          // try to preserve cascade order with the assumption that it's most
          // important that last added styles override previous styles.
  
          var styleSet = flatStyles.reduceRight((set, s) => {
            set.add(s); // on IE set.add does not return the set.
  
            return set;
          }, new Set()); // Array.from does not work on Set in IE
  
          styleSet.forEach(v => styles.unshift(v));
        } else if (userStyles) {
          styles.push(userStyles);
        }
  
        return styles;
      }
      /**
       * Performs element initialization. By default this calls `createRenderRoot`
       * to create the element `renderRoot` node and captures any pre-set values for
       * registered properties.
       */
  
  
      initialize() {
        super.initialize();
        this.renderRoot = this.createRenderRoot(); // Note, if renderRoot is not a shadowRoot, styles would/could apply to the
        // element's getRootNode(). While this could be done, we're choosing not to
        // support this now since it would require different logic around de-duping.
  
        if (window.ShadowRoot && this.renderRoot instanceof window.ShadowRoot) {
          this.adoptStyles();
        }
      }
      /**
       * Returns the node into which the element should render and by default
       * creates and returns an open shadowRoot. Implement to customize where the
       * element's DOM is rendered. For example, to render into the element's
       * childNodes, return `this`.
       * @returns {Element|DocumentFragment} Returns a node into which to render.
       */
  
  
      createRenderRoot() {
        return this.attachShadow({
          mode: 'open'
        });
      }
      /**
       * Applies styling to the element shadowRoot using the `static get styles`
       * property. Styling will apply using `shadowRoot.adoptedStyleSheets` where
       * available and will fallback otherwise. When Shadow DOM is polyfilled,
       * ShadyCSS scopes styles and adds them to the document. When Shadow DOM
       * is available but `adoptedStyleSheets` is not, styles are appended to the
       * end of the `shadowRoot` to [mimic spec
       * behavior](https://wicg.github.io/construct-stylesheets/#using-constructed-stylesheets).
       */
  
  
      adoptStyles() {
        var styles = this.constructor._styles;
  
        if (styles.length === 0) {
          return;
        } // There are three separate cases here based on Shadow DOM support.
        // (1) shadowRoot polyfilled: use ShadyCSS
        // (2) shadowRoot.adoptedStyleSheets available: use it.
        // (3) shadowRoot.adoptedStyleSheets polyfilled: append styles after
        // rendering
  
  
        if (window.ShadyCSS !== undefined && !window.ShadyCSS.nativeShadow) {
          window.ShadyCSS.ScopingShim.prepareAdoptedCssText(styles.map(s => s.cssText), this.localName);
        } else if (supportsAdoptingStyleSheets) {
          this.renderRoot.adoptedStyleSheets = styles.map(s => s.styleSheet);
        } else {
          // This must be done after rendering so the actual style insertion is done
          // in `update`.
          this._needsShimAdoptedStyleSheets = true;
        }
      }
  
      connectedCallback() {
        super.connectedCallback(); // Note, first update/render handles styleElement so we only call this if
        // connected after first update.
  
        if (this.hasUpdated && window.ShadyCSS !== undefined) {
          window.ShadyCSS.styleElement(this);
        }
      }
      /**
       * Updates the element. This method reflects property values to attributes
       * and calls `render` to render DOM via lit-html. Setting properties inside
       * this method will *not* trigger another update.
       * * @param _changedProperties Map of changed properties with old values
       */
  
  
      update(changedProperties) {
        super.update(changedProperties);
        var templateResult = this.render();
  
        if (templateResult instanceof TemplateResult) {
          this.constructor.render(templateResult, this.renderRoot, {
            scopeName: this.localName,
            eventContext: this
          });
        } // When native Shadow DOM is used but adoptedStyles are not supported,
        // insert styling after rendering to ensure adoptedStyles have highest
        // priority.
  
  
        if (this._needsShimAdoptedStyleSheets) {
          this._needsShimAdoptedStyleSheets = false;
  
          this.constructor._styles.forEach(s => {
            var style = document.createElement('style');
            style.textContent = s.cssText;
            this.renderRoot.appendChild(style);
          });
        }
      }
      /**
       * Invoked on each update to perform rendering tasks. This method must return
       * a lit-html TemplateResult. Setting properties inside this method will *not*
       * trigger the element to update.
       */
  
  
      render() {}
  
    }
    /**
     * Ensure this class is marked as `finalized` as an optimization ensuring
     * it will not needlessly try to `finalize`.
     *
     * Note this property name is a string to prevent breaking Closure JS Compiler
     * optimizations. See updating-element.ts for more information.
     */
  
    LitElement['finalized'] = true;
    /**
     * Render method used to render the lit-html TemplateResult to the element's
     * DOM.
     * @param {TemplateResult} Template to render.
     * @param {Element|DocumentFragment} Node into which to render.
     * @param {String} Element name.
     * @nocollapse
     */
  
    LitElement.render = render$1;
  
    /**
     * lodash (Custom Build) <https://lodash.com/>
     * Build: `lodash modularize exports="npm" -o ./`
     * Copyright jQuery Foundation and other contributors <https://jquery.org/>
     * Released under MIT license <https://lodash.com/license>
     * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
     * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
     */
  
    /** `Object#toString` result references. */
    var objectTag = '[object Object]';
    /**
     * Checks if `value` is a host object in IE < 9.
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
     */
  
    function isHostObject(value) {
      // Many host objects are `Object` objects that can coerce to strings
      // despite having improperly defined `toString` methods.
      var result = false;
  
      if (value != null && typeof value.toString != 'function') {
        try {
          result = !!(value + '');
        } catch (e) {}
      }
  
      return result;
    }
    /**
     * Creates a unary function that invokes `func` with its argument transformed.
     *
     * @private
     * @param {Function} func The function to wrap.
     * @param {Function} transform The argument transform.
     * @returns {Function} Returns the new function.
     */
  
  
    function overArg(func, transform) {
      return function (arg) {
        return func(transform(arg));
      };
    }
    /** Used for built-in method references. */
  
  
    var funcProto = Function.prototype,
        objectProto = Object.prototype;
    /** Used to resolve the decompiled source of functions. */
  
    var funcToString = funcProto.toString;
    /** Used to check objects for own properties. */
  
    var hasOwnProperty = objectProto.hasOwnProperty;
    /** Used to infer the `Object` constructor. */
  
    var objectCtorString = funcToString.call(Object);
    /**
     * Used to resolve the
     * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
     * of values.
     */
  
    var objectToString = objectProto.toString;
    /** Built-in value references. */
  
    var getPrototype = overArg(Object.getPrototypeOf, Object);
    /**
     * Checks if `value` is object-like. A value is object-like if it's not `null`
     * and has a `typeof` result of "object".
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
     * @example
     *
     * _.isObjectLike({});
     * // => true
     *
     * _.isObjectLike([1, 2, 3]);
     * // => true
     *
     * _.isObjectLike(_.noop);
     * // => false
     *
     * _.isObjectLike(null);
     * // => false
     */
  
    function isObjectLike(value) {
      return !!value && typeof value == 'object';
    }
    /**
     * Checks if `value` is a plain object, that is, an object created by the
     * `Object` constructor or one with a `[[Prototype]]` of `null`.
     *
     * @static
     * @memberOf _
     * @since 0.8.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
     * @example
     *
     * function Foo() {
     *   this.a = 1;
     * }
     *
     * _.isPlainObject(new Foo);
     * // => false
     *
     * _.isPlainObject([1, 2, 3]);
     * // => false
     *
     * _.isPlainObject({ 'x': 0, 'y': 0 });
     * // => true
     *
     * _.isPlainObject(Object.create(null));
     * // => true
     */
  
  
    function isPlainObject(value) {
      if (!isObjectLike(value) || objectToString.call(value) != objectTag || isHostObject(value)) {
        return false;
      }
  
      var proto = getPrototype(value);
  
      if (proto === null) {
        return true;
      }
  
      var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
      return typeof Ctor == 'function' && Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString;
    }
  
    /**
     * A collection of shims that provide minimal functionality of the ES6 collections.
     *
     * These implementations are not meant to be used outside of the ResizeObserver
     * modules as they cover only a limited range of use cases.
     */
  
    /* eslint-disable require-jsdoc, valid-jsdoc */
    var MapShim = function () {
      if (typeof Map !== 'undefined') {
        return Map;
      }
      /**
       * Returns index in provided array that matches the specified key.
       *
       * @param {Array<Array>} arr
       * @param {*} key
       * @returns {number}
       */
  
  
      function getIndex(arr, key) {
        var result = -1;
        arr.some(function (entry, index) {
          if (entry[0] === key) {
            result = index;
            return true;
          }
  
          return false;
        });
        return result;
      }
  
      return (
        /** @class */
        function () {
          function class_1() {
            this.__entries__ = [];
          }
  
          Object.defineProperty(class_1.prototype, "size", {
            /**
             * @returns {boolean}
             */
            get: function get() {
              return this.__entries__.length;
            },
            enumerable: true,
            configurable: true
          });
          /**
           * @param {*} key
           * @returns {*}
           */
  
          class_1.prototype.get = function (key) {
            var index = getIndex(this.__entries__, key);
            var entry = this.__entries__[index];
            return entry && entry[1];
          };
          /**
           * @param {*} key
           * @param {*} value
           * @returns {void}
           */
  
  
          class_1.prototype.set = function (key, value) {
            var index = getIndex(this.__entries__, key);
  
            if (~index) {
              this.__entries__[index][1] = value;
            } else {
              this.__entries__.push([key, value]);
            }
          };
          /**
           * @param {*} key
           * @returns {void}
           */
  
  
          class_1.prototype.delete = function (key) {
            var entries = this.__entries__;
            var index = getIndex(entries, key);
  
            if (~index) {
              entries.splice(index, 1);
            }
          };
          /**
           * @param {*} key
           * @returns {void}
           */
  
  
          class_1.prototype.has = function (key) {
            return !!~getIndex(this.__entries__, key);
          };
          /**
           * @returns {void}
           */
  
  
          class_1.prototype.clear = function () {
            this.__entries__.splice(0);
          };
          /**
           * @param {Function} callback
           * @param {*} [ctx=null]
           * @returns {void}
           */
  
  
          class_1.prototype.forEach = function (callback, ctx) {
            if (ctx === void 0) {
              ctx = null;
            }
  
            for (var _i = 0, _a = this.__entries__; _i < _a.length; _i++) {
              var entry = _a[_i];
              callback.call(ctx, entry[1], entry[0]);
            }
          };
  
          return class_1;
        }()
      );
    }();
    /**
     * Detects whether window and document objects are available in current environment.
     */
  
  
    var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined' && window.document === document; // Returns global object of a current environment.
  
    var global$1 = function () {
      if (typeof global !== 'undefined' && global.Math === Math) {
        return global;
      }
  
      if (typeof self !== 'undefined' && self.Math === Math) {
        return self;
      }
  
      if (typeof window !== 'undefined' && window.Math === Math) {
        return window;
      } // eslint-disable-next-line no-new-func
  
  
      return Function('return this')();
    }();
    /**
     * A shim for the requestAnimationFrame which falls back to the setTimeout if
     * first one is not supported.
     *
     * @returns {number} Requests' identifier.
     */
  
  
    var requestAnimationFrame$1 = function () {
      if (typeof requestAnimationFrame === 'function') {
        // It's required to use a bounded function because IE sometimes throws
        // an "Invalid calling object" error if rAF is invoked without the global
        // object on the left hand side.
        return requestAnimationFrame.bind(global$1);
      }
  
      return function (callback) {
        return setTimeout(function () {
          return callback(Date.now());
        }, 1000 / 60);
      };
    }(); // Defines minimum timeout before adding a trailing call.
  
  
    var trailingTimeout = 2;
    /**
     * Creates a wrapper function which ensures that provided callback will be
     * invoked only once during the specified delay period.
     *
     * @param {Function} callback - Function to be invoked after the delay period.
     * @param {number} delay - Delay after which to invoke callback.
     * @returns {Function}
     */
  
    function throttle(callback, delay) {
      var leadingCall = false,
          trailingCall = false,
          lastCallTime = 0;
      /**
       * Invokes the original callback function and schedules new invocation if
       * the "proxy" was called during current request.
       *
       * @returns {void}
       */
  
      function resolvePending() {
        if (leadingCall) {
          leadingCall = false;
          callback();
        }
  
        if (trailingCall) {
          proxy();
        }
      }
      /**
       * Callback invoked after the specified delay. It will further postpone
       * invocation of the original function delegating it to the
       * requestAnimationFrame.
       *
       * @returns {void}
       */
  
  
      function timeoutCallback() {
        requestAnimationFrame$1(resolvePending);
      }
      /**
       * Schedules invocation of the original function.
       *
       * @returns {void}
       */
  
  
      function proxy() {
        var timeStamp = Date.now();
  
        if (leadingCall) {
          // Reject immediately following calls.
          if (timeStamp - lastCallTime < trailingTimeout) {
            return;
          } // Schedule new call to be in invoked when the pending one is resolved.
          // This is important for "transitions" which never actually start
          // immediately so there is a chance that we might miss one if change
          // happens amids the pending invocation.
  
  
          trailingCall = true;
        } else {
          leadingCall = true;
          trailingCall = false;
          setTimeout(timeoutCallback, delay);
        }
  
        lastCallTime = timeStamp;
      }
  
      return proxy;
    } // Minimum delay before invoking the update of observers.
  
  
    var REFRESH_DELAY = 20; // A list of substrings of CSS properties used to find transition events that
    // might affect dimensions of observed elements.
  
    var transitionKeys = ['top', 'right', 'bottom', 'left', 'width', 'height', 'size', 'weight']; // Check if MutationObserver is available.
  
    var mutationObserverSupported = typeof MutationObserver !== 'undefined';
    /**
     * Singleton controller class which handles updates of ResizeObserver instances.
     */
  
    var ResizeObserverController =
    /** @class */
    function () {
      /**
       * Creates a new instance of ResizeObserverController.
       *
       * @private
       */
      function ResizeObserverController() {
        /**
         * Indicates whether DOM listeners have been added.
         *
         * @private {boolean}
         */
        this.connected_ = false;
        /**
         * Tells that controller has subscribed for Mutation Events.
         *
         * @private {boolean}
         */
  
        this.mutationEventsAdded_ = false;
        /**
         * Keeps reference to the instance of MutationObserver.
         *
         * @private {MutationObserver}
         */
  
        this.mutationsObserver_ = null;
        /**
         * A list of connected observers.
         *
         * @private {Array<ResizeObserverSPI>}
         */
  
        this.observers_ = [];
        this.onTransitionEnd_ = this.onTransitionEnd_.bind(this);
        this.refresh = throttle(this.refresh.bind(this), REFRESH_DELAY);
      }
      /**
       * Adds observer to observers list.
       *
       * @param {ResizeObserverSPI} observer - Observer to be added.
       * @returns {void}
       */
  
  
      ResizeObserverController.prototype.addObserver = function (observer) {
        if (!~this.observers_.indexOf(observer)) {
          this.observers_.push(observer);
        } // Add listeners if they haven't been added yet.
  
  
        if (!this.connected_) {
          this.connect_();
        }
      };
      /**
       * Removes observer from observers list.
       *
       * @param {ResizeObserverSPI} observer - Observer to be removed.
       * @returns {void}
       */
  
  
      ResizeObserverController.prototype.removeObserver = function (observer) {
        var observers = this.observers_;
        var index = observers.indexOf(observer); // Remove observer if it's present in registry.
  
        if (~index) {
          observers.splice(index, 1);
        } // Remove listeners if controller has no connected observers.
  
  
        if (!observers.length && this.connected_) {
          this.disconnect_();
        }
      };
      /**
       * Invokes the update of observers. It will continue running updates insofar
       * it detects changes.
       *
       * @returns {void}
       */
  
  
      ResizeObserverController.prototype.refresh = function () {
        var changesDetected = this.updateObservers_(); // Continue running updates if changes have been detected as there might
        // be future ones caused by CSS transitions.
  
        if (changesDetected) {
          this.refresh();
        }
      };
      /**
       * Updates every observer from observers list and notifies them of queued
       * entries.
       *
       * @private
       * @returns {boolean} Returns "true" if any observer has detected changes in
       *      dimensions of it's elements.
       */
  
  
      ResizeObserverController.prototype.updateObservers_ = function () {
        // Collect observers that have active observations.
        var activeObservers = this.observers_.filter(function (observer) {
          return observer.gatherActive(), observer.hasActive();
        }); // Deliver notifications in a separate cycle in order to avoid any
        // collisions between observers, e.g. when multiple instances of
        // ResizeObserver are tracking the same element and the callback of one
        // of them changes content dimensions of the observed target. Sometimes
        // this may result in notifications being blocked for the rest of observers.
  
        activeObservers.forEach(function (observer) {
          return observer.broadcastActive();
        });
        return activeObservers.length > 0;
      };
      /**
       * Initializes DOM listeners.
       *
       * @private
       * @returns {void}
       */
  
  
      ResizeObserverController.prototype.connect_ = function () {
        // Do nothing if running in a non-browser environment or if listeners
        // have been already added.
        if (!isBrowser || this.connected_) {
          return;
        } // Subscription to the "Transitionend" event is used as a workaround for
        // delayed transitions. This way it's possible to capture at least the
        // final state of an element.
  
  
        document.addEventListener('transitionend', this.onTransitionEnd_);
        window.addEventListener('resize', this.refresh);
  
        if (mutationObserverSupported) {
          this.mutationsObserver_ = new MutationObserver(this.refresh);
          this.mutationsObserver_.observe(document, {
            attributes: true,
            childList: true,
            characterData: true,
            subtree: true
          });
        } else {
          document.addEventListener('DOMSubtreeModified', this.refresh);
          this.mutationEventsAdded_ = true;
        }
  
        this.connected_ = true;
      };
      /**
       * Removes DOM listeners.
       *
       * @private
       * @returns {void}
       */
  
  
      ResizeObserverController.prototype.disconnect_ = function () {
        // Do nothing if running in a non-browser environment or if listeners
        // have been already removed.
        if (!isBrowser || !this.connected_) {
          return;
        }
  
        document.removeEventListener('transitionend', this.onTransitionEnd_);
        window.removeEventListener('resize', this.refresh);
  
        if (this.mutationsObserver_) {
          this.mutationsObserver_.disconnect();
        }
  
        if (this.mutationEventsAdded_) {
          document.removeEventListener('DOMSubtreeModified', this.refresh);
        }
  
        this.mutationsObserver_ = null;
        this.mutationEventsAdded_ = false;
        this.connected_ = false;
      };
      /**
       * "Transitionend" event handler.
       *
       * @private
       * @param {TransitionEvent} event
       * @returns {void}
       */
  
  
      ResizeObserverController.prototype.onTransitionEnd_ = function (_a) {
        var _b = _a.propertyName,
            propertyName = _b === void 0 ? '' : _b; // Detect whether transition may affect dimensions of an element.
  
        var isReflowProperty = transitionKeys.some(function (key) {
          return !!~propertyName.indexOf(key);
        });
  
        if (isReflowProperty) {
          this.refresh();
        }
      };
      /**
       * Returns instance of the ResizeObserverController.
       *
       * @returns {ResizeObserverController}
       */
  
  
      ResizeObserverController.getInstance = function () {
        if (!this.instance_) {
          this.instance_ = new ResizeObserverController();
        }
  
        return this.instance_;
      };
      /**
       * Holds reference to the controller's instance.
       *
       * @private {ResizeObserverController}
       */
  
  
      ResizeObserverController.instance_ = null;
      return ResizeObserverController;
    }();
    /**
     * Defines non-writable/enumerable properties of the provided target object.
     *
     * @param {Object} target - Object for which to define properties.
     * @param {Object} props - Properties to be defined.
     * @returns {Object} Target object.
     */
  
  
    var defineConfigurable = function defineConfigurable(target, props) {
      for (var _i = 0, _a = Object.keys(props); _i < _a.length; _i++) {
        var key = _a[_i];
        Object.defineProperty(target, key, {
          value: props[key],
          enumerable: false,
          writable: false,
          configurable: true
        });
      }
  
      return target;
    };
    /**
     * Returns the global object associated with provided element.
     *
     * @param {Object} target
     * @returns {Object}
     */
  
  
    var getWindowOf = function getWindowOf(target) {
      // Assume that the element is an instance of Node, which means that it
      // has the "ownerDocument" property from which we can retrieve a
      // corresponding global object.
      var ownerGlobal = target && target.ownerDocument && target.ownerDocument.defaultView; // Return the local global object if it's not possible extract one from
      // provided element.
  
      return ownerGlobal || global$1;
    }; // Placeholder of an empty content rectangle.
  
  
    var emptyRect = createRectInit(0, 0, 0, 0);
    /**
     * Converts provided string to a number.
     *
     * @param {number|string} value
     * @returns {number}
     */
  
    function toFloat(value) {
      return parseFloat(value) || 0;
    }
    /**
     * Extracts borders size from provided styles.
     *
     * @param {CSSStyleDeclaration} styles
     * @param {...string} positions - Borders positions (top, right, ...)
     * @returns {number}
     */
  
  
    function getBordersSize(styles) {
      var positions = [];
  
      for (var _i = 1; _i < arguments.length; _i++) {
        positions[_i - 1] = arguments[_i];
      }
  
      return positions.reduce(function (size, position) {
        var value = styles['border-' + position + '-width'];
        return size + toFloat(value);
      }, 0);
    }
    /**
     * Extracts paddings sizes from provided styles.
     *
     * @param {CSSStyleDeclaration} styles
     * @returns {Object} Paddings box.
     */
  
  
    function getPaddings(styles) {
      var positions = ['top', 'right', 'bottom', 'left'];
      var paddings = {};
  
      for (var _i = 0, positions_1 = positions; _i < positions_1.length; _i++) {
        var position = positions_1[_i];
        var value = styles['padding-' + position];
        paddings[position] = toFloat(value);
      }
  
      return paddings;
    }
    /**
     * Calculates content rectangle of provided SVG element.
     *
     * @param {SVGGraphicsElement} target - Element content rectangle of which needs
     *      to be calculated.
     * @returns {DOMRectInit}
     */
  
  
    function getSVGContentRect(target) {
      var bbox = target.getBBox();
      return createRectInit(0, 0, bbox.width, bbox.height);
    }
    /**
     * Calculates content rectangle of provided HTMLElement.
     *
     * @param {HTMLElement} target - Element for which to calculate the content rectangle.
     * @returns {DOMRectInit}
     */
  
  
    function getHTMLElementContentRect(target) {
      // Client width & height properties can't be
      // used exclusively as they provide rounded values.
      var clientWidth = target.clientWidth,
          clientHeight = target.clientHeight; // By this condition we can catch all non-replaced inline, hidden and
      // detached elements. Though elements with width & height properties less
      // than 0.5 will be discarded as well.
      //
      // Without it we would need to implement separate methods for each of
      // those cases and it's not possible to perform a precise and performance
      // effective test for hidden elements. E.g. even jQuery's ':visible' filter
      // gives wrong results for elements with width & height less than 0.5.
  
      if (!clientWidth && !clientHeight) {
        return emptyRect;
      }
  
      var styles = getWindowOf(target).getComputedStyle(target);
      var paddings = getPaddings(styles);
      var horizPad = paddings.left + paddings.right;
      var vertPad = paddings.top + paddings.bottom; // Computed styles of width & height are being used because they are the
      // only dimensions available to JS that contain non-rounded values. It could
      // be possible to utilize the getBoundingClientRect if only it's data wasn't
      // affected by CSS transformations let alone paddings, borders and scroll bars.
  
      var width = toFloat(styles.width),
          height = toFloat(styles.height); // Width & height include paddings and borders when the 'border-box' box
      // model is applied (except for IE).
  
      if (styles.boxSizing === 'border-box') {
        // Following conditions are required to handle Internet Explorer which
        // doesn't include paddings and borders to computed CSS dimensions.
        //
        // We can say that if CSS dimensions + paddings are equal to the "client"
        // properties then it's either IE, and thus we don't need to subtract
        // anything, or an element merely doesn't have paddings/borders styles.
        if (Math.round(width + horizPad) !== clientWidth) {
          width -= getBordersSize(styles, 'left', 'right') + horizPad;
        }
  
        if (Math.round(height + vertPad) !== clientHeight) {
          height -= getBordersSize(styles, 'top', 'bottom') + vertPad;
        }
      } // Following steps can't be applied to the document's root element as its
      // client[Width/Height] properties represent viewport area of the window.
      // Besides, it's as well not necessary as the <html> itself neither has
      // rendered scroll bars nor it can be clipped.
  
  
      if (!isDocumentElement(target)) {
        // In some browsers (only in Firefox, actually) CSS width & height
        // include scroll bars size which can be removed at this step as scroll
        // bars are the only difference between rounded dimensions + paddings
        // and "client" properties, though that is not always true in Chrome.
        var vertScrollbar = Math.round(width + horizPad) - clientWidth;
        var horizScrollbar = Math.round(height + vertPad) - clientHeight; // Chrome has a rather weird rounding of "client" properties.
        // E.g. for an element with content width of 314.2px it sometimes gives
        // the client width of 315px and for the width of 314.7px it may give
        // 314px. And it doesn't happen all the time. So just ignore this delta
        // as a non-relevant.
  
        if (Math.abs(vertScrollbar) !== 1) {
          width -= vertScrollbar;
        }
  
        if (Math.abs(horizScrollbar) !== 1) {
          height -= horizScrollbar;
        }
      }
  
      return createRectInit(paddings.left, paddings.top, width, height);
    }
    /**
     * Checks whether provided element is an instance of the SVGGraphicsElement.
     *
     * @param {Element} target - Element to be checked.
     * @returns {boolean}
     */
  
  
    var isSVGGraphicsElement = function () {
      // Some browsers, namely IE and Edge, don't have the SVGGraphicsElement
      // interface.
      if (typeof SVGGraphicsElement !== 'undefined') {
        return function (target) {
          return target instanceof getWindowOf(target).SVGGraphicsElement;
        };
      } // If it's so, then check that element is at least an instance of the
      // SVGElement and that it has the "getBBox" method.
      // eslint-disable-next-line no-extra-parens
  
  
      return function (target) {
        return target instanceof getWindowOf(target).SVGElement && typeof target.getBBox === 'function';
      };
    }();
    /**
     * Checks whether provided element is a document element (<html>).
     *
     * @param {Element} target - Element to be checked.
     * @returns {boolean}
     */
  
  
    function isDocumentElement(target) {
      return target === getWindowOf(target).document.documentElement;
    }
    /**
     * Calculates an appropriate content rectangle for provided html or svg element.
     *
     * @param {Element} target - Element content rectangle of which needs to be calculated.
     * @returns {DOMRectInit}
     */
  
  
    function getContentRect(target) {
      if (!isBrowser) {
        return emptyRect;
      }
  
      if (isSVGGraphicsElement(target)) {
        return getSVGContentRect(target);
      }
  
      return getHTMLElementContentRect(target);
    }
    /**
     * Creates rectangle with an interface of the DOMRectReadOnly.
     * Spec: https://drafts.fxtf.org/geometry/#domrectreadonly
     *
     * @param {DOMRectInit} rectInit - Object with rectangle's x/y coordinates and dimensions.
     * @returns {DOMRectReadOnly}
     */
  
  
    function createReadOnlyRect(_a) {
      var x = _a.x,
          y = _a.y,
          width = _a.width,
          height = _a.height; // If DOMRectReadOnly is available use it as a prototype for the rectangle.
  
      var Constr = typeof DOMRectReadOnly !== 'undefined' ? DOMRectReadOnly : Object;
      var rect = Object.create(Constr.prototype); // Rectangle's properties are not writable and non-enumerable.
  
      defineConfigurable(rect, {
        x: x,
        y: y,
        width: width,
        height: height,
        top: y,
        right: x + width,
        bottom: height + y,
        left: x
      });
      return rect;
    }
    /**
     * Creates DOMRectInit object based on the provided dimensions and the x/y coordinates.
     * Spec: https://drafts.fxtf.org/geometry/#dictdef-domrectinit
     *
     * @param {number} x - X coordinate.
     * @param {number} y - Y coordinate.
     * @param {number} width - Rectangle's width.
     * @param {number} height - Rectangle's height.
     * @returns {DOMRectInit}
     */
  
  
    function createRectInit(x, y, width, height) {
      return {
        x: x,
        y: y,
        width: width,
        height: height
      };
    }
    /**
     * Class that is responsible for computations of the content rectangle of
     * provided DOM element and for keeping track of it's changes.
     */
  
  
    var ResizeObservation =
    /** @class */
    function () {
      /**
       * Creates an instance of ResizeObservation.
       *
       * @param {Element} target - Element to be observed.
       */
      function ResizeObservation(target) {
        /**
         * Broadcasted width of content rectangle.
         *
         * @type {number}
         */
        this.broadcastWidth = 0;
        /**
         * Broadcasted height of content rectangle.
         *
         * @type {number}
         */
  
        this.broadcastHeight = 0;
        /**
         * Reference to the last observed content rectangle.
         *
         * @private {DOMRectInit}
         */
  
        this.contentRect_ = createRectInit(0, 0, 0, 0);
        this.target = target;
      }
      /**
       * Updates content rectangle and tells whether it's width or height properties
       * have changed since the last broadcast.
       *
       * @returns {boolean}
       */
  
  
      ResizeObservation.prototype.isActive = function () {
        var rect = getContentRect(this.target);
        this.contentRect_ = rect;
        return rect.width !== this.broadcastWidth || rect.height !== this.broadcastHeight;
      };
      /**
       * Updates 'broadcastWidth' and 'broadcastHeight' properties with a data
       * from the corresponding properties of the last observed content rectangle.
       *
       * @returns {DOMRectInit} Last observed content rectangle.
       */
  
  
      ResizeObservation.prototype.broadcastRect = function () {
        var rect = this.contentRect_;
        this.broadcastWidth = rect.width;
        this.broadcastHeight = rect.height;
        return rect;
      };
  
      return ResizeObservation;
    }();
  
    var ResizeObserverEntry =
    /** @class */
    function () {
      /**
       * Creates an instance of ResizeObserverEntry.
       *
       * @param {Element} target - Element that is being observed.
       * @param {DOMRectInit} rectInit - Data of the element's content rectangle.
       */
      function ResizeObserverEntry(target, rectInit) {
        var contentRect = createReadOnlyRect(rectInit); // According to the specification following properties are not writable
        // and are also not enumerable in the native implementation.
        //
        // Property accessors are not being used as they'd require to define a
        // private WeakMap storage which may cause memory leaks in browsers that
        // don't support this type of collections.
  
        defineConfigurable(this, {
          target: target,
          contentRect: contentRect
        });
      }
  
      return ResizeObserverEntry;
    }();
  
    var ResizeObserverSPI =
    /** @class */
    function () {
      /**
       * Creates a new instance of ResizeObserver.
       *
       * @param {ResizeObserverCallback} callback - Callback function that is invoked
       *      when one of the observed elements changes it's content dimensions.
       * @param {ResizeObserverController} controller - Controller instance which
       *      is responsible for the updates of observer.
       * @param {ResizeObserver} callbackCtx - Reference to the public
       *      ResizeObserver instance which will be passed to callback function.
       */
      function ResizeObserverSPI(callback, controller, callbackCtx) {
        /**
         * Collection of resize observations that have detected changes in dimensions
         * of elements.
         *
         * @private {Array<ResizeObservation>}
         */
        this.activeObservations_ = [];
        /**
         * Registry of the ResizeObservation instances.
         *
         * @private {Map<Element, ResizeObservation>}
         */
  
        this.observations_ = new MapShim();
  
        if (typeof callback !== 'function') {
          throw new TypeError('The callback provided as parameter 1 is not a function.');
        }
  
        this.callback_ = callback;
        this.controller_ = controller;
        this.callbackCtx_ = callbackCtx;
      }
      /**
       * Starts observing provided element.
       *
       * @param {Element} target - Element to be observed.
       * @returns {void}
       */
  
  
      ResizeObserverSPI.prototype.observe = function (target) {
        if (!arguments.length) {
          throw new TypeError('1 argument required, but only 0 present.');
        } // Do nothing if current environment doesn't have the Element interface.
  
  
        if (typeof Element === 'undefined' || !(Element instanceof Object)) {
          return;
        }
  
        if (!(target instanceof getWindowOf(target).Element)) {
          throw new TypeError('parameter 1 is not of type "Element".');
        }
  
        var observations = this.observations_; // Do nothing if element is already being observed.
  
        if (observations.has(target)) {
          return;
        }
  
        observations.set(target, new ResizeObservation(target));
        this.controller_.addObserver(this); // Force the update of observations.
  
        this.controller_.refresh();
      };
      /**
       * Stops observing provided element.
       *
       * @param {Element} target - Element to stop observing.
       * @returns {void}
       */
  
  
      ResizeObserverSPI.prototype.unobserve = function (target) {
        if (!arguments.length) {
          throw new TypeError('1 argument required, but only 0 present.');
        } // Do nothing if current environment doesn't have the Element interface.
  
  
        if (typeof Element === 'undefined' || !(Element instanceof Object)) {
          return;
        }
  
        if (!(target instanceof getWindowOf(target).Element)) {
          throw new TypeError('parameter 1 is not of type "Element".');
        }
  
        var observations = this.observations_; // Do nothing if element is not being observed.
  
        if (!observations.has(target)) {
          return;
        }
  
        observations.delete(target);
  
        if (!observations.size) {
          this.controller_.removeObserver(this);
        }
      };
      /**
       * Stops observing all elements.
       *
       * @returns {void}
       */
  
  
      ResizeObserverSPI.prototype.disconnect = function () {
        this.clearActive();
        this.observations_.clear();
        this.controller_.removeObserver(this);
      };
      /**
       * Collects observation instances the associated element of which has changed
       * it's content rectangle.
       *
       * @returns {void}
       */
  
  
      ResizeObserverSPI.prototype.gatherActive = function () {
        var _this = this;
  
        this.clearActive();
        this.observations_.forEach(function (observation) {
          if (observation.isActive()) {
            _this.activeObservations_.push(observation);
          }
        });
      };
      /**
       * Invokes initial callback function with a list of ResizeObserverEntry
       * instances collected from active resize observations.
       *
       * @returns {void}
       */
  
  
      ResizeObserverSPI.prototype.broadcastActive = function () {
        // Do nothing if observer doesn't have active observations.
        if (!this.hasActive()) {
          return;
        }
  
        var ctx = this.callbackCtx_; // Create ResizeObserverEntry instance for every active observation.
  
        var entries = this.activeObservations_.map(function (observation) {
          return new ResizeObserverEntry(observation.target, observation.broadcastRect());
        });
        this.callback_.call(ctx, entries, ctx);
        this.clearActive();
      };
      /**
       * Clears the collection of active observations.
       *
       * @returns {void}
       */
  
  
      ResizeObserverSPI.prototype.clearActive = function () {
        this.activeObservations_.splice(0);
      };
      /**
       * Tells whether observer has active observations.
       *
       * @returns {boolean}
       */
  
  
      ResizeObserverSPI.prototype.hasActive = function () {
        return this.activeObservations_.length > 0;
      };
  
      return ResizeObserverSPI;
    }(); // Registry of internal observers. If WeakMap is not available use current shim
    // for the Map collection as it has all required methods and because WeakMap
    // can't be fully polyfilled anyway.
  
  
    var observers = typeof WeakMap !== 'undefined' ? new WeakMap() : new MapShim();
    /**
     * ResizeObserver API. Encapsulates the ResizeObserver SPI implementation
     * exposing only those methods and properties that are defined in the spec.
     */
  
    var ResizeObserver =
    /** @class */
    function () {
      /**
       * Creates a new instance of ResizeObserver.
       *
       * @param {ResizeObserverCallback} callback - Callback that is invoked when
       *      dimensions of the observed elements change.
       */
      function ResizeObserver(callback) {
        if (!(this instanceof ResizeObserver)) {
          throw new TypeError('Cannot call a class as a function.');
        }
  
        if (!arguments.length) {
          throw new TypeError('1 argument required, but only 0 present.');
        }
  
        var controller = ResizeObserverController.getInstance();
        var observer = new ResizeObserverSPI(callback, controller, this);
        observers.set(this, observer);
      }
  
      return ResizeObserver;
    }(); // Expose public methods of ResizeObserver.
  
  
    ['observe', 'unobserve', 'disconnect'].forEach(function (method) {
      ResizeObserver.prototype[method] = function () {
        var _a;
  
        return (_a = observers.get(this))[method].apply(_a, arguments);
      };
    });
  
    var index = function () {
      // Export existing implementation if available.
      if (typeof global$1.ResizeObserver !== 'undefined') {
        return global$1.ResizeObserver;
      }
  
      return ResizeObserver;
    }();
  
    var FlowLayout = {
      placeLayoutElement(element, context) {
        var {
          parentNode,
          closestTo: {
            node,
            isParent,
            placement
          }
        } = context;
  
        if (isParent) {
          if (placement === 'start') {
            parentNode.prepend(element);
          } else {
            parentNode.append(element);
          }
        } else {
          if (placement === 'left' || placement === 'top') {
            parentNode.insertBefore(element, node);
          } else {
            parentNode.insertBefore(element, node.nextSibling);
          }
        }
      }
  
    };
    var AbsoluteLayout = {
      placeLayoutElement(element, context) {
        var {
          x,
          y,
          parentNode
        } = context;
        element.style.position = 'absolute';
        element.style.left = "".concat(x, "px");
        element.style.top = "".concat(y, "px");
        parentNode.append(element);
      }
  
    };
  
    function isSourceObject(value) {
      return value instanceof Object && value !== null && value.constructor.__WEBBIT_CLASSNAME__ === 'Source';
    }
  
    class Webbit extends LitElement {
      static get __WEBBIT_CLASSNAME__() {
        return 'Webbit';
      }
  
      constructor() {
        var _this;
  
        super();
        _this = this;
        this.defaultProps = {};
        this.hasUpdatedAtleastOnce = new Promise(
        /*#__PURE__*/
        function () {
          var _ref = _asyncToGenerator(function* (resolve) {
            yield _this.updateComplete;
            resolve();
          });
  
          return function (_x) {
            return _ref.apply(this, arguments);
          };
        }());
  
        var _loop = function _loop(name) {
          var property = _this.constructor.properties[name];
  
          if (['sourceProvider', 'sourceKey', 'webbitId', 'fromProperties'].includes(name)) {
            return "continue";
          }
  
          var {
            type,
            attribute,
            reflect,
            structure
          } = property;
  
          if (attribute === false || !reflect) {
            return "continue";
          }
  
          Object.defineProperty(_this, name, {
            get() {
              var getter = this.constructor.properties[name].get;
  
              if (typeof getter === 'function') {
                return getter.bind(this)();
              }
  
              return this["_".concat(name)];
            },
  
            set(value) {
              var setter = this.constructor.properties[name].set;
              var sourceProvider = store.getSourceProvider(this.sourceProvider);
  
              if (this.isClone) {
                if (isPlainObject(value) && (value.__fromSource__ || value.__fromDefault__)) {
                  return;
                }
  
                var _oldValue = this["_".concat(name)];
                this["_".concat(name)] = typeof setter === 'function' ? setter.bind(this)(value) : value;
                this.requestUpdate(name, _oldValue);
  
                this._dispatchPropertyChange(name, _oldValue, value);
  
                return;
              }
  
              if (isPlainObject(value) && (value.__fromSource__ || value.__fromDefault__)) {
                var _oldValue2 = this["_".concat(name)];
                this["_".concat(name)] = typeof setter === 'function' ? setter.bind(this)(value.__value__) : value.__value__;
                this.requestUpdate(name, _oldValue2);
  
                this._dispatchPropertyChange(name, _oldValue2, value.__value__);
  
                return;
              } else if (typeof this.sourceKey === 'string' && sourceProvider) {
                var source = sourceProvider.getRawSource(this.sourceKey);
  
                if (source) {
                  var propSource = source.__sources__[name];
  
                  if (typeof propSource === 'undefined') {
                    if (this.constructor.properties[name].primary && source.__fromProvider__) {
                      sourceProvider.userUpdate(this.sourceKey, value);
                      return;
                    }
                  } else if (propSource.__fromProvider__) {
                    sourceProvider.userUpdate(propSource.__key__, value);
                    return;
                  }
                }
              }
  
              var oldValue = this["_".concat(name)];
              this["_".concat(name)] = typeof setter === 'function' ? setter.bind(this)(value) : value;
              this.requestUpdate(name, oldValue);
  
              this._dispatchPropertyChange(name, oldValue, value);
            }
  
          });
        };
  
        for (var name in this.constructor.properties) {
          var _ret = _loop(name);
  
          if (_ret === "continue") continue;
        }
  
        Object.defineProperty(this, 'sourceProvider', {
          get() {
            return this._sourceProvider || store.getDefaultSourceProvider();
          },
  
          set(value) {
            var _this2 = this;
  
            return _asyncToGenerator(function* () {
              var oldValue = _this2._sourceProvider;
              _this2._sourceProvider = value;
              yield _this2.requestUpdate('sourceProvider', oldValue);
  
              _this2._dispatchSourceProviderChange();
  
              if (store.hasSourceProvider(value)) {
                _this2._subscribeToSource();
  
                _this2.setSourcesFromProperties();
              }
            })();
          }
  
        });
        Object.defineProperty(this, 'fromProperties', {
          get() {
            return this._fromProperties;
          },
  
          set(value) {
            var _this3 = this;
  
            return _asyncToGenerator(function* () {
              var oldValue = _this3._fromProperties;
              _this3._fromProperties = value;
              yield _this3.requestUpdate('fromProperties', oldValue);
  
              _this3.setSourcesFromProperties();
            })();
          }
  
        });
        Object.defineProperty(this, 'sourceKey', {
          get() {
            return this._sourceKey;
          },
  
          set(value) {
            var _this4 = this;
  
            return _asyncToGenerator(function* () {
              var oldValue = _this4._sourceKey;
              _this4._sourceKey = value;
              yield _this4.requestUpdate('sourceKey', oldValue);
  
              _this4._dispatchSourceKeyChange();
  
              _this4._subscribeToSource();
  
              _this4.setSourcesFromProperties();
            })();
          }
  
        });
        Object.defineProperty(this, 'webbitId', {
          get() {
            return this._webbitId;
          },
  
          set(value) {
            var oldValue = this._webbitId; // If a node is currently being cloned, we want to
            // make sure the cloned node and all its children
            // maintain the same Webbit IDs.
  
            if (window.webbitRegistry.isCloning()) {
              this._webbitId = value;
              this.requestUpdate('webbitId', oldValue);
              return;
            }
  
            if (value === oldValue) {
              return;
            }
  
            var webbitId = window.webbitRegistry._generateWebbitId(this, value);
  
            if (!window.webbitRegistry.hasWebbit(oldValue)) {
              window.webbitRegistry._created(webbitId, this);
            } else {
              window.webbitRegistry._changedWebbitId(oldValue, webbitId, this);
            }
  
            this._webbitId = webbitId;
            this.requestUpdate('webbitId', oldValue);
  
            if (this.getAttribute('webbit-id') !== webbitId) {
              this.setAttribute('webbit-id', webbitId);
            }
  
            this._dispatchWebbitIdChange();
          }
  
        });
        this.sourceProvider = null;
        this.sourceKey = null;
        this.fromProperties = [];
        this._source = null;
        this._unsubscribeSource = null;
        this.webbitId = null;
        this.isClone = false;
        var resizeObserver = new index(() => {
          this.resized();
        });
        resizeObserver.observe(this);
        store.sourceProviderAdded(providerName => {
          if (providerName === this.sourceProvider) {
            this._subscribeToSource();
  
            this.setSourcesFromProperties();
          }
        });
        store.defaultSourceProviderSet(defaultSourceProvider => {
          if (!this._sourceProvider) {
            this.sourceProvider = defaultSourceProvider;
          }
  
          this._subscribeToSource();
  
          this.setSourcesFromProperties();
        });
      }
  
      _subscribeToSource() {
        var _this5 = this;
  
        return _asyncToGenerator(function* () {
          yield _this5.hasUpdatedAtleastOnce;
  
          if (_this5._unsubscribeSource) {
            _this5._unsubscribeSource();
          }
  
          var sourceProvider = store.getSourceProvider(_this5.sourceProvider);
  
          if (_this5.sourceKey && sourceProvider) {
            _this5._unsubscribeSource = sourceProvider.subscribe(_this5.sourceKey, source => {
              _this5._setPropsFromSource(source); // Request update in case there are no props but we need an update anyway
  
  
              _this5.requestUpdate();
            });
  
            _this5._setPropsFromSource(sourceProvider.getSource(_this5.sourceKey)); // Request update in case there are no props but we need an update anyway
  
  
            _this5.requestUpdate();
          }
        })();
      }
  
      _dispatchSourceKeyChange() {
        var event = new CustomEvent('source-key-change', {
          detail: {
            sourceKey: this.sourceKey
          },
          bubbles: true,
          composed: true
        });
        this.dispatchEvent(event);
      }
  
      _dispatchPropertyChange(property, oldValue, newValue) {
        var event = new CustomEvent('property-change', {
          detail: {
            property,
            oldValue,
            newValue
          },
          bubbles: true,
          composed: true
        });
        this.dispatchEvent(event);
      }
  
      _dispatchSourceProviderChange() {
        var event = new CustomEvent('source-provider-change', {
          detail: {
            sourceProvider: this.sourceProvider
          },
          bubbles: true,
          composed: true
        });
        this.dispatchEvent(event);
      }
  
      _dispatchWebbitIdChange() {
        var event = new CustomEvent('source-add', {
          detail: {
            webbitId: this.webbitId
          },
          bubbles: true,
          composed: true
        });
        this.dispatchEvent(event);
      }
  
      _setPropsFromSource(source) {
        this._source = source;
  
        for (var name in this.constructor.properties) {
          var property = this.constructor.properties[name];
  
          if (['sourceProvider', 'sourceKey', 'webbitId', 'fromProperties'].includes(name)) {
            continue;
          }
  
          var {
            type,
            attribute,
            reflect,
            structure,
            primary
          } = property;
  
          if (attribute === false || !reflect) {
            continue;
          }
  
          var propSource = source ? source[name] : undefined;
  
          if (typeof propSource === 'undefined') {
            if (primary && !isSourceObject(source) && typeof source !== 'undefined') {
              this[name] = {
                __fromSource__: true,
                __value__: source
              }; // If we're no longer using the source to set the prop
              // change the prop to the default value
            } else {
              this.setPropToDefault(name);
            }
          } else {
            this[name] = {
              __fromSource__: true,
              __value__: propSource
            };
          }
        }
      }
  
      setSourcesFromProperties() {
        var sourceProvider = store.getSourceProvider(this.sourceProvider);
  
        if (!this.hasSource() || !sourceProvider) {
          return;
        }
  
        if (isSourceObject(this.getSource()) || typeof sourceProvider.getRawSource(this.sourceKey) === 'undefined') {
          var allProps = Object.keys(this.constructor.properties);
          var sourceProps = allProps.filter(prop => !['sourceProvider', 'sourceKey', 'fromProperties', 'webbitId'].includes(prop));
          this.fromProperties.forEach(fromProperty => {
            if (!sourceProps.includes(fromProperty)) {
              return;
            }
  
            var key = "".concat(this.sourceKey, "/").concat(fromProperty);
  
            if (typeof sourceProvider.getRawSource(key) === 'undefined') {
              sourceProvider.userUpdate(key, this.defaultProps[fromProperty]);
            }
          });
        }
      }
  
      firstUpdated() {
        for (var name in this.constructor.properties) {
          if (['sourceProvider', 'sourceKey', 'webbitId', 'fromProperties'].includes(name)) {
            continue;
          }
  
          this.setDefaultValue(name, this["_".concat(name)]);
        }
      }
  
      setDefaultValue(property, value) {
        this.defaultProps[property] = value;
      }
  
      setPropToDefault(property) {
        this[property] = {
          __fromDefault__: true,
          __value__: this.defaultProps[property]
        };
      }
  
      isPropertyConnectedToSource(name) {
        if (!this.hasSource()) {
          return false;
        }
  
        var source = this.getSource();
  
        if (!isSourceObject(source)) {
          var property = this.constructor.properties[name];
          return !!property && !!property.primary;
        }
  
        return name in source;
      }
  
      hasSource() {
        return this.sourceKey !== null && typeof this.sourceKey !== 'undefined';
      }
  
      getSource() {
        return this.hasSource() ? this._source : undefined;
      }
  
      resized() {}
  
      placeLayoutElement(element, context) {
        FlowLayout.placeLayoutElement(element, context);
      }
  
    }
  
    var Webbit$1 = Webbit;
  
    exports.AbsoluteLayout = AbsoluteLayout;
    exports.CSSResult = CSSResult;
    exports.FlowLayout = FlowLayout;
    exports.LitElement = LitElement;
    exports.SVGTemplateResult = SVGTemplateResult;
    exports.TemplateResult = TemplateResult;
    exports.UpdatingElement = UpdatingElement;
    exports.Webbit = Webbit$1;
    exports.css = css;
    exports.customElement = customElement;
    exports.defaultConverter = defaultConverter;
    exports.eventOptions = eventOptions;
    exports.html = html;
    exports.notEqual = notEqual;
    exports.property = property;
    exports.query = query;
    exports.queryAll = queryAll;
    exports.supportsAdoptingStyleSheets = supportsAdoptingStyleSheets;
    exports.svg = svg;
    exports.unsafeCSS = unsafeCSS;
  
    Object.defineProperty(exports, '__esModule', { value: true });
  
  })));
  