(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.components = {}));
})(this, (function (exports) { 'use strict';

  /**
   * @type {{ [type: string]: any }}
   */const EMPTY={OBJ:{},ARR:[],BOOL:true,FUN:()=>{}};/**
   * @typedef {any[]} ActiveTreeCache
   * @type {ActiveTreeCache}
   */const ActiveRenderState=[];const ComponentTreeCache=new Map;/**
   * @typedef {Map<VTree, any>} InstanceCache
   * @type {InstanceCache}
   */const InstanceCache=new Map;/**
   * @typedef {Map<Transaction, Set<any>>} MountCache
   * @type {MountCache}
   */const MountCache=new Map;

  const caches={ComponentTreeCache,InstanceCache};

  var internals = /*#__PURE__*/Object.freeze({
    __proto__: null,
    caches: caches
  });

  const $$render=Symbol.for("diff.render");const $$vTree=Symbol.for("diff.vTree");const $$unsubscribe=Symbol.for("diff.unsubscribe");const $$type=Symbol.for("diff.type");const $$hooks=Symbol.for("diff.hooks");const $$insertAfter=Symbol.for("diff.after");

  /**
   * Create state allows a class or function component to create state from the
   * render function. Any other attempt to use this will fail. All createState
   * invocations must be in the exact same order, every render.
   *
   * Borrowed from the concept introduced by React, useState. This will be used by
   * the React Compatibility later renamed as `useState`. The reason this is named
   * `createState` is due to no guarentees of parity with React hooks.
   *
   * @param {any} defaultValue
   *
   * @returns {any[]}
   */function createState$1(defaultValue={}){if(ActiveRenderState.length===0){throw new Error("Cannot create state unless in render function")}const[activeComponent]=ActiveRenderState;const hooks=activeComponent[$$hooks];const activeHook=hooks.fns[hooks.i];const currentValue=activeHook?activeHook[0]:defaultValue;const retVal=activeHook||[currentValue];/**
     * @param {any} newValue
     */const setState=newValue=>{retVal[0]=newValue;return activeComponent.forceUpdate()};if(retVal.length===1){retVal.push(setState);}// Return currentValue and setState.
  hooks.fns[hooks.i]=retVal;// Increment the hooks count.
  hooks.i+=1;return retVal}

  /**
   * Allow a function component to hook into lifecycle methods in a manner
   * consistent with class components. Meaning you can leverage existing lifecycle
   * events in a function component.
   *
   * @param {Function=} didMountOrUpdate - A function that is called whenever the
   * component is mounted. To hook into component updates, return a function. This
   * returned function will be called whenever the component updates.
   *
   * @param {Function=} unMount - A function that is called whenever a component
   * is unmounted.
   *
   * @returns {void}
   */function createSideEffect(didMountOrUpdate,unMount){if(ActiveRenderState.length===0){throw new Error("Cannot create side effect unless in render function")}if(typeof didMountOrUpdate!=="function"&&typeof unMount!=="function"){throw new Error("Missing function for side effect")}const[activeComponent]=ActiveRenderState;const hooks=activeComponent[$$hooks];const isSet=Boolean(hooks.fns[hooks.i]);// Indicate this hook has been installed.
  hooks.fns[hooks.i]=true;// Increment the hooks count.
  activeComponent[$$hooks].i+=1;// Short-circuit if effects are already installed.
  if(isSet){return}// Schedule a componentDidMount if a function was provided
  if(typeof didMountOrUpdate==="function"){const oldDidMount=activeComponent.componentDidMount;// Install the componentDidMount lifecycle hook.
  activeComponent.componentDidMount=()=>{if(typeof oldDidMount==="function"){oldDidMount();}// Install the componentDidUpdate lifecycle hook.
  const didUpdate=didMountOrUpdate();const oldComponentDidUpdate=activeComponent.componentDidUpdate;// Then if the user specifies a return function, use that as didUpdate
  if(typeof didUpdate==="function"){activeComponent.componentDidUpdate=()=>{if(typeof oldComponentDidUpdate==="function"){oldComponentDidUpdate();}didUpdate();};}};}// Install the componentWillUnmount lifecycle hook.
  if(typeof unMount==="function"){const oldWillUnmount=activeComponent.componentWillUnmount;activeComponent.componentWillUnmount=()=>{if(typeof oldWillUnmount==="function"){oldWillUnmount();}unMount();};}}

  function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError("Cannot call a class as a function");
    }
  }

  function _defineProperties(target, props) {
    for (var i = 0; i < props.length; i++) {
      var descriptor = props[i];
      descriptor.enumerable = descriptor.enumerable || false;
      descriptor.configurable = true;
      if ("value" in descriptor) descriptor.writable = true;
      Object.defineProperty(target, descriptor.key, descriptor);
    }
  }

  function _createClass(Constructor, protoProps, staticProps) {
    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
    if (staticProps) _defineProperties(Constructor, staticProps);
    Object.defineProperty(Constructor, "prototype", {
      writable: false
    });
    return Constructor;
  }

  function _inherits(subClass, superClass) {
    if (typeof superClass !== "function" && superClass !== null) {
      throw new TypeError("Super expression must either be null or a function");
    }

    subClass.prototype = Object.create(superClass && superClass.prototype, {
      constructor: {
        value: subClass,
        writable: true,
        configurable: true
      }
    });
    Object.defineProperty(subClass, "prototype", {
      writable: false
    });
    if (superClass) _setPrototypeOf(subClass, superClass);
  }

  function _getPrototypeOf(o) {
    _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
      return o.__proto__ || Object.getPrototypeOf(o);
    };
    return _getPrototypeOf(o);
  }

  function _setPrototypeOf(o, p) {
    _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
      o.__proto__ = p;
      return o;
    };

    return _setPrototypeOf(o, p);
  }

  function _isNativeReflectConstruct() {
    if (typeof Reflect === "undefined" || !Reflect.construct) return false;
    if (Reflect.construct.sham) return false;
    if (typeof Proxy === "function") return true;

    try {
      Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
      return true;
    } catch (e) {
      return false;
    }
  }

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

    return self;
  }

  function _possibleConstructorReturn(self, call) {
    if (call && (typeof call === "object" || typeof call === "function")) {
      return call;
    } else if (call !== void 0) {
      throw new TypeError("Derived constructors may only return object or undefined");
    }

    return _assertThisInitialized(self);
  }

  function _createSuper(Derived) {
    var hasNativeReflectConstruct = _isNativeReflectConstruct();

    return function _createSuperInternal() {
      var Super = _getPrototypeOf(Derived),
          result;

      if (hasNativeReflectConstruct) {
        var NewTarget = _getPrototypeOf(this).constructor;

        result = Reflect.construct(Super, arguments, NewTarget);
      } else {
        result = Super.apply(this, arguments);
      }

      return _possibleConstructorReturn(this, result);
    };
  }

  /** @type {{ [key: string]: any }} */var globalThis = typeof global==="object"?global:(typeof window==="object"?window:self)||{};

  /**
   * @returns {DIFF_BINDING}
   */var diff = /** @type {DIFF_BINDING} */ /** @type {any} */globalThis[Symbol.for("diffHTML")];

  const{release: release$1,Internals: Internals$2}=diff;/**
   * This is called whenever a component is removed or in the case of a function
   * component is called whenever a component is updated.
   *
   * @param {VTree} vTree - The respecting tree pointing to the component
   */function componentWillUnmount(vTree){const componentTree=ComponentTreeCache.get(vTree);ComponentTreeCache.forEach((parentTree,childTree)=>{});const domNode=Internals$2.NodeCache.get(vTree);// Clean up attached Shadow DOM.
  if(domNode&&/** @type {any} */domNode.shadowRoot){release$1(/** @type {any} */domNode.shadowRoot);}vTree.childNodes.forEach(componentWillUnmount);if(!InstanceCache.has(componentTree)){return}const instance=InstanceCache.get(componentTree);InstanceCache.delete(componentTree);// Empty out all hooks for gc. If using a stateless class or function, they
  // may not have this value set.
  if(instance[$$hooks]){instance[$$hooks].fns.length=0;instance[$$hooks].i=0;}ComponentTreeCache.delete(vTree);// If there is a parent, ensure it is called recursively.
  if(ComponentTreeCache.has(componentTree)){componentWillUnmount(componentTree);}// Ensure this is a stateful component. Stateless components do not get
  // lifecycle events yet.
  instance&&instance.componentWillUnmount&&instance.componentWillUnmount();}

  const{Internals: Internals$1}=diff;/**
   * @param {any} target
   * @param {VTree} vTree
   * @param {HTMLElement | VTree | null=} value
   */const invokeRef=(target=EMPTY.OBJ,vTree,value)=>{let{ref}=target.props||target;// Allow refs to be passed to HTML elements. When in a DOM environment
  // a Node will be passed to the ref function and assigned.
  if(!ref){target=Internals$1.NodeCache.get(vTree);ref=vTree.attributes.ref;}// Only backfill the value with target if no value was provided (either null
  // or a truthy value).
  if(value===undefined){value=target;}if(typeof ref==="function"){ref(value);}else if(typeof ref==="object"&&ref){ref.current=value;}else if(typeof ref==="string"){target.refs={...target.refs,[ref]:value};}};/**
   * @param {VTree} vTree - Element to start search, crawl for refs to invoke
   * @param {HTMLElement | VTree | null} value - Value to populate ref with
   */function invokeRefsForVTree(vTree,value){const componentTree=ComponentTreeCache.get(vTree);if(vTree.childNodes.length){vTree.childNodes.filter(Boolean).forEach(childNode=>{invokeRefsForVTree(childNode,value);});}const instance=InstanceCache.get(componentTree||vTree);if(!instance){invokeRef(Internals$1.NodeCache.get(vTree),vTree,value);return}// If any instances exist, loop through them and invoke the respective `ref`
  // logic.
  invokeRef(instance,vTree,value);}

  const{createNode,NodeCache,PATCH_TYPE,decodeEntities}=diff.Internals;const uppercaseEx=/[A-Z]/g;/**
   * @param {Transaction} transaction
   */var beforeMount = (transaction=>{if(transaction.aborted){return}const{patches}=transaction;const{length}=patches;let i=0;while(true){const patchType=patches[i];// Exhausted remaining patches.
  if(i===length){break}switch(patchType){case PATCH_TYPE.SET_ATTRIBUTE:{const vTree=patches[i+1];const name=patches[i+2];const value=patches[i+3];uppercaseEx.lastIndex=0;// Normalize uppercase attributes.
  if(uppercaseEx.test(name)){uppercaseEx.lastIndex=0;const newName=name.replace(uppercaseEx,(/** @type {string} */ch)=>`-${ch.toLowerCase()}`);if(value&&typeof value==="string"){const decodedValue=decodeEntities(value);if(NodeCache.has(vTree)){/** @type {HTMLElement} */NodeCache.get(vTree).setAttribute(newName,decodedValue);}}}if(name==="ref"){invokeRef(createNode(vTree),vTree);}i+=4;break}case PATCH_TYPE.REMOVE_ATTRIBUTE:{i+=3;break}case PATCH_TYPE.REPLACE_CHILD:{const oldTree=patches[i+2];componentWillUnmount(oldTree);i+=3;break}case PATCH_TYPE.NODE_VALUE:case PATCH_TYPE.INSERT_BEFORE:{i+=4;break}case PATCH_TYPE.REMOVE_CHILD:{const vTree=patches[i+1];invokeRefsForVTree(vTree,null);componentWillUnmount(vTree);i+=2;break}}}});

  const{createTree: createTree$1}=diff;/**
   * Used during a synchronization flow. Takes in a vTree and a context object
   * and renders the component as a class or a function. Calls standard lifecycle
   * methods.
   *
   * @param {VTree} vTree - tree to render
   * @param {Transaction} transaction - used to key mounts to a transaction
   *
   * @returns {VTree | null}
   */function renderComponent(vTree,transaction){const props=vTree.attributes;const RawComponent=vTree.rawNodeName;const isNewable=RawComponent.prototype&&RawComponent.prototype.render;const isInstance=InstanceCache.has(vTree);/** @type {VTree|null} */let renderedTree=null;// Existing class component rerender.
  if(isInstance){const instance=InstanceCache.get(vTree);if(instance.componentWillReceiveProps){instance.componentWillReceiveProps(props);}if(instance.shouldComponentUpdate&&instance.shouldComponentUpdate(props,instance.state)){ActiveRenderState.push(instance);// Reset the hooks iterator.
  instance[$$hooks].i=0;renderedTree=createTree$1(instance.render(props,instance.state));ActiveRenderState.length=0;if(instance.componentDidUpdate&&instance.componentDidUpdate){instance.componentDidUpdate(instance.props,instance.state);}}else {return null}}// New class instance.
  else if(isNewable){const instance=new RawComponent(props);// Associate the instance to the vTree.
  InstanceCache.set(vTree,instance);ActiveRenderState.push(instance);// Initial render of the class component, this should not be called again
  // for the same component in the same position. It will be picked up
  // automatically as a class component and rendered via its own Transaction.
  const renderRetVal=instance.render(props,instance.state);ActiveRenderState.length=0;MountCache.get(transaction)?.add(instance);renderedTree=createTree$1(renderRetVal||"#text");if(typeof renderedTree.rawNodeName!=="function"&&renderedTree.nodeType===11&&!renderedTree.childNodes.length){renderedTree=createTree$1("#text");}// Set up the HoC parent/child relationship.
  if(typeof renderedTree.rawNodeName==="function"){ComponentTreeCache.set(renderedTree,vTree);}// Associate the instance with the vTree.
  instance[$$vTree]=vTree;}// Function component, upgrade to a class to make it reactive.
  else {let FunctionComponent=/*#__PURE__*/function(_Component){_inherits(FunctionComponent,_Component);var _super=_createSuper(FunctionComponent);/**
         * @param {any} props
         */function FunctionComponent(props){var _this;_classCallCheck(this,FunctionComponent);_this=_super.call(this,props);_this[$$vTree]=null;return _this}/**
         * @param {any} props
         * @param {any} state
         */_createClass(FunctionComponent,[{key:"render",value:function render(props,state){// Always render the latest `rawNodeName` of a VTree in case of
  // hot-reloading the cached value above wouldn't be correct.
  return createTree$1(RawComponent(props,state))}/** @type {VTree | null} */}]);return FunctionComponent}(Component);const instance=new FunctionComponent(props);// Associate the instance to the vTree.
  InstanceCache.set(vTree,instance);// Allow hooks to "hook" into the active rendering component.
  ActiveRenderState.push(instance);let renderRetVal=null;try{renderRetVal=instance.render(props,instance.state);}catch(e){// Clean up after a potential failure.
  ActiveRenderState.length=0;MountCache.delete(transaction);throw e}ActiveRenderState.length=0;MountCache.get(transaction)?.add(instance);renderedTree=createTree$1(renderRetVal||"#text");// If the rendered return value is an empty fragment, default to an empty
  // text value.
  if(typeof renderedTree.rawNodeName!=="function"&&renderedTree.nodeType===11&&!renderedTree.childNodes.length){renderedTree=createTree$1("#text");}// Set up the HoC parent/child relationship.
  if(typeof renderedTree.rawNodeName==="function"){ComponentTreeCache.set(renderedTree,vTree);}// Associate the instance with the vTree.
  instance[$$vTree]=vTree;}if(renderedTree!==vTree){// Map all top-level fragment elements to this parent node.
  if(renderedTree.nodeType===11){renderedTree.childNodes.forEach(childNode=>{ComponentTreeCache.set(childNode,vTree);});}// Otherwise directly map the rendered VTree to the component tree.
  else {ComponentTreeCache.set(renderedTree,vTree);}}return renderedTree}

  const{assign: assign$1}=Object;const{tasks}=diff.Internals;/**
   * @param {VTree} oldTree
   * @param {VTree} newTree
   * @param {Transaction} transaction
   *
   * @returns {VTree | null}
   */function render(oldTree,newTree,transaction){let oldComponentTree=null;// When there is an oldTree and it has childNodes, attempt to look up first
  // by the top-level element, or by the first element.
  if(oldTree){// First try and lookup the old tree as a component.
  oldComponentTree=ComponentTreeCache.get(oldTree);// If that fails, try looking up its first child.
  if(!oldComponentTree&&oldTree.childNodes){oldComponentTree=ComponentTreeCache.get(oldTree.childNodes[0]);}}// If there is no old component, or if the components do not match, then we
  // are rendering a brand new component.
  if(!oldComponentTree||oldComponentTree.rawNodeName!==newTree.rawNodeName){return renderComponent(newTree,transaction)}// Otherwise re-use the existing component if the constructors are the same.
  if(oldComponentTree){// Update the incoming props/attrs.
  assign$1(oldComponentTree.attributes,newTree.attributes);return renderComponent(oldComponentTree,transaction)}return oldTree}/**
   * @param {VTree} vTree
   */const releaseHook=vTree=>componentWillUnmount(vTree);/**
   * @param {VTree} vTree
   */const createTreeHook=vTree=>{const{customElements}=globalThis;const Constructor=customElements&&customElements.get(vTree.nodeName);if(typeof vTree.rawNodeName==="function"||Constructor){vTree.attributes.children=vTree.attributes.children||vTree.childNodes;}};/**
   * @param {VTree} vTree
   */const createNodeHook=vTree=>{// Only look up elements with a dash in the name.
  if(!vTree.nodeName.includes("-"))return;// Convert this to globalThis
  const{customElements}=globalThis;const Constructor=customElements&&customElements.get(vTree.nodeName);if(Constructor){return new Constructor(vTree.attributes)}};/**
   * @param {VTree} oldTree
   * @param {VTree} newTree
   * @param {Transaction} transaction
   */const syncTreeHook=(oldTree,newTree,transaction)=>{// Render components during synchronization.
  if(// When child is a Component
  typeof newTree.rawNodeName==="function"&&(// If there is an oldTree and it's not the existing component, trigger a
  // render.
  oldTree&&oldTree.rawNodeName?oldTree.rawNodeName!==newTree.rawNodeName:false)){return render(oldTree,newTree,transaction)}if(!newTree.childNodes){return oldTree}// Loop through childNodes seeking out components to render.
  for(let i=0;i<newTree.childNodes.length;i++){const newChildTree=newTree.childNodes[i];const oldChildTree=oldTree.childNodes&&oldTree.childNodes[i]||EMPTY.OBJ;const isNewFunction=typeof newChildTree.rawNodeName==="function";// Search through the DOM tree for more components to render.
  if(isNewFunction){const renderTree=render(oldChildTree,newChildTree,transaction);// If nothing was rendered, return the oldTree.
  if(!renderTree){return oldTree}// Inject the rendered tree into the position.
  if(renderTree){newTree.childNodes[i]=renderTree;// If the rendered tree is a fragment, splice in the children, as this
  // is simply a container for the nodes.
  if(renderTree.nodeType===11){// If a function was returned, re-run the inspection over this
  // element.
  if(typeof renderTree.rawNodeName==="function"){i=i-1;}// Replace the fragment with the rendered elements. This reduces and
  // flattens the fragments into their respective nodes. If there are
  // none, then they are removed from the DOM and nothing is rendered.
  else {newTree.childNodes.splice(i,1,...renderTree.childNodes);}}}}}};var middleware = (()=>assign$1((/** @type {Transaction} */transaction)=>{MountCache.set(transaction,new Set);// Splice after syncTrees to handle componentWillUnmount and modifying
  // attributes.
  if(transaction.tasks.includes(tasks.syncTrees)){const syncTreesIndex=transaction.tasks.indexOf(tasks.syncTrees);transaction.tasks.splice(syncTreesIndex+1,0,function beforeMountLifecycle(){beforeMount(transaction);return transaction});}// Splice after patchNode to handle componentDidMount and refs.
  if(transaction.tasks.includes(tasks.patchNode)){const patchNodeIndex=transaction.tasks.indexOf(tasks.patchNode);transaction.tasks.splice(patchNodeIndex+1,0,function afterMountLifecycle(){MountCache.get(transaction)?.forEach(instance=>{invokeRef(instance,instance[$$vTree]);if(typeof instance.componentDidMount==="function"){instance.componentDidMount();}});return transaction});}return (/** @type {Transaction} */transaction)=>{MountCache.delete(transaction);}},{displayName:"componentTask",syncTreeHook,createNodeHook,createTreeHook,releaseHook}));

  const{outerHTML,innerHTML,createTree,release,Internals}=diff;const{isArray}=Array;const{setPrototypeOf,defineProperty,keys,assign}=Object;const RenderDebounce=new WeakMap;/**
   * @param {Props} defaultProps
   * @returns {string[]}
   */const getObserved=({defaultProps})=>defaultProps?keys(defaultProps):EMPTY.ARR;/**
   * Creates the `component.props` object.
   *
   * @param {any} domNode
   * @param {Props} existingProps
   */const createProps=(domNode,existingProps={})=>{return getObserved(domNode.constructor).reduce((props,attr)=>({[attr]:(domNode.hasAttribute(attr)?domNode.getAttribute(attr):domNode[attr])||props[attr]||domNode.constructor.defaultProps[attr],...props}),existingProps)};/**
   * Creates the `component.state` object.
   *
   * @param {Component} domNode
   * @param {State} newState
   */const createState=(domNode,newState)=>assign({},domNode.state,newState);/**
   * Finds all VTrees associated with a component.
   *
   * @param {VTree[]} childTrees
   * @param {VTree} vTree
   */const getChildTrees=(childTrees,vTree)=>{ComponentTreeCache.forEach((parentTree,childTree)=>{if(parentTree===vTree){ComponentTreeCache.delete(childTree);if(typeof childTree.rawNodeName!=="function"){childTrees.push(childTree);}else {getChildTrees(childTrees,childTree);}}});};/**
   * Represents a vanilla JavaScript Component. This is a lightweight version of
   * what you'd find in most modern web application libraries. It provides a
   * React-inspired API.
   */let Component=/*#__PURE__*/function(){/**
     * Creates a lightweight stateful JavaScript component. Takes the static
     * default props and applies them to the incoming initial props.
     *
     * @param {Props} initialProps
     */function Component(initialProps){_classCallCheck(this,Component);this.state={};this[$$type]="class";this[$$vTree]=null;this[$$hooks]={fns:[],i:0};let instance=this;// This is how we detect if this is a Web Component or not. The class
  // must be registered ahead of time within the customElements global
  // registry. This will allow us to construct the HTMLElement and attach the
  // shadow root.
  try{instance=Reflect.construct(HTMLElement,[],new.target);/** @type {any} */instance.attachShadow({mode:"open"});/** @type {any} */instance[$$type]="web";}catch(e){// Not a Web Component.
  /** @type {any} */instance[$$type]="class";}const props=instance.props=assign({},initialProps);const{defaultProps=EMPTY.OBJ}=/** @type {any} */instance.constructor;// Merge default props into props object.
  if(typeof defaultProps==="object"&&!isArray(defaultProps)){keys(defaultProps||EMPTY.OBJ).forEach(prop=>{if(prop in props&&props[prop]!==undefined){return}instance.props[prop]=defaultProps[prop];});}return instance}/**
     * @param {Props} props
     * @param {State} state
     *
     * @returns {VTree[] | VTree | undefined}
     */ // @ts-ignore
  _createClass(Component,[{key:"render",value:function render(props,state){return undefined}/**
     * Changes the component state synchronously by shallow merging the incoming
     * state into the previous state. Rendering will then be scheduled to the
     * next reachable tick. If this is called multiple times on a single tick
     * all that will happen is the state will be updated by no rendering will
     * occur until the next tick.
     *
     * You can await this method to know when rendering has completed.
     *
     * @param {State} state
     */},{key:"setState",value:function setState(state){this.state=assign({},this.state,state);if(!RenderDebounce.has(this)){RenderDebounce.set(this,new Promise(resolve=>setTimeout(()=>{RenderDebounce.delete(this);this.componentWillReceiveProps(this.props,this.state);if(this.shouldComponentUpdate(this.props,this.state)){resolve(this[$$render]());}else {resolve(null);}})));}return RenderDebounce.get(this)}/**
     * Schedule a render to happen, bypassing shouldComponentUpdate. Bound to the
     * same tick logic as setState, allowing this to be called as many times as
     * you want.
     */},{key:"forceUpdate",value:function forceUpdate(){if(!RenderDebounce.has(this)){RenderDebounce.set(this,new Promise(resolve=>setTimeout(()=>{RenderDebounce.delete(this);this.componentWillReceiveProps(this.props,this.state);resolve(this[$$render]());})));}return RenderDebounce.get(this)}/** @type {State} */},{key:$$render,value:/**
     * Stateful render. Used when a component changes and needs to re-render
     * itself. This is triggered on `setState` and `forceUpdate` calls.
     *
     * @return {Transaction | undefined}
     */function(){// This is a WebComponent, so do something different.
  if(this[$$type]==="web"){const oldProps=this.props;const oldState=this.state;this.props=createProps(this,this.props);this.state=createState(this,this.state);ActiveRenderState.push(this);if($$hooks in this){this[$$hooks].i=0;}const transaction=/** @type {Transaction} */innerHTML(/** @type {any} */this.shadowRoot,this.render(this.props,this.state));ActiveRenderState.length=0;this.componentDidUpdate(oldProps,oldState);return transaction}// Get the fragment tree associated with this component. This is used to
  // lookup rendered children.
  let vTree=this[$$vTree];/**
       * Find all previously rendered top-level children associated to this
       * component. This will be used to diff against the newly rendered
       * elements.
       *
       * @type {VTree[]}
       */const childTrees=[];// Lookup all DOM nodes that were associated at the top level with this
  // component.
  vTree&&getChildTrees(childTrees,vTree);// Render directly from the Component.
  ActiveRenderState.push(this);if($$hooks in this){this[$$hooks].i=0;}let renderTree=this.render(this.props,this.state);ActiveRenderState.length=0;// Do not render.
  if(!renderTree){return}const renderTreeAsVTree=/** @type {VTree} */renderTree;// Always compare a fragment to a fragment. If the renderTree was not
  // wrapped, ensure it is here.
  if(renderTreeAsVTree.nodeType!==11){const isList=("length"in renderTree);const renderTreeAsList=/** @type {VTree[]} */renderTree;renderTree=createTree(isList?renderTreeAsList:[renderTreeAsVTree]);}// Put all the nodes together into a fragment for diffing.
  const fragment=createTree(childTrees);const tasks=[...Internals.defaultTasks];const syncTreesIndex=tasks.indexOf(Internals.tasks.syncTrees);// Inject a custom task after syncing has finished, but before patching has
  // occured. This gives us time to add additional patch logic per render.
  tasks.splice(syncTreesIndex+1,0,(/** @type {Transaction} */transaction)=>{let lastTree=null;// Reconcile all top-level replacements and additions.
  for(let i=0;i<fragment.childNodes.length;i++){const childTree=fragment.childNodes[i];// Replace if the nodes are different.
  if(childTree&&childTrees[i]&&childTrees[i]!==childTree){transaction.patches.push(Internals.PATCH_TYPE.REPLACE_CHILD,childTree,childTrees[i]);lastTree=childTree;}// Add if there is no old Node.
  else if(lastTree&&!childTrees[i]){transaction.patches.push(Internals.PATCH_TYPE.INSERT_BEFORE,$$insertAfter,childTree,lastTree);lastTree=childTree;}// Keep the old node.
  else {lastTree=childTrees[i];}ComponentTreeCache.set(childTree,vTree);}return transaction});// Compare the existing component node(s) to the new node(s).
  const transaction=/** @type {Transaction} */outerHTML(fragment,renderTree,{tasks});// Empty the fragment after using.
  fragment.childNodes.length=0;release(fragment);this.componentDidUpdate(this.props,this.state);return transaction}},{key:"connectedCallback",value:function connectedCallback(){const{defaultProps={}}=/** @type {any} */this.constructor;// This callback gets called during replace operations, there is no point
  // in re-rendering or creating a new shadow root due to this.
  // Always do a full render when mounting, so that something is visible.
  this[$$render]();this.componentDidMount();keys(defaultProps).forEach(propName=>{defineProperty(this,propName,{get:()=>this.props[propName],set:value=>{this.props[propName]=value;this.componentWillReceiveProps(this.props,this.state);if(this.shouldComponentUpdate(this.props,this.state)){this[$$render]();}}});});}},{key:"disconnectedCallback",value:function disconnectedCallback(){this.componentWillUnmount();}},{key:"attributeChangedCallback",value:function attributeChangedCallback(){const nextProps=createProps(this,this.props);const nextState=createState(this,this.state);this.componentWillReceiveProps(nextProps,nextState);if(this.shouldComponentUpdate(nextProps,nextState)){this[$$render]();}}/**
     * @param {Props} props
     * @param {State} state
     *
     * @returns {boolean}
     */ // @ts-ignore
  },{key:"shouldComponentUpdate",value:function shouldComponentUpdate(props,state){return true}},{key:"componentWillMount",value:function componentWillMount(){}},{key:"componentDidMount",value:function componentDidMount(){}/**
     * @param {Props} props
     * @param {State} state
     */ // @ts-ignore
  },{key:"componentWillReceiveProps",value:function componentWillReceiveProps(props,state){}/**
     * @param {Props} props
     * @param {State} state
     *
     * @returns {void}
     */ // @ts-ignore
  },{key:"componentDidUpdate",value:function componentDidUpdate(props,state){}},{key:"componentWillUnmount",value:function componentWillUnmount(){}}],[{key:"observedAttributes",get:function(){return getObserved(this).map(key=>key.toLowerCase())}/**
     * Allow tests to unbind this task, you would not typically need to do this in
     * a web application, as this code loads once and is not reloaded.
     *
     * @type {Function | null}
     */},{key:"subscribeMiddleware",value:/**
     * Adds the Component middleware, but first unregisters any previous
     * Component middleware.
     *
     * @returns {void}
     */function subscribeMiddleware(){const unsubscribe=Component[$$unsubscribe];unsubscribe&&unsubscribe();Component[$$unsubscribe]=diff.use(middleware());}/**
     * Removes the Component middleware and clears the internal caches.
     *
     * @returns {void}
     */},{key:"unsubscribeMiddleware",value:function unsubscribeMiddleware(){const unsubscribe=Component[$$unsubscribe];unsubscribe&&unsubscribe();ComponentTreeCache.clear();InstanceCache.clear();}}]);return Component}();// TODO: Can this be done inside the constructor so that class components do not
  // need to inherit from HTMLElement?
  Component[$$unsubscribe]=null;try{setPrototypeOf(Component.prototype,HTMLElement.prototype);}catch{}// Automatically subscribe the Component middleware.
  Component.subscribeMiddleware();

  exports.Component = Component;
  exports.Internals = internals;
  exports.createSideEffect = createSideEffect;
  exports.createState = createState$1;

  Object.defineProperty(exports, '__esModule', { value: true });

}));
