text: import { r as registerInstance, e as getContext, h, g as getElement } from './index-7e7ca1ac.js';
  import { s as stripTrailingSlash, a as addLeadingSlash, h as hasBasename, b as stripBasename, c as createLocation, d as createKey, e as createPath, f as stripLeadingSlash, l as locationsAreEqual } from './location-utils-fea12957.js';
  import { s as storageAvailable, a as supportsHistory, b as supportsPopStateOnHashChange, g as getConfirmation, c as isExtraneousPopstateEvent, d as supportsGoWithoutReloadUsingHash } from './dom-utils-109a7d75.js';
  import { A as ActiveRouter } from './active-router-82933e3d.js';
  
  const warning = (value, ...args) => {
      if (!value) {
          console.warn(...args);
      }
  };
  
  // Adapted from the https://github.com/ReactTraining/history and converted to TypeScript
  const createTransitionManager = () => {
      let prompt;
      let listeners = [];
      const setPrompt = (nextPrompt) => {
          warning(prompt == null, 'A history supports only one prompt at a time');
          prompt = nextPrompt;
          return () => {
              if (prompt === nextPrompt) {
                  prompt = null;
              }
          };
      };
      const confirmTransitionTo = (location, action, getUserConfirmation, callback) => {
          // TODO: If another transition starts while we're still confirming
          // the previous one, we may end up in a weird state. Figure out the
          // best way to handle this.
          if (prompt != null) {
              const result = typeof prompt === 'function' ? prompt(location, action) : prompt;
              if (typeof result === 'string') {
                  if (typeof getUserConfirmation === 'function') {
                      getUserConfirmation(result, callback);
                  }
                  else {
                      warning(false, 'A history needs a getUserConfirmation function in order to use a prompt message');
                      callback(true);
                  }
              }
              else {
                  // Return false from a transition hook to cancel the transition.
                  callback(result !== false);
              }
          }
          else {
              callback(true);
          }
      };
      const appendListener = (fn) => {
          let isActive = true;
          const listener = (...args) => {
              if (isActive) {
                  fn(...args);
              }
          };
          listeners.push(listener);
          return () => {
              isActive = false;
              listeners = listeners.filter(item => item !== listener);
          };
      };
      const notifyListeners = (...args) => {
          listeners.forEach(listener => listener(...args));
      };
      return {
          setPrompt,
          confirmTransitionTo,
          appendListener,
          notifyListeners
      };
  };
  
  const createScrollHistory = (win, applicationScrollKey = 'scrollPositions') => {
      let scrollPositions = new Map();
      const set = (key, value) => {
          scrollPositions.set(key, value);
          if (storageAvailable(win, 'sessionStorage')) {
              const arrayData = [];
              scrollPositions.forEach((value, key) => {
                  arrayData.push([key, value]);
              });
              win.sessionStorage.setItem('scrollPositions', JSON.stringify(arrayData));
          }
      };
      const get = (key) => {
          return scrollPositions.get(key);
      };
      const has = (key) => {
          return scrollPositions.has(key);
      };
      const capture = (key) => {
          set(key, [win.scrollX, win.scrollY]);
      };
      if (storageAvailable(win, 'sessionStorage')) {
          const scrollData = win.sessionStorage.getItem(applicationScrollKey);
          scrollPositions = scrollData ?
              new Map(JSON.parse(scrollData)) :
              scrollPositions;
      }
      if ('scrollRestoration' in win.history) {
          history.scrollRestoration = 'manual';
      }
      return {
          set,
          get,
          has,
          capture
      };
  };
  
  // Adapted from the https://github.com/ReactTraining/history and converted to TypeScript
  const PopStateEvent = 'popstate';
  const HashChangeEvent$1 = 'hashchange';
  /**
   * Creates a history object that uses the HTML5 history API including
   * pushState, replaceState, and the popstate event.
   */
  const createBrowserHistory = (win, props = {}) => {
      let forceNextPop = false;
      const globalHistory = win.history;
      const globalLocation = win.location;
      const globalNavigator = win.navigator;
      const canUseHistory = supportsHistory(win);
      const needsHashChangeListener = !supportsPopStateOnHashChange(globalNavigator);
      const scrollHistory = createScrollHistory(win);
      const forceRefresh = (props.forceRefresh != null) ? props.forceRefresh : false;
      const getUserConfirmation = (props.getUserConfirmation != null) ? props.getUserConfirmation : getConfirmation;
      const keyLength = (props.keyLength != null) ? props.keyLength : 6;
      const basename = props.basename ? stripTrailingSlash(addLeadingSlash(props.basename)) : '';
      const getHistoryState = () => {
          try {
              return win.history.state || {};
          }
          catch (e) {
              // IE 11 sometimes throws when accessing window.history.state
              // See https://github.com/ReactTraining/history/pull/289
              return {};
          }
      };
      const getDOMLocation = (historyState) => {
          historyState = historyState || {};
          const { key, state } = historyState;
          const { pathname, search, hash } = globalLocation;
          let path = pathname + search + hash;
          warning((!basename || hasBasename(path, basename)), 'You are attempting to use a basename on a page whose URL path does not begin ' +
              'with the basename. Expected path "' + path + '" to begin with "' + basename + '".');
          if (basename) {
              path = stripBasename(path, basename);
          }
          return createLocation(path, state, key || createKey(keyLength));
      };
      const transitionManager = createTransitionManager();
      const setState = (nextState) => {
          // Capture location for the view before changing history.
          scrollHistory.capture(history.location.key);
          Object.assign(history, nextState);
          // Set scroll position based on its previous storage value
          history.location.scrollPosition = scrollHistory.get(history.location.key);
          history.length = globalHistory.length;
          transitionManager.notifyListeners(history.location, history.action);
      };
      const handlePopState = (event) => {
          // Ignore extraneous popstate events in WebKit.
          if (!isExtraneousPopstateEvent(globalNavigator, event)) {
              handlePop(getDOMLocation(event.state));
          }
      };
      const handleHashChange = () => {
          handlePop(getDOMLocation(getHistoryState()));
      };
      const handlePop = (location) => {
          if (forceNextPop) {
              forceNextPop = false;
              setState();
          }
          else {
              const action = 'POP';
              transitionManager.confirmTransitionTo(location, action, getUserConfirmation, (ok) => {
                  if (ok) {
                      setState({ action, location });
                  }
                  else {
                      revertPop(location);
                  }
              });
          }
      };
      const revertPop = (fromLocation) => {
          const toLocation = history.location;
          // TODO: We could probably make this more reliable by
          // keeping a list of keys we've seen in sessionStorage.
          // Instead, we just default to 0 for keys we don't know.
          let toIndex = allKeys.indexOf(toLocation.key);
          let fromIndex = allKeys.indexOf(fromLocation.key);
          if (toIndex === -1) {
              toIndex = 0;
          }
          if (fromIndex === -1) {
              fromIndex = 0;
          }
          const delta = toIndex - fromIndex;
          if (delta) {
              forceNextPop = true;
              go(delta);
          }
      };
      const initialLocation = getDOMLocation(getHistoryState());
      let allKeys = [initialLocation.key];
      let listenerCount = 0;
      let isBlocked = false;
      // Public interface
      const createHref = (location) => {
          return basename + createPath(location);
      };
      const push = (path, state) => {
          warning(!(typeof path === 'object' && path.state !== undefined && state !== undefined), 'You should avoid providing a 2nd state argument to push when the 1st ' +
              'argument is a location-like object that already has state; it is ignored');
          const action = 'PUSH';
          const location = createLocation(path, state, createKey(keyLength), history.location);
          transitionManager.confirmTransitionTo(location, action, getUserConfirmation, (ok) => {
              if (!ok) {
                  return;
              }
              const href = createHref(location);
              const { key, state } = location;
              if (canUseHistory) {
                  globalHistory.pushState({ key, state }, '', href);
                  if (forceRefresh) {
                      globalLocation.href = href;
                  }
                  else {
                      const prevIndex = allKeys.indexOf(history.location.key);
                      const nextKeys = allKeys.slice(0, prevIndex === -1 ? 0 : prevIndex + 1);
                      nextKeys.push(location.key);
                      allKeys = nextKeys;
                      setState({ action, location });
                  }
              }
              else {
                  warning(state === undefined, 'Browser history cannot push state in browsers that do not support HTML5 history');
                  globalLocation.href = href;
              }
          });
      };
      const replace = (path, state) => {
          warning(!(typeof path === 'object' && path.state !== undefined && state !== undefined), 'You should avoid providing a 2nd state argument to replace when the 1st ' +
              'argument is a location-like object that already has state; it is ignored');
          const action = 'REPLACE';
          const location = createLocation(path, state, createKey(keyLength), history.location);
          transitionManager.confirmTransitionTo(location, action, getUserConfirmation, (ok) => {
              if (!ok) {
                  return;
              }
              const href = createHref(location);
              const { key, state } = location;
              if (canUseHistory) {
                  globalHistory.replaceState({ key, state }, '', href);
                  if (forceRefresh) {
                      globalLocation.replace(href);
                  }
                  else {
                      const prevIndex = allKeys.indexOf(history.location.key);
                      if (prevIndex !== -1) {
                          allKeys[prevIndex] = location.key;
                      }
                      setState({ action, location });
                  }
              }
              else {
                  warning(state === undefined, 'Browser history cannot replace state in browsers that do not support HTML5 history');
                  globalLocation.replace(href);
              }
          });
      };
      const go = (n) => {
          globalHistory.go(n);
      };
      const goBack = () => go(-1);
      const goForward = () => go(1);
      const checkDOMListeners = (delta) => {
          listenerCount += delta;
          if (listenerCount === 1) {
              win.addEventListener(PopStateEvent, handlePopState);
              if (needsHashChangeListener) {
                  win.addEventListener(HashChangeEvent$1, handleHashChange);
              }
          }
          else if (listenerCount === 0) {
              win.removeEventListener(PopStateEvent, handlePopState);
              if (needsHashChangeListener) {
                  win.removeEventListener(HashChangeEvent$1, handleHashChange);
              }
          }
      };
      const block = (prompt = '') => {
          const unblock = transitionManager.setPrompt(prompt);
          if (!isBlocked) {
              checkDOMListeners(1);
              isBlocked = true;
          }
          return () => {
              if (isBlocked) {
                  isBlocked = false;
                  checkDOMListeners(-1);
              }
              return unblock();
          };
      };
      const listen = (listener) => {
          const unlisten = transitionManager.appendListener(listener);
          checkDOMListeners(1);
          return () => {
              checkDOMListeners(-1);
              unlisten();
          };
      };
      const history = {
          length: globalHistory.length,
          action: 'POP',
          location: initialLocation,
          createHref,
          push,
          replace,
          go,
          goBack,
          goForward,
          block,
          listen,
          win: win
      };
      return history;
  };
  
  // Adapted from the https://github.com/ReactTraining/history and converted to TypeScript
  const HashChangeEvent = 'hashchange';
  const HashPathCoders = {
      hashbang: {
          encodePath: (path) => path.charAt(0) === '!' ? path : '!/' + stripLeadingSlash(path),
          decodePath: (path) => path.charAt(0) === '!' ? path.substr(1) : path
      },
      noslash: {
          encodePath: stripLeadingSlash,
          decodePath: addLeadingSlash
      },
      slash: {
          encodePath: addLeadingSlash,
          decodePath: addLeadingSlash
      }
  };
  const createHashHistory = (win, props = {}) => {
      let forceNextPop = false;
      let ignorePath = null;
      let listenerCount = 0;
      let isBlocked = false;
      const globalLocation = win.location;
      const globalHistory = win.history;
      const canGoWithoutReload = supportsGoWithoutReloadUsingHash(win.navigator);
      const keyLength = (props.keyLength != null) ? props.keyLength : 6;
      const { getUserConfirmation = getConfirmation, hashType = 'slash' } = props;
      const basename = props.basename ? stripTrailingSlash(addLeadingSlash(props.basename)) : '';
      const { encodePath, decodePath } = HashPathCoders[hashType];
      const getHashPath = () => {
          // We can't use window.location.hash here because it's not
          // consistent across browsers - Firefox will pre-decode it!
          const href = globalLocation.href;
          const hashIndex = href.indexOf('#');
          return hashIndex === -1 ? '' : href.substring(hashIndex + 1);
      };
      const pushHashPath = (path) => (globalLocation.hash = path);
      const replaceHashPath = (path) => {
          const hashIndex = globalLocation.href.indexOf('#');
          globalLocation.replace(globalLocation.href.slice(0, hashIndex >= 0 ? hashIndex : 0) + '#' + path);
      };
      const getDOMLocation = () => {
          let path = decodePath(getHashPath());
          warning((!basename || hasBasename(path, basename)), 'You are attempting to use a basename on a page whose URL path does not begin ' +
              'with the basename. Expected path "' + path + '" to begin with "' + basename + '".');
          if (basename) {
              path = stripBasename(path, basename);
          }
          return createLocation(path, undefined, createKey(keyLength));
      };
      const transitionManager = createTransitionManager();
      const setState = (nextState) => {
          Object.assign(history, nextState);
          history.length = globalHistory.length;
          transitionManager.notifyListeners(history.location, history.action);
      };
      const handleHashChange = () => {
          const path = getHashPath();
          const encodedPath = encodePath(path);
          if (path !== encodedPath) {
              // Ensure we always have a properly-encoded hash.
              replaceHashPath(encodedPath);
          }
          else {
              const location = getDOMLocation();
              const prevLocation = history.location;
              if (!forceNextPop && locationsAreEqual(prevLocation, location)) {
                  return; // A hashchange doesn't always == location change.
              }
              if (ignorePath === createPath(location)) {
                  return; // Ignore this change; we already setState in push/replace.
              }
              ignorePath = null;
              handlePop(location);
          }
      };
      const handlePop = (location) => {
          if (forceNextPop) {
              forceNextPop = false;
              setState();
          }
          else {
              const action = 'POP';
              transitionManager.confirmTransitionTo(location, action, getUserConfirmation, (ok) => {
                  if (ok) {
                      setState({ action, location });
                  }
                  else {
                      revertPop(location);
                  }
              });
          }
      };
      const revertPop = (fromLocation) => {
          const toLocation = history.location;
          // TODO: We could probably make this more reliable by
          // keeping a list of paths we've seen in sessionStorage.
          // Instead, we just default to 0 for paths we don't know.
          let toIndex = allPaths.lastIndexOf(createPath(toLocation));
          let fromIndex = allPaths.lastIndexOf(createPath(fromLocation));
          if (toIndex === -1) {
              toIndex = 0;
          }
          if (fromIndex === -1) {
              fromIndex = 0;
          }
          const delta = toIndex - fromIndex;
          if (delta) {
              forceNextPop = true;
              go(delta);
          }
      };
      // Ensure the hash is encoded properly before doing anything else.
      const path = getHashPath();
      const encodedPath = encodePath(path);
      if (path !== encodedPath) {
          replaceHashPath(encodedPath);
      }
      const initialLocation = getDOMLocation();
      let allPaths = [createPath(initialLocation)];
      // Public interface
      const createHref = (location) => ('#' + encodePath(basename + createPath(location)));
      const push = (path, state) => {
          warning(state === undefined, 'Hash history cannot push state; it is ignored');
          const action = 'PUSH';
          const location = createLocation(path, undefined, createKey(keyLength), history.location);
          transitionManager.confirmTransitionTo(location, action, getUserConfirmation, (ok) => {
              if (!ok) {
                  return;
              }
              const path = createPath(location);
              const encodedPath = encodePath(basename + path);
              const hashChanged = getHashPath() !== encodedPath;
              if (hashChanged) {
                  // We cannot tell if a hashchange was caused by a PUSH, so we'd
                  // rather setState here and ignore the hashchange. The caveat here
                  // is that other hash histories in the page will consider it a POP.
                  ignorePath = path;
                  pushHashPath(encodedPath);
                  const prevIndex = allPaths.lastIndexOf(createPath(history.location));
                  const nextPaths = allPaths.slice(0, prevIndex === -1 ? 0 : prevIndex + 1);
                  nextPaths.push(path);
                  allPaths = nextPaths;
                  setState({ action, location });
              }
              else {
                  warning(false, 'Hash history cannot PUSH the same path; a new entry will not be added to the history stack');
                  setState();
              }
          });
      };
      const replace = (path, state) => {
          warning(state === undefined, 'Hash history cannot replace state; it is ignored');
          const action = 'REPLACE';
          const location = createLocation(path, undefined, createKey(keyLength), history.location);
          transitionManager.confirmTransitionTo(location, action, getUserConfirmation, (ok) => {
              if (!ok) {
                  return;
              }
              const path = createPath(location);
              const encodedPath = encodePath(basename + path);
              const hashChanged = getHashPath() !== encodedPath;
              if (hashChanged) {
                  // We cannot tell if a hashchange was caused by a REPLACE, so we'd
                  // rather setState here and ignore the hashchange. The caveat here
                  // is that other hash histories in the page will consider it a POP.
                  ignorePath = path;
                  replaceHashPath(encodedPath);
              }
              const prevIndex = allPaths.indexOf(createPath(history.location));
              if (prevIndex !== -1) {
                  allPaths[prevIndex] = path;
              }
              setState({ action, location });
          });
      };
      const go = (n) => {
          warning(canGoWithoutReload, 'Hash history go(n) causes a full page reload in this browser');
          globalHistory.go(n);
      };
      const goBack = () => go(-1);
      const goForward = () => go(1);
      const checkDOMListeners = (win, delta) => {
          listenerCount += delta;
          if (listenerCount === 1) {
              win.addEventListener(HashChangeEvent, handleHashChange);
          }
          else if (listenerCount === 0) {
              win.removeEventListener(HashChangeEvent, handleHashChange);
          }
      };
      const block = (prompt = '') => {
          const unblock = transitionManager.setPrompt(prompt);
          if (!isBlocked) {
              checkDOMListeners(win, 1);
              isBlocked = true;
          }
          return () => {
              if (isBlocked) {
                  isBlocked = false;
                  checkDOMListeners(win, -1);
              }
              return unblock();
          };
      };
      const listen = (listener) => {
          const unlisten = transitionManager.appendListener(listener);
          checkDOMListeners(win, 1);
          return () => {
              checkDOMListeners(win, -1);
              unlisten();
          };
      };
      const history = {
          length: globalHistory.length,
          action: 'POP',
          location: initialLocation,
          createHref,
          push,
          replace,
          go,
          goBack,
          goForward,
          block,
          listen,
          win: win
      };
      return history;
  };
  
  const getLocation = (location, root) => {
    // Remove the root URL if found at beginning of string
    const pathname = location.pathname.indexOf(root) == 0 ?
      '/' + location.pathname.slice(root.length) :
      location.pathname;
    return Object.assign({}, location, { pathname });
  };
  const HISTORIES = {
    'browser': createBrowserHistory,
    'hash': createHashHistory
  };
  const Router = class {
    constructor(hostRef) {
      registerInstance(this, hostRef);
      this.root = '/';
      this.historyType = 'browser';
      // A suffix to append to the page title whenever
      // it's updated through RouteTitle
      this.titleSuffix = '';
      this.routeViewsUpdated = (options = {}) => {
        if (this.history && options.scrollToId && this.historyType === 'browser') {
          const elm = this.history.win.document.getElementById(options.scrollToId);
          if (elm) {
            return elm.scrollIntoView();
          }
        }
        this.scrollTo(options.scrollTopOffset || this.scrollTopOffset);
      };
      this.isServer = getContext(this, "isServer");
      this.queue = getContext(this, "queue");
    }
    componentWillLoad() {
      this.history = HISTORIES[this.historyType](this.el.ownerDocument.defaultView);
      this.history.listen((location) => {
        location = getLocation(location, this.root);
        this.location = location;
      });
      this.location = getLocation(this.history.location, this.root);
    }
    scrollTo(scrollToLocation) {
      const history = this.history;
      if (scrollToLocation == null || this.isServer || !history) {
        return;
      }
      if (history.action === 'POP' && Array.isArray(history.location.scrollPosition)) {
        return this.queue.write(() => {
          if (history && history.location && Array.isArray(history.location.scrollPosition)) {
            history.win.scrollTo(history.location.scrollPosition[0], history.location.scrollPosition[1]);
          }
        });
      }
      // okay, the frame has passed. Go ahead and render now
      return this.queue.write(() => {
        history.win.scrollTo(0, scrollToLocation);
      });
    }
    render() {
      if (!this.location || !this.history) {
        return;
      }
      const state = {
        historyType: this.historyType,
        location: this.location,
        titleSuffix: this.titleSuffix,
        root: this.root,
        history: this.history,
        routeViewsUpdated: this.routeViewsUpdated
      };
      return (h(ActiveRouter.Provider, { state: state }, h("slot", null)));
    }
    get el() { return getElement(this); }
  };
  
  export { Router as stencil_router };
  